From 47173cf67f0ed55012b0820397f6d620d8ad4473 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Tue, 30 Jun 2009 09:55:33 +0100 Subject: mesa/dlist: shortcircuit some redundant statechanges at compile time Currently, state-changes in mesa display lists are more or less a verbatim recording of the GL calls made during compilation. This change introduces a minor optimization to recognize and eliminate cases where the application emits redundant state changes, eg: glShadeModel( GL_FLAT ); glBegin( prim ) ... glEnd() glShadeModel( GL_FLAT ); glBegin( prim ) ... glEnd() The big win is when we can eliminate all the statechanges between two primitive blocks and combine them into a single VBO node. This commit implements state-change elimination for Material and ShadeModel only. This is enough to make a start on debugging, etc. --- src/mesa/main/dlist.c | 63 +++++++++++++++++++++++++++++++++++--------------- src/mesa/main/mtypes.h | 7 ++++++ 2 files changed, 51 insertions(+), 19 deletions(-) (limited to 'src/mesa/main') diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c index 782f847904..3647401a1b 100644 --- a/src/mesa/main/dlist.c +++ b/src/mesa/main/dlist.c @@ -3177,14 +3177,21 @@ 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; + + 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 +5153,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,6 +5197,28 @@ save_Materialfv(GLenum face, GLenum pname, const GLfloat * param) _mesa_compile_error(ctx, GL_INVALID_ENUM, "material(pname)"); return; } + + if (ctx->ExecuteFlag) { + CALL_Materialfv(ctx->Exec, (face, pname, param)); + } + + bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, NULL); + + /* Try to eliminate redundant statechanges + */ + for (i = 0; i < MAT_ATTRIB_MAX; i++) { + if (bitmask & (1 << i)) { + if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END && + ctx->ListState.ActiveMaterialSize[i] == args && + compare4fv(ctx->ListState.CurrentMaterial[i], param, args)) + return; + + ctx->ListState.ActiveMaterialSize[i] = args; + COPY_SZ_4V(ctx->ListState.CurrentMaterial[i], args, param); + } + } + + SAVE_FLUSH_VERTICES(ctx); n = ALLOC_INSTRUCTION(ctx, OPCODE_MATERIAL, 6); if (n) { @@ -5191,19 +5227,6 @@ save_Materialfv(GLenum face, GLenum pname, const GLfloat * param) for (i = 0; i < args; i++) n[3 + i].f = param[i]; } - - { - GLuint bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, NULL); - for (i = 0; i < MAT_ATTRIB_MAX; i++) - if (bitmask & (1 << i)) { - ctx->ListState.ActiveMaterialSize[i] = args; - COPY_SZ_4V(ctx->ListState.CurrentMaterial[i], args, param); - } - } - - if (ctx->ExecuteFlag) { - CALL_Materialfv(ctx->Exec, (face, pname, param)); - } } static void GLAPIENTRY @@ -6812,6 +6835,8 @@ _mesa_NewList(GLuint name, GLenum mode) 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; ctx->Driver.NewList(ctx, name, mode); diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 84a082b253..bdaa4977b7 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; }; -- cgit v1.2.3