summaryrefslogtreecommitdiff
path: root/src/mesa/main/dlist.c
diff options
context:
space:
mode:
authorKeith Whitwell <keithw@vmware.com>2009-06-30 09:55:33 +0100
committerKeith Whitwell <keithw@vmware.com>2009-06-30 09:55:33 +0100
commit47173cf67f0ed55012b0820397f6d620d8ad4473 (patch)
tree802b6513d708298290d8e0655fcd30a69ecea863 /src/mesa/main/dlist.c
parent9014f475ff6720b694ba28906ebfe7e77795b173 (diff)
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.
Diffstat (limited to 'src/mesa/main/dlist.c')
-rw-r--r--src/mesa/main/dlist.c63
1 files changed, 44 insertions, 19 deletions
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);