diff options
Diffstat (limited to 'xc/programs/Xserver/hw/xfree86')
11 files changed, 264 insertions, 233 deletions
diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h index c29db273b..20ad35cbc 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_reg.h @@ -1068,36 +1068,36 @@ #define RADEON_PP_TXFORMAT_0 0x1c58 #define RADEON_PP_TXFORMAT_1 0x1c70 #define RADEON_PP_TXFORMAT_2 0x1c88 -# define RADEON_TXF_8BPP_I (0 << 0) -# define RADEON_TXF_16BPP_AI88 (1 << 0) -# define RADEON_TXF_8BPP_RGB332 (2 << 0) -# define RADEON_TXF_16BPP_ARGB1555 (3 << 0) -# define RADEON_TXF_16BPP_RGB565 (4 << 0) -# define RADEON_TXF_16BPP_ARGB4444 (5 << 0) -# define RADEON_TXF_32BPP_ARGB8888 (6 << 0) -# define RADEON_TXF_32BPP_RGBA8888 (7 << 0) -# define RADEON_TXF_8BPP_Y (8 << 0) -# define RADEON_TXF_FORMAT_MASK (31 << 0) -# define RADEON_TXF_FORMAT_SHIFT 0 -# define RADEON_TXF_APPLE_YUV_MODE (1 << 5) -# define RADEON_TXF_ALPHA_IN_MAP (1 << 6) -# define RADEON_TXF_NON_POWER2 (1 << 7) -# define RADEON_TXF_WIDTH_MASK (15 << 8) -# define RADEON_TXF_WIDTH_SHIFT 8 -# define RADEON_TXF_HEIGHT_MASK (15 << 12) -# define RADEON_TXF_HEIGHT_SHIFT 12 -# define RADEON_TXF_ST_ROUTE_STQ0 (0 << 24) -# define RADEON_TXF_ST_ROUTE_MASK (3 << 24) -# define RADEON_TXF_ST_ROUTE_STQ1 (1 << 24) -# define RADEON_TXF_ST_ROUTE_STQ2 (2 << 24) -# define RADEON_TXF_ENDIAN_NO_SWAP (0 << 26) -# define RADEON_TXF_ENDIAN_16BPP_SWAP (1 << 26) -# define RADEON_TXF_ENDIAN_32BPP_SWAP (2 << 26) -# define RADEON_TXF_ENDIAN_HALFDW_SWAP (3 << 26) -# define RADEON_TXF_ALPHA_MASK_ENABLE (1 << 28) -# define RADEON_TXF_CHROMA_KEY_ENABLE (1 << 29) -# define RADEON_TXF_CUBIC_MAP_ENABLE (1 << 30) -# define RADEON_TXF_PERSPECTIVE_ENABLE (1 << 31) +# define RADEON_TXFORMAT_I8 (0 << 0) +# define RADEON_TXFORMAT_AI88 (1 << 0) +# define RADEON_TXFORMAT_RGB332 (2 << 0) +# define RADEON_TXFORMAT_ARGB1555 (3 << 0) +# define RADEON_TXFORMAT_RGB565 (4 << 0) +# define RADEON_TXFORMAT_ARGB4444 (5 << 0) +# define RADEON_TXFORMAT_ARGB8888 (6 << 0) +# define RADEON_TXFORMAT_RGBA8888 (7 << 0) +# define RADEON_TXFORMAT_Y8 (8 << 0) +# define RADEON_TXFORMAT_FORMAT_MASK (31 << 0) +# define RADEON_TXFORMAT_FORMAT_SHIFT 0 +# define RADEON_TXFORMAT_APPLE_YUV_MODE (1 << 5) +# define RADEON_TXFORMAT_ALPHA_IN_MAP (1 << 6) +# define RADEON_TXFORMAT_NON_POWER2 (1 << 7) +# define RADEON_TXFORMAT_WIDTH_MASK (15 << 8) +# define RADEON_TXFORMAT_WIDTH_SHIFT 8 +# define RADEON_TXFORMAT_HEIGHT_MASK (15 << 12) +# define RADEON_TXFORMAT_HEIGHT_SHIFT 12 +# define RADEON_TXFORMAT_ST_ROUTE_STQ0 (0 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_MASK (3 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_STQ1 (1 << 24) +# define RADEON_TXFORMAT_ST_ROUTE_STQ2 (2 << 24) +# define RADEON_TXFORMAT_ENDIAN_NO_SWAP (0 << 26) +# define RADEON_TXFORMAT_ENDIAN_16BPP_SWAP (1 << 26) +# define RADEON_TXFORMAT_ENDIAN_32BPP_SWAP (2 << 26) +# define RADEON_TXFORMAT_ENDIAN_HALFDW_SWAP (3 << 26) +# define RADEON_TXFORMAT_ALPHA_MASK_ENABLE (1 << 28) +# define RADEON_TXFORMAT_CHROMA_KEY_ENABLE (1 << 29) +# define RADEON_TXFORMAT_CUBIC_MAP_ENABLE (1 << 30) +# define RADEON_TXFORMAT_PERSPECTIVE_ENABLE (1 << 31) #define RADEON_PP_TXOFFSET_0 0x1c5c #define RADEON_PP_TXOFFSET_1 0x1c74 #define RADEON_PP_TXOFFSET_2 0x1c8c diff --git a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h index 14cb002fd..b80f35e52 100644 --- a/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h +++ b/xc/programs/Xserver/hw/xfree86/drivers/ati/radeon_sarea.h @@ -81,7 +81,7 @@ /* Vertex/indirect buffer size */ -#define RADEON_BUFFER_SIZE 16384 +#define RADEON_BUFFER_SIZE 65536 /* Byte offsets for indirect buffer data */ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h index 40a85875b..30b75e1e3 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/drm.h @@ -439,7 +439,7 @@ typedef struct drm_agp_info { #define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t) #define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t) #define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t) -#define DRM_IOCTL_RADEON_BLIT DRM_IOW( 0x4b, drm_radeon_blit_t) +#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4b, drm_radeon_texture_t) #define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t) #define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_cp.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_cp.c index 2f20806c9..3feb4b240 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_cp.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_cp.c @@ -843,11 +843,8 @@ int radeon_cp_start( struct inode *inode, struct file *filp, drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "%s\n", __FUNCTION__ ); - 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; - } + LOCK_TEST_WITH_RETURN( dev ); + if ( dev_priv->cp_running ) { DRM_DEBUG( "%s while CP running\n", __FUNCTION__ ); return 0; @@ -876,11 +873,7 @@ int radeon_cp_stop( struct inode *inode, struct file *filp, int ret; DRM_DEBUG( "%s\n", __FUNCTION__ ); - 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; - } + LOCK_TEST_WITH_RETURN( dev ); if ( copy_from_user( &stop, (drm_radeon_init_t *)arg, sizeof(stop) ) ) return -EFAULT; @@ -922,11 +915,8 @@ int radeon_cp_reset( struct inode *inode, struct file *filp, drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "%s\n", __FUNCTION__ ); - 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; - } + LOCK_TEST_WITH_RETURN( dev ); + if ( !dev_priv ) { DRM_DEBUG( "%s called before init done\n", __FUNCTION__ ); return -EINVAL; @@ -948,11 +938,7 @@ int radeon_cp_idle( struct inode *inode, struct file *filp, drm_radeon_private_t *dev_priv = dev->dev_private; DRM_DEBUG( "%s\n", __FUNCTION__ ); - 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; - } + LOCK_TEST_WITH_RETURN( dev ); return radeon_do_cp_idle( dev_priv ); } @@ -964,11 +950,7 @@ int radeon_engine_reset( struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; DRM_DEBUG( "%s\n", __FUNCTION__ ); - 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; - } + LOCK_TEST_WITH_RETURN( dev ); return radeon_do_engine_reset( dev ); } @@ -1018,11 +1000,7 @@ int radeon_fullscreen( struct inode *inode, struct file *filp, drm_device_t *dev = priv->dev; drm_radeon_fullscreen_t fs; - 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; - } + LOCK_TEST_WITH_RETURN( dev ); if ( copy_from_user( &fs, (drm_radeon_fullscreen_t *)arg, sizeof(fs) ) ) @@ -1246,14 +1224,10 @@ int radeon_cp_buffers( struct inode *inode, struct file *filp, int ret = 0; drm_dma_t d; - if ( copy_from_user( &d, (drm_dma_t *) arg, sizeof(d) ) ) - return -EFAULT; + 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( &d, (drm_dma_t *)arg, sizeof(d) ) ) + return -EFAULT; /* Please don't send us buffers. */ @@ -1277,7 +1251,7 @@ int radeon_cp_buffers( struct inode *inode, struct file *filp, ret = radeon_cp_get_buffers( dev, &d ); } - if ( copy_to_user( (drm_dma_t *) arg, &d, sizeof(d) ) ) + if ( copy_to_user( (drm_dma_t *)arg, &d, sizeof(d) ) ) return -EFAULT; return ret; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drm.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drm.h index a7d7a71bb..50a7d6ed8 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drm.h @@ -73,7 +73,7 @@ /* Vertex/indirect buffer size */ -#define RADEON_BUFFER_SIZE 16384 +#define RADEON_BUFFER_SIZE 65536 /* Byte offsets for indirect buffer data */ @@ -304,14 +304,20 @@ typedef struct drm_radeon_indices { int discard; /* Client finished with buffer? */ } drm_radeon_indices_t; -typedef struct drm_radeon_blit { - int idx; - int pitch; +typedef struct drm_radeon_tex_image { + unsigned int x, y; /* Blit coordinates */ + unsigned int width, height; + const void *data; +} drm_radeon_tex_image_t; + +typedef struct drm_radeon_texture { int offset; + int pitch; int format; - unsigned short x, y; - unsigned short width, height; -} drm_radeon_blit_t; + int width; /* Texture image coordinates */ + int height; + drm_radeon_tex_image_t *image; +} drm_radeon_texture_t; typedef struct drm_radeon_stipple { unsigned int *mask; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c index cf59f866a..1aa889aee 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.c @@ -36,7 +36,7 @@ #define DRIVER_NAME "radeon" #define DRIVER_DESC "ATI Radeon" -#define DRIVER_DATE "20010216" +#define DRIVER_DATE "20010305" #define DRIVER_MAJOR 1 #define DRIVER_MINOR 0 @@ -55,7 +55,7 @@ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_CLEAR)] = { radeon_cp_clear, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_VERTEX)] = { radeon_cp_vertex, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDICES)] = { radeon_cp_indices, 1, 0 }, \ - [DRM_IOCTL_NR(DRM_IOCTL_RADEON_BLIT)] = { radeon_cp_blit, 1, 0 }, \ + [DRM_IOCTL_NR(DRM_IOCTL_RADEON_TEXTURE)] = { radeon_cp_texture, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_STIPPLE)] = { radeon_cp_stipple, 1, 0 }, \ [DRM_IOCTL_NR(DRM_IOCTL_RADEON_INDIRECT)] = { radeon_cp_indirect, 1, 1 }, diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.h b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.h index e67a610fb..d279b0467 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_drv.h @@ -161,8 +161,8 @@ extern int radeon_cp_vertex( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int radeon_cp_indices( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); -extern int radeon_cp_blit( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ); +extern int radeon_cp_texture( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); extern int radeon_cp_stipple( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int radeon_cp_indirect( struct inode *inode, struct file *filp, @@ -478,14 +478,14 @@ extern int radeon_cp_indirect( struct inode *inode, struct file *filp, #define RADEON_COLOR_FORMAT_RGB8 9 #define RADEON_COLOR_FORMAT_ARGB4444 15 -#define RADEON_TXF_8BPP_I 0 -#define RADEON_TXF_16BPP_AI88 1 -#define RADEON_TXF_8BPP_RGB332 2 -#define RADEON_TXF_16BPP_ARGB1555 3 -#define RADEON_TXF_16BPP_RGB565 4 -#define RADEON_TXF_16BPP_ARGB4444 5 -#define RADEON_TXF_32BPP_ARGB8888 6 -#define RADEON_TXF_32BPP_RGBA8888 7 +#define RADEON_TXFORMAT_I8 0 +#define RADEON_TXFORMAT_AI88 1 +#define RADEON_TXFORMAT_RGB332 2 +#define RADEON_TXFORMAT_ARGB1555 3 +#define RADEON_TXFORMAT_RGB565 4 +#define RADEON_TXFORMAT_ARGB4444 5 +#define RADEON_TXFORMAT_ARGB8888 6 +#define RADEON_TXFORMAT_RGBA8888 7 /* Constants */ #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ @@ -586,6 +586,16 @@ extern int RADEON_READ_PLL( drm_device_t *dev, int addr ); * Misc helper macros */ +#define LOCK_TEST_WITH_RETURN( dev ) \ +do { \ + 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; \ + } \ +} while (0) + #define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \ do { \ drm_radeon_ring_buffer_t *ring = &dev_priv->ring; int i; \ diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c index 9b84a7397..ff1b3512f 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/kernel/radeon_state.c @@ -972,50 +972,67 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev, sarea_priv->nbox = 0; } -static int radeon_cp_dispatch_blit( drm_device_t *dev, - drm_radeon_blit_t *blit ) +#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 ) { 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 *data; - int dword_shift, dwords; + u32 *buffer; + u8 *data; + int size, dwords, tex_width, blit_width; + u32 y, height; + int ret = 0, i; 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 ); - radeon_update_ring_snapshot( dev_priv ); + /* 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; /* 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 RADEON_TXF_32BPP_ARGB8888: - case RADEON_TXF_32BPP_RGBA8888: + switch ( tex->format ) { + case RADEON_TXFORMAT_ARGB8888: + case RADEON_TXFORMAT_RGBA8888: format = RADEON_COLOR_FORMAT_ARGB8888; - dword_shift = 0; + tex_width = tex->width * 4; + blit_width = image->width * 4; break; - case RADEON_TXF_16BPP_AI88: - case RADEON_TXF_16BPP_ARGB1555: - case RADEON_TXF_16BPP_RGB565: - case RADEON_TXF_16BPP_ARGB4444: + case RADEON_TXFORMAT_AI88: + case RADEON_TXFORMAT_ARGB1555: + case RADEON_TXFORMAT_RGB565: + case RADEON_TXFORMAT_ARGB4444: format = RADEON_COLOR_FORMAT_RGB565; - dword_shift = 1; + tex_width = tex->width * 2; + blit_width = image->width * 2; break; - case RADEON_TXF_8BPP_I: - case RADEON_TXF_8BPP_RGB332: + case RADEON_TXFORMAT_I8: + case RADEON_TXFORMAT_RGB332: format = RADEON_COLOR_FORMAT_CI8; - dword_shift = 2; + tex_width = tex->width * 1; + blit_width = image->width * 1; break; default: - DRM_ERROR( "invalid blit format %d\n", blit->format ); + DRM_ERROR( "invalid texture format %d\n", tex->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. @@ -1027,46 +1044,81 @@ static int radeon_cp_dispatch_blit( drm_device_t *dev, ADVANCE_RING(); - /* Dispatch the indirect buffer. + /* Make a copy of the parameters in case we have to update them + * for a multi-pass texture blit. */ - buf = dma->buflist[blit->idx]; - buf_priv = buf->dev_private; + y = image->y; + height = image->height; + data = (u8 *)image->data; - 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; - } + size = height * blit_width; - buf_priv->discard = 1; + if ( size > RADEON_MAX_TEXTURE_SIZE ) { + /* Texture image is too large, do a multipass upload */ + ret = -EAGAIN; - dwords = (blit->width * blit->height) >> dword_shift; - if ( !dwords ) dwords = 1; + /* Adjust the blit size to fit the indirect buffer */ + height = RADEON_MAX_TEXTURE_SIZE / blit_width; + size = height * blit_width; - data = (u32 *)((char *)dev_priv->buffers->handle + buf->offset); + /* Update the input parameters for next time */ + image->y += height; + image->height -= height; + image->data = (char *)image->data + size; - 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); + if ( copy_to_user( tex->image, image, sizeof(*image) ) ) + return -EFAULT; + } else if ( size < 4 ) { + 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; + dwords = size / 4; + + /* 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) ) ) + 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 ) ) + 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 ); @@ -1081,7 +1133,7 @@ static int radeon_cp_dispatch_blit( drm_device_t *dev, ADVANCE_RING(); - return 0; + return ret; } static void radeon_cp_dispatch_stipple( drm_device_t *dev, u32 *stipple ) @@ -1122,11 +1174,7 @@ int radeon_cp_clear( struct inode *inode, struct file *filp, drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; DRM_DEBUG( "%s\n", __FUNCTION__ ); - 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; - } + LOCK_TEST_WITH_RETURN( dev ); if ( copy_from_user( &clear, (drm_radeon_clear_t *)arg, sizeof(clear) ) ) @@ -1156,11 +1204,7 @@ 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__ ); - 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; - } + LOCK_TEST_WITH_RETURN( dev ); RING_SPACE_TEST_WITH_RETURN( dev_priv ); @@ -1189,11 +1233,8 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp, drm_radeon_buf_priv_t *buf_priv; drm_radeon_vertex_t vertex; - 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; - } + LOCK_TEST_WITH_RETURN( dev ); + if ( !dev_priv || dev_priv->is_pci ) { DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ ); return -EINVAL; @@ -1255,11 +1296,8 @@ int radeon_cp_indices( struct inode *inode, struct file *filp, drm_radeon_indices_t elts; int count; - 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; - } + LOCK_TEST_WITH_RETURN( dev ); + if ( !dev_priv || dev_priv->is_pci ) { DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ ); return -EINVAL; @@ -1321,38 +1359,34 @@ int radeon_cp_indices( struct inode *inode, struct file *filp, return 0; } -int radeon_cp_blit( struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg ) +int radeon_cp_texture( 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_device_dma_t *dma = dev->dma; - drm_radeon_blit_t blit; + drm_radeon_texture_t tex; + drm_radeon_tex_image_t image; - 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; - } + LOCK_TEST_WITH_RETURN( dev ); - if ( copy_from_user( &blit, (drm_radeon_blit_t *)arg, - sizeof(blit) ) ) + if ( copy_from_user( &tex, (drm_radeon_texture_t *)arg, sizeof(tex) ) ) return -EFAULT; - 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 ); + if ( tex.image == NULL ) { + DRM_ERROR( "null texture image!\n" ); 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 ); - return radeon_cp_dispatch_blit( dev, &blit ); + return radeon_cp_dispatch_texture( dev, &tex, &image ); } int radeon_cp_stipple( struct inode *inode, struct file *filp, @@ -1364,18 +1398,13 @@ int radeon_cp_stipple( struct inode *inode, struct file *filp, drm_radeon_stipple_t stipple; u32 mask[32]; - 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; - } + LOCK_TEST_WITH_RETURN( dev ); 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 ); @@ -1397,11 +1426,8 @@ int radeon_cp_indirect( struct inode *inode, struct file *filp, drm_radeon_indirect_t indirect; RING_LOCALS; - 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; - } + LOCK_TEST_WITH_RETURN( dev ); + if ( !dev_priv || dev_priv->is_pci ) { DRM_ERROR( "%s called with a PCI card\n", __FUNCTION__ ); return -EINVAL; diff --git a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRadeon.c b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRadeon.c index 62caddadc..944a030ff 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRadeon.c +++ b/xc/programs/Xserver/hw/xfree86/os-support/linux/drm/xf86drmRadeon.c @@ -311,25 +311,32 @@ int drmRadeonFlushIndices( int fd, int prim, int index, } } -int drmRadeonTextureBlit( int fd, int index, - int offset, int pitch, int format, - int x, int y, int width, int height ) +int drmRadeonLoadTexture( int fd, int offset, int pitch, int format, + int width, int height, drmRadeonTexImage *image ) { - drm_radeon_blit_t blit; - - blit.idx = index; - blit.offset = offset; - blit.pitch = pitch; - blit.format = format; - blit.x = x; - blit.y = y; - blit.width = width; - blit.height = height; - - if ( ioctl( fd, DRM_IOCTL_RADEON_BLIT, &blit ) < 0 ) { - return -errno; - } else { + drm_radeon_texture_t tex; + drm_radeon_tex_image_t tmp; + int ret; + + tex.offset = offset; + tex.pitch = pitch; + tex.format = format; + tex.width = width; + tex.height = height; + tex.image = &tmp; + + /* This gets updated by the kernel when a multipass blit is needed. + */ + memcpy( &tmp, image, sizeof(drm_radeon_tex_image_t) ); + + do { + ret = ioctl( fd, DRM_IOCTL_RADEON_TEXTURE, &tex ); + } while ( ret && errno == EAGAIN ); + + if ( ret == 0 ) { return 0; + } else { + return -errno; } } diff --git a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h index 40a85875b..30b75e1e3 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/shared/drm/kernel/drm.h @@ -439,7 +439,7 @@ typedef struct drm_agp_info { #define DRM_IOCTL_RADEON_CLEAR DRM_IOW( 0x48, drm_radeon_clear_t) #define DRM_IOCTL_RADEON_VERTEX DRM_IOW( 0x49, drm_radeon_vertex_t) #define DRM_IOCTL_RADEON_INDICES DRM_IOW( 0x4a, drm_radeon_indices_t) -#define DRM_IOCTL_RADEON_BLIT DRM_IOW( 0x4b, drm_radeon_blit_t) +#define DRM_IOCTL_RADEON_TEXTURE DRM_IOWR(0x4b, drm_radeon_texture_t) #define DRM_IOCTL_RADEON_STIPPLE DRM_IOW( 0x4c, drm_radeon_stipple_t) #define DRM_IOCTL_RADEON_INDIRECT DRM_IOWR(0x4d, drm_radeon_indirect_t) diff --git a/xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h index 87f70590d..e3bf83fdd 100644 --- a/xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h +++ b/xc/programs/Xserver/hw/xfree86/os-support/xf86drmRadeon.h @@ -43,27 +43,35 @@ #define DRM_RADEON_DEPTH 0x4 typedef struct { - int sarea_priv_offset; - int is_pci; - int cp_mode; - int agp_size; - int ring_size; - int usec_timeout; - - unsigned int fb_bpp; - unsigned int front_offset, front_pitch; - unsigned int back_offset, back_pitch; - unsigned int depth_bpp; - unsigned int depth_offset, depth_pitch; - - unsigned int fb_offset; - unsigned int mmio_offset; - unsigned int ring_offset; - unsigned int ring_rptr_offset; - unsigned int buffers_offset; - unsigned int agp_textures_offset; + int sarea_priv_offset; + int is_pci; + int cp_mode; + int agp_size; + int ring_size; + int usec_timeout; + + unsigned int fb_bpp; + unsigned int front_offset, front_pitch; + unsigned int back_offset, back_pitch; + unsigned int depth_bpp; + unsigned int depth_offset, depth_pitch; + + unsigned int fb_offset; + unsigned int mmio_offset; + unsigned int ring_offset; + unsigned int ring_rptr_offset; + unsigned int buffers_offset; + unsigned int agp_textures_offset; } drmRadeonInit; +typedef struct { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + void *data; +} drmRadeonTexImage; + extern int drmRadeonInitCP( int fd, drmRadeonInit *info ); extern int drmRadeonCleanupCP( int fd ); @@ -87,9 +95,9 @@ extern int drmRadeonFlushVertexBuffer( int fd, int prim, int index, extern int drmRadeonFlushIndices( int fd, int prim, int index, int start, int end, int discard ); -extern int drmRadeonTextureBlit( int fd, int index, - int offset, int pitch, int format, - int x, int y, int width, int height ); +extern int drmRadeonLoadTexture( int fd, int offset, int pitch, int format, + int width, int height, + drmRadeonTexImage *image ); extern int drmRadeonPolygonStipple( int fd, unsigned int *mask ); |