Mesa (master): mesa: optimize glCallLists by using loops inside a switch

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Thu Jan 21 00:30:50 UTC 2021


Module: Mesa
Branch: master
Commit: 8e825dac4298a622e9ebb8b43fb33fd76e8842b0
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=8e825dac4298a622e9ebb8b43fb33fd76e8842b0

Author: Marek Olšák <marek.olsak at amd.com>
Date:   Wed Dec 23 14:06:02 2020 -0500

mesa: optimize glCallLists by using loops inside a switch

This changes glCallLists from using a switch inside a loop to using loops
inside a switch.

Also fix the comments that didn't tell WHY something was important.

Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer at amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8297>

---

 src/mesa/main/dlist.c | 160 +++++++++++++++++++++++++-------------------------
 1 file changed, 81 insertions(+), 79 deletions(-)

diff --git a/src/mesa/main/dlist.c b/src/mesa/main/dlist.c
index 1c720508e0c..64d470b9a5e 100644
--- a/src/mesa/main/dlist.c
+++ b/src/mesa/main/dlist.c
@@ -1458,63 +1458,6 @@ destroy_list(struct gl_context *ctx, GLuint list)
 }
 
 
-/*
- * Translate the nth element of list from <type> to GLint.
- */
-static GLint
-translate_id(GLsizei n, GLenum type, const GLvoid * list)
-{
-   GLbyte *bptr;
-   GLubyte *ubptr;
-   GLshort *sptr;
-   GLushort *usptr;
-   GLint *iptr;
-   GLuint *uiptr;
-   GLfloat *fptr;
-
-   switch (type) {
-   case GL_BYTE:
-      bptr = (GLbyte *) list;
-      return (GLint) bptr[n];
-   case GL_UNSIGNED_BYTE:
-      ubptr = (GLubyte *) list;
-      return (GLint) ubptr[n];
-   case GL_SHORT:
-      sptr = (GLshort *) list;
-      return (GLint) sptr[n];
-   case GL_UNSIGNED_SHORT:
-      usptr = (GLushort *) list;
-      return (GLint) usptr[n];
-   case GL_INT:
-      iptr = (GLint *) list;
-      return iptr[n];
-   case GL_UNSIGNED_INT:
-      uiptr = (GLuint *) list;
-      return (GLint) uiptr[n];
-   case GL_FLOAT:
-      fptr = (GLfloat *) list;
-      return (GLint) floorf(fptr[n]);
-   case GL_2_BYTES:
-      ubptr = ((GLubyte *) list) + 2 * n;
-      return (GLint) ubptr[0] * 256
-           + (GLint) ubptr[1];
-   case GL_3_BYTES:
-      ubptr = ((GLubyte *) list) + 3 * n;
-      return (GLint) ubptr[0] * 65536
-           + (GLint) ubptr[1] * 256
-           + (GLint) ubptr[2];
-   case GL_4_BYTES:
-      ubptr = ((GLubyte *) list) + 4 * n;
-      return (GLint) ubptr[0] * 16777216
-           + (GLint) ubptr[1] * 65536
-           + (GLint) ubptr[2] * 256
-           + (GLint) ubptr[3];
-   default:
-      return 0;
-   }
-}
-
-
 /**
  * Wrapper for _mesa_unpack_image/bitmap() that handles pixel buffer objects.
  * If width < 0 or height < 0 or format or type are invalid we'll just
@@ -13786,8 +13729,9 @@ _mesa_CallList(GLuint list)
    if (0)
       mesa_print_display_list( list );
 
-   /* VERY IMPORTANT:  Save the CompileFlag status, turn it off,
-    * execute the display list, and restore the CompileFlag.
+   /* Save the CompileFlag status, turn it off, execute the display list,
+    * and restore the CompileFlag. This is needed for GL_COMPILE_AND_EXECUTE
+    * because the call is already recorded and we just need to execute it.
     */
    save_compile_flag = ctx->CompileFlag;
    if (save_compile_flag) {
@@ -13874,26 +13818,12 @@ void GLAPIENTRY
 _mesa_CallLists(GLsizei n, GLenum type, const GLvoid * lists)
 {
    GET_CURRENT_CONTEXT(ctx);
-   GLint i;
    GLboolean save_compile_flag;
 
    if (MESA_VERBOSE & VERBOSE_API)
       _mesa_debug(ctx, "glCallLists %d\n", n);
 
-   switch (type) {
-   case GL_BYTE:
-   case GL_UNSIGNED_BYTE:
-   case GL_SHORT:
-   case GL_UNSIGNED_SHORT:
-   case GL_INT:
-   case GL_UNSIGNED_INT:
-   case GL_FLOAT:
-   case GL_2_BYTES:
-   case GL_3_BYTES:
-   case GL_4_BYTES:
-      /* OK */
-      break;
-   default:
+   if (type < GL_BYTE || type > GL_4_BYTES) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glCallLists(type)");
       return;
    }
@@ -13910,15 +13840,87 @@ _mesa_CallLists(GLsizei n, GLenum type, const GLvoid * lists)
       return;
    }
 
-   /* Save the CompileFlag status, turn it off, execute display list,
-    * and restore the CompileFlag.
+   /* Save the CompileFlag status, turn it off, execute the display lists,
+    * and restore the CompileFlag. This is needed for GL_COMPILE_AND_EXECUTE
+    * because the call is already recorded and we just need to execute it.
     */
    save_compile_flag = ctx->CompileFlag;
    ctx->CompileFlag = GL_FALSE;
 
-   for (i = 0; i < n; i++) {
-      GLuint list = (GLuint) (ctx->List.ListBase + translate_id(i, type, lists));
-      execute_list(ctx, list);
+   GLbyte *bptr;
+   GLubyte *ubptr;
+   GLshort *sptr;
+   GLushort *usptr;
+   GLint *iptr;
+   GLuint *uiptr;
+   GLfloat *fptr;
+
+   GLuint base = ctx->List.ListBase;
+
+   /* A loop inside a switch is faster than a switch inside a loop. */
+   switch (type) {
+   case GL_BYTE:
+      bptr = (GLbyte *) lists;
+      for (unsigned i = 0; i < n; i++)
+         execute_list(ctx, base + (int)bptr[i]);
+      break;
+   case GL_UNSIGNED_BYTE:
+      ubptr = (GLubyte *) lists;
+      for (unsigned i = 0; i < n; i++)
+         execute_list(ctx, base + (int)ubptr[i]);
+      break;
+   case GL_SHORT:
+      sptr = (GLshort *) lists;
+      for (unsigned i = 0; i < n; i++)
+         execute_list(ctx, base + (int)sptr[i]);
+      break;
+   case GL_UNSIGNED_SHORT:
+      usptr = (GLushort *) lists;
+      for (unsigned i = 0; i < n; i++)
+         execute_list(ctx, base + (int)usptr[i]);
+      break;
+   case GL_INT:
+      iptr = (GLint *) lists;
+      for (unsigned i = 0; i < n; i++)
+         execute_list(ctx, base + (int)iptr[i]);
+      break;
+   case GL_UNSIGNED_INT:
+      uiptr = (GLuint *) lists;
+      for (unsigned i = 0; i < n; i++)
+         execute_list(ctx, base + (int)uiptr[i]);
+      break;
+   case GL_FLOAT:
+      fptr = (GLfloat *) lists;
+      for (unsigned i = 0; i < n; i++)
+         execute_list(ctx, base + (int)fptr[i]);
+      break;
+   case GL_2_BYTES:
+      ubptr = (GLubyte *) lists;
+      for (unsigned i = 0; i < n; i++) {
+         execute_list(ctx, base +
+                      (int)ubptr[2 * i] * 256 +
+                      (int)ubptr[2 * i + 1]);
+      }
+      break;
+   case GL_3_BYTES:
+      ubptr = (GLubyte *) lists;
+      for (unsigned i = 0; i < n; i++) {
+         execute_list(ctx, base +
+                      (int)ubptr[3 * i] * 65536 +
+                      (int)ubptr[3 * i + 1] * 256 +
+                      (int)ubptr[3 * i + 2]);
+      }
+      break;
+   case GL_4_BYTES:
+      ubptr = (GLubyte *) lists;
+      for (unsigned i = 0; i < n; i++) {
+         execute_list(ctx, base +
+                      (int)ubptr[4 * i] * 16777216 +
+                      (int)ubptr[4 * i + 1] * 65536 +
+                      (int)ubptr[4 * i + 2] * 256 +
+                      (int)ubptr[4 * i + 3]);
+      }
+      break;
    }
 
    ctx->CompileFlag = save_compile_flag;



More information about the mesa-commit mailing list