summaryrefslogtreecommitdiff
path: root/linux/radeon_state.c
diff options
context:
space:
mode:
Diffstat (limited to 'linux/radeon_state.c')
-rw-r--r--linux/radeon_state.c312
1 files changed, 138 insertions, 174 deletions
diff --git a/linux/radeon_state.c b/linux/radeon_state.c
index 9360c43b0..7bfefb2ca 100644
--- a/linux/radeon_state.c
+++ b/linux/radeon_state.c
@@ -23,12 +23,12 @@
* DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
+ * Gareth Hughes <gareth@valinux.com>
+ *
*/
#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;