From 0e5b8d77cfe0f86698041aebe31c54f59c877825 Mon Sep 17 00:00:00 2001 From: David Dawes Date: Mon, 19 Mar 2001 17:45:52 +0000 Subject: Import of XFree86 4.0.99.1 --- linux/radeon_state.c | 312 +++++++++++++++++++++++---------------------------- 1 file changed, 138 insertions(+), 174 deletions(-) (limited to 'linux/radeon_state.c') diff --git a/linux/radeon_state.c b/linux/radeon_state.c index 9360c43b..7bfefb2c 100644 --- a/linux/radeon_state.c +++ b/linux/radeon_state.c @@ -23,12 +23,12 @@ * DEALINGS IN THE SOFTWARE. * * Authors: - * Gareth Hughes * Kevin E. Martin + * Gareth Hughes + * */ #define __NO_VERSION__ -#include "radeon.h" #include "drmP.h" #include "radeon_drv.h" #include "drm.h" @@ -486,8 +486,7 @@ static void radeon_print_dirty( const char *msg, unsigned int flags ) } static void radeon_cp_dispatch_clear( drm_device_t *dev, - drm_radeon_clear_t *clear, - drm_radeon_clear_rect_t *depth_boxes ) + drm_radeon_clear_t *clear ) { drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; @@ -498,6 +497,8 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev, RING_LOCALS; DRM_DEBUG( "%s\n", __FUNCTION__ ); + radeon_update_ring_snapshot( dev_priv ); + if ( dev_priv->page_flipping && dev_priv->current_page == 1 ) { unsigned int tmp = flags; @@ -524,7 +525,7 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev, RADEON_WAIT_UNTIL_3D_IDLE(); OUT_RING( CP_PACKET0( RADEON_DP_WRITE_MASK, 0 ) ); - OUT_RING( clear->color_mask ); + OUT_RING( sarea_priv->context_state.rb3d_planemask ); ADVANCE_RING(); @@ -608,17 +609,17 @@ static void radeon_cp_dispatch_clear( drm_device_t *dev, RADEON_VTX_FMT_RADEON_MODE | (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( clear->rect.ui[CLEAR_X1] ); + OUT_RING( clear->rect.ui[CLEAR_Y1] ); + OUT_RING( clear->rect.ui[CLEAR_DEPTH] ); - 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( clear->rect.ui[CLEAR_X1] ); + OUT_RING( clear->rect.ui[CLEAR_Y2] ); + OUT_RING( clear->rect.ui[CLEAR_DEPTH] ); - 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( clear->rect.ui[CLEAR_X2] ); + OUT_RING( clear->rect.ui[CLEAR_Y2] ); + OUT_RING( clear->rect.ui[CLEAR_DEPTH] ); ADVANCE_RING(); @@ -654,6 +655,8 @@ static void radeon_cp_dispatch_swap( drm_device_t *dev ) RING_LOCALS; DRM_DEBUG( "%s\n", __FUNCTION__ ); + radeon_update_ring_snapshot( dev_priv ); + #if RADEON_PERFORMANCE_BOXES /* Do some trivial performance monitoring... */ @@ -721,6 +724,8 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev ) RING_LOCALS; DRM_DEBUG( "%s: page=%d\n", __FUNCTION__, dev_priv->current_page ); + radeon_update_ring_snapshot( dev_priv ); + #if RADEON_PERFORMANCE_BOXES /* Do some trivial performance monitoring... */ @@ -771,7 +776,9 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev, RING_LOCALS; DRM_DEBUG( "%s: nbox=%d\n", __FUNCTION__, sarea_priv->nbox ); - if ( 0 ) + radeon_update_ring_snapshot( dev_priv ); + + if ( 1 ) radeon_print_dirty( "dispatch_vertex", sarea_priv->dirty ); if ( buf->used ) { @@ -837,6 +844,8 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev, DRM_DEBUG( "indirect: buf=%d s=0x%x e=0x%x\n", buf->idx, start, end ); + radeon_update_ring_snapshot( dev_priv ); + if ( start != end ) { int offset = (dev_priv->agp_buffers_offset + buf->offset + start); @@ -899,6 +908,8 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev, RING_LOCALS; DRM_DEBUG( "indices: s=%d e=%d c=%d\n", start, end, count ); + radeon_update_ring_snapshot( dev_priv ); + if ( 0 ) radeon_print_dirty( "dispatch_indices", sarea_priv->dirty ); @@ -960,67 +971,50 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev, sarea_priv->nbox = 0; } -#define RADEON_MAX_TEXTURE_SIZE (RADEON_BUFFER_SIZE - 8 * sizeof(u32)) - -static int radeon_cp_dispatch_texture( drm_device_t *dev, - drm_radeon_texture_t *tex, - drm_radeon_tex_image_t *image ) +static int radeon_cp_dispatch_blit( drm_device_t *dev, + drm_radeon_blit_t *blit ) { drm_radeon_private_t *dev_priv = dev->dev_private; + drm_device_dma_t *dma = dev->dma; drm_buf_t *buf; drm_radeon_buf_priv_t *buf_priv; u32 format; - u32 *buffer; - u8 *data; - int size, dwords, tex_width, blit_width; - u32 y, height; - int ret = 0, i; + u32 *data; + int dword_shift, dwords; RING_LOCALS; + DRM_DEBUG( "blit: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n", + blit->offset >> 10, blit->pitch, blit->format, + blit->x, blit->y, blit->width, blit->height ); - /* FIXME: Be smarter about this... - */ - buf = radeon_freelist_get( dev ); - if ( !buf ) return -EAGAIN; - - 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 ); - - buf_priv = buf->dev_private; + radeon_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 ( tex->format ) { - case RADEON_TXFORMAT_ARGB8888: - case RADEON_TXFORMAT_RGBA8888: + switch ( blit->format ) { + case RADEON_TXF_32BPP_ARGB8888: + case RADEON_TXF_32BPP_RGBA8888: format = RADEON_COLOR_FORMAT_ARGB8888; - tex_width = tex->width * 4; - blit_width = image->width * 4; + dword_shift = 0; break; - case RADEON_TXFORMAT_AI88: - case RADEON_TXFORMAT_ARGB1555: - case RADEON_TXFORMAT_RGB565: - case RADEON_TXFORMAT_ARGB4444: + case RADEON_TXF_16BPP_AI88: + case RADEON_TXF_16BPP_ARGB1555: + case RADEON_TXF_16BPP_RGB565: + case RADEON_TXF_16BPP_ARGB4444: format = RADEON_COLOR_FORMAT_RGB565; - tex_width = tex->width * 2; - blit_width = image->width * 2; + dword_shift = 1; break; - case RADEON_TXFORMAT_I8: - case RADEON_TXFORMAT_RGB332: + case RADEON_TXF_8BPP_I: + case RADEON_TXF_8BPP_RGB332: format = RADEON_COLOR_FORMAT_CI8; - tex_width = tex->width * 1; - blit_width = image->width * 1; + dword_shift = 2; break; default: - DRM_ERROR( "invalid texture format %d\n", tex->format ); + DRM_ERROR( "invalid blit format %d\n", blit->format ); return -EINVAL; } - DRM_DEBUG( " tex=%dx%d blit=%d\n", - tex_width, tex->height, blit_width ); - /* 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. @@ -1032,88 +1026,46 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev, ADVANCE_RING(); - /* Make a copy of the parameters in case we have to update them - * for a multi-pass texture blit. + /* Dispatch the indirect buffer. */ - y = image->y; - height = image->height; - data = (u8 *)image->data; + buf = dma->buflist[blit->idx]; + buf_priv = buf->dev_private; - size = height * blit_width; + 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; + } - if ( size > RADEON_MAX_TEXTURE_SIZE ) { - /* Texture image is too large, do a multipass upload */ - ret = -EAGAIN; + buf_priv->discard = 1; - /* Adjust the blit size to fit the indirect buffer */ - height = RADEON_MAX_TEXTURE_SIZE / blit_width; - size = height * blit_width; + dwords = (blit->width * blit->height) >> dword_shift; + if ( !dwords ) dwords = 1; - /* Update the input parameters for next time */ - image->y += height; - image->height -= height; - image->data = (char *)image->data + size; + data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset); - if ( copy_to_user( tex->image, image, sizeof(*image) ) ) { - DRM_ERROR( "EFAULT on tex->image\n" ); - return -EFAULT; - } - } else if ( size < 4 ) { - size = 4; - } + data[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 ); + data[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | + RADEON_GMC_BRUSH_NONE | + (format << 8) | + RADEON_GMC_SRC_DATATYPE_COLOR | + RADEON_ROP3_S | + RADEON_DP_SRC_SOURCE_HOST_DATA | + RADEON_GMC_CLR_CMP_CNTL_DIS | + RADEON_GMC_WR_MSK_DIS); - dwords = size / 4; + data[2] = (blit->pitch << 22) | (blit->offset >> 10); + data[3] = 0xffffffff; + data[4] = 0xffffffff; + data[5] = (blit->y << 16) | blit->x; + data[6] = (blit->height << 16) | blit->width; + data[7] = dwords; - /* Dispatch the indirect buffer. - */ - buffer = (u32 *)((char *)dev_priv->buffers->handle + buf->offset); - - buffer[0] = CP_PACKET3( RADEON_CNTL_HOSTDATA_BLT, dwords + 6 ); - buffer[1] = (RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_NONE | - (format << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP3_S | - RADEON_DP_SRC_SOURCE_HOST_DATA | - RADEON_GMC_CLR_CMP_CNTL_DIS | - RADEON_GMC_WR_MSK_DIS); - - buffer[2] = (tex->pitch << 22) | (tex->offset >> 10); - buffer[3] = 0xffffffff; - buffer[4] = 0xffffffff; - buffer[5] = (y << 16) | image->x; - buffer[6] = (height << 16) | image->width; - buffer[7] = dwords; - - buffer += 8; - - if ( tex_width >= 32 ) { - /* Texture image width is larger than the minimum, so we - * can upload it directly. - */ - if ( copy_from_user( buffer, data, dwords * sizeof(u32) ) ) { - DRM_ERROR( "EFAULT on data, %d dwords\n", dwords ); - return -EFAULT; - } - } else { - /* Texture image width is less than the minimum, so we - * need to pad out each image scanline to the minimum - * width. - */ - for ( i = 0 ; i < tex->height ; i++ ) { - if ( copy_from_user( buffer, data, tex_width ) ) { - DRM_ERROR( "EFAULT on pad, %d bytes\n", - tex_width ); - return -EFAULT; - } - buffer += 8; - data += tex_width; - } - } - - buf->pid = current->pid; buf->used = (dwords + 8) * sizeof(u32); - buf_priv->discard = 1; radeon_cp_dispatch_indirect( dev, buf, 0, buf->used ); @@ -1128,7 +1080,7 @@ static int radeon_cp_dispatch_texture( drm_device_t *dev, ADVANCE_RING(); - return ret; + return 0; } static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple ) @@ -1138,6 +1090,8 @@ static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple ) RING_LOCALS; DRM_DEBUG( "%s\n", __FUNCTION__ ); + radeon_update_ring_snapshot( dev_priv ); + BEGIN_RING( 35 ); OUT_RING( CP_PACKET0( RADEON_RE_STIPPLE_ADDR, 0 ) ); @@ -1164,25 +1118,22 @@ int radeon_cp_clear( struct inode *inode, struct file *filp, drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; drm_radeon_clear_t clear; - drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; DRM_DEBUG( "%s\n", __FUNCTION__ ); - LOCK_TEST_WITH_RETURN( dev ); + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); + return -EINVAL; + } - if ( copy_from_user( &clear, (drm_radeon_clear_t *)arg, + if ( copy_from_user( &clear, (drm_radeon_clear_t *) arg, sizeof(clear) ) ) return -EFAULT; - RING_SPACE_TEST_WITH_RETURN( dev_priv ); - if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS ) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; - if ( copy_from_user( &depth_boxes, clear.depth_boxes, - sarea_priv->nbox * sizeof(depth_boxes[0]) ) ) - return -EFAULT; - - radeon_cp_dispatch_clear( dev, &clear, depth_boxes ); + radeon_cp_dispatch_clear( dev, &clear ); return 0; } @@ -1196,9 +1147,11 @@ int radeon_cp_swap( struct inode *inode, struct file *filp, drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv; DRM_DEBUG( "%s\n", __FUNCTION__ ); - LOCK_TEST_WITH_RETURN( dev ); - - RING_SPACE_TEST_WITH_RETURN( dev_priv ); + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); + return -EINVAL; + } if ( sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS ) sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; @@ -1225,8 +1178,11 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp, drm_radeon_buf_priv_t *buf_priv; drm_radeon_vertex_t vertex; - LOCK_TEST_WITH_RETURN( dev ); - + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); + return -EINVAL; + } if ( !dev_priv || dev_priv->is_pci ) { DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ ); return -EINVAL; @@ -1251,8 +1207,7 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp, return -EINVAL; } - RING_SPACE_TEST_WITH_RETURN( dev_priv ); - VB_AGE_TEST_WITH_RETURN( dev_priv ); + VB_AGE_CHECK_WITH_RET( dev_priv ); buf = dma->buflist[vertex.idx]; buf_priv = buf->dev_private; @@ -1288,8 +1243,11 @@ int radeon_cp_indices( struct inode *inode, struct file *filp, drm_radeon_indices_t elts; int count; - LOCK_TEST_WITH_RETURN( dev ); - + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); + return -EINVAL; + } if ( !dev_priv || dev_priv->is_pci ) { DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ ); return -EINVAL; @@ -1314,8 +1272,7 @@ int radeon_cp_indices( struct inode *inode, struct file *filp, return -EINVAL; } - RING_SPACE_TEST_WITH_RETURN( dev_priv ); - VB_AGE_TEST_WITH_RETURN( dev_priv ); + VB_AGE_CHECK_WITH_RET( dev_priv ); buf = dma->buflist[elts.idx]; buf_priv = buf->dev_private; @@ -1351,34 +1308,37 @@ int radeon_cp_indices( struct inode *inode, struct file *filp, return 0; } -int radeon_cp_texture( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) +int radeon_cp_blit( 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_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_texture_t tex; - drm_radeon_tex_image_t image; + drm_device_dma_t *dma = dev->dma; + drm_radeon_blit_t blit; - LOCK_TEST_WITH_RETURN( dev ); + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); + return -EINVAL; + } - if ( copy_from_user( &tex, (drm_radeon_texture_t *)arg, sizeof(tex) ) ) + if ( copy_from_user( &blit, (drm_radeon_blit_t *)arg, + sizeof(blit) ) ) return -EFAULT; - if ( tex.image == NULL ) { - DRM_ERROR( "null texture image!\n" ); + DRM_DEBUG( "%s: pid=%d index=%d\n", + __FUNCTION__, current->pid, blit.idx ); + + if ( blit.idx < 0 || blit.idx > dma->buf_count ) { + DRM_ERROR( "sending %d buffers (of %d max)\n", + blit.idx, dma->buf_count ); return -EINVAL; } - if ( copy_from_user( &image, - (drm_radeon_tex_image_t *)tex.image, - sizeof(image) ) ) - return -EFAULT; - - RING_SPACE_TEST_WITH_RETURN( dev_priv ); - VB_AGE_TEST_WITH_RETURN( dev_priv ); + VB_AGE_CHECK_WITH_RET( dev_priv ); - return radeon_cp_dispatch_texture( dev, &tex, &image ); + return radeon_cp_dispatch_blit( dev, &blit ); } int radeon_cp_stipple( struct inode *inode, struct file *filp, @@ -1386,21 +1346,23 @@ int radeon_cp_stipple( struct inode *inode, struct file *filp, { drm_file_t *priv = filp->private_data; drm_device_t *dev = priv->dev; - drm_radeon_private_t *dev_priv = dev->dev_private; drm_radeon_stipple_t stipple; u32 mask[32]; - LOCK_TEST_WITH_RETURN( dev ); + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); + return -EINVAL; + } if ( copy_from_user( &stipple, (drm_radeon_stipple_t *)arg, sizeof(stipple) ) ) return -EFAULT; - if ( copy_from_user( &mask, stipple.mask, 32 * sizeof(u32) ) ) + if ( copy_from_user( &mask, stipple.mask, + 32 * sizeof(u32) ) ) return -EFAULT; - RING_SPACE_TEST_WITH_RETURN( dev_priv ); - radeon_cp_dispatch_stipple( dev, mask ); return 0; @@ -1418,8 +1380,11 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp, drm_radeon_indirect_t indirect; RING_LOCALS; - LOCK_TEST_WITH_RETURN( dev ); - + if ( !_DRM_LOCK_IS_HELD( dev->lock.hw_lock->lock ) || + dev->lock.pid != current->pid ) { + DRM_ERROR( "%s called without lock held\n", __FUNCTION__ ); + return -EINVAL; + } if ( !dev_priv || dev_priv->is_pci ) { DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ ); return -EINVAL; @@ -1458,8 +1423,7 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp, return -EINVAL; } - RING_SPACE_TEST_WITH_RETURN( dev_priv ); - VB_AGE_TEST_WITH_RETURN( dev_priv ); + VB_AGE_CHECK_WITH_RET( dev_priv ); buf->used = indirect.end; buf_priv->discard = indirect.discard; -- cgit v1.2.3