diff options
-rw-r--r-- | src/mesa/tnl/t_context.h | 6 | ||||
-rw-r--r-- | src/mesa/tnl/t_vtx_api.c | 36 |
2 files changed, 37 insertions, 5 deletions
diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h index 9eaff95b73d..f36dec23a59 100644 --- a/src/mesa/tnl/t_context.h +++ b/src/mesa/tnl/t_context.h @@ -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; diff --git a/src/mesa/tnl/t_vtx_api.c b/src/mesa/tnl/t_vtx_api.c index 0ce6b4ad799..d52d2f7a471 100644 --- a/src/mesa/tnl/t_vtx_api.c +++ b/src/mesa/tnl/t_vtx_api.c @@ -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 ); |