summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGareth Hughes <gareth@users.sourceforge.net>2000-12-01 15:39:32 +0000
committerGareth Hughes <gareth@users.sourceforge.net>2000-12-01 15:39:32 +0000
commit7950295132b834df9a1cb01a94868c372b91a39f (patch)
tree3440b9f3e751b8b4e64ce606533d79109a704cdd
parentaa1a793f55a3d1b723e9bf3bfffb25bf97530753 (diff)
- Fixed polygon stipple. Was still using SubmitPackets...ati-4-1-1-20001202-mergeati-4-1-1-20001201-freezeati-4-1-1-branch
- 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.
-rw-r--r--linux-core/r128_drv.c8
-rw-r--r--linux/drm.h4
-rw-r--r--linux/r128_cce.c9
-rw-r--r--linux/r128_drm.h24
-rw-r--r--linux/r128_drv.c8
-rw-r--r--linux/r128_drv.h19
-rw-r--r--linux/r128_state.c500
-rw-r--r--shared-core/drm.h4
-rw-r--r--shared/drm.h4
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)