vbo: Pull the _mesa_set_draw_vao calls out of the if clauses.
[mesa.git] / src / mesa / vbo / vbo_save_loopback.c
index 430333b84dd002bfe88558df486882627bfd0f43..eeb4580c54ce7879705dd028bf66554362470d09 100644 (file)
@@ -1,8 +1,8 @@
 /**************************************************************************
- * 
- * Copyright 2005 Tungsten Graphics, Inc., Cedar Park, Texas.
+ *
+ * Copyright 2005 VMware, Inc.
  * All Rights Reserved.
- * 
+ *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the
  * "Software"), to deal in the Software without restriction, including
  * distribute, sub license, and/or sell copies of the Software, and to
  * permit persons to whom the Software is furnished to do so, subject to
  * the following conditions:
- * 
+ *
  * The above copyright notice and this permission notice (including the
  * next paragraph) shall be included in all copies or substantial portions
  * of the Software.
- * 
+ *
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
+ *
  **************************************************************************/
 
-#include "swrast_setup/swrast_setup.h"
-#include "swrast/swrast.h"
-#include "tnl/tnl.h"
-#include "context.h"
+#include <stdio.h>
+#include "main/context.h"
+#include "main/glheader.h"
+#include "main/enums.h"
+#include "main/imports.h"
+#include "main/dispatch.h"
+#include "glapi/glapi.h"
 
-#include "vbo_context.h"
+#include "vbo_private.h"
 
-#include "glheader.h"
-#include "enums.h"
-#include "glapi.h"
-#include "imports.h"
-#include "macros.h"
-#include "mtypes.h"
-#include "dispatch.h"
 
-
-typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * );
+typedef void (*attr_func)(struct gl_context *ctx, GLint index, const GLfloat *);
 
 
 /* This file makes heavy use of the aliasing of NV vertex attributes
  * with the legacy attributes, and also with ARB and Material
  * attributes as currently implemented.
  */
-static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+static void
+VertexAttrib1fvNV(struct gl_context *ctx, GLint index, const GLfloat *v)
 {
-   CALL_VertexAttrib1fvNV(ctx->Exec, (target, v));
+   CALL_VertexAttrib1fvNV(ctx->Exec, (index, v));
 }
 
-static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+
+static void
+VertexAttrib2fvNV(struct gl_context *ctx, GLint index, const GLfloat *v)
 {
-   CALL_VertexAttrib2fvNV(ctx->Exec, (target, v));
+   CALL_VertexAttrib2fvNV(ctx->Exec, (index, v));
 }
 
-static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+
+static void
+VertexAttrib3fvNV(struct gl_context *ctx, GLint index, const GLfloat *v)
 {
-   CALL_VertexAttrib3fvNV(ctx->Exec, (target, v));
+   CALL_VertexAttrib3fvNV(ctx->Exec, (index, v));
 }
 
-static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v)
+
+static void
+VertexAttrib4fvNV(struct gl_context *ctx, GLint index, const GLfloat *v)
 {
-   CALL_VertexAttrib4fvNV(ctx->Exec, (target, v));
+   CALL_VertexAttrib4fvNV(ctx->Exec, (index, v));
 }
 
+
 static attr_func vert_attrfunc[4] = {
    VertexAttrib1fvNV,
    VertexAttrib2fvNV,
@@ -75,59 +78,53 @@ static attr_func vert_attrfunc[4] = {
    VertexAttrib4fvNV
 };
 
+
 struct loopback_attr {
-   GLint target;
-   GLint sz;
+   enum vbo_attrib index;
+   GLuint offset;
    attr_func func;
 };
 
-/* Don't emit ends and begins on wrapped primitives.  Don't replay
- * wrapped vertices.  If we get here, it's probably because the the
+
+/**
+ * Don't emit ends and begins on wrapped primitives.  Don't replay
+ * wrapped vertices.  If we get here, it's probably because the
  * precalculated wrapping is wrong.
  */
-static void loopback_prim( GLcontext *ctx,
-                          const GLfloat *buffer,
-                          const struct _mesa_prim *prim,
-                          GLuint wrap_count,
-                          GLuint vertex_size,
-                          const struct loopback_attr *la, GLuint nr )
+static void
+loopback_prim(struct gl_context *ctx,
+              const GLubyte *buffer,
+              const struct _mesa_prim *prim,
+              GLuint wrap_count,
+              GLuint stride,
+              const struct loopback_attr *la, GLuint nr)
 {
-   GLint start = prim->start;
-   GLint end = start + prim->count;
-   const GLfloat *data;
-   GLint j;
-   GLuint k;
+   GLuint start = prim->start;
+   const GLuint end = start + prim->count;
+   const GLubyte *data;
 
    if (0)
-      _mesa_printf("loopback prim %s(%s,%s) verts %d..%d\n",
-                  _mesa_lookup_enum_by_nr(prim->mode),
-                  prim->begin ? "begin" : "..",
-                  prim->end ? "end" : "..",
-                  start, 
-                  end);
+      printf("loopback prim %s(%s,%s) verts %d..%d  vsize %d\n",
+             _mesa_lookup_prim_by_nr(prim->mode),
+             prim->begin ? "begin" : "..",
+             prim->end ? "end" : "..",
+             start, end,
+             stride);
 
    if (prim->begin) {
-      CALL_Begin(GET_DISPATCH(), ( prim->mode ));
+      CALL_Begin(GET_DISPATCH(), (prim->mode));
    }
    else {
-      assert(start == 0);
       start += wrap_count;
    }
 
-   data = buffer + start * vertex_size;
+   data = buffer + start * stride;
 
-   for (j = start ; j < end ; j++) {
-      const GLfloat *tmp = data + la[0].sz;
+   for (GLuint j = start; j < end; j++) {
+      for (GLuint k = 0; k < nr; k++)
+         la[k].func(ctx, la[k].index, (const GLfloat *)(data + la[k].offset));
 
-      for (k = 1 ; k < nr ; k++) {
-        la[k].func( ctx, la[k].target, tmp );
-        tmp += la[k].sz;
-      }
-        
-      /* Fire the vertex
-       */
-      la[0].func( ctx, VBO_ATTRIB_POS, data );
-      data = tmp;
+      data += stride;
    }
 
    if (prim->end) {
@@ -135,60 +132,77 @@ static void loopback_prim( GLcontext *ctx,
    }
 }
 
-/* Primitives generated by DrawArrays/DrawElements/Rectf may be
- * caught here.  If there is no primitive in progress, execute them
- * normally, otherwise need to track and discard the generated
- * primitives.
- */
-static void loopback_weak_prim( GLcontext *ctx,
-                               const struct _mesa_prim *prim )
+
+static inline void
+append_attr(GLuint *nr, struct loopback_attr la[], int i, int shift,
+            const struct gl_vertex_array_object *vao)
 {
-   /* Use the prim_weak flag to ensure that if this primitive
-    * wraps, we don't mistake future vertex_lists for part of the
-    * surrounding primitive.
-    *
-    * While this flag is set, we are simply disposing of data
-    * generated by an operation now known to be a noop.
-    */
-   if (prim->begin)
-      ctx->Driver.CurrentExecPrimitive |= VBO_SAVE_PRIM_WEAK;
-   if (prim->end)
-      ctx->Driver.CurrentExecPrimitive &= ~VBO_SAVE_PRIM_WEAK;
+   la[*nr].index = shift + i;
+   la[*nr].offset = vao->VertexAttrib[i].RelativeOffset;
+   la[*nr].func = vert_attrfunc[vao->VertexAttrib[i].Size - 1];
+   (*nr)++;
 }
 
 
-void vbo_loopback_vertex_list( GLcontext *ctx,
-                              const GLfloat *buffer,
-                              const GLubyte *attrsz,
-                              const struct _mesa_prim *prim,
-                              GLuint prim_count,
-                              GLuint wrap_count,
-                              GLuint vertex_size)
+void
+_vbo_loopback_vertex_list(struct gl_context *ctx,
+                          const struct vbo_save_vertex_list* node)
 {
    struct loopback_attr la[VBO_ATTRIB_MAX];
-   GLuint i, nr = 0;
+   GLuint nr = 0;
 
    /* All Legacy, NV, ARB and Material attributes are routed through
     * the NV attributes entrypoints:
     */
-   for (i = 0 ; i < VBO_ATTRIB_MAX ; i++) {
-      if (attrsz[i]) {
-        la[nr].target = i;
-        la[nr].sz = attrsz[i];
-        la[nr].func = vert_attrfunc[attrsz[i]-1];
-        nr++;
-      }
+   const struct gl_vertex_array_object *vao = node->VAO[VP_MODE_FF];
+   GLbitfield mask = vao->_Enabled & VERT_BIT_MAT_ALL;
+   while (mask) {
+      const int i = u_bit_scan(&mask);
+      append_attr(&nr, la, i, VBO_MATERIAL_SHIFT, vao);
+   }
+
+   vao = node->VAO[VP_MODE_SHADER];
+   mask = vao->_Enabled & ~(VERT_BIT_POS | VERT_BIT_GENERIC0);
+   while (mask) {
+      const int i = u_bit_scan(&mask);
+      append_attr(&nr, la, i, 0, vao);
+   }
+
+   /* The last in the list should be the vertex provoking attribute */
+   if (vao->_Enabled & VERT_BIT_GENERIC0) {
+      append_attr(&nr, la, VERT_ATTRIB_GENERIC0, 0, vao);
+   } else if (vao->_Enabled & VERT_BIT_POS) {
+      append_attr(&nr, la, VERT_ATTRIB_POS, 0, vao);
+   }
+
+   const GLuint wrap_count = node->wrap_count;
+   const GLuint stride = _vbo_save_get_stride(node);
+   const GLubyte *buffer = NULL;
+   if (0 < nr) {
+      /* Compute the minimal offset into the vertex buffer object */
+      GLuint offset = ~0u;
+      for (GLuint i = 0; i < nr; ++i)
+         offset = MIN2(offset, la[i].offset);
+      for (GLuint i = 0; i < nr; ++i)
+         la[i].offset -= offset;
+
+      /* Get the mapped base pointer, assert sufficient mapping */
+      struct gl_buffer_object *bufferobj = vao->BufferBinding[0].BufferObj;
+      assert(bufferobj && bufferobj->Mappings[MAP_INTERNAL].Pointer);
+      buffer = bufferobj->Mappings[MAP_INTERNAL].Pointer;
+      assert(bufferobj->Mappings[MAP_INTERNAL].Offset
+             <= vao->BufferBinding[0].Offset + offset
+             + stride*(_vbo_save_get_min_index(node) + wrap_count));
+      buffer += vao->BufferBinding[0].Offset + offset
+         - bufferobj->Mappings[MAP_INTERNAL].Offset;
+      assert(stride*(_vbo_save_get_vertex_count(node) - wrap_count)
+             <= bufferobj->Mappings[MAP_INTERNAL].Length);
    }
 
-   for (i = 0 ; i < prim_count ; i++) {
-      if ((prim[i].mode & VBO_SAVE_PRIM_WEAK) &&
-         (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END))
-      {
-        loopback_weak_prim( ctx, &prim[i] );
-      }
-      else
-      {
-        loopback_prim( ctx, buffer, &prim[i], wrap_count, vertex_size, la, nr );
-      }
+   /* Replay the primitives */
+   const struct _mesa_prim *prims = node->prims;
+   const GLuint prim_count = node->prim_count;
+   for (GLuint i = 0; i < prim_count; i++) {
+      loopback_prim(ctx, buffer, &prims[i], wrap_count, stride, la, nr);
    }
 }