Implemented checks that prevent r300 from locking up when bad number of verts are given. Also tweaked WARN_ONCE a bit to handle va-args.

This commit is contained in:
Aapo Tahkola 2005-02-08 04:31:29 +00:00
parent 3f847b73f3
commit 315afce941
2 changed files with 105 additions and 61 deletions

View File

@ -56,13 +56,17 @@ typedef struct r300_context *r300ContextPtr;
/* Checkpoint.. for convenience */
#define CPT { fprintf(stderr, "%s:%s line %d\n", __FILE__, __FUNCTION__, __LINE__); }
#define WARN_ONCE(a) { \
/* From http://gcc.gnu.org/onlinedocs/gcc-3.2.3/gcc/Variadic-Macros.html .
I suppose we could inline this and use macro to fetch out __LINE__ and stuff in case we run into trouble
with other compilers ... GLUE!
*/
#define WARN_ONCE(a, ...) { \
static int warn##__LINE__=1; \
if(warn##__LINE__){ \
fprintf(stderr, "*********************************WARN_ONCE*********************************\n"); \
fprintf(stderr, "File %s function %s line %d\n", \
__FILE__, __FUNCTION__, __LINE__); \
fprintf(stderr, a);\
fprintf(stderr, a, ## __VA_ARGS__);\
fprintf(stderr, "***************************************************************************\n"); \
warn##__LINE__=0;\
} \

View File

@ -123,70 +123,43 @@ static void update_zbias(GLcontext * ctx, int prim)
* rasterization hardware for rendering.
**********************************************************************/
static int r300_get_primitive_type(r300ContextPtr rmesa,
GLcontext *ctx,
int start,
int end,
int prim)
static int r300_get_primitive_type(r300ContextPtr rmesa, GLcontext *ctx, int prim)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint i;
int type=-1, min_vertices=0;
char *name="UNKNOWN";
if(end<=start)return -1; /* do we need to watch for this ? */
int type=-1;
switch (prim & PRIM_MODE_MASK) {
case GL_POINTS:
name="P";
type=R300_VAP_VF_CNTL__PRIM_POINTS;
min_vertices=1;
break;
case GL_LINES:
name="L";
type=R300_VAP_VF_CNTL__PRIM_LINES;
min_vertices=2;
break;
case GL_LINE_STRIP:
name="LS";
type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
min_vertices=2;
break;
case GL_LINE_LOOP:
name="LL";
min_vertices=2;
return -1;
type=R300_VAP_VF_CNTL__PRIM_LINE_LOOP;
break;
case GL_TRIANGLES:
name="T";
type=R300_VAP_VF_CNTL__PRIM_TRIANGLES;
min_vertices=3;
break;
case GL_TRIANGLE_STRIP:
name="TS";
type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
min_vertices=3;
break;
case GL_TRIANGLE_FAN:
name="TF";
type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
min_vertices=3;
break;
case GL_QUADS:
name="Q";
type=R300_VAP_VF_CNTL__PRIM_QUADS;
min_vertices=4;
break;
case GL_QUAD_STRIP:
name="QS";
type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
min_vertices=4;
break;
case GL_POLYGON:
name="P";
type=R300_VAP_VF_CNTL__PRIM_POLYGON;
min_vertices=3;
type=R300_VAP_VF_CNTL__PRIM_POLYGON;
break;
default:
fprintf(stderr, "%s:%s Do not know how to handle primitive %02x - help me !\n",
@ -195,22 +168,87 @@ static int r300_get_primitive_type(r300ContextPtr rmesa,
return -1;
break;
}
#if 0
fprintf(stderr, "[%d-%d]%s ", start, end, name);
#endif
if(start+min_vertices>end){
static int warn_once=1;
if(warn_once){
fprintf(stderr, "%s:%s ***WARN_ONCE*** Not enough vertices to draw primitive %02x - help me !\n",
__FILE__, __FUNCTION__,
prim & PRIM_MODE_MASK);
warn_once=0;
}
return -1;
}
return type;
}
static int r300_get_num_verts(r300ContextPtr rmesa,
GLcontext *ctx,
int num_verts,
int prim)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint i;
int type=-1, verts_off=0;
char *name="UNKNOWN";
switch (prim & PRIM_MODE_MASK) {
case GL_POINTS:
name="P";
verts_off = 0;
break;
case GL_LINES:
name="L";
verts_off = num_verts % 2;
break;
case GL_LINE_STRIP:
name="LS";
verts_off = num_verts % 2;
break;
case GL_LINE_LOOP:
name="LL";
verts_off = num_verts % 2;
break;
case GL_TRIANGLES:
name="T";
verts_off = num_verts % 3;
break;
case GL_TRIANGLE_STRIP:
name="TS";
if(num_verts < 3)
verts_off = num_verts;
break;
case GL_TRIANGLE_FAN:
name="TF";
if(num_verts < 3)
verts_off = num_verts;
break;
case GL_QUADS:
name="Q";
verts_off = num_verts % 4;
break;
case GL_QUAD_STRIP:
name="QS";
if(num_verts < 4)
verts_off = num_verts;
else
verts_off = num_verts % 2;
break;
case GL_POLYGON:
name="P";
if(num_verts < 3)
verts_off = num_verts;
break;
default:
fprintf(stderr, "%s:%s Do not know how to handle primitive %02x - help me !\n",
__FILE__, __FUNCTION__,
prim & PRIM_MODE_MASK);
return -1;
break;
}
if(num_verts - verts_off == 0){
WARN_ONCE("user error: Need more than %d vertices to draw primitive %s !\n", num_verts, name);
return 0;
}
if(verts_off > 0){
WARN_ONCE("user error: %d is not a valid number of vertices for primitive %s !\n", num_verts, name);
}
return num_verts - verts_off;
}
/* This function compiles GL context into state registers that
describe data routing inside of R300 pipeline.
@ -249,11 +287,12 @@ static void r300_render_immediate_primitive(r300ContextPtr rmesa,
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint i, render_inputs;
int k, type;
int k, type, num_verts;
LOCAL_VARS
type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
type=r300_get_primitive_type(rmesa, ctx, prim);
num_verts=r300_get_num_verts(rmesa, ctx, end-start, prim);
#if 0
fprintf(stderr,"ObjPtr: size=%d stride=%d\n",
VB->ObjPtr->size, VB->ObjPtr->stride);
@ -263,14 +302,14 @@ static void r300_render_immediate_primitive(r300ContextPtr rmesa,
VB->TexCoordPtr[0]->size, VB->TexCoordPtr[0]->stride);
#endif
if(type<0)return;
if(type<0 || num_verts <= 0)return;
if(!VB->ObjPtr){
WARN_ONCE("FIXME: Don't know how to handle GL_ARB_vertex_buffer_object correctly\n");
return;
}
/* A packet cannot have more than 16383 data words.. */
if(((end-start)*4*rmesa->state.aos_count)>16380){
if((num_verts*4*rmesa->state.aos_count)>16380){
WARN_ONCE("Too many vertices to paint. Fix me !\n");
return;
}
@ -289,9 +328,9 @@ static void r300_render_immediate_primitive(r300ContextPtr rmesa,
return;
}
start_immediate_packet(end-start, type, 4*rmesa->state.aos_count);
start_immediate_packet(num_verts, type, 4*rmesa->state.aos_count);
for(i=start;i<end;i++){
for(i=start;i<start+num_verts;i++){
#if 0
fprintf(stderr, "* (%f %f %f %f) (%f %f %f %f)\n",
VEC_ELT(VB->ObjPtr, GLfloat, i)[0],
@ -526,15 +565,16 @@ static void r300_render_vb_primitive(r300ContextPtr rmesa,
int end,
int prim)
{
int type;
int type, num_verts;
LOCAL_VARS
if(end<=start)return; /* do we need to watch for this ? */
type=r300_get_primitive_type(rmesa, ctx, start, end, prim);
if(type<0)return;
fire_AOS(PASS_PREFIX end-start, type);
type=r300_get_primitive_type(rmesa, ctx, prim);
num_verts=r300_get_num_verts(rmesa, ctx, end-start, prim);
if(type<0 || num_verts <= 0)return;
fire_AOS(PASS_PREFIX num_verts, type);
}
static GLboolean r300_run_vb_render(GLcontext *ctx,
@ -612,7 +652,7 @@ static GLboolean r300_run_render(GLcontext *ctx,
if (RADEON_DEBUG == DEBUG_PRIMS)
fprintf(stderr, "%s\n", __FUNCTION__);
#if 1