📄 r128_state.c
字号:
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( 2 ); OUT_RING( CCE_PACKET0( R128_LAST_FRAME_REG, 0 ) ); OUT_RING( dev_priv->sarea_priv->last_frame ); ADVANCE_RING();}static void r128_cce_dispatch_vertex( drm_device_t *dev, drm_buf_t *buf ){ drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_buf_priv_t *buf_priv = buf->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; int format = sarea_priv->vc_format; int offset = dev_priv->buffers->offset + buf->offset - dev->agp->base; int size = buf->used; int prim = buf_priv->prim; int i = 0; RING_LOCALS; DRM_DEBUG( "%s: buf=%d nbox=%d\n", __FUNCTION__, buf->idx, sarea_priv->nbox ); r128_update_ring_snapshot( dev_priv ); if ( 0 ) r128_print_dirty( "dispatch_vertex", sarea_priv->dirty ); if ( buf->used ) { buf_priv->dispatched = 1; if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) { r128_emit_state( dev_priv ); } do { /* Emit the next set of up to three cliprects */ if ( i < sarea_priv->nbox ) { r128_emit_clip_rects( dev_priv, &sarea_priv->boxes[i], sarea_priv->nbox - i ); } /* Emit the vertex buffer rendering commands */ BEGIN_RING( 5 ); OUT_RING( CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, 3 ) ); OUT_RING( offset ); OUT_RING( size ); OUT_RING( format ); OUT_RING( prim | R128_CCE_VC_CNTL_PRIM_WALK_LIST | (size << R128_CCE_VC_CNTL_NUM_SHIFT) ); ADVANCE_RING(); i += 3; } while ( i < sarea_priv->nbox ); } if ( buf_priv->discard ) { buf_priv->age = dev_priv->sarea_priv->last_dispatch; /* Emit the vertex buffer age */ BEGIN_RING( 2 ); OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) ); OUT_RING( buf_priv->age ); ADVANCE_RING(); buf->pending = 1; buf->used = 0; /* FIXME: Check dispatched field */ buf_priv->dispatched = 0; } dev_priv->sarea_priv->last_dispatch++;#if 0 if ( dev_priv->submit_age == R128_MAX_VB_AGE ) { ret = r128_do_cce_idle( dev_priv ); if ( ret < 0 ) return ret; dev_priv->submit_age = 0; r128_freelist_reset( dev ); }#endif sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS; sarea_priv->nbox = 0;}static void r128_cce_dispatch_indirect( drm_device_t *dev, drm_buf_t *buf, int start, int end ){ drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_buf_priv_t *buf_priv = buf->dev_private; RING_LOCALS; DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end ); r128_update_ring_snapshot( dev_priv ); if ( start != end ) { int offset = (dev_priv->buffers->offset - dev->agp->base + 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 CCE packet. */ if ( dwords & 1 ) { u32 *data = (u32 *) ((char *)dev_priv->buffers->handle + buf->offset + start); data[dwords++] = R128_CCE_PACKET2; } buf_priv->dispatched = 1; /* Fire off the indirect buffer */ BEGIN_RING( 3 ); OUT_RING( CCE_PACKET0( R128_PM4_IW_INDOFF, 1 ) ); OUT_RING( offset ); OUT_RING( dwords ); ADVANCE_RING(); } if ( buf_priv->discard ) { buf_priv->age = dev_priv->sarea_priv->last_dispatch; /* Emit the indirect buffer age */ BEGIN_RING( 2 ); OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) ); OUT_RING( buf_priv->age ); ADVANCE_RING(); buf->pending = 1; buf->used = 0; /* FIXME: Check dispatched field */ buf_priv->dispatched = 0; } dev_priv->sarea_priv->last_dispatch++;#if 0 if ( dev_priv->submit_age == R128_MAX_VB_AGE ) { ret = r128_do_cce_idle( dev_priv ); if ( ret < 0 ) return ret; dev_priv->submit_age = 0; r128_freelist_reset( dev ); }#endif}static void r128_cce_dispatch_indices( drm_device_t *dev, drm_buf_t *buf, int start, int end, int count ){ drm_r128_private_t *dev_priv = dev->dev_private; drm_r128_buf_priv_t *buf_priv = buf->dev_private; drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; int format = sarea_priv->vc_format; int offset = dev_priv->buffers->offset - dev->agp->base; int prim = buf_priv->prim; u32 *data; int dwords; int i = 0; RING_LOCALS; DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count ); r128_update_ring_snapshot( dev_priv ); if ( 0 ) r128_print_dirty( "dispatch_indices", sarea_priv->dirty ); if ( start != end ) { buf_priv->dispatched = 1; if ( sarea_priv->dirty & ~R128_UPLOAD_CLIPRECTS ) { r128_emit_state( dev_priv ); } dwords = (end - start + 3) / sizeof(u32); data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset + start); data[0] = CCE_PACKET3( R128_3D_RNDR_GEN_INDX_PRIM, dwords-2 ); data[1] = offset; data[2] = R128_MAX_VB_VERTS; data[3] = format; data[4] = (prim | R128_CCE_VC_CNTL_PRIM_WALK_IND | (count << 16)); if ( count & 0x1 ) { data[dwords-1] &= 0x0000ffff; } do { /* Emit the next set of up to three cliprects */ if ( i < sarea_priv->nbox ) { r128_emit_clip_rects( dev_priv, &sarea_priv->boxes[i], sarea_priv->nbox - i ); } r128_cce_dispatch_indirect( dev, buf, start, end ); i += 3; } while ( i < sarea_priv->nbox ); } if ( buf_priv->discard ) { buf_priv->age = dev_priv->sarea_priv->last_dispatch; /* Emit the vertex buffer age */ BEGIN_RING( 2 ); OUT_RING( CCE_PACKET0( R128_LAST_DISPATCH_REG, 0 ) ); OUT_RING( buf_priv->age ); ADVANCE_RING(); buf->pending = 1; /* FIXME: Check dispatched field */ buf_priv->dispatched = 0; } dev_priv->sarea_priv->last_dispatch++;#if 0 if ( dev_priv->submit_age == R128_MAX_VB_AGE ) { ret = r128_do_cce_idle( dev_priv ); if ( ret < 0 ) return ret; dev_priv->submit_age = 0; r128_freelist_reset( dev ); }#endif sarea_priv->dirty &= ~R128_UPLOAD_CLIPRECTS; sarea_priv->nbox = 0;}static int r128_cce_dispatch_blit( drm_device_t *dev, drm_r128_blit_t *blit ){ drm_r128_private_t *dev_priv = dev->dev_private; drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_r128_buf_priv_t *buf_priv; u32 *data; int dword_shift, dwords; RING_LOCALS; DRM_DEBUG( "%s\n", __FUNCTION__ ); r128_update_ring_snapshot( dev_priv ); /* 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 ( blit->format ) { case R128_DATATYPE_ARGB1555: case R128_DATATYPE_RGB565: case R128_DATATYPE_ARGB4444: dword_shift = 1; break; case R128_DATATYPE_ARGB8888: dword_shift = 0; break; default: DRM_ERROR( "invalid blit format %d\n", blit->format ); return -EINVAL; } /* Flush the pixel cache, and mark the contents as Read Invalid. * 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( 2 ); OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) ); OUT_RING( R128_PC_RI_GUI | R128_PC_FLUSH_GUI ); ADVANCE_RING(); /* Dispatch the indirect buffer. */ buf = dma->buflist[blit->idx]; buf_priv = buf->dev_private; if ( buf->pid != current->pid ) { DRM_ERROR( "process %d using buffer owned by %d\n", current->pid, buf->pid ); return -EINVAL; } if ( buf->pending ) { DRM_ERROR( "sending pending buffer %d\n", blit->idx ); return -EINVAL; } buf_priv->discard = 1; dwords = (blit->width * blit->height) >> dword_shift; data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset); data[0] = CCE_PACKET3( R128_CNTL_HOSTDATA_BLT, dwords + 6 ); data[1] = ( R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_NONE | (blit->format << 8) | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_S | R128_DP_SRC_SOURCE_HOST_DATA | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS ); data[2] = (blit->pitch << 21) | (blit->offset >> 5); data[3] = 0xffffffff; data[4] = 0xffffffff; data[5] = (blit->y << 16) | blit->x; data[6] = (blit->height << 16) | blit->width; data[7] = dwords; buf->used = (dwords + 8) * sizeof(u32); r128_cce_dispatch_indirect( dev, buf, 0, buf->used ); /* Flush the pixel cache after the blit completes. This ensures * the texture data is written out to memory before rendering * continues. */ BEGIN_RING( 2 ); OUT_RING( CCE_PACKET0( R128_PC_GUI_CTLSTAT, 0 ) ); OUT_RING( R128_PC_FLUSH_GUI ); ADVANCE_RING(); return 0;}/* ================================================================ * Tiled depth buffer management * * FIXME: These should all set the destination write mask for when we * have hardware stencil support. */static int r128_cce_dispatch_write_span( drm_device_t *dev, drm_r128_depth_t *depth ){ drm_r128_private_t *dev_priv = dev->dev_private; int count, x, y; u32 *buffer; u8 *mask; u32 depth_bpp; int i; RING_LOCALS; DRM_DEBUG( "%s\n", __FUNCTION__ ); r128_update_ring_snapshot( dev_priv ); switch ( dev_priv->depth_bpp ) { case 16: depth_bpp = R128_GMC_DST_16BPP; break; case 24: case 32: depth_bpp = R128_GMC_DST_32BPP; break; default: return -EINVAL; } count = depth->n; if ( copy_from_user( &x, depth->x, sizeof(x) ) ) { return -EFAULT; } if ( copy_from_user( &y, depth->y, sizeof(y) ) ) { return -EFAULT; } buffer = kmalloc( depth->n * sizeof(u32), 0 ); if ( buffer == NULL ) return -ENOMEM; if ( copy_from_user( buffer, depth->buffer, depth->n * sizeof(u32) ) ) { kfree( buffer ); return -EFAULT; } if ( depth->mask ) { mask = kmalloc( depth->n * sizeof(u8), 0 ); if ( mask == NULL ) { kfree( buffer ); return -ENOMEM; } if ( copy_from_user( mask, depth->mask, depth->n * sizeof(u8) ) ) { kfree( buffer ); kfree( mask ); return -EFAULT; } for ( i = 0 ; i < count ; i++, x++ ) { if ( mask[i] ) { BEGIN_RING( 6 ); OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_SOLID_COLOR | depth_bpp | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_P | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS ); OUT_RING( dev_priv->depth_pitch_offset_c ); OUT_RING( buffer[i] ); OUT_RING( (x << 16) | y ); OUT_RING( (1 << 16) | 1 ); ADVANCE_RING(); } } kfree( mask ); } else { for ( i = 0 ; i < count ; i++, x++ ) { BEGIN_RING( 6 ); OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 4 ) ); OUT_RING( R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_SOLID_COLOR | depth_bpp | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_P | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_WR_MSK_DIS ); OUT_RING( dev_priv->depth_pitch_offset_c ); OUT_RING( buffer[i] ); OUT_RING( (x << 16) | y ); OUT_RING( (1 << 16) | 1 ); ADVANCE_RING(); } } kfree( buffer ); return 0;}static int r128_cce_dispatch_write_pixels( drm_device_t *dev, drm_r128_depth_t *depth ){ drm_r128_private_t *dev_priv = dev->dev_private; int count, *x, *y; u32 *buffer; u8 *mask; u32 depth_bpp; int i; RING_LOCALS; DRM_DEBUG( "%s\n", __FUNCTION__ ); r128_update_ring_snapshot( dev_priv ); switch ( dev_priv->depth_bpp ) { case 16: depth_bpp = R128_GMC_DST_16BPP; break; case 24: case 32: depth_bpp = R128_GMC_DST_32BPP; break; default: return -EINVAL; } count = depth->n; x = kmalloc( count * sizeof(*x), 0 ); if ( x == NULL ) { return -ENOMEM; } y = kmalloc( count * sizeof(*y), 0 ); if ( y == NULL ) { kfree( x ); return -ENOMEM; } if ( copy_from_user( x, depth->x, count * sizeof(int) ) ) { kfree( x ); kfree( y ); return -EFAULT; } if ( copy_from_user( y, depth->y, count * sizeof(int) ) ) { kfree( x ); kfree( y ); return -EFAULT; } buffer = kmalloc( depth->n * sizeof(u32), 0 ); if ( buffer == NULL ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -