glthread: track instance divisor changes
[mesa.git] / src / mesa / main / glthread_varray.c
index 9e45aa287554be2201be067b3052747df92e4311..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 *
@@ -133,23 +130,26 @@ _mesa_glthread_GenVertexArrays(struct gl_context *ctx,
    }
 }
 
+/* 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)
 {
-   struct glthread_state *glthread = &ctx->GLThread;
-   struct glthread_vao *vao;
-
    if (attrib >= VERT_ATTRIB_MAX)
       return;
 
-   if (vaobj) {
-      vao = lookup_vao(ctx, *vaobj);
-      if (!vao)
-         return;
-   } else {
-      vao = glthread->CurrentVAO;
-   }
+   struct glthread_vao *vao = get_vao(ctx, vaobj);
+   if (!vao)
+      return;
 
    if (enable)
       vao->Enabled |= 1u << attrib;
@@ -157,11 +157,70 @@ _mesa_glthread_ClientState(struct gl_context *ctx, GLuint *vaobj,
       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->CurrentArrayBufferName == 0)
-      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);
 }