Fix backwards compatibility on tcl branch. Add checks on number of vertices

per primitive.
This commit is contained in:
Keith Whitwell 2002-02-22 20:01:09 +00:00
parent ccc1b6edec
commit 36f6fb67f4
3 changed files with 174 additions and 33 deletions

View file

@ -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,12 +258,20 @@ 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];

View file

@ -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)

View file

@ -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);