diff options
Diffstat (limited to 'linux/r128_state.c')
-rw-r--r-- | linux/r128_state.c | 279 |
1 files changed, 272 insertions, 7 deletions
diff --git a/linux/r128_state.c b/linux/r128_state.c index 124d9938..b9ea930b 100644 --- a/linux/r128_state.c +++ b/linux/r128_state.c @@ -181,7 +181,7 @@ static inline void r128_emit_tex0( drm_r128_private_t *dev_priv ) RING_LOCALS; DRM_DEBUG( " %s\n", __FUNCTION__ ); - BEGIN_RING( 3 ); + BEGIN_RING( 7 + R128_TEX_MAXLEVELS ); OUT_RING( CCE_PACKET0( R128_PRIM_TEX_CNTL_C, 2 + R128_TEX_MAXLEVELS ) ); @@ -207,7 +207,7 @@ static inline void r128_emit_tex1( drm_r128_private_t *dev_priv ) RING_LOCALS; DRM_DEBUG( " %s\n", __FUNCTION__ ); - BEGIN_RING( 3 ); + BEGIN_RING( 5 + R128_TEX_MAXLEVELS ); OUT_RING( CCE_PACKET0( R128_SEC_TEX_CNTL_C, 1 + R128_TEX_MAXLEVELS ) ); @@ -274,16 +274,214 @@ static inline void r128_emit_state( drm_r128_private_t *dev_priv ) * CCE command dispatch functions */ -static void r128_cce_dispatch_swap( drm_device_t *dev ) +static void r128_print_dirty( const char *msg, unsigned int flags ) { - + DRM_INFO( "%s: (0x%x) %s%s%s%s%s%s%s%s%s\n", + msg, + flags, + (flags & R128_UPLOAD_CORE) ? "core, " : "", + (flags & R128_UPLOAD_CONTEXT) ? "context, " : "", + (flags & R128_UPLOAD_SETUP) ? "setup, " : "", + (flags & R128_UPLOAD_TEX0) ? "tex0, " : "", + (flags & R128_UPLOAD_TEX1) ? "tex1, " : "", + (flags & R128_UPLOAD_MASKS) ? "masks, " : "", + (flags & R128_UPLOAD_WINDOW) ? "window, " : "", + (flags & R128_UPLOAD_CLIPRECTS) ? "cliprects, " : "", + (flags & R128_REQUIRE_QUIESCENCE) ? "quiescence, " : "" ); } -static void r128_cce_dispatch_clear( drm_device_t *dev, int flags, +static void r128_cce_dispatch_clear( drm_device_t *dev, + unsigned int flags, + int cx, int cy, int cw, int ch, unsigned int clear_color, - unsigned int clear_depth ) + unsigned int clear_depth, + unsigned int color_mask, + unsigned int depth_mask ) { + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; + int nbox = sarea_priv->nbox; + drm_clip_rect_t *pbox = sarea_priv->boxes; + u32 fb_bpp, depth_bpp; + int i; + RING_LOCALS; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + switch ( dev_priv->fb_bpp ) { + case 16: + fb_bpp = R128_GMC_DST_16BPP; + break; + case 24: + fb_bpp = R128_GMC_DST_24BPP; + break; + case 32: + default: + fb_bpp = R128_GMC_DST_32BPP; + break; + } + switch ( dev_priv->depth_bpp ) { + case 16: + depth_bpp = R128_GMC_DST_16BPP; + break; + case 24: + depth_bpp = R128_GMC_DST_32BPP; + break; + case 32: + depth_bpp = R128_GMC_DST_32BPP; + break; + default: + return; + } + + 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 clear %d,%d-%d,%d flags 0x%x\n", + pbox[i].x1, pbox[i].y1, pbox[i].x2, + pbox[i].y2, flags ); + + if ( flags & (R128_FRONT | R128_BACK) ) { + BEGIN_RING( 7 ); + + OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) ); + OUT_RING( color_mask ); + + ADVANCE_RING(); + } + + if ( flags & R128_FRONT ) { + int fx = x + dev_priv->front_x; + int fy = y + dev_priv->front_y; + + DRM_DEBUG( "clear front\n"); + BEGIN_RING( 5 ); + + OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 3 ) ); + OUT_RING( R128_GMC_BRUSH_SOLID_COLOR + | fb_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS ); + OUT_RING( clear_color ); + OUT_RING( (fx << 16) | fy ); + OUT_RING( (w << 16) | h ); + + ADVANCE_RING(); + } + + if ( flags & R128_BACK ) { + int bx = x + dev_priv->back_x; + int by = y + dev_priv->back_y; + + DRM_DEBUG( "clear back\n" ); + BEGIN_RING( 5 ); + + OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 3 ) ); + OUT_RING( R128_GMC_BRUSH_SOLID_COLOR + | fb_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS ); + OUT_RING( clear_color ); + OUT_RING( (bx << 16) | by ); + OUT_RING( (w << 16) | h ); + + ADVANCE_RING(); + } + + if ( flags & R128_DEPTH ) { + int dx = x + dev_priv->depth_x; + int dy = y + dev_priv->depth_y; + + DRM_DEBUG( "clear depth\n" ); + BEGIN_RING( 7 ); + + OUT_RING( CCE_PACKET0( R128_DP_WRITE_MASK, 0 ) ); + OUT_RING( depth_mask ); + + OUT_RING( CCE_PACKET3( R128_CNTL_PAINT_MULTI, 3 ) ); + OUT_RING( R128_GMC_BRUSH_SOLID_COLOR + | depth_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_P + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS ); + OUT_RING( clear_depth ); + OUT_RING( (dx << 16) | dy ); + OUT_RING( (w << 16) | h ); + + ADVANCE_RING(); + } + } +} + +static void r128_cce_dispatch_swap( drm_device_t *dev ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; + int nbox = sarea_priv->nbox; + drm_clip_rect_t *pbox = sarea_priv->boxes; + u32 fb_bpp; + int i; + RING_LOCALS; + DRM_INFO( "%s\n", __FUNCTION__ ); + + switch ( dev_priv->fb_bpp ) { + case 16: + fb_bpp = R128_GMC_DST_16BPP; + break; + case 24: + fb_bpp = R128_GMC_DST_24BPP; + break; + case 32: + default: + fb_bpp = R128_GMC_DST_32BPP; + break; + } + + for ( i = 0 ; i < nbox ; i++ ) { + int fx = pbox[i].x1; + int fy = pbox[i].y1; + int fw = pbox[i].x2 - fx; + int fh = pbox[i].y2 - fy; + int bx = fx + dev_priv->back_x; + int by = fy + dev_priv->back_y; + + fx += dev_priv->front_x; + fy += dev_priv->front_x; + + BEGIN_RING( 5 ); + + OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 3 ) ); + OUT_RING( R128_GMC_BRUSH_NONE + | R128_GMC_SRC_DATATYPE_COLOR + | R128_DP_SRC_SOURCE_MEMORY + | fb_bpp + | R128_ROP3_S + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_AUX_CLIP_DIS + | R128_GMC_WR_MSK_DIS ); + + OUT_RING( (bx << 16) | by ); + OUT_RING( (fx << 16) | fy ); + OUT_RING( (fw << 16) | fh ); + ADVANCE_RING(); + } + +#if 0 + BEGIN_RING( 2 ); + + OUT_RING( CCE_PACKET0( R128_SWAP_AGE_REG, 0 ) ); + OUT_RING( r128ctx->lastSwapAge ); + + ADVANCE_RING(); +#endif } static void r128_cce_dispatch_vertex( drm_device_t *dev, @@ -295,7 +493,7 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev, int vertsize = sarea_priv->vertsize; int format = sarea_priv->vc_format; int index = buf->idx; - int offset = dev_priv->agp_vertbufs->offset + int offset = dev_priv->vertex_buffers->offset + buf->offset - dev->agp->base; int size = buf->used / (vertsize * sizeof(u32)); int prim; @@ -309,6 +507,11 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev, DRM_DEBUG( "vertex size = %d\n", vertsize ); DRM_DEBUG( "vertex format = 0x%x\n", format ); + r128_update_ring_snapshot( dev_priv ); + + if ( 0 ) + r128_print_dirty( "dispatch_vertex", sarea_priv->dirty ); + prim = R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST; if ( buf->used ) { @@ -389,6 +592,68 @@ static void r128_get_vertex_buffer( drm_device_t *dev, drm_r128_vertex_t *v ) v->granted = 1; } +int r128_cce_clear( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; + drm_r128_clear_t clear; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "r128_cce_clear called without lock held\n" ); + return -EINVAL; + } + + if ( copy_from_user( &clear, (drm_r128_clear_t *) arg, + sizeof(clear) ) ) + return -EFAULT; + + if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS ) + sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; + + r128_cce_dispatch_clear( dev, clear.flags, + clear.x, clear.y, clear.w, clear.h, + clear.clear_color, clear.clear_depth, + clear.color_mask, clear.depth_mask ); + + /* Make sure we restore the 3D state next time. + */ + dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS; + + return 0; +} + +int r128_cce_swap( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ) +{ + drm_file_t *priv = filp->private_data; + drm_device_t *dev = priv->dev; + drm_r128_private_t *dev_priv = dev->dev_private; + drm_r128_sarea_t *sarea_priv = dev_priv->sarea_priv; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "r128_cce_swap called without lock held\n" ); + return -EINVAL; + } + + if ( sarea_priv->nbox > R128_NR_SAREA_CLIPRECTS ) + sarea_priv->nbox = R128_NR_SAREA_CLIPRECTS; + + r128_cce_dispatch_swap( dev ); + + /* Make sure we restore the 3D state next time. + */ + dev_priv->sarea_priv->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS; + + return 0; +} + int r128_cce_vertex( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ) { |