summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2002-02-22 20:01:09 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2002-02-22 20:01:09 +0000
commit36f6fb67f4b8cb41ae1f0686bdb4b1b5cb304414 (patch)
tree513597191673bc9d39e195b0686ba01267f848ee
parentccc1b6edec56a28a77767a1f070655e6fb0a955c (diff)
Fix backwards compatibility on tcl branch. Add checks on number of vertices
per primitive.
-rw-r--r--linux/radeon_drm.h23
-rw-r--r--linux/radeon_drv.h12
-rw-r--r--linux/radeon_state.c172
3 files changed, 174 insertions, 33 deletions
diff --git a/linux/radeon_drm.h b/linux/radeon_drm.h
index e858e02b5..f553203a4 100644
--- a/linux/radeon_drm.h
+++ b/linux/radeon_drm.h
@@ -131,6 +131,17 @@ typedef union {
/* Primitive types
*/
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_NONE 0x00000000
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_POINT 0x00000001
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE 0x00000002
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP 0x00000003
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST 0x00000004
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN 0x00000005
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP 0x00000006
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_TYPE_2 0x00000007
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST 0x00000008
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST 0x00000009
+#define RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST 0x0000000a
#define RADEON_POINTS 0x1
#define RADEON_LINES 0x2
#define RADEON_LINE_STRIP 0x3
@@ -247,13 +258,21 @@ typedef struct {
typedef struct {
unsigned int start;
unsigned int finish;
- unsigned int prim;
- unsigned int stateidx:16;
+ unsigned int prim:8;
+ unsigned int stateidx:8;
unsigned int numverts:16; /* overloaded as offset/64 for elt prims */
unsigned int vc_format; /* vertex format */
} drm_radeon_prim_t;
typedef struct {
+ unsigned int start;
+ unsigned int finish;
+ unsigned int prim;
+ unsigned int numverts; /* overloaded as offset/64 for elt prims */
+ unsigned int vc_format; /* vertex format */
+} drm_radeon_tcl_prim_t;
+
+typedef struct {
drm_radeon_context_regs_t context;
drm_radeon_texture_regs_t tex[RADEON_MAX_TEXTURE_UNITS];
drm_radeon_context2_regs_t context2;
diff --git a/linux/radeon_drv.h b/linux/radeon_drv.h
index c6b77daf7..47e234b0b 100644
--- a/linux/radeon_drv.h
+++ b/linux/radeon_drv.h
@@ -710,7 +710,7 @@ do { \
#define RADEON_VERBOSE 0
-#define RING_LOCALS int write; unsigned int mask; volatile u32 *ring;
+#define RING_LOCALS int write, _nr; unsigned int mask; volatile u32 *ring;
#define BEGIN_RING( n ) do { \
if ( RADEON_VERBOSE ) { \
@@ -720,7 +720,7 @@ do { \
if ( dev_priv->ring.space <= (n) * sizeof(u32) ) { \
radeon_wait_ring( dev_priv, (n) * sizeof(u32) ); \
} \
- dev_priv->ring.space -= (n) * sizeof(u32); \
+ _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \
ring = dev_priv->ring.start; \
write = dev_priv->ring.tail; \
mask = dev_priv->ring.tail_mask; \
@@ -732,7 +732,13 @@ do { \
write, dev_priv->ring.tail ); \
} \
radeon_flush_write_combine(); \
- dev_priv->ring.tail = write; \
+ if (((dev_priv->ring.tail + _nr) & mask) != write) { \
+ DRM_ERROR( \
+ "ADVANCE_RING(): mismatch: nr: %x write: %x\n", \
+ ((dev_priv->ring.tail + _nr) & mask), \
+ write); \
+ } else \
+ dev_priv->ring.tail = write; \
RADEON_WRITE( RADEON_CP_RB_WPTR, write ); \
} while (0)
diff --git a/linux/radeon_state.c b/linux/radeon_state.c
index 5ce676407..aa6f426da 100644
--- a/linux/radeon_state.c
+++ b/linux/radeon_state.c
@@ -605,7 +605,7 @@ static void radeon_cp_dispatch_flip( drm_device_t *dev )
static void radeon_cp_dispatch_vertex( drm_device_t *dev,
drm_buf_t *buf,
- drm_radeon_prim_t *prim,
+ drm_radeon_tcl_prim_t *prim,
drm_clip_rect_t *boxes,
int nbox )
@@ -628,13 +628,54 @@ static void radeon_cp_dispatch_vertex( drm_device_t *dev,
/* prim->numverts, */
/* prim->stateidx); */
- if ( /* (prim->start & 0x7) || */
- (prim->prim & RADEON_PRIM_TYPE_MASK) >
- RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
+ switch (prim->prim & RADEON_PRIM_TYPE_MASK) {
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_NONE:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_POINT:
+ if (prim->numverts < 1) {
+ DRM_ERROR( "Bad nr verts for line %d\n",
+ prim->numverts);
+ return;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE:
+ if (prim->numverts & 1) {
+ DRM_ERROR( "Bad nr verts for line %d\n",
+ prim->numverts);
+ return;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP:
+ if (prim->numverts < 2) {
+ DRM_ERROR( "Bad nr verts for line_strip %d\n",
+ prim->numverts);
+ return;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST:
+ if (prim->numverts % 3) {
+ DRM_ERROR( "Bad nr verts for tri %d\n",
+ prim->numverts);
+ return;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP:
+ if (prim->numverts < 3) {
+ DRM_ERROR( "Bad nr verts for strip/fan %d\n",
+ prim->numverts);
+ return;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_TYPE_2:
+ default:
+ /* don't understand this one */
DRM_ERROR( "buffer prim %x start %x\n",
prim->prim, prim->start );
return;
- }
+ }
do {
/* Emit the next cliprect */
@@ -709,6 +750,7 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev,
u32 *data = (u32 *)
((char *)dev_priv->buffers->handle
+ buf->offset + start);
+/* printk("ODD DWORDS!!!\n\n\n"); */
data[dwords++] = RADEON_CP_PACKET2;
}
@@ -722,6 +764,9 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev,
OUT_RING( dwords );
ADVANCE_RING();
+
+/* radeon_do_cp_idle( dev_priv ); */
+
}
dev_priv->sarea_priv->last_dispatch++;
@@ -730,7 +775,7 @@ static void radeon_cp_dispatch_indirect( drm_device_t *dev,
static void radeon_cp_dispatch_indices( drm_device_t *dev,
drm_buf_t *elt_buf,
- drm_radeon_prim_t *prim,
+ drm_radeon_tcl_prim_t *prim,
drm_clip_rect_t *boxes,
int nbox )
{
@@ -752,10 +797,55 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev,
/* prim->numverts, */
/* prim->stateidx); */
+ switch (prim->prim & RADEON_PRIM_TYPE_MASK) {
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_NONE:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_POINT:
+ if (count < 1) {
+ DRM_ERROR( "Bad nr verts for line %d\n",
+ count);
+ return;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE:
+ if (count & 1) {
+ DRM_ERROR( "Bad nr verts for line %d\n",
+ count);
+ return;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_LINE_STRIP:
+ if (count < 2) {
+ DRM_ERROR( "Bad nr verts for line_strip %d\n",
+ count);
+ return;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_LIST:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_POINT_LIST:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_3VRT_LINE_LIST:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_RECT_LIST:
+ if (count % 3) {
+ DRM_ERROR( "Bad nr verts for tri %d\n", count);
+ return;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_FAN:
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_STRIP:
+ if (count < 3) {
+ DRM_ERROR( "Bad nr verts for strip/fan %d\n", count);
+ return;
+ }
+ break;
+ case RADEON_CP_VC_CNTL_PRIM_TYPE_TRI_TYPE_2:
+ default:
+ /* don't understand this one */
+ DRM_ERROR( "buffer prim %x start %x\n",
+ prim->prim, prim->start );
+ return;
+ }
+
if ( start >= prim->finish ||
- (prim->start & 0x7) ||
- (prim->prim & RADEON_PRIM_TYPE_MASK) >
- RADEON_PRIM_TYPE_3VRT_LINE_LIST ) {
+ (prim->start & 0x7) ) {
DRM_ERROR( "buffer prim %d\n", prim->prim );
return;
}
@@ -775,10 +865,12 @@ static void radeon_cp_dispatch_indices( drm_device_t *dev,
RADEON_VTX_FMT_RADEON_MODE |
(count << RADEON_NUM_VERTICES_SHIFT) );
+#if 0
if ( count & 0x1 ) {
/* unnecessary? */
data[dwords-1] &= 0x0000ffff;
}
+#endif
do {
if ( i < nbox ) {
@@ -1079,7 +1171,7 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp,
drm_buf_t *buf;
drm_radeon_buf_priv_t *buf_priv;
drm_radeon_vertex_t vertex;
- drm_radeon_prim_t prim;
+ drm_radeon_tcl_prim_t prim;
LOCK_TEST_WITH_RETURN( dev );
@@ -1142,7 +1234,6 @@ int radeon_cp_vertex( struct inode *inode, struct file *filp,
prim.start = 0;
prim.finish = vertex.count; /* unused */
prim.prim = vertex.prim;
- prim.stateidx = 0xff; /* unused */
prim.numverts = vertex.count;
prim.vc_format = dev_priv->sarea_priv->vc_format;
@@ -1167,7 +1258,7 @@ int radeon_cp_indices( struct inode *inode, struct file *filp,
drm_buf_t *buf;
drm_radeon_buf_priv_t *buf_priv;
drm_radeon_indices_t elts;
- drm_radeon_prim_t prim;
+ drm_radeon_tcl_prim_t prim;
int count;
LOCK_TEST_WITH_RETURN( dev );
@@ -1244,7 +1335,6 @@ int radeon_cp_indices( struct inode *inode, struct file *filp,
prim.start = elts.start;
prim.finish = elts.end; /* unused */
prim.prim = elts.prim;
- prim.stateidx = 0xff; /* unused */
prim.numverts = count;
prim.vc_format = dev_priv->sarea_priv->vc_format;
@@ -1446,6 +1536,7 @@ int radeon_cp_vertex2( struct inode *inode, struct file *filp,
for (laststate = 0xff, i = 0 ; i < vertex.nr_prims ; i++) {
drm_radeon_prim_t prim;
+ drm_radeon_tcl_prim_t tclprim;
if ( copy_from_user( &prim, &vertex.prim[i], sizeof(prim) ) )
return -EFAULT;
@@ -1463,12 +1554,18 @@ int radeon_cp_vertex2( struct inode *inode, struct file *filp,
laststate = prim.stateidx;
}
+ tclprim.start = prim.start;
+ tclprim.finish = prim.finish;
+ tclprim.prim = prim.prim;
+ tclprim.numverts = prim.numverts;
+ tclprim.vc_format = prim.vc_format;
+
if ( prim.prim & RADEON_PRIM_WALK_IND ) {
- radeon_cp_dispatch_indices( dev, buf, &prim,
+ radeon_cp_dispatch_indices( dev, buf, &tclprim,
sarea_priv->boxes,
sarea_priv->nbox);
} else {
- radeon_cp_dispatch_vertex( dev, buf, &prim,
+ radeon_cp_dispatch_vertex( dev, buf, &tclprim,
sarea_priv->boxes,
sarea_priv->nbox);
}
@@ -1527,7 +1624,7 @@ static inline int radeon_emit_scalars(
int start = header.scalars.offset;
int stride = header.scalars.stride;
RING_LOCALS;
- DRM_DEBUG( " %s\n", __FUNCTION__ );
+/* printk( " %s\n", __FUNCTION__ ); */
BEGIN_RING( 3+sz );
OUT_RING( CP_PACKET0( RADEON_SE_TCL_SCALAR_INDX_REG, 0 ) );
@@ -1558,17 +1655,22 @@ static inline int radeon_emit_vectors(
/* printk( " %s (start %x stride %d count %d)\n", __FUNCTION__, */
/* start, stride, sz); */
- BEGIN_RING( 3+sz );
- OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) );
- OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
- OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) );
- for ( i = 0 ; i < sz ; i++ ) {
- if (__get_user( tmp, &data[i] ))
- return -EFAULT;
+/* if (start == 122) { */
+/* printk("skipping GLT\n"); */
+/* } else */
+ {
+ BEGIN_RING( 3+sz );
+ OUT_RING( CP_PACKET0( RADEON_SE_TCL_VECTOR_INDX_REG, 0 ) );
+ OUT_RING( start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT));
+ OUT_RING( CP_PACKET0_TABLE( RADEON_SE_TCL_VECTOR_DATA_REG, (sz-1) ) );
+ for ( i = 0 ; i < sz ; i++ ) {
+ if (__get_user( tmp, &data[i] ))
+ return -EFAULT;
/* printk("%d: %x\n", i, tmp); */
- OUT_RING( tmp );
- }
- ADVANCE_RING();
+ OUT_RING( tmp );
+ }
+ ADVANCE_RING();
+ }
cmdbuf->buf += sz * sizeof(int);
cmdbuf->bufsz -= sz * sizeof(int);
@@ -1580,7 +1682,7 @@ static int radeon_emit_primitive(
drm_buf_t *buf,
drm_radeon_cmd_buffer_t *cmdbuf )
{
- drm_radeon_prim_t prim;
+ drm_radeon_tcl_prim_t prim;
if (cmdbuf->bufsz < sizeof(prim))
return -EFAULT;
@@ -1589,6 +1691,16 @@ static int radeon_emit_primitive(
return -EFAULT;
+/* printk( "%s: hwprim 0x%x vfmt 0x%x %d..%d %d verts \n", */
+/* __FUNCTION__, */
+/* prim.prim, */
+/* prim.vc_format, */
+/* prim.start, */
+/* prim.finish, */
+/* (prim.prim & RADEON_PRIM_WALK_IND) */
+/* ? ((prim.finish-prim.start-20)/2) */
+/* : prim.numverts); */
+
if ( prim.prim & RADEON_PRIM_WALK_IND ) {
radeon_cp_dispatch_indices( dev, buf, &prim,
cmdbuf->boxes,
@@ -1604,6 +1716,10 @@ static int radeon_emit_primitive(
cmdbuf->buf += sizeof(prim);
cmdbuf->bufsz -= sizeof(prim);
+
+
+/* printk( "%s: DONE\n", __FUNCTION__); */
+
return 0;
}
@@ -1655,7 +1771,7 @@ int radeon_cp_cmdbuf( struct inode *inode, struct file *filp,
DRM_ERROR("__get_user %p\n", cmdbuf.buf);
return -EFAULT;
}
-/* printk("cmdbuf.buf: %x/%x\n", cmdbuf.buf, header.i); */
+/* printk("cmdbuf.buf: %x/%x\n", cmdbuf.buf, header.i); */
cmdbuf.buf += sizeof(header);
cmdbuf.bufsz -= sizeof(header);