mesa: Install a minimal dispatch table during glBegin()/glEnd().
This is a step toward getting rid of ASSERT_OUTSIDE_BEGIN_END() in Mesa. v2: Finish create_beginend_table() comment, move loopback API init into it, and add a const flag. (suggestions by Brian) Reviewed-by: Brian Paul <brianp@vmware.com> (v1) Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> (v1)
This commit is contained in:
parent
0aaf0445ba
commit
c572251417
|
@ -81,6 +81,7 @@
|
|||
#include "imports.h"
|
||||
#include "accum.h"
|
||||
#include "api_exec.h"
|
||||
#include "api_loopback.h"
|
||||
#include "arrayobj.h"
|
||||
#include "attrib.h"
|
||||
#include "blend.h"
|
||||
|
@ -859,6 +860,81 @@ _mesa_alloc_dispatch_table(int size)
|
|||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a minimal dispatch table for use within glBegin()/glEnd().
|
||||
*
|
||||
* This ensures that we generate GL_INVALID_OPERATION errors from most
|
||||
* functions, since the set of functions that are valid within Begin/End is
|
||||
* very small.
|
||||
*
|
||||
* From the GL 1.0 specification section 2.6.3, "GL Commands within
|
||||
* Begin/End"
|
||||
*
|
||||
* "The only GL commands that are allowed within any Begin/End pairs are
|
||||
* the commands for specifying vertex coordinates, vertex color, normal
|
||||
* coordinates, and texture coordinates (Vertex, Color, Index, Normal,
|
||||
* TexCoord), EvalCoord and EvalPoint commands (see section 5.1),
|
||||
* commands for specifying lighting material parameters (Material
|
||||
* commands see section 2.12.2), display list invocation commands
|
||||
* (CallList and CallLists see section 5.4), and the EdgeFlag
|
||||
* command. Executing Begin after Begin has already been executed but
|
||||
* before an End is issued generates the INVALID OPERATION error, as does
|
||||
* executing End without a previous corresponding Begin. Executing any
|
||||
* other GL command within Begin/End results in the error INVALID
|
||||
* OPERATION."
|
||||
*
|
||||
* The table entries for specifying vertex attributes are set up by
|
||||
* install_vtxfmt() and _mesa_loopback_init_api_table(), and End() and dlists
|
||||
* are set by install_vtxfmt() as well.
|
||||
*/
|
||||
static struct _glapi_table *
|
||||
create_beginend_table(const struct gl_context *ctx)
|
||||
{
|
||||
struct _glapi_table *table;
|
||||
|
||||
table = _mesa_alloc_dispatch_table(_gloffset_COUNT);
|
||||
if (!table)
|
||||
return NULL;
|
||||
|
||||
/* Fill in functions which return a value, since they should return some
|
||||
* specific value even if they emit a GL_INVALID_OPERATION error from them
|
||||
* being called within glBegin()/glEnd().
|
||||
*/
|
||||
#define COPY_DISPATCH(func) SET_##func(table, GET_##func(ctx->Exec))
|
||||
|
||||
COPY_DISPATCH(GenLists);
|
||||
COPY_DISPATCH(IsProgram);
|
||||
COPY_DISPATCH(IsVertexArray);
|
||||
COPY_DISPATCH(IsBuffer);
|
||||
COPY_DISPATCH(IsEnabled);
|
||||
COPY_DISPATCH(IsEnabledi);
|
||||
COPY_DISPATCH(IsRenderbuffer);
|
||||
COPY_DISPATCH(IsFramebuffer);
|
||||
COPY_DISPATCH(CheckFramebufferStatus);
|
||||
COPY_DISPATCH(RenderMode);
|
||||
COPY_DISPATCH(GetString);
|
||||
COPY_DISPATCH(GetStringi);
|
||||
COPY_DISPATCH(GetPointerv);
|
||||
COPY_DISPATCH(IsQuery);
|
||||
COPY_DISPATCH(IsSampler);
|
||||
COPY_DISPATCH(IsSync);
|
||||
COPY_DISPATCH(IsTexture);
|
||||
COPY_DISPATCH(IsTransformFeedback);
|
||||
COPY_DISPATCH(DeleteQueries);
|
||||
COPY_DISPATCH(AreTexturesResident);
|
||||
COPY_DISPATCH(FenceSync);
|
||||
COPY_DISPATCH(ClientWaitSync);
|
||||
COPY_DISPATCH(MapBuffer);
|
||||
COPY_DISPATCH(UnmapBuffer);
|
||||
COPY_DISPATCH(MapBufferRange);
|
||||
COPY_DISPATCH(MapBufferRange);
|
||||
COPY_DISPATCH(ObjectPurgeableAPPLE);
|
||||
COPY_DISPATCH(ObjectUnpurgeableAPPLE);
|
||||
|
||||
_mesa_loopback_init_api_table(ctx, table);
|
||||
|
||||
return table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a struct gl_context struct (rendering context).
|
||||
|
@ -933,19 +1009,15 @@ _mesa_initialize_context(struct gl_context *ctx,
|
|||
|
||||
_mesa_reference_shared_state(ctx, &ctx->Shared, shared);
|
||||
|
||||
if (!init_attrib_groups( ctx )) {
|
||||
_mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
|
||||
return GL_FALSE;
|
||||
}
|
||||
if (!init_attrib_groups( ctx ))
|
||||
goto fail;
|
||||
|
||||
/* setup the API dispatch tables with all nop functions */
|
||||
ctx->Exec = _mesa_alloc_dispatch_table(_gloffset_COUNT);
|
||||
|
||||
if (!ctx->Exec) {
|
||||
_mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
|
||||
return GL_FALSE;
|
||||
}
|
||||
ctx->CurrentDispatch = ctx->Exec;
|
||||
ctx->OutsideBeginEnd = _mesa_alloc_dispatch_table(_gloffset_COUNT);
|
||||
if (!ctx->OutsideBeginEnd)
|
||||
goto fail;
|
||||
ctx->Exec = ctx->OutsideBeginEnd;
|
||||
ctx->CurrentDispatch = ctx->OutsideBeginEnd;
|
||||
|
||||
ctx->FragmentProgram._MaintainTexEnvProgram
|
||||
= (_mesa_getenv("MESA_TEX_PROG") != NULL);
|
||||
|
@ -967,12 +1039,10 @@ _mesa_initialize_context(struct gl_context *ctx,
|
|||
|
||||
switch (ctx->API) {
|
||||
case API_OPENGL_COMPAT:
|
||||
ctx->BeginEnd = create_beginend_table(ctx);
|
||||
ctx->Save = _mesa_create_save_table(ctx);
|
||||
if (!ctx->Save) {
|
||||
_mesa_reference_shared_state(ctx, &ctx->Shared, NULL);
|
||||
free(ctx->Exec);
|
||||
return GL_FALSE;
|
||||
}
|
||||
if (!ctx->BeginEnd || !ctx->Save)
|
||||
goto fail;
|
||||
|
||||
/* fall-through */
|
||||
case API_OPENGL_CORE:
|
||||
|
@ -1002,6 +1072,12 @@ _mesa_initialize_context(struct gl_context *ctx,
|
|||
ctx->FirstTimeCurrent = GL_TRUE;
|
||||
|
||||
return GL_TRUE;
|
||||
|
||||
fail:
|
||||
free(ctx->BeginEnd);
|
||||
free(ctx->Exec);
|
||||
free(ctx->Save);
|
||||
return GL_FALSE;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -3440,9 +3440,28 @@ struct gl_context
|
|||
/** \name API function pointer tables */
|
||||
/*@{*/
|
||||
gl_api API;
|
||||
struct _glapi_table *Save; /**< Display list save functions */
|
||||
struct _glapi_table *Exec; /**< Execute functions */
|
||||
struct _glapi_table *CurrentDispatch; /**< == Save or Exec !! */
|
||||
/**
|
||||
* The current dispatch table for non-displaylist-saving execution, either
|
||||
* BeginEnd or OutsideBeginEnd
|
||||
*/
|
||||
struct _glapi_table *Exec;
|
||||
/**
|
||||
* The normal dispatch table for non-displaylist-saving, non-begin/end
|
||||
*/
|
||||
struct _glapi_table *OutsideBeginEnd;
|
||||
/** The dispatch table used between glNewList() and glEndList() */
|
||||
struct _glapi_table *Save;
|
||||
/**
|
||||
* The dispatch table used between glBegin() and glEnd() (outside of a
|
||||
* display list). Only valid functions between those two are set, which is
|
||||
* mostly just the set in a GLvertexformat struct.
|
||||
*/
|
||||
struct _glapi_table *BeginEnd;
|
||||
/**
|
||||
* Tracks the current dispatch table out of the 3 above, so that it can be
|
||||
* re-set on glXMakeCurrent().
|
||||
*/
|
||||
struct _glapi_table *CurrentDispatch;
|
||||
/*@}*/
|
||||
|
||||
struct gl_config Visual;
|
||||
|
|
|
@ -252,6 +252,8 @@ void
|
|||
_mesa_install_exec_vtxfmt(struct gl_context *ctx, const GLvertexformat *vfmt)
|
||||
{
|
||||
install_vtxfmt( ctx, ctx->Exec, vfmt );
|
||||
if (ctx->BeginEnd)
|
||||
install_vtxfmt( ctx, ctx->BeginEnd, vfmt );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -833,6 +833,17 @@ static void GLAPIENTRY vbo_exec_Begin( GLenum mode )
|
|||
exec->vtx.prim[i].base_instance = 0;
|
||||
|
||||
ctx->Driver.CurrentExecPrimitive = mode;
|
||||
|
||||
ctx->Exec = ctx->BeginEnd;
|
||||
/* We may have been called from a display list, in which case we should
|
||||
* leave dlist.c's dispatch table in place.
|
||||
*/
|
||||
if (ctx->CurrentDispatch == ctx->OutsideBeginEnd) {
|
||||
ctx->CurrentDispatch = ctx->BeginEnd;
|
||||
_glapi_set_dispatch(ctx->CurrentDispatch);
|
||||
} else {
|
||||
assert(ctx->CurrentDispatch == ctx->Save);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -849,6 +860,12 @@ static void GLAPIENTRY vbo_exec_End( void )
|
|||
return;
|
||||
}
|
||||
|
||||
ctx->Exec = ctx->OutsideBeginEnd;
|
||||
if (ctx->CurrentDispatch == ctx->BeginEnd) {
|
||||
ctx->CurrentDispatch = ctx->OutsideBeginEnd;
|
||||
_glapi_set_dispatch(ctx->CurrentDispatch);
|
||||
}
|
||||
|
||||
if (exec->vtx.prim_count > 0) {
|
||||
/* close off current primitive */
|
||||
int idx = exec->vtx.vert_count;
|
||||
|
|
Loading…
Reference in New Issue