mesa: Use SATURATE
[mesa.git] / src / mesa / main / glthread_varray.c
index 8049a9d2ff1f6a59d1b547eaa398f7a0742d5dc0..8fae4af3123c39353c1cee8248434eca81a48c7f 100644 (file)
  */
 
 #include "main/glthread.h"
+#include "main/glformats.h"
 #include "main/mtypes.h"
 #include "main/hash.h"
 #include "main/dispatch.h"
+#include "main/varray.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)
  */
 
+void
+_mesa_glthread_reset_vao(struct glthread_vao *vao)
+{
+   static unsigned default_elem_size[VERT_ATTRIB_MAX] = {
+      [VERT_ATTRIB_NORMAL] = 12,
+      [VERT_ATTRIB_COLOR1] = 12,
+      [VERT_ATTRIB_FOG] = 4,
+      [VERT_ATTRIB_COLOR_INDEX] = 4,
+      [VERT_ATTRIB_EDGEFLAG] = 1,
+      [VERT_ATTRIB_POINT_SIZE] = 4,
+   };
+
+   vao->CurrentElementBufferName = 0;
+   vao->UserEnabled = 0;
+   vao->Enabled = 0;
+   vao->UserPointerMask = 0;
+   vao->NonZeroDivisorMask = 0;
+
+   for (unsigned i = 0; i < ARRAY_SIZE(vao->Attrib); i++) {
+      unsigned elem_size = default_elem_size[i];
+      if (!elem_size)
+         elem_size = 16;
+
+      vao->Attrib[i].ElementSize = elem_size;
+      vao->Attrib[i].Stride = elem_size;
+      vao->Attrib[i].Divisor = 0;
+      vao->Attrib[i].Pointer = NULL;
+   }
+}
+
 static struct glthread_vao *
 lookup_vao(struct gl_context *ctx, GLuint id)
 {
@@ -129,15 +157,240 @@ _mesa_glthread_GenVertexArrays(struct gl_context *ctx,
          continue; /* Is that all we can do? */
 
       vao->Name = id;
+      _mesa_glthread_reset_vao(vao);
       _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;
+}
+
+static void
+update_primitive_restart(struct gl_context *ctx)
+{
+   struct glthread_state *glthread = &ctx->GLThread;
+
+   glthread->_PrimitiveRestart = glthread->PrimitiveRestart ||
+                                 glthread->PrimitiveRestartFixedIndex;
+   glthread->_RestartIndex[0] =
+      _mesa_get_prim_restart_index(glthread->PrimitiveRestartFixedIndex,
+                                   glthread->RestartIndex, 1);
+   glthread->_RestartIndex[1] =
+      _mesa_get_prim_restart_index(glthread->PrimitiveRestartFixedIndex,
+                                   glthread->RestartIndex, 2);
+   glthread->_RestartIndex[3] =
+      _mesa_get_prim_restart_index(glthread->PrimitiveRestartFixedIndex,
+                                   glthread->RestartIndex, 4);
+}
+
+void
+_mesa_glthread_set_prim_restart(struct gl_context *ctx, GLenum cap, bool value)
+{
+   switch (cap) {
+   case GL_PRIMITIVE_RESTART:
+      ctx->GLThread.PrimitiveRestart = value;
+      break;
+   case GL_PRIMITIVE_RESTART_FIXED_INDEX:
+      ctx->GLThread.PrimitiveRestartFixedIndex = value;
+      break;
+   }
+
+   update_primitive_restart(ctx);
+}
+
 void
-_mesa_glthread_AttribPointer(struct gl_context *ctx)
+_mesa_glthread_PrimitiveRestartIndex(struct gl_context *ctx, GLuint index)
+{
+   ctx->GLThread.RestartIndex = index;
+   update_primitive_restart(ctx);
+}
+
+void
+_mesa_glthread_ClientState(struct gl_context *ctx, GLuint *vaobj,
+                           gl_vert_attrib attrib, bool enable)
+{
+   /* The primitive restart client state uses a special value. */
+   if (attrib == VERT_ATTRIB_PRIMITIVE_RESTART_NV) {
+      ctx->GLThread.PrimitiveRestart = enable;
+      update_primitive_restart(ctx);
+      return;
+   }
+
+   if (attrib >= VERT_ATTRIB_MAX)
+      return;
+
+   struct glthread_vao *vao = get_vao(ctx, vaobj);
+   if (!vao)
+      return;
+
+   if (enable)
+      vao->UserEnabled |= 1u << attrib;
+   else
+      vao->UserEnabled &= ~(1u << attrib);
+
+   /* The generic0 attribute superseeds the position attribute */
+   vao->Enabled = vao->UserEnabled;
+   if (vao->Enabled & VERT_BIT_GENERIC0)
+      vao->Enabled &= ~VERT_BIT_POS;
+}
+
+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, gl_vert_attrib attrib,
+                             GLint size, GLenum type, GLsizei stride,
+                             const void *pointer)
+{
+   struct glthread_state *glthread = &ctx->GLThread;
+
+   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);
+}
+
+void
+_mesa_glthread_PushClientAttrib(struct gl_context *ctx, GLbitfield mask,
+                                bool set_default)
+{
+   struct glthread_state *glthread = &ctx->GLThread;
+
+   if (glthread->ClientAttribStackTop >= MAX_CLIENT_ATTRIB_STACK_DEPTH)
+      return;
+
+   struct glthread_client_attrib *top =
+      &glthread->ClientAttribStack[glthread->ClientAttribStackTop];
+
+   if (mask & GL_CLIENT_VERTEX_ARRAY_BIT) {
+      top->VAO = *glthread->CurrentVAO;
+      top->CurrentArrayBufferName = glthread->CurrentArrayBufferName;
+      top->ClientActiveTexture = glthread->ClientActiveTexture;
+      top->RestartIndex = glthread->RestartIndex;
+      top->PrimitiveRestart = glthread->PrimitiveRestart;
+      top->PrimitiveRestartFixedIndex = glthread->PrimitiveRestartFixedIndex;
+      top->Valid = true;
+   } else {
+      top->Valid = false;
+   }
+
+   glthread->ClientAttribStackTop++;
+
+   if (set_default)
+      _mesa_glthread_ClientAttribDefault(ctx, mask);
+}
+
+void
+_mesa_glthread_PopClientAttrib(struct gl_context *ctx)
 {
    struct glthread_state *glthread = &ctx->GLThread;
 
-   if (glthread->CurrentArrayBufferName == 0)
-      glthread->CurrentVAO->HasUserPointer = true;
+   if (glthread->ClientAttribStackTop == 0)
+      return;
+
+   glthread->ClientAttribStackTop--;
+
+   struct glthread_client_attrib *top =
+      &glthread->ClientAttribStack[glthread->ClientAttribStackTop];
+
+   if (!top->Valid)
+      return;
+
+   /* Popping a delete VAO is an error. */
+   struct glthread_vao *vao = NULL;
+   if (top->VAO.Name) {
+      vao = lookup_vao(ctx, top->VAO.Name);
+      if (!vao)
+         return;
+   }
+
+   /* Restore states. */
+   glthread->CurrentArrayBufferName = top->CurrentArrayBufferName;
+   glthread->ClientActiveTexture = top->ClientActiveTexture;
+   glthread->RestartIndex = top->RestartIndex;
+   glthread->PrimitiveRestart = top->PrimitiveRestart;
+   glthread->PrimitiveRestartFixedIndex = top->PrimitiveRestartFixedIndex;
+
+   if (!vao)
+      vao = &glthread->DefaultVAO;
+
+   assert(top->VAO.Name == vao->Name);
+   *vao = top->VAO; /* Copy all fields. */
+   glthread->CurrentVAO = vao;
+}
+
+void
+_mesa_glthread_ClientAttribDefault(struct gl_context *ctx, GLbitfield mask)
+{
+   struct glthread_state *glthread = &ctx->GLThread;
+
+   if (!(mask & GL_CLIENT_VERTEX_ARRAY_BIT))
+      return;
+
+   glthread->CurrentArrayBufferName = 0;
+   glthread->ClientActiveTexture = 0;
+   glthread->RestartIndex = 0;
+   glthread->PrimitiveRestart = false;
+   glthread->PrimitiveRestartFixedIndex = false;
+   glthread->CurrentVAO = &glthread->DefaultVAO;
+   _mesa_glthread_reset_vao(glthread->CurrentVAO);
 }