summaryrefslogtreecommitdiffstats
path: root/src/mesa/tnl
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa/tnl')
-rw-r--r--src/mesa/tnl/t_context.h6
-rw-r--r--src/mesa/tnl/t_vtx_api.c36
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 );