dlist: use a separate opcode for vbo replay using loopback
authorPierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Wed, 16 Jun 2021 08:30:11 +0000 (10:30 +0200)
committerMarge Bot <eric+marge@anholt.net>
Fri, 9 Jul 2021 10:05:46 +0000 (10:05 +0000)
Remember is the current list needs to fallback to loopback,
and patch the list in glEndList.

Reviewed-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11493>

src/mesa/main/dlist.c
src/mesa/main/mtypes.h
src/mesa/vbo/vbo.h
src/mesa/vbo/vbo_save.h
src/mesa/vbo/vbo_save_api.c
src/mesa/vbo/vbo_save_draw.c

index 9d961d2..2971a56 100644 (file)
@@ -627,6 +627,7 @@ typedef enum
    OPCODE_NAMED_PROGRAM_LOCAL_PARAMETER,
 
    OPCODE_VERTEX_LIST,
+   OPCODE_VERTEX_LIST_LOOPBACK,
 
    /* The following three are meta instructions */
    OPCODE_ERROR,                /* raise compiled-in error */
@@ -813,15 +814,20 @@ vbo_destroy_vertex_list(struct gl_context *ctx, struct vbo_save_vertex_list *nod
 }
 
 static void
-vbo_print_vertex_list(struct gl_context *ctx, struct vbo_save_vertex_list *node, FILE *f)
+vbo_print_vertex_list(struct gl_context *ctx, struct vbo_save_vertex_list *node, OpCode op, FILE *f)
 {
    GLuint i;
    struct gl_buffer_object *buffer = node->VAO[0]->BufferBinding[0].BufferObj;
    const GLuint vertex_size = _vbo_save_get_stride(node)/sizeof(GLfloat);
    (void) ctx;
 
-   fprintf(f, "VBO-VERTEX-LIST, %u vertices, %d primitives, %d vertsize, "
+   const char *label[] = {
+      "VBO-VERTEX-LIST", "VBO-VERTEX-LIST-LOOPBACK"
+   };
+
+   fprintf(f, "%s, %u vertices, %d primitives, %d vertsize, "
            "buffer %p\n",
+           label[op - OPCODE_VERTEX_LIST],
            node->cold->vertex_count, node->cold->prim_count, vertex_size,
            buffer);
 
@@ -1356,6 +1362,7 @@ _mesa_delete_list(struct gl_context *ctx, struct gl_display_list *dlist)
             free(get_pointer(&n[5]));
             break;
          case OPCODE_VERTEX_LIST:
+         case OPCODE_VERTEX_LIST_LOOPBACK:
             vbo_destroy_vertex_list(ctx, (struct vbo_save_vertex_list *) &n[1]);
             break;
          case OPCODE_CONTINUE:
@@ -2056,7 +2063,10 @@ invalidate_saved_current_state(struct gl_context *ctx)
    for (i = 0; i < MAT_ATTRIB_MAX; i++)
       ctx->ListState.ActiveMaterialSize[i] = 0;
 
+   /* Loopback usage applies recursively, so remember this state */
+   bool use_loopback = ctx->ListState.Current.UseLoopback;
    memset(&ctx->ListState.Current, 0, sizeof ctx->ListState.Current);
+   ctx->ListState.Current.UseLoopback = use_loopback;
 
    ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
 }
@@ -11226,8 +11236,6 @@ execute_list(struct gl_context *ctx, GLuint list)
 
    ctx->ListState.CallDepth++;
 
-   vbo_save_BeginCallList(ctx, dlist);
-
    n = dlist->Head;
 
    while (1) {
@@ -13407,6 +13415,10 @@ execute_list(struct gl_context *ctx, GLuint list)
             vbo_save_playback_vertex_list(ctx, &n[1]);
             break;
 
+         case OPCODE_VERTEX_LIST_LOOPBACK:
+            vbo_save_playback_vertex_list_loopback(ctx, &n[1]);
+            break;
+
          case OPCODE_CONTINUE:
             n = (Node *) get_pointer(&n[1]);
             continue;
@@ -13422,7 +13434,6 @@ execute_list(struct gl_context *ctx, GLuint list)
             }
             FALLTHROUGH;
          case OPCODE_END_OF_LIST:
-            vbo_save_EndCallList(ctx);
             ctx->ListState.CallDepth--;
             return;
       }
@@ -13585,6 +13596,7 @@ _mesa_NewList(GLuint name, GLenum mode)
    ctx->ListState.CurrentList = make_list(name, BLOCK_SIZE);
    ctx->ListState.CurrentBlock = ctx->ListState.CurrentList->Head;
    ctx->ListState.CurrentPos = 0;
+   ctx->ListState.Current.UseLoopback = false;
 
    vbo_save_NewList(ctx, name, mode);
 
@@ -13597,6 +13609,110 @@ _mesa_NewList(GLuint name, GLenum mode)
 
 
 /**
+ * Walk all the opcode from a given list, recursively if OPCODE_CALL_LIST(S) is used,
+ * and replace OPCODE_VERTEX_LIST[_COPY_CURRENT] occurences by OPCODE_VERTEX_LIST_LOOPBACK.
+ */
+static void
+replace_op_vertex_list_recursively(struct gl_context *ctx, struct gl_display_list *dlist)
+{
+   Node *n = dlist->Head;
+   while (true) {
+      const OpCode opcode = n[0].opcode;
+      switch (opcode) {
+         case OPCODE_VERTEX_LIST:
+            n[0].opcode = OPCODE_VERTEX_LIST_LOOPBACK;
+            break;
+         case OPCODE_CONTINUE:
+            n = (Node *)get_pointer(&n[1]);
+            continue;
+         case OPCODE_CALL_LIST:
+            replace_op_vertex_list_recursively(ctx, _mesa_lookup_list(ctx, (int)n[1].ui, true));
+            break;
+         case OPCODE_CALL_LISTS: {
+            GLbyte *bptr;
+            GLubyte *ubptr;
+            GLshort *sptr;
+            GLushort *usptr;
+            GLint *iptr;
+            GLuint *uiptr;
+            GLfloat *fptr;
+            switch(n[2].e) {
+               case GL_BYTE:
+                  bptr = (GLbyte *) get_pointer(&n[3]);
+                  for (unsigned i = 0; i < n[1].i; i++)
+                     replace_op_vertex_list_recursively(ctx, _mesa_lookup_list(ctx, (int)bptr[i], true));
+                  break;
+               case GL_UNSIGNED_BYTE:
+                  ubptr = (GLubyte *) get_pointer(&n[3]);
+                  for (unsigned i = 0; i < n[1].i; i++)
+                     replace_op_vertex_list_recursively(ctx, _mesa_lookup_list(ctx, (int)ubptr[i], true));
+                  break;
+               case GL_SHORT:
+                  sptr = (GLshort *) get_pointer(&n[3]);
+                  for (unsigned i = 0; i < n[1].i; i++)
+                     replace_op_vertex_list_recursively(ctx, _mesa_lookup_list(ctx, (int)sptr[i], true));
+                  break;
+               case GL_UNSIGNED_SHORT:
+                  usptr = (GLushort *) get_pointer(&n[3]);
+                  for (unsigned i = 0; i < n[1].i; i++)
+                     replace_op_vertex_list_recursively(ctx, _mesa_lookup_list(ctx, (int)usptr[i], true));
+                  break;
+               case GL_INT:
+                  iptr = (GLint *) get_pointer(&n[3]);
+                  for (unsigned i = 0; i < n[1].i; i++)
+                     replace_op_vertex_list_recursively(ctx, _mesa_lookup_list(ctx, (int)iptr[i], true));
+                  break;
+               case GL_UNSIGNED_INT:
+                  uiptr = (GLuint *) get_pointer(&n[3]);
+                  for (unsigned i = 0; i < n[1].i; i++)
+                     replace_op_vertex_list_recursively(ctx, _mesa_lookup_list(ctx, (int)uiptr[i], true));
+                  break;
+               case GL_FLOAT:
+                  fptr = (GLfloat *) get_pointer(&n[3]);
+                  for (unsigned i = 0; i < n[1].i; i++)
+                     replace_op_vertex_list_recursively(ctx, _mesa_lookup_list(ctx, (int)fptr[i], true));
+                  break;
+               case GL_2_BYTES:
+                  ubptr = (GLubyte *) get_pointer(&n[3]);
+                  for (unsigned i = 0; i < n[1].i; i++) {
+                     replace_op_vertex_list_recursively(ctx,
+                                                _mesa_lookup_list(ctx, (int)ubptr[2 * i] * 256 +
+                                                                       (int)ubptr[2 * i + 1], true));
+                  }
+                  break;
+               case GL_3_BYTES:
+                  ubptr = (GLubyte *) get_pointer(&n[3]);
+                  for (unsigned i = 0; i < n[1].i; i++) {
+                     replace_op_vertex_list_recursively(ctx,
+                                                _mesa_lookup_list(ctx, (int)ubptr[3 * i] * 65536 +
+                                                                  (int)ubptr[3 * i + 1] * 256 +
+                                                                  (int)ubptr[3 * i + 2], true));
+                  }
+                  break;
+               case GL_4_BYTES:
+                  ubptr = (GLubyte *) get_pointer(&n[3]);
+                  for (unsigned i = 0; i < n[1].i; i++) {
+                     replace_op_vertex_list_recursively(ctx,
+                                                _mesa_lookup_list(ctx, (int)ubptr[4 * i] * 16777216 +
+                                                                  (int)ubptr[4 * i + 1] * 65536 +
+                                                                  (int)ubptr[4 * i + 2] * 256 +
+                                                                  (int)ubptr[4 * i + 3], true));
+                  }
+                  break;
+               }
+            break;
+         }
+         case OPCODE_END_OF_LIST:
+            return;
+         default:
+            break;
+      }
+      n += n[0].InstSize;
+   }
+}
+
+
+/**
  * End definition of current display list.
  */
 void GLAPIENTRY
@@ -13627,6 +13743,12 @@ _mesa_EndList(void)
 
    (void) alloc_instruction(ctx, OPCODE_END_OF_LIST, 0);
 
+   if (ctx->ListState.Current.UseLoopback) {
+      _mesa_HashLockMutex(ctx->Shared->DisplayList);
+      replace_op_vertex_list_recursively(ctx, ctx->ListState.CurrentList);
+      _mesa_HashUnlockMutex(ctx->Shared->DisplayList);
+   }
+
    trim_list(ctx);
 
    /* Destroy old list, if any */
@@ -14833,7 +14955,8 @@ print_list(struct gl_context *ctx, GLuint list, const char *fname)
             fprintf(f, "NOP\n");
             break;
          case OPCODE_VERTEX_LIST:
-            vbo_print_vertex_list(ctx, (struct vbo_save_vertex_list *) &n[1], f);
+         case OPCODE_VERTEX_LIST_LOOPBACK:
+            vbo_print_vertex_list(ctx, (struct vbo_save_vertex_list *) &n[1], opcode, f);
             break;
          default:
             if (opcode < 0 || opcode > OPCODE_END_OF_LIST) {
index ad59701..dab8d62 100644 (file)
@@ -4695,7 +4695,6 @@ union gl_dlist_node;
 struct gl_display_list
 {
    GLuint Name;
-   GLbitfield Flags;  /**< DLIST_x flags */
    GLchar *Label;     /**< GL_KHR_debug */
    /** The dlist commands are in a linked list of nodes */
    union gl_dlist_node *Head;
@@ -4725,6 +4724,7 @@ struct gl_dlist_state
        * list.  Used to eliminate some redundant state changes.
        */
       GLenum16 ShadeModel;
+      bool UseLoopback;
    } Current;
 };
 
index efad2d8..784af43 100644 (file)
@@ -169,8 +169,6 @@ struct vbo_save_context {
 
    GLboolean out_of_memory;  /**< True if last VBO allocation failed */
 
-   GLbitfield replay_flags;
-
    struct _mesa_prim *prims;
    GLuint prim_count, prim_max;
 
@@ -232,13 +230,6 @@ void
 vbo_save_EndList(struct gl_context *ctx);
 
 void
-vbo_save_BeginCallList(struct gl_context *ctx, struct gl_display_list *list);
-
-void
-vbo_save_EndCallList(struct gl_context *ctx);
-
-
-void
 vbo_delete_minmax_cache(struct gl_buffer_object *bufferObj);
 
 void
index a517376..aa37942 100644 (file)
@@ -178,6 +178,9 @@ void
 vbo_save_playback_vertex_list(struct gl_context *ctx, void *data);
 
 void
+vbo_save_playback_vertex_list_loopback(struct gl_context *ctx, void *data);
+
+void
 vbo_save_api_init(struct vbo_save_context *save);
 
 fi_type *
index 555bb43..58d3e34 100644 (file)
@@ -94,12 +94,6 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #undef ERROR
 #endif
 
-/**
- * Display list flag only used by this VBO code.
- */
-#define DLIST_DANGLING_REFS     0x1
-
-
 /* An interesting VBO number/name to help with debugging */
 #define VBO_BUF_ID  12345
 
@@ -626,7 +620,7 @@ compile_vertex_list(struct gl_context *ctx)
    assert(save->attrsz[VBO_ATTRIB_POS] != 0 || node->cold->vertex_count == 0);
 
    if (save->dangling_attr_ref)
-      ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS;
+      ctx->ListState.Current.UseLoopback = true;
 
    save->vertex_store->used += save->vertex_size * node->cold->vertex_count;
    save->prim_store->used += node->cold->prim_count;
@@ -1932,33 +1926,6 @@ vbo_save_EndList(struct gl_context *ctx)
    assert(save->vertex_size == 0);
 }
 
-
-/**
- * Called from the display list code when we're about to execute a
- * display list.
- */
-void
-vbo_save_BeginCallList(struct gl_context *ctx, struct gl_display_list *dlist)
-{
-   struct vbo_save_context *save = &vbo_context(ctx)->save;
-   save->replay_flags |= dlist->Flags;
-}
-
-
-/**
- * Called from the display list code when we're finished executing a
- * display list.
- */
-void
-vbo_save_EndCallList(struct gl_context *ctx)
-{
-   struct vbo_save_context *save = &vbo_context(ctx)->save;
-
-   if (ctx->ListState.CallDepth == 1)
-      save->replay_flags = 0;
-}
-
-
 /**
  * Called during context creation/init.
  */
index 94ecfc0..c5bee16 100644 (file)
@@ -157,13 +157,8 @@ loopback_vertex_list(struct gl_context *ctx,
 }
 
 
-/**
- * Execute the buffer and save copied verts.
- * This is called from the display list code when executing
- * a drawing command.
- */
 void
-vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
+vbo_save_playback_vertex_list_loopback(struct gl_context *ctx, void *data)
 {
    const struct vbo_save_vertex_list *node =
       (const struct vbo_save_vertex_list *) data;
@@ -193,13 +188,37 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
                   "draw operation inside glBegin/End");
       goto end;
    }
-   else if (save->replay_flags) {
-      /* Various degenerate cases: translate into immediate mode
-       * calls rather than trying to execute in place.
-       */
-      loopback_vertex_list(ctx, node);
+   /* Various degenerate cases: translate into immediate mode
+    * calls rather than trying to execute in place.
+    */
+   loopback_vertex_list(ctx, node);
 
-      goto end;
+end:
+   if (remap_vertex_store) {
+      save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);
+   }
+}
+
+/**
+ * Execute the buffer and save copied verts.
+ * This is called from the display list code when executing
+ * a drawing command.
+ */
+void
+vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
+{
+   const struct vbo_save_vertex_list *node =
+      (const struct vbo_save_vertex_list *) data;
+
+   FLUSH_FOR_DRAW(ctx);
+
+   if (_mesa_inside_begin_end(ctx) && node->cold->prims[0].begin) {
+      /* Error: we're about to begin a new primitive but we're already
+       * inside a glBegin/End pair.
+       */
+      _mesa_error(ctx, GL_INVALID_OPERATION,
+                  "draw operation inside glBegin/End");
+      return;
    }
 
    bind_vertex_list(ctx, node);
@@ -237,9 +256,4 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
    /* Copy to current?
     */
    playback_copy_to_current(ctx, node);
-
-end:
-   if (remap_vertex_store) {
-      save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);
-   }
 }