radeon_state.c
来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 2,403 行 · 第 1/5 页
C
2,403 行
(3 << RADEON_NUM_VERTICES_SHIFT)) ); OUT_RING( depth_boxes[i].ui[CLEAR_X1] ); OUT_RING( depth_boxes[i].ui[CLEAR_Y1] ); OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] ); OUT_RING( 0x0 ); OUT_RING( depth_boxes[i].ui[CLEAR_X1] ); OUT_RING( depth_boxes[i].ui[CLEAR_Y2] ); OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] ); OUT_RING( 0x0 ); OUT_RING( depth_boxes[i].ui[CLEAR_X2] ); OUT_RING( depth_boxes[i].ui[CLEAR_Y2] ); OUT_RING( depth_boxes[i].ui[CLEAR_DEPTH] ); OUT_RING( 0x0 ); ADVANCE_RING(); } } /* Increment the clear counter. The client-side 3D driver must * wait on this value before performing the clear ioctl. We * need this because the card's so damned fast... */ dev_priv->sarea_priv->last_clear++; BEGIN_RING( 4 ); RADEON_CLEAR_AGE( dev_priv->sarea_priv->last_clear ); RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING();}static void radeon_cp_dispatch_swap( drm_device_t *dev ){ drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; int nbox = sarea_priv->nbox; drm_clip_rect_t *pbox = sarea_priv->boxes; int i; RING_LOCALS; DRM_DEBUG( "\n" ); /* Do some trivial performance monitoring... */ if (dev_priv->do_boxes) radeon_cp_performance_boxes( dev_priv ); /* Wait for the 3D stream to idle before dispatching the bitblt. * This will prevent data corruption between the two streams. */ BEGIN_RING( 2 ); RADEON_WAIT_UNTIL_3D_IDLE(); ADVANCE_RING(); for ( i = 0 ; i < nbox ; i++ ) { int x = pbox[i].x1; int y = pbox[i].y1; int w = pbox[i].x2 - x; int h = pbox[i].y2 - y; DRM_DEBUG( "dispatch swap %d,%d-%d,%d\n", x, y, w, h ); BEGIN_RING( 7 ); OUT_RING( CP_PACKET3( RADEON_CNTL_BITBLT_MULTI, 5 ) ); OUT_RING( RADEON_GMC_SRC_PITCH_OFFSET_CNTL | RADEON_GMC_DST_PITCH_OFFSET_CNTL | RADEON_GMC_BRUSH_NONE | (dev_priv->color_fmt << 8) | RADEON_GMC_SRC_DATATYPE_COLOR | RADEON_ROP3_S | RADEON_DP_SRC_SOURCE_MEMORY | RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS ); /* Make this work even if front & back are flipped: */ if (dev_priv->current_page == 0) { OUT_RING( dev_priv->back_pitch_offset ); OUT_RING( dev_priv->front_pitch_offset ); } else { OUT_RING( dev_priv->front_pitch_offset ); OUT_RING( dev_priv->back_pitch_offset ); } OUT_RING( (x << 16) | y ); OUT_RING( (x << 16) | y ); OUT_RING( (w << 16) | h ); ADVANCE_RING(); } /* Increment the frame counter. The client-side 3D driver must * throttle the framerate by waiting for this value before * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; BEGIN_RING( 4 ); RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame ); RADEON_WAIT_UNTIL_2D_IDLE(); ADVANCE_RING();}static void radeon_cp_dispatch_flip( drm_device_t *dev ){ drm_radeon_private_t *dev_priv = dev->dev_private; drm_sarea_t *sarea = (drm_sarea_t *)dev_priv->sarea->handle; int offset = (dev_priv->current_page == 1) ? dev_priv->front_offset : dev_priv->back_offset; RING_LOCALS; DRM_DEBUG( "%s: page=%d pfCurrentPage=%d\n", __FUNCTION__, dev_priv->current_page, dev_priv->sarea_priv->pfCurrentPage); /* Do some trivial performance monitoring... */ if (dev_priv->do_boxes) { dev_priv->stats.boxes |= RADEON_BOX_FLIP; radeon_cp_performance_boxes( dev_priv ); } /* Update the frame offsets for both CRTCs */ BEGIN_RING( 6 ); RADEON_WAIT_UNTIL_3D_IDLE(); OUT_RING_REG( RADEON_CRTC_OFFSET, ( ( sarea->frame.y * dev_priv->front_pitch + sarea->frame.x * ( dev_priv->color_fmt - 2 ) ) & ~7 ) + offset ); OUT_RING_REG( RADEON_CRTC2_OFFSET, dev_priv->sarea_priv->crtc2_base + offset ); ADVANCE_RING(); /* Increment the frame counter. The client-side 3D driver must * throttle the framerate by waiting for this value before * performing the swapbuffer ioctl. */ dev_priv->sarea_priv->last_frame++; dev_priv->sarea_priv->pfCurrentPage = dev_priv->current_page = 1 - dev_priv->current_page; BEGIN_RING( 2 ); RADEON_FRAME_AGE( dev_priv->sarea_priv->last_frame ); ADVANCE_RING();}static int bad_prim_vertex_nr( int primitive, int nr ){ switch (primitive & RADEON_PRIM_TYPE_MASK) { case RADEON_PRIM_TYPE_NONE: case RADEON_PRIM_TYPE_POINT: return nr < 1; case RADEON_PRIM_TYPE_LINE: return (nr & 1) || nr == 0; case RADEON_PRIM_TYPE_LINE_STRIP: return nr < 2; case RADEON_PRIM_TYPE_TRI_LIST: case RADEON_PRIM_TYPE_3VRT_POINT_LIST: case RADEON_PRIM_TYPE_3VRT_LINE_LIST: case RADEON_PRIM_TYPE_RECT_LIST: return nr % 3 || nr == 0; case RADEON_PRIM_TYPE_TRI_FAN: case RADEON_PRIM_TYPE_TRI_STRIP: return nr < 3; default: return 1; } }typedef struct { unsigned int start; unsigned int finish; unsigned int prim; unsigned int numverts; unsigned int offset; unsigned int vc_format;} drm_radeon_tcl_prim_t;static void radeon_cp_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf, drm_radeon_tcl_prim_t *prim ){ drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start; int numverts = (int)prim->numverts; int nbox = sarea_priv->nbox; int i = 0; RING_LOCALS; DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n", prim->prim, prim->vc_format, prim->start, prim->finish, prim->numverts); if (bad_prim_vertex_nr( prim->prim, prim->numverts )) { DRM_ERROR( "bad prim %x numverts %d\n", prim->prim, prim->numverts ); return; } do { /* Emit the next cliprect */ if ( i < nbox ) { radeon_emit_clip_rect( dev_priv, &sarea_priv->boxes[i] ); } /* Emit the vertex buffer rendering commands */ BEGIN_RING( 5 ); OUT_RING( CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, 3 ) ); OUT_RING( offset ); OUT_RING( numverts ); OUT_RING( prim->vc_format ); OUT_RING( prim->prim | RADEON_PRIM_WALK_LIST | RADEON_COLOR_ORDER_RGBA | RADEON_VTX_FMT_RADEON_MODE | (numverts << RADEON_NUM_VERTICES_SHIFT) ); ADVANCE_RING(); i++; } while ( i < nbox );}static void radeon_cp_discard_buffer( drm_device_t *dev, drm_buf_t *buf ){ drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_buf_priv_t *buf_priv = buf->dev_private; RING_LOCALS; buf_priv->age = ++dev_priv->sarea_priv->last_dispatch; /* Emit the vertex buffer age */ BEGIN_RING( 2 ); RADEON_DISPATCH_AGE( buf_priv->age ); ADVANCE_RING(); buf->pending = 1; buf->used = 0;}static void radeon_cp_dispatch_indirect( drm_device_t *dev, drm_buf_t *buf, int start, int end ){ drm_radeon_private_t *dev_priv = dev->dev_private; RING_LOCALS; DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end ); if ( start != end ) { int offset = (dev_priv->gart_buffers_offset + buf->offset + start); int dwords = (end - start + 3) / sizeof(u32); /* Indirect buffer data must be an even number of * dwords, so if we've been given an odd number we must * pad the data with a Type-2 CP packet. */ if ( dwords & 1 ) { u32 *data = (u32 *) ((char *)dev_priv->buffers->handle + buf->offset + start); data[dwords++] = RADEON_CP_PACKET2; } /* Fire off the indirect buffer */ BEGIN_RING( 3 ); OUT_RING( CP_PACKET0( RADEON_CP_IB_BASE, 1 ) ); OUT_RING( offset ); OUT_RING( dwords ); ADVANCE_RING(); }}static void radeon_cp_dispatch_indices( drm_device_t *dev, drm_buf_t *elt_buf, drm_radeon_tcl_prim_t *prim ){ drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; int offset = dev_priv->gart_buffers_offset + prim->offset; u32 *data; int dwords; int i = 0; int start = prim->start + RADEON_INDEX_PRIM_OFFSET; int count = (prim->finish - start) / sizeof(u16); int nbox = sarea_priv->nbox; DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n", prim->prim, prim->vc_format, prim->start, prim->finish, prim->offset, prim->numverts); if (bad_prim_vertex_nr( prim->prim, count )) { DRM_ERROR( "bad prim %x count %d\n", prim->prim, count ); return; } if ( start >= prim->finish || (prim->start & 0x7) ) { DRM_ERROR( "buffer prim %d\n", prim->prim ); return; } dwords = (prim->finish - prim->start + 3) / sizeof(u32); data = (u32 *)((char *)dev_priv->buffers->handle + elt_buf->offset + prim->start); data[0] = CP_PACKET3( RADEON_3D_RNDR_GEN_INDX_PRIM, dwords-2 ); data[1] = offset; data[2] = prim->numverts; data[3] = prim->vc_format; data[4] = (prim->prim | RADEON_PRIM_WALK_IND | RADEON_COLOR_ORDER_RGBA | RADEON_VTX_FMT_RADEON_MODE | (count << RADEON_NUM_VERTICES_SHIFT) ); do { if ( i < nbox ) radeon_emit_clip_rect( dev_priv, &sarea_priv->boxes[i] ); radeon_cp_dispatch_indirect( dev, elt_buf, prim->start, prim->finish ); i++; } while ( i < nbox );}#define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32))static int radeon_cp_dispatch_texture( DRMFILE filp, drm_device_t *dev, drm_radeon_texture_t *tex, drm_radeon_tex_image_t *image ){ drm_radeon_private_t *dev_priv = dev->dev_private; drm_file_t *filp_priv; drm_buf_t *buf; u32 format; u32 *buffer; const u8 __user *data; int size, dwords, tex_width, blit_width; u32 height; int i; RING_LOCALS; DRM_GET_PRIV_WITH_RETURN( filp_priv, filp ); if ( radeon_check_and_fixup_offset( dev_priv, filp_priv, &tex->offset ) ) { DRM_ERROR( "Invalid destination offset\n" ); return DRM_ERR( EINVAL ); } dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD; /* Flush the pixel cache. This ensures no pixel data gets mixed * up with the texture data from the host data blit, otherwise * part of the texture image may be corrupted. */ BEGIN_RING( 4 ); RADEON_FLUSH_CACHE(); RADEON_WAIT_UNTIL_IDLE(); ADVANCE_RING();#ifdef __BIG_ENDIAN /* The Mesa texture functions provide the data in little endian as the * chip wants it, but we need to compensate for the fact that the CP * ring gets byte-swapped */ BEGIN_RING( 2 ); OUT_RING_REG( RADEON_RBBM_GUICNTL, RADEON_HOST_DATA_SWAP_32BIT ); ADVANCE_RING();#endif /* The compiler won't optimize away a division by a variable, * even if the only legal values are powers of two. Thus, we'll * use a shift instead. */ switch ( tex->format ) { case RADEON_TXFORMAT_ARGB8888: case RADEON_TXFORMAT_RGBA8888: format = RADEON_COLOR_FORMAT_ARGB8888; tex_width = tex->width * 4; blit_width = image->width * 4; break; case RADEON_TXFORMAT_AI88: case RADEON_TXFORMAT_ARGB1555: case RADEON_TXFORMAT_RGB565: case RADEON_TXFORMAT_ARGB4444: case RADEON_TXFORMAT_VYUY422: case RADEON_TXFORMAT_YVYU422: format = RADEON_COLOR_FORMAT_RGB565; tex_width = tex->width * 2; blit_width = image->width * 2; break; case RADEON_TXFORMAT_I8: case RADEON_TXFORMAT_RGB332: format = RADEON_COLOR_FORMAT_CI8; tex_width = tex->width * 1; blit_width = image->width * 1; break; default: DRM_ERROR( "invalid texture format %d\n", tex->format ); return DRM_ERR(EINVAL); } DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width ); do { DRM_DEBUG( "tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n", tex->offset >> 10, tex->pitch, tex->format, image->x, image->y, image->width, image->height ); /* Make a copy of some parameters in case we have to * update them for a multi-pass texture blit. */ height = image->height; data = (const u8 __user *)image->data; size = height * blit_width; if ( size > RADEON_MAX_TEXTURE_SIZE ) { height = RADEON_MAX_TEXTURE_SIZE / blit_width; size = height * blit_width; } else if ( size < 4 && size > 0 ) { size = 4; } else if ( size == 0 ) { return 0; } buf = radeon_freelist_get( dev ); if ( 0 && !buf ) { radeon_do_cp_idle( dev_priv ); buf = radeon_freelist_get( dev ); } if ( !buf ) { DRM_DEBUG("radeon_cp_dispatch_texture: EAGAIN\n"); DRM_COPY_TO_USER( tex->image, image, sizeof(*image) ); return DRM_ERR(EAGAIN); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?