diff options
author | Keith Whitwell <[email protected]> | 2009-07-02 13:29:46 +0100 |
---|---|---|
committer | Keith Whitwell <[email protected]> | 2009-07-02 13:29:46 +0100 |
commit | 1668a679c4aadb37f5af0d6126c414fb9fbbf748 (patch) | |
tree | b3edf4157c658f1c37d5e046752135bd2ec566ea /src/mesa | |
parent | b3e8e1cd4c1584f735e35914861ae2e8ae5b6b2b (diff) | |
parent | 1fa4cde757cc94c0afa40d855309911247974e98 (diff) |
Merge commit 'origin/dlist-statechange-shortcircuit' into mesa_7_5_branch
Conflicts:
progs/trivial/Makefile
Pull in a minimal version of statechange shortcircuiting in display
list compilation. This affects only glMaterial and glShadeModel state,
and includes quite a few tests to exercise various tricky cases.
If this goes well, will consider extending to all state in the future.
Diffstat (limited to 'src/mesa')
-rw-r--r-- | src/mesa/main/dlist.c | 112 | ||||
-rw-r--r-- | src/mesa/main/enums.c | 22 | ||||
-rw-r--r-- | src/mesa/main/enums.h | 6 | ||||
-rw-r--r-- | src/mesa/main/mtypes.h | 7 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_exec_draw.c | 2 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_save_api.c | 2 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_save_loopback.c | 2 | ||||
-rw-r--r-- | src/mesa/vbo/vbo_split_copy.c | 2 |
8 files changed, 118 insertions, 37 deletions
diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index 782f847904e..c5a1c1f38fc 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -957,6 +957,20 @@ save_BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) } } +static void invalidate_saved_current_state( GLcontext *ctx ) +{ + GLint i; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + ctx->ListState.ActiveAttribSize[i] = 0; + + for (i = 0; i < MAT_ATTRIB_MAX; i++) + ctx->ListState.ActiveMaterialSize[i] = 0; + + memset(&ctx->ListState.Current, 0, sizeof ctx->ListState.Current); + + ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; +} void GLAPIENTRY _mesa_save_CallList(GLuint list) @@ -970,9 +984,10 @@ _mesa_save_CallList(GLuint list) n[1].ui = list; } - /* After this, we don't know what begin/end state we're in: + /* After this, we don't know what state we're in. Invalidate all + * cached information previously gathered: */ - ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; + invalidate_saved_current_state( ctx ); if (ctx->ExecuteFlag) { _mesa_CallList(list); @@ -1015,9 +1030,10 @@ _mesa_save_CallLists(GLsizei n, GLenum type, const GLvoid * lists) } } - /* After this, we don't know what begin/end state we're in: + /* After this, we don't know what state we're in. Invalidate all + * cached information previously gathered: */ - ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; + invalidate_saved_current_state( ctx ); if (ctx->ExecuteFlag) { CALL_CallLists(ctx->Exec, (n, type, lists)); @@ -3177,14 +3193,26 @@ save_ShadeModel(GLenum mode) { GET_CURRENT_CONTEXT(ctx); Node *n; - ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx); + ASSERT_OUTSIDE_SAVE_BEGIN_END(ctx); + + if (ctx->ExecuteFlag) { + CALL_ShadeModel(ctx->Exec, (mode)); + } + + if (ctx->ListState.Current.ShadeModel == mode) + return; + + SAVE_FLUSH_VERTICES(ctx); + + /* Only save the value if we know the statechange will take effect: + */ + if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END) + ctx->ListState.Current.ShadeModel = mode; + n = ALLOC_INSTRUCTION(ctx, OPCODE_SHADE_MODEL, 1); if (n) { n[1].e = mode; } - if (ctx->ExecuteFlag) { - CALL_ShadeModel(ctx->Exec, (mode)); - } } @@ -5146,14 +5174,21 @@ save_EdgeFlag(GLboolean x) save_Attr1fNV(VERT_ATTRIB_EDGEFLAG, x ? (GLfloat)1.0 : (GLfloat)0.0); } +static INLINE GLboolean compare4fv( const GLfloat *a, + const GLfloat *b, + GLuint count ) +{ + return memcmp( a, b, count * sizeof(GLfloat) ) == 0; +} + + static void GLAPIENTRY save_Materialfv(GLenum face, GLenum pname, const GLfloat * param) { GET_CURRENT_CONTEXT(ctx); Node *n; int args, i; - - SAVE_FLUSH_VERTICES(ctx); + GLuint bitmask; switch (face) { case GL_BACK: @@ -5183,26 +5218,43 @@ save_Materialfv(GLenum face, GLenum pname, const GLfloat * param) _mesa_compile_error(ctx, GL_INVALID_ENUM, "material(pname)"); return; } - - n = ALLOC_INSTRUCTION(ctx, OPCODE_MATERIAL, 6); - if (n) { - n[1].e = face; - n[2].e = pname; - for (i = 0; i < args; i++) - n[3 + i].f = param[i]; + + if (ctx->ExecuteFlag) { + CALL_Materialfv(ctx->Exec, (face, pname, param)); } - { - GLuint bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, NULL); - for (i = 0; i < MAT_ATTRIB_MAX; i++) - if (bitmask & (1 << i)) { + bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, NULL); + + /* Try to eliminate redundant statechanges. Because it is legal to + * call glMaterial even inside begin/end calls, don't need to worry + * about ctx->Driver.CurrentSavePrimitive here. + */ + for (i = 0; i < MAT_ATTRIB_MAX; i++) { + if (bitmask & (1 << i)) { + if (ctx->ListState.ActiveMaterialSize[i] == args && + compare4fv(ctx->ListState.CurrentMaterial[i], param, args)) { + bitmask &= ~(1 << i); + } + else { ctx->ListState.ActiveMaterialSize[i] = args; COPY_SZ_4V(ctx->ListState.CurrentMaterial[i], args, param); } + } } - if (ctx->ExecuteFlag) { - CALL_Materialfv(ctx->Exec, (face, pname, param)); + /* If this call has effect, return early: + */ + if (bitmask == 0) + return; + + SAVE_FLUSH_VERTICES(ctx); + + n = ALLOC_INSTRUCTION(ctx, OPCODE_MATERIAL, 6); + if (n) { + n[1].e = face; + n[2].e = pname; + for (i = 0; i < args; i++) + n[3 + i].f = param[i]; } } @@ -6771,7 +6823,6 @@ void GLAPIENTRY _mesa_NewList(GLuint name, GLenum mode) { GET_CURRENT_CONTEXT(ctx); - GLint i; FLUSH_CURRENT(ctx, 0); /* must be called before assert */ ASSERT_OUTSIDE_BEGIN_END(ctx); @@ -6799,20 +6850,15 @@ _mesa_NewList(GLuint name, GLenum mode) ctx->CompileFlag = GL_TRUE; ctx->ExecuteFlag = (mode == GL_COMPILE_AND_EXECUTE); + /* Reset acumulated list state: + */ + invalidate_saved_current_state( ctx ); + /* Allocate new display list */ ctx->ListState.CurrentList = make_list(name, BLOCK_SIZE); ctx->ListState.CurrentBlock = ctx->ListState.CurrentList->Head; ctx->ListState.CurrentPos = 0; - /* Reset acumulated list state: - */ - for (i = 0; i < VERT_ATTRIB_MAX; i++) - ctx->ListState.ActiveAttribSize[i] = 0; - - for (i = 0; i < MAT_ATTRIB_MAX; i++) - ctx->ListState.ActiveMaterialSize[i] = 0; - - ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; ctx->Driver.NewList(ctx, name, mode); ctx->CurrentDispatch = ctx->Save; diff --git a/src/mesa/main/enums.c b/src/mesa/main/enums.c index cf893fdac51..417cee8fb2a 100644 --- a/src/mesa/main/enums.c +++ b/src/mesa/main/enums.c @@ -5059,6 +5059,28 @@ const char *_mesa_lookup_enum_by_nr( int nr ) } } +/* Get the name of an enum given that it is a primitive type. Avoids + * GL_FALSE/GL_POINTS ambiguity and others. + */ +const char *_mesa_lookup_prim_by_nr( int nr ) +{ + switch (nr) { + case GL_POINTS: return "GL_POINTS"; + case GL_LINES: return "GL_LINES"; + case GL_LINE_STRIP: return "GL_LINE_STRIP"; + case GL_LINE_LOOP: return "GL_LINE_LOOP"; + case GL_TRIANGLES: return "GL_TRIANGLES"; + case GL_TRIANGLE_STRIP: return "GL_TRIANGLE_STRIP"; + case GL_TRIANGLE_FAN: return "GL_TRIANGLE_FAN"; + case GL_QUADS: return "GL_QUADS"; + case GL_QUAD_STRIP: return "GL_QUAD_STRIP"; + case GL_POLYGON: return "GL_POLYGON"; + case GL_POLYGON+1: return "OUTSIDE_BEGIN_END"; + default: return "<invalid>"; + } +} + + int _mesa_lookup_enum_by_name( const char *symbol ) { enum_elt * f = NULL; diff --git a/src/mesa/main/enums.h b/src/mesa/main/enums.h index 23a4767f350..b5f69001b84 100644 --- a/src/mesa/main/enums.h +++ b/src/mesa/main/enums.h @@ -40,6 +40,12 @@ #if defined(_HAVE_FULL_GL) && _HAVE_FULL_GL extern const char *_mesa_lookup_enum_by_nr( int nr ); + +/* Get the name of an enum given that it is a primitive type. Avoids + * GL_FALSE/GL_POINTS ambiguity and others. + */ +const char *_mesa_lookup_prim_by_nr( int nr ); + extern int _mesa_lookup_enum_by_name( const char *symbol ); #else diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 84a082b253e..bdaa4977b72 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2806,6 +2806,13 @@ struct gl_dlist_state GLubyte ActiveEdgeFlag; GLboolean CurrentEdgeFlag; + + struct { + /* State known to have been set by the currently-compiling display + * list. Used to eliminate some redundant state changes. + */ + GLenum ShadeModel; + } Current; }; diff --git a/src/mesa/vbo/vbo_exec_draw.c b/src/mesa/vbo/vbo_exec_draw.c index fdacb42e357..c53a4eee00c 100644 --- a/src/mesa/vbo/vbo_exec_draw.c +++ b/src/mesa/vbo/vbo_exec_draw.c @@ -50,7 +50,7 @@ static void vbo_exec_debug_verts( struct vbo_exec_context *exec ) struct _mesa_prim *prim = &exec->vtx.prim[i]; _mesa_printf(" prim %d: %s%s %d..%d %s %s\n", i, - _mesa_lookup_enum_by_nr(prim->mode), + _mesa_lookup_prim_by_nr(prim->mode), prim->weak ? " (weak)" : "", prim->start, prim->start + prim->count, diff --git a/src/mesa/vbo/vbo_save_api.c b/src/mesa/vbo/vbo_save_api.c index 7dcb5c82422..85cb79c71ce 100644 --- a/src/mesa/vbo/vbo_save_api.c +++ b/src/mesa/vbo/vbo_save_api.c @@ -1162,7 +1162,7 @@ static void vbo_print_vertex_list( GLcontext *ctx, void *data ) struct _mesa_prim *prim = &node->prim[i]; _mesa_debug(NULL, " prim %d: %s%s %d..%d %s %s\n", i, - _mesa_lookup_enum_by_nr(prim->mode), + _mesa_lookup_prim_by_nr(prim->mode), prim->weak ? " (weak)" : "", prim->start, prim->start + prim->count, diff --git a/src/mesa/vbo/vbo_save_loopback.c b/src/mesa/vbo/vbo_save_loopback.c index 92ca4ea95d3..b7a74e4535a 100644 --- a/src/mesa/vbo/vbo_save_loopback.c +++ b/src/mesa/vbo/vbo_save_loopback.c @@ -97,7 +97,7 @@ static void loopback_prim( GLcontext *ctx, if (0) _mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n", - _mesa_lookup_enum_by_nr(prim->mode), + _mesa_lookup_prim_by_nr(prim->mode), prim->begin ? "begin" : "..", prim->end ? "end" : "..", start, diff --git a/src/mesa/vbo/vbo_split_copy.c b/src/mesa/vbo/vbo_split_copy.c index 5fb66d3318f..b9a5c569876 100644 --- a/src/mesa/vbo/vbo_split_copy.c +++ b/src/mesa/vbo/vbo_split_copy.c @@ -180,7 +180,7 @@ static void begin( struct copy_context *copy, GLenum mode, GLboolean begin_flag { struct _mesa_prim *prim = ©->dstprim[copy->dstprim_nr]; -/* _mesa_printf("begin %s (%d)\n", _mesa_lookup_enum_by_nr(mode), begin_flag); */ +/* _mesa_printf("begin %s (%d)\n", _mesa_lookup_prim_by_nr(mode), begin_flag); */ prim->mode = mode; prim->begin = begin_flag; |