From 7950295132b834df9a1cb01a94868c372b91a39f Mon Sep 17 00:00:00 2001 From: Gareth Hughes Date: Fri, 1 Dec 2000 15:39:32 +0000 Subject: - Fixed polygon stipple. Was still using SubmitPackets... - Implemented HW-assisted depth span functions. All access to the depth buffer is done via the engine, so we don't have to worry about the differences between linear and tiled memory. - Implemented significantly more 3D-friendly static partitioning of offscreen memory. 2D still gets enough pixmap cache to be performant. For example, 800x600@16bpp texture memory goes from ~3mb to 11.5mb on a 16mb card. --- linux-core/r128_drv.c | 8 +- linux/drm.h | 4 +- linux/r128_cce.c | 9 +- linux/r128_drm.h | 24 ++- linux/r128_drv.c | 8 +- linux/r128_drv.h | 19 +- linux/r128_state.c | 500 +++++++++++++++++++++++++++++++++++++++++++++++--- shared-core/drm.h | 4 +- shared/drm.h | 4 +- 9 files changed, 530 insertions(+), 50 deletions(-) diff --git a/linux-core/r128_drv.c b/linux-core/r128_drv.c index f73d4c0b..89b68696 100644 --- a/linux-core/r128_drv.c +++ b/linux-core/r128_drv.c @@ -37,10 +37,10 @@ #define R128_NAME "r128" #define R128_DESC "ATI Rage 128" -#define R128_DATE "20001129" +#define R128_DATE "20001201" #define R128_MAJOR 2 -#define R128_MINOR 0 -#define R128_PATCHLEVEL 1 +#define R128_MINOR 1 +#define R128_PATCHLEVEL 0 static drm_device_t r128_device; drm_ctx_t r128_res_ctx; @@ -119,6 +119,8 @@ static drm_ioctl_desc_t r128_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)] = { r128_cce_depth, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 }, }; #define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls) diff --git a/linux/drm.h b/linux/drm.h index 5d383427..20691ccf 100644 --- a/linux/drm.h +++ b/linux/drm.h @@ -374,7 +374,9 @@ typedef struct drm_agp_info { #define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t) #define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t) #define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t) -#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4c, drm_r128_packet_t) +#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t) +#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t) +#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4e, drm_r128_packet_t) /* SiS specific ioctls */ #define SIS_IOCTL_FB_ALLOC DRM_IOWR( 0x44, drm_sis_mem_t) diff --git a/linux/r128_cce.c b/linux/r128_cce.c index cab9acd6..0b1576a9 100644 --- a/linux/r128_cce.c +++ b/linux/r128_cce.c @@ -437,18 +437,13 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) dev_priv->fb_bpp = init->fb_bpp; dev_priv->front_offset = init->front_offset; dev_priv->front_pitch = init->front_pitch; - dev_priv->front_x = init->front_x; - dev_priv->front_y = init->front_y; dev_priv->back_offset = init->back_offset; dev_priv->back_pitch = init->back_pitch; - dev_priv->back_x = init->back_x; - dev_priv->back_y = init->back_y; dev_priv->depth_bpp = init->depth_bpp; dev_priv->depth_offset = init->depth_offset; dev_priv->depth_pitch = init->depth_pitch; - dev_priv->depth_x = init->depth_x; - dev_priv->depth_y = init->depth_y; + dev_priv->span_offset = init->span_offset; dev_priv->front_pitch_offset_c = (((dev_priv->front_pitch/8) << 21) | (dev_priv->front_offset >> 5)); @@ -457,6 +452,8 @@ static int r128_do_init_cce( drm_device_t *dev, drm_r128_init_t *init ) dev_priv->depth_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) | (dev_priv->depth_offset >> 5) | R128_DST_TILE); + dev_priv->span_pitch_offset_c = (((dev_priv->depth_pitch/8) << 21) | + (dev_priv->span_offset >> 5)); /* FIXME: We want multiple shared areas, including one shared * only by the X Server and kernel module. diff --git a/linux/r128_drm.h b/linux/r128_drm.h index 51e31cd3..b81d2fca 100644 --- a/linux/r128_drm.h +++ b/linux/r128_drm.h @@ -94,7 +94,7 @@ #define R128_LOCAL_TEX_HEAP 0 #define R128_AGP_TEX_HEAP 1 #define R128_NR_TEX_HEAPS 2 -#define R128_NR_TEX_REGIONS 16 +#define R128_NR_TEX_REGIONS 64 #define R128_LOG_TEX_GRANULARITY 16 #define R128_NR_CONTEXT_REGS 12 @@ -196,12 +196,10 @@ typedef struct drm_r128_init { unsigned int fb_bpp; unsigned int front_offset, front_pitch; - unsigned int front_x, front_y; unsigned int back_offset, back_pitch; - unsigned int back_x, back_y; unsigned int depth_bpp; unsigned int depth_offset, depth_pitch; - unsigned int depth_x, depth_y; + unsigned int span_offset; unsigned int fb_offset; unsigned int mmio_offset; @@ -249,6 +247,24 @@ typedef struct drm_r128_blit { unsigned short width, height; } drm_r128_blit_t; +typedef struct drm_r128_depth { + enum { + R128_WRITE_SPAN = 0x01, + R128_WRITE_PIXELS = 0x02, + R128_READ_SPAN = 0x03, + R128_READ_PIXELS = 0x04 + } func; + int n; + int *x; + int *y; + unsigned int *buffer; + unsigned char *mask; +} drm_r128_depth_t; + +typedef struct drm_r128_stipple { + unsigned int *mask; +} drm_r128_stipple_t; + typedef struct drm_r128_packet { unsigned int *buffer; int count; diff --git a/linux/r128_drv.c b/linux/r128_drv.c index f73d4c0b..89b68696 100644 --- a/linux/r128_drv.c +++ b/linux/r128_drv.c @@ -37,10 +37,10 @@ #define R128_NAME "r128" #define R128_DESC "ATI Rage 128" -#define R128_DATE "20001129" +#define R128_DATE "20001201" #define R128_MAJOR 2 -#define R128_MINOR 0 -#define R128_PATCHLEVEL 1 +#define R128_MINOR 1 +#define R128_PATCHLEVEL 0 static drm_device_t r128_device; drm_ctx_t r128_res_ctx; @@ -119,6 +119,8 @@ static drm_ioctl_desc_t r128_ioctls[] = { [DRM_IOCTL_NR(DRM_IOCTL_R128_VERTEX)] = { r128_cce_vertex, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_R128_INDICES)] = { r128_cce_indices, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_R128_BLIT)] = { r128_cce_blit, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_DEPTH)] = { r128_cce_depth, 1, 0 }, + [DRM_IOCTL_NR(DRM_IOCTL_R128_STIPPLE)] = { r128_cce_stipple, 1, 0 }, [DRM_IOCTL_NR(DRM_IOCTL_R128_PACKET)] = { r128_cce_packet, 1, 0 }, }; #define R128_IOCTL_COUNT DRM_ARRAY_SIZE(r128_ioctls) diff --git a/linux/r128_drv.h b/linux/r128_drv.h index 1aa6bde5..cffd0800 100644 --- a/linux/r128_drv.h +++ b/linux/r128_drv.h @@ -73,22 +73,18 @@ typedef struct drm_r128_private { unsigned int fb_bpp; unsigned int front_offset; unsigned int front_pitch; - unsigned int front_x; - unsigned int front_y; unsigned int back_offset; unsigned int back_pitch; - unsigned int back_x; - unsigned int back_y; unsigned int depth_bpp; unsigned int depth_offset; unsigned int depth_pitch; - unsigned int depth_x; - unsigned int depth_y; + unsigned int span_offset; u32 front_pitch_offset_c; u32 back_pitch_offset_c; u32 depth_pitch_offset_c; + u32 span_pitch_offset_c; drm_map_t *sarea; drm_map_t *fb; @@ -154,6 +150,10 @@ extern int r128_cce_indices( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); extern int r128_cce_blit( struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg ); +extern int r128_cce_depth( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); +extern int r128_cce_stipple( struct inode *inode, struct file *filp, + unsigned int cmd, unsigned long arg ); /* r128_bufs.c */ extern int r128_addbufs(struct inode *inode, struct file *filp, @@ -208,6 +208,7 @@ extern int r128_context_switch_complete(drm_device_t *dev, int new); #define R128_AUX3_SC_TOP 0x168c #define R128_AUX3_SC_BOTTOM 0x1690 +#define R128_BRUSH_DATA0 0x1480 #define R128_BUS_CNTL 0x0030 # define R128_BUS_MASTER_DIS (1 << 6) @@ -425,7 +426,7 @@ extern int R128_READ_PLL(drm_device_t *dev, int addr); #define R128_VERBOSE 0 -#define RING_LOCALS int write; unsigned int mask; volatile u32 *ring; +#define RING_LOCALS int write; unsigned int tail_mask; volatile u32 *ring; #define BEGIN_RING( n ) do { \ if ( R128_VERBOSE ) { \ @@ -438,7 +439,7 @@ extern int R128_READ_PLL(drm_device_t *dev, int addr); dev_priv->ring.space -= n * sizeof(u32); \ ring = dev_priv->ring.start; \ write = dev_priv->ring.tail; \ - mask = dev_priv->ring.tail_mask; \ + tail_mask = dev_priv->ring.tail_mask; \ } while (0) #define ADVANCE_RING() do { \ @@ -457,7 +458,7 @@ extern int R128_READ_PLL(drm_device_t *dev, int addr); (unsigned int)(x), write ); \ } \ ring[write++] = x; \ - write &= mask; \ + write &= tail_mask; \ } while (0) #define R128_PERFORMANCE_BOXES 0 diff --git a/linux/r128_state.c b/linux/r128_state.c index 6671518f..faad25a2 100644 --- a/linux/r128_state.c +++ b/linux/r128_state.c @@ -534,10 +534,10 @@ static void r128_cce_dispatch_swap( drm_device_t *dev ) OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL | R128_GMC_DST_PITCH_OFFSET_CNTL | R128_GMC_BRUSH_NONE - | R128_GMC_SRC_DATATYPE_COLOR - | R128_DP_SRC_SOURCE_MEMORY | fb_bpp + | R128_GMC_SRC_DATATYPE_COLOR | R128_ROP3_S + | R128_DP_SRC_SOURCE_MEMORY | R128_GMC_CLR_CMP_CNTL_DIS | R128_GMC_AUX_CLIP_DIS | R128_GMC_WR_MSK_DIS ); @@ -550,12 +550,12 @@ static void r128_cce_dispatch_swap( drm_device_t *dev ) OUT_RING( (x << 16) | y ); OUT_RING( (w << 16) | h ); #else - OUT_RING( dev_priv->depth_pitch_offset_c & ~R128_DST_TILE ); + OUT_RING( dev_priv->depth_pitch_offset_c /*& ~R128_DST_TILE*/ ); OUT_RING( dev_priv->front_pitch_offset_c ); OUT_RING( (0 << 16) | 0 ); OUT_RING( (0 << 16) | 0 ); - OUT_RING( (1024 << 16) | 768 ); + OUT_RING( (800 << 16) | 600 ); #endif ADVANCE_RING(); @@ -581,9 +581,7 @@ static void r128_cce_dispatch_vertex( drm_device_t *dev, 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 vertsize = sarea_priv->vertsize; int format = sarea_priv->vc_format; - int index = buf->idx; int offset = dev_priv->buffers->offset + buf->offset - dev->agp->base; int size = buf->used; int prim = buf_priv->prim; @@ -691,21 +689,6 @@ static void r128_cce_dispatch_indirect( drm_device_t *dev, data[dwords++] = R128_CCE_PACKET2; } - DRM_DEBUG( "indirect: offset=0x%x dwords=%d\n", - offset, dwords ); - - if ( 0 ) { - u32 *data = (u32 *) - ((char *)dev_priv->buffers->handle - + buf->offset + start); - int i; - DRM_INFO( "data = %p\n", data ); - for ( i = 0 ; i < dwords ; i++ ) { - DRM_INFO( "data[0x%x] = 0x%08x\n", - i, data[i] ); - } - } - buf_priv->dispatched = 1; /* Fire off the indirect buffer */ @@ -941,7 +924,422 @@ static int r128_cce_dispatch_blit( drm_device_t *dev, /* ================================================================ - * + * Tiled depth buffer management + */ + +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: + depth_bpp = R128_GMC_DST_32BPP; + break; + 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: + depth_bpp = R128_GMC_DST_32BPP; + break; + 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 ) { + kfree( x ); + kfree( y ); + return -ENOMEM; + } + if ( copy_from_user( buffer, depth->buffer, + depth->n * sizeof(u32) ) ) { + kfree( x ); + kfree( y ); + kfree( buffer ); + return -EFAULT; + } + + if ( depth->mask ) { + mask = kmalloc( depth->n * sizeof(u8), 0 ); + if ( mask == NULL ) { + kfree( x ); + kfree( y ); + kfree( buffer ); + return -ENOMEM; + } + if ( copy_from_user( mask, depth->mask, + depth->n * sizeof(u8) ) ) { + kfree( x ); + kfree( y ); + kfree( buffer ); + kfree( mask ); + return -EFAULT; + } + + for ( i = 0 ; i < count ; i++ ) { + 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[i] << 16) | y[i] ); + OUT_RING( (1 << 16) | 1 ); + + ADVANCE_RING(); + } + } + + kfree( mask ); + } else { + for ( i = 0 ; i < count ; 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[i] << 16) | y[i] ); + OUT_RING( (1 << 16) | 1 ); + + ADVANCE_RING(); + } + } + + kfree( x ); + kfree( y ); + kfree( buffer ); + + return 0; +} + +static int r128_cce_dispatch_read_span( drm_device_t *dev, + drm_r128_depth_t *depth ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int count, x, y; + u32 depth_bpp; + 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: + depth_bpp = R128_GMC_DST_32BPP; + break; + 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; + } + + BEGIN_RING( 7 ); + + OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) ); + OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL + | R128_GMC_DST_PITCH_OFFSET_CNTL + | R128_GMC_BRUSH_NONE + | depth_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_S + | R128_DP_SRC_SOURCE_MEMORY + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_WR_MSK_DIS ); + + OUT_RING( dev_priv->depth_pitch_offset_c ); + OUT_RING( dev_priv->span_pitch_offset_c ); + + OUT_RING( (x << 16) | y ); + OUT_RING( (0 << 16) | 0 ); + OUT_RING( (count << 16) | 1 ); + + ADVANCE_RING(); + + return 0; +} + +static int r128_cce_dispatch_read_pixels( drm_device_t *dev, + drm_r128_depth_t *depth ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int count, *x, *y; + 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: + depth_bpp = R128_GMC_DST_32BPP; + break; + case 32: + depth_bpp = R128_GMC_DST_32BPP; + break; + default: + return -EINVAL; + } + + count = depth->n; + if ( count > dev_priv->depth_pitch ) { + count = dev_priv->depth_pitch; + } + + 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; + } + + for ( i = 0 ; i < count ; i++ ) { + BEGIN_RING( 7 ); + + OUT_RING( CCE_PACKET3( R128_CNTL_BITBLT_MULTI, 5 ) ); + OUT_RING( R128_GMC_SRC_PITCH_OFFSET_CNTL + | R128_GMC_DST_PITCH_OFFSET_CNTL + | R128_GMC_BRUSH_NONE + | depth_bpp + | R128_GMC_SRC_DATATYPE_COLOR + | R128_ROP3_S + | R128_DP_SRC_SOURCE_MEMORY + | R128_GMC_CLR_CMP_CNTL_DIS + | R128_GMC_WR_MSK_DIS ); + + OUT_RING( dev_priv->depth_pitch_offset_c ); + OUT_RING( dev_priv->span_pitch_offset_c ); + + OUT_RING( (x[i] << 16) | y[i] ); + OUT_RING( (i << 16) | 0 ); + OUT_RING( (1 << 16) | 1 ); + + ADVANCE_RING(); + } + + kfree( x ); + kfree( y ); + + return 0; +} + + +/* ================================================================ + * Polygon stipple + */ + +static void r128_cce_dispatch_stipple( drm_device_t *dev, u32 *stipple ) +{ + drm_r128_private_t *dev_priv = dev->dev_private; + int i; + RING_LOCALS; + DRM_DEBUG( "%s\n", __FUNCTION__ ); + + r128_update_ring_snapshot( dev_priv ); + + BEGIN_RING( 33 ); + + OUT_RING( CCE_PACKET0( R128_BRUSH_DATA0, 31 ) ); + for ( i = 0 ; i < 32 ; i++ ) { + OUT_RING( stipple[i] ); + } + + ADVANCE_RING(); +} + + +/* ================================================================ + * IOCTL functions */ int r128_cce_clear( struct inode *inode, struct file *filp, @@ -1172,3 +1570,61 @@ int r128_cce_blit( struct inode *inode, struct file *filp, return r128_cce_dispatch_blit( dev, &blit ); } + +int r128_cce_depth( 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_depth_t depth; + + 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( &depth, (drm_r128_depth_t *)arg, + sizeof(depth) ) ) + return -EFAULT; + + switch ( depth.func ) { + case R128_WRITE_SPAN: + return r128_cce_dispatch_write_span( dev, &depth ); + case R128_WRITE_PIXELS: + return r128_cce_dispatch_write_pixels( dev, &depth ); + case R128_READ_SPAN: + return r128_cce_dispatch_read_span( dev, &depth ); + case R128_READ_PIXELS: + return r128_cce_dispatch_read_pixels( dev, &depth ); + } + + return -EINVAL; +} + +int r128_cce_stipple( 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_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; + } + + if ( copy_from_user( &stipple, (drm_r128_stipple_t *)arg, + sizeof(stipple) ) ) + return -EFAULT; + + if ( copy_from_user( &mask, stipple.mask, + 32 * sizeof(u32) ) ) + return -EFAULT; + + r128_cce_dispatch_stipple( dev, mask ); + + return 0; +} diff --git a/shared-core/drm.h b/shared-core/drm.h index 5d383427..20691ccf 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -374,7 +374,9 @@ typedef struct drm_agp_info { #define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t) #define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t) #define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t) -#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4c, drm_r128_packet_t) +#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t) +#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t) +#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4e, drm_r128_packet_t) /* SiS specific ioctls */ #define SIS_IOCTL_FB_ALLOC DRM_IOWR( 0x44, drm_sis_mem_t) diff --git a/shared/drm.h b/shared/drm.h index 5d383427..20691ccf 100644 --- a/shared/drm.h +++ b/shared/drm.h @@ -374,7 +374,9 @@ typedef struct drm_agp_info { #define DRM_IOCTL_R128_VERTEX DRM_IOW( 0x49, drm_r128_vertex_t) #define DRM_IOCTL_R128_INDICES DRM_IOW( 0x4a, drm_r128_indices_t) #define DRM_IOCTL_R128_BLIT DRM_IOW( 0x4b, drm_r128_blit_t) -#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4c, drm_r128_packet_t) +#define DRM_IOCTL_R128_DEPTH DRM_IOW( 0x4c, drm_r128_depth_t) +#define DRM_IOCTL_R128_STIPPLE DRM_IOW( 0x4d, drm_r128_stipple_t) +#define DRM_IOCTL_R128_PACKET DRM_IOWR(0x4e, drm_r128_packet_t) /* SiS specific ioctls */ #define SIS_IOCTL_FB_ALLOC DRM_IOWR( 0x44, drm_sis_mem_t) -- cgit v1.2.3