glthread: track instance divisor changes
[mesa.git] / src / mesa / main / glthread_varray.c
index d246d2d4253b936f2765a21024803e5421e285f3..bcbd229320b2dd9bb448387d63eace56ca4e8793 100644 (file)
  */
 
 #include "main/glthread.h"
+#include "main/glformats.h"
 #include "main/mtypes.h"
 #include "main/hash.h"
 #include "main/dispatch.h"
 
 /* TODO:
- *   - Implement better tracking of user pointers
- *   - These can unbind user pointers:
- *       ARB_vertex_attrib_binding
- *       ARB_direct_state_access
- *       EXT_direct_state_access
+ *   - Handle ARB_vertex_attrib_binding (incl. EXT_dsa and ARB_dsa)
  */
 
 static struct glthread_vao *
@@ -124,21 +121,106 @@ _mesa_glthread_GenVertexArrays(struct gl_context *ctx,
       GLuint id = arrays[i];
       struct glthread_vao *vao;
 
-      vao = malloc(sizeof(*vao));
+      vao = calloc(1, sizeof(*vao));
       if (!vao)
          continue; /* Is that all we can do? */
 
       vao->Name = id;
-      vao->HasUserPointer = false;
       _mesa_HashInsertLocked(glthread->VAOs, id, vao);
    }
 }
 
+/* If vaobj is NULL, use the currently-bound VAO. */
+static inline struct glthread_vao *
+get_vao(struct gl_context *ctx, const GLuint *vaobj)
+{
+   if (vaobj)
+      return lookup_vao(ctx, *vaobj);
+
+   return ctx->GLThread.CurrentVAO;
+}
+
+void
+_mesa_glthread_ClientState(struct gl_context *ctx, GLuint *vaobj,
+                           gl_vert_attrib attrib, bool enable)
+{
+   if (attrib >= VERT_ATTRIB_MAX)
+      return;
+
+   struct glthread_vao *vao = get_vao(ctx, vaobj);
+   if (!vao)
+      return;
+
+   if (enable)
+      vao->Enabled |= 1u << attrib;
+   else
+      vao->Enabled &= ~(1u << attrib);
+}
+
+void _mesa_glthread_AttribDivisor(struct gl_context *ctx, const GLuint *vaobj,
+                                  gl_vert_attrib attrib, GLuint divisor)
+{
+   if (attrib >= VERT_ATTRIB_MAX)
+      return;
+
+   struct glthread_vao *vao = get_vao(ctx, vaobj);
+   if (!vao)
+      return;
+
+   vao->Attrib[attrib].Divisor = divisor;
+
+   if (divisor)
+      vao->NonZeroDivisorMask |= 1u << attrib;
+   else
+      vao->NonZeroDivisorMask &= ~(1u << attrib);
+}
+
+static void
+attrib_pointer(struct glthread_state *glthread, struct glthread_vao *vao,
+               GLuint buffer, gl_vert_attrib attrib,
+               GLint size, GLenum type, GLsizei stride,
+               const void *pointer)
+{
+   if (attrib >= VERT_ATTRIB_MAX)
+      return;
+
+   unsigned elem_size = _mesa_bytes_per_vertex_attrib(size, type);
+
+   vao->Attrib[attrib].ElementSize = elem_size;
+   vao->Attrib[attrib].Stride = stride ? stride : elem_size;
+   vao->Attrib[attrib].Pointer = pointer;
+
+   if (buffer != 0)
+      vao->UserPointerMask &= ~(1u << attrib);
+   else
+      vao->UserPointerMask |= 1u << attrib;
+}
+
 void
-_mesa_glthread_AttribPointer(struct gl_context *ctx)
+_mesa_glthread_AttribPointer(struct gl_context *ctx, gl_vert_attrib attrib,
+                             GLint size, GLenum type, GLsizei stride,
+                             const void *pointer)
 {
    struct glthread_state *glthread = &ctx->GLThread;
 
-   if (!glthread->vertex_array_is_vbo)
-      glthread->CurrentVAO->HasUserPointer = true;
+   attrib_pointer(glthread, glthread->CurrentVAO,
+                  glthread->CurrentArrayBufferName,
+                  attrib, size, type, stride, pointer);
+}
+
+void
+_mesa_glthread_DSAAttribPointer(struct gl_context *ctx, GLuint vaobj,
+                                GLuint buffer, gl_vert_attrib attrib,
+                                GLint size, GLenum type, GLsizei stride,
+                                GLintptr offset)
+{
+   struct glthread_state *glthread = &ctx->GLThread;
+   struct glthread_vao *vao;
+
+   vao = lookup_vao(ctx, vaobj);
+   if (!vao)
+      return;
+
+   attrib_pointer(glthread, vao, buffer, attrib, size, type, stride,
+                  (const void*)offset);
 }