Mesa (mesa_7_5_branch): mesa/dlist: shortcircuit some redundant statechanges at compile time

Keith Whitwell keithw at kemper.freedesktop.org
Thu Jul 2 12:31:52 UTC 2009


Module: Mesa
Branch: mesa_7_5_branch
Commit: 47173cf67f0ed55012b0820397f6d620d8ad4473
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=47173cf67f0ed55012b0820397f6d620d8ad4473

Author: Keith Whitwell <keithw at vmware.com>
Date:   Tue Jun 30 09:55:33 2009 +0100

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(-)

diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index 782f847..3647401 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 84a082b..bdaa497 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;
 };
 
 




More information about the mesa-commit mailing list