Implemented checks that prevent r300 from locking up when bad number of verts are...
authorAapo Tahkola <aet@rasterburn.org>
Tue, 8 Feb 2005 04:31:29 +0000 (04:31 +0000)
committerAapo Tahkola <aet@rasterburn.org>
Tue, 8 Feb 2005 04:31:29 +0000 (04:31 +0000)
src/mesa/drivers/dri/r300/r300_context.h
src/mesa/drivers/dri/r300/r300_render.c

index 54cc7e3fc1aa780636b9d4a9c2204350bd07d1c9..428614b7a657b86d7c45f70d508a508f55c3dc52 100644 (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;\
                } \
index 7623e9e23aee6f85a52b115378e89abdf933f930..9a79b97cc049ad9494e37efa6b32f5e40cf9b05c 100644 (file)
@@ -123,70 +123,111 @@ static void update_zbias(GLcontext * ctx, int prim)
 * rasterization hardware for rendering.
 **********************************************************************/
 
-static int r300_get_primitive_type(r300ContextPtr rmesa, 
+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;
+   
+       switch (prim & PRIM_MODE_MASK) {
+       case GL_POINTS:
+               type=R300_VAP_VF_CNTL__PRIM_POINTS;
+               break;          
+       case GL_LINES:
+               type=R300_VAP_VF_CNTL__PRIM_LINES;
+               break;          
+       case GL_LINE_STRIP:
+               type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
+               break;
+       case GL_LINE_LOOP:
+               type=R300_VAP_VF_CNTL__PRIM_LINE_LOOP;
+               break;
+       case GL_TRIANGLES:
+               type=R300_VAP_VF_CNTL__PRIM_TRIANGLES;
+               break;
+       case GL_TRIANGLE_STRIP:
+               type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
+               break;
+       case GL_TRIANGLE_FAN:
+               type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
+               break;
+       case GL_QUADS:
+               type=R300_VAP_VF_CNTL__PRIM_QUADS;
+               break;
+       case GL_QUAD_STRIP:
+               type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
+               break;
+       case GL_POLYGON:
+               type=R300_VAP_VF_CNTL__PRIM_POLYGON;
+               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;
+       }
+   return type;
+}
+
+static int r300_get_num_verts(r300ContextPtr rmesa, 
        GLcontext *ctx,
-       int start,
-       int end,
+       int num_verts,
        int prim)
 {
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    struct vertex_buffer *VB = &tnl->vb;
    GLuint i;
-   int type=-1, min_vertices=0;
+   int type=-1, verts_off=0;
    char *name="UNKNOWN";
    
-   if(end<=start)return -1; /* do we need to watch for this ? */
-   
        switch (prim & PRIM_MODE_MASK) {
        case GL_POINTS:
                name="P";
-               type=R300_VAP_VF_CNTL__PRIM_POINTS;
-               min_vertices=1;
+               verts_off = 0;
                break;          
        case GL_LINES:
                name="L";
-               type=R300_VAP_VF_CNTL__PRIM_LINES;
-               min_vertices=2;
+               verts_off = num_verts % 2;
                break;          
        case GL_LINE_STRIP:
                name="LS";
-               type=R300_VAP_VF_CNTL__PRIM_LINE_STRIP;
-               min_vertices=2;
+               verts_off = num_verts % 2;
                break;
        case GL_LINE_LOOP:
                name="LL";
-               min_vertices=2;
-               return -1;
+               verts_off = num_verts % 2;
                break;
        case GL_TRIANGLES:
                name="T";
-               type=R300_VAP_VF_CNTL__PRIM_TRIANGLES;
-               min_vertices=3;
+               verts_off = num_verts % 3;
                break;
        case GL_TRIANGLE_STRIP:
                name="TS";
-               type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_STRIP;
-               min_vertices=3;
+               if(num_verts < 3)
+                       verts_off = num_verts;
                break;
        case GL_TRIANGLE_FAN:
                name="TF";
-               type=R300_VAP_VF_CNTL__PRIM_TRIANGLE_FAN;
-               min_vertices=3;
+               if(num_verts < 3)
+                       verts_off = num_verts;
                break;
        case GL_QUADS:
                name="Q";
-               type=R300_VAP_VF_CNTL__PRIM_QUADS;
-               min_vertices=4;
+               verts_off = num_verts % 4;
                break;
        case GL_QUAD_STRIP:
                name="QS";
-               type=R300_VAP_VF_CNTL__PRIM_QUAD_STRIP;
-               min_vertices=4;
+               if(num_verts < 4)
+                       verts_off = num_verts;
+               else
+                       verts_off = num_verts % 2;
                break;
        case GL_POLYGON:
                name="P";
-                       type=R300_VAP_VF_CNTL__PRIM_POLYGON;
-               min_vertices=3;
+               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",
@@ -195,20 +236,17 @@ 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;
+       
+       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 
@@ -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