Added error checking in _tnl_Begin to detect incomplete framebuffer.
authorBrian Paul <brian.paul@tungstengraphics.com>
Wed, 16 Nov 2005 02:47:16 +0000 (02:47 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Wed, 16 Nov 2005 02:47:16 +0000 (02:47 +0000)
Set new tnl->DiscardPrimitive field to true when such error is
detected to discard the glBegin/End primitive when flushing.
Added some new comments.

src/mesa/tnl/t_context.h
src/mesa/tnl/t_vtx_api.c

index 9eaff95b73d85cb78fae366d3da3b3adc041f587..f36dec23a596adbdd54eb80afeb14b454a5ed982 100644 (file)
@@ -782,6 +782,12 @@ typedef struct
 
    GLboolean _DoVertexFog;  /* eval fog function at each vertex? */
 
+   /* If True, it means we started a glBegin/End primtive with an invalid
+    * vertex/fragment program or incomplete framebuffer.  In that case,
+    * discard any buffered vertex data.
+    */
+   GLboolean DiscardPrimitive;
+
    GLuint render_inputs;
 
    GLvertexformat exec_vtxfmt;
index 0ce6b4ad79999951c8450310221544dfee3cb40b..d52d2f7a4716ef1548e0ccf712d3dc7f09940ad9 100644 (file)
@@ -728,8 +728,9 @@ static void GLAPIENTRY _tnl_EvalPoint2( GLint i, GLint j )
 }
 
 
-/* Build a list of primitives on the fly.  Keep
- * ctx->Driver.CurrentExecPrimitive uptodate as well.
+/**
+ * Called from glBegin.
+ * ctx->Driver.CurrentExecPrimitive will be set to <mode>.
  */
 static void GLAPIENTRY _tnl_Begin( GLenum mode )
 {
@@ -738,7 +739,7 @@ static void GLAPIENTRY _tnl_Begin( GLenum mode )
    if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) {
       /* we're not inside a glBegin/End pair */
       TNLcontext *tnl = TNL_CONTEXT(ctx); 
-      int i;
+      GLuint i;
 
       if (ctx->NewState) {
         _mesa_update_state( ctx );
@@ -747,9 +748,19 @@ static void GLAPIENTRY _tnl_Begin( GLenum mode )
             (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
             _mesa_error(ctx, GL_INVALID_OPERATION,
                         "glBegin (invalid vertex/fragment program)");
+            tnl->DiscardPrimitive = GL_TRUE;
             return;
          }
 
+         if (ctx->DrawBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+            _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
+                        "glBegin(incomplete framebuffer)");
+            tnl->DiscardPrimitive = GL_TRUE;
+            return;
+         }
+
+         tnl->DiscardPrimitive = GL_FALSE;
+
         if (!(tnl->Driver.NotifyBegin && 
               tnl->Driver.NotifyBegin( ctx, mode )))
             CALL_Begin(ctx->Exec, (mode));
@@ -776,11 +787,15 @@ static void GLAPIENTRY _tnl_Begin( GLenum mode )
 }
 
 
+/**
+ * Called from glEnd.
+ */
 static void GLAPIENTRY _tnl_End( void )
 {
    GET_CURRENT_CONTEXT( ctx ); 
 
    if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+      /* closing an open glBegin primitive */
       TNLcontext *tnl = TNL_CONTEXT(ctx); 
       int idx = tnl->vtx.initial_counter - tnl->vtx.counter;
       int i = tnl->vtx.prim_count - 1;
@@ -802,8 +817,10 @@ static void GLAPIENTRY _tnl_End( void )
 #endif
 
    }
-   else 
+   else {
+      /* glBegin hasn't been called! */
       _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
+   }
 }
 
 
@@ -840,8 +857,17 @@ void _tnl_FlushVertices( GLcontext *ctx, GLuint flags )
    TNLcontext *tnl = TNL_CONTEXT(ctx);
    (void) flags;
 
-   if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)
+   if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
+      /* still inside a glBegin/End pair.  How'd we get here??? */
       return;
+   }
+
+   if (tnl->DiscardPrimitive) {
+      /* discard any primitives */
+      tnl->vtx.prim_count = 0;
+      tnl->vtx.counter = tnl->vtx.initial_counter;
+      tnl->vtx.vbptr = tnl->vtx.buffer;
+   }
 
    if (tnl->vtx.counter != tnl->vtx.initial_counter) {
       _tnl_flush_vtx( ctx );