vbo: remove dead code in vbo_can_merge_prims
[mesa.git] / src / mesa / vbo / vbo_save_draw.c
index e961c1d5c26b591faf49ea1663020e53e7c529ef..b5807bb377c4d14102c1114f45bcb928ffe2a2e5 100644 (file)
  */
 
 /* Author:
- *    Keith Whitwell <keith@tungstengraphics.com>
+ *    Keith Whitwell <keithw@vmware.com>
  */
 
+#include <stdbool.h>
+#include "main/arrayobj.h"
 #include "main/glheader.h"
 #include "main/bufferobj.h"
 #include "main/context.h"
 #include "main/imports.h"
-#include "main/mtypes.h"
 #include "main/macros.h"
 #include "main/light.h"
 #include "main/state.h"
+#include "main/varray.h"
+#include "util/bitscan.h"
 
-#include "vbo_context.h"
+#include "vbo_private.h"
 
 
-/**
- * After playback, copy everything but the position from the
- * last vertex to the saved state
- */
 static void
-_playback_copy_to_current(struct gl_context *ctx,
-                          const struct vbo_save_vertex_list *node)
+copy_vao(struct gl_context *ctx, const struct gl_vertex_array_object *vao,
+         GLbitfield mask, GLbitfield state, int shift, fi_type **data)
 {
    struct vbo_context *vbo = vbo_context(ctx);
-   GLfloat vertex[VBO_ATTRIB_MAX * 4];
-   GLfloat *data;
-   GLuint i, offset;
-
-   if (node->current_size == 0)
-      return;
 
-   if (node->current_data) {
-      data = node->current_data;
-   }
-   else {
-      data = vertex;
-
-      if (node->count)
-         offset = (node->buffer_offset + 
-                   (node->count-1) * node->vertex_size * sizeof(GLfloat));
+   mask &= vao->Enabled;
+   while (mask) {
+      const int i = u_bit_scan(&mask);
+      const struct gl_array_attributes *attrib = &vao->VertexAttrib[i];
+      struct gl_array_attributes *currval = &vbo->current[shift + i];
+      const GLubyte size = attrib->Format.Size;
+      const GLenum16 type = attrib->Format.Type;
+      fi_type tmp[8];
+      int dmul = 1;
+
+      if (type == GL_DOUBLE ||
+          type == GL_UNSIGNED_INT64_ARB)
+         dmul = 2;
+
+      if (dmul == 2)
+         memcpy(tmp, *data, size * dmul * sizeof(GLfloat));
       else
-         offset = node->buffer_offset;
+         COPY_CLEAN_4V_TYPE_AS_UNION(tmp, size, *data, type);
 
-      ctx->Driver.GetBufferSubData( ctx, offset,
-                                    node->vertex_size * sizeof(GLfloat), 
-                                    data, node->vertex_store->bufferobj );
+      if (type != currval->Format.Type ||
+          memcmp(currval->Ptr, tmp, 4 * sizeof(GLfloat) * dmul) != 0) {
+         memcpy((fi_type*)currval->Ptr, tmp, 4 * sizeof(GLfloat) * dmul);
 
-      data += node->attrsz[0]; /* skip vertex position */
-   }
+         vbo_set_vertex_format(&currval->Format, size, type);
 
-   for (i = VBO_ATTRIB_POS+1 ; i < VBO_ATTRIB_MAX ; i++) {
-      if (node->attrsz[i]) {
-        GLfloat *current = (GLfloat *)vbo->currval[i].Ptr;
-         GLfloat tmp[4];
-
-         COPY_CLEAN_4V_TYPE_AS_FLOAT(tmp,
-                                     node->attrsz[i],
-                                     data,
-                                     node->attrtype[i]);
-         
-         if (node->attrtype[i] != vbo->currval[i].Type ||
-             memcmp(current, tmp, 4 * sizeof(GLfloat)) != 0) {
-            memcpy(current, tmp, 4 * sizeof(GLfloat));
-
-            vbo->currval[i].Size = node->attrsz[i];
-            vbo->currval[i]._ElementSize = vbo->currval[i].Size * sizeof(GLfloat);
-            vbo->currval[i].Type = node->attrtype[i];
-            vbo->currval[i].Integer =
-                  vbo_attrtype_to_integer_flag(node->attrtype[i]);
-
-            if (i >= VBO_ATTRIB_FIRST_MATERIAL &&
-                i <= VBO_ATTRIB_LAST_MATERIAL)
-               ctx->NewState |= _NEW_LIGHT;
-
-            ctx->NewState |= _NEW_CURRENT_ATTRIB;
-         }
-
-        data += node->attrsz[i];
+         ctx->NewState |= state;
       }
+
+      *data += size;
    }
+}
+
+/**
+ * After playback, copy everything but the position from the
+ * last vertex to the saved state
+ */
+static void
+playback_copy_to_current(struct gl_context *ctx,
+                         const struct vbo_save_vertex_list *node)
+{
+   if (!node->current_data)
+      return;
+
+   fi_type *data = node->current_data;
+   /* Copy conventional attribs and generics except pos */
+   copy_vao(ctx, node->VAO[VP_MODE_SHADER], ~VERT_BIT_POS & VERT_BIT_ALL,
+            _NEW_CURRENT_ATTRIB, 0, &data);
+   /* Copy materials */
+   copy_vao(ctx, node->VAO[VP_MODE_FF], VERT_BIT_MAT_ALL,
+            _NEW_CURRENT_ATTRIB | _NEW_LIGHT, VBO_MATERIAL_SHIFT, &data);
 
    /* Colormaterial -- this kindof sucks.
     */
@@ -113,129 +107,40 @@ _playback_copy_to_current(struct gl_context *ctx,
    /* CurrentExecPrimitive
     */
    if (node->prim_count) {
-      const struct _mesa_prim *prim = &node->prim[node->prim_count - 1];
+      const struct _mesa_prim *prim = &node->prims[node->prim_count - 1];
       if (prim->end)
-        ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
+         ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
       else
-        ctx->Driver.CurrentExecPrimitive = prim->mode;
+         ctx->Driver.CurrentExecPrimitive = prim->mode;
    }
 }
 
 
 
 /**
- * Treat the vertex storage as a VBO, define vertex arrays pointing
- * into it:
+ * Set the appropriate VAO to draw.
  */
-static void vbo_bind_vertex_list(struct gl_context *ctx,
-                                 const struct vbo_save_vertex_list *node)
+static void
+bind_vertex_list(struct gl_context *ctx,
+                 const struct vbo_save_vertex_list *node)
 {
-   struct vbo_context *vbo = vbo_context(ctx);
-   struct vbo_save_context *save = &vbo->save;
-   struct gl_client_array *arrays = save->arrays;
-   GLuint buffer_offset = node->buffer_offset;
-   const GLuint *map;
-   GLuint attr;
-   GLubyte node_attrsz[VBO_ATTRIB_MAX];  /* copy of node->attrsz[] */
-   GLenum node_attrtype[VBO_ATTRIB_MAX];  /* copy of node->attrtype[] */
-   GLbitfield64 varying_inputs = 0x0;
-
-   memcpy(node_attrsz, node->attrsz, sizeof(node->attrsz));
-   memcpy(node_attrtype, node->attrtype, sizeof(node->attrtype));
-
-   /* Install the default (ie Current) attributes first, then overlay
-    * all active ones.
-    */
-   switch (get_program_mode(ctx)) {
-   case VP_NONE:
-      for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) {
-         save->inputs[attr] = &vbo->currval[VBO_ATTRIB_POS+attr];
-      }
-      for (attr = 0; attr < MAT_ATTRIB_MAX; attr++) {
-         save->inputs[VERT_ATTRIB_GENERIC(attr)] =
-            &vbo->currval[VBO_ATTRIB_MAT_FRONT_AMBIENT+attr];
-      }
-      map = vbo->map_vp_none;
-      break;
-   case VP_ARB:
-      for (attr = 0; attr < VERT_ATTRIB_FF_MAX; attr++) {
-         save->inputs[attr] = &vbo->currval[VBO_ATTRIB_POS+attr];
-      }
-      for (attr = 0; attr < VERT_ATTRIB_GENERIC_MAX; attr++) {
-         save->inputs[VERT_ATTRIB_GENERIC(attr)] =
-            &vbo->currval[VBO_ATTRIB_GENERIC0+attr];
-      }
-      map = vbo->map_vp_arb;
-
-      /* check if VERT_ATTRIB_POS is not read but VERT_BIT_GENERIC0 is read.
-       * In that case we effectively need to route the data from
-       * glVertexAttrib(0, val) calls to feed into the GENERIC0 input.
-       */
-      if ((ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_POS) == 0 &&
-          (ctx->VertexProgram._Current->Base.InputsRead & VERT_BIT_GENERIC0)) {
-         save->inputs[VERT_ATTRIB_GENERIC0] = save->inputs[0];
-         node_attrsz[VERT_ATTRIB_GENERIC0] = node_attrsz[0];
-         node_attrtype[VERT_ATTRIB_GENERIC0] = node_attrtype[0];
-         node_attrsz[0] = 0;
-      }
-      break;
-   default:
-      assert(0);
-   }
-
-   for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
-      const GLuint src = map[attr];
-
-      if (node_attrsz[src]) {
-         /* override the default array set above */
-         save->inputs[attr] = &arrays[attr];
-
-        arrays[attr].Ptr = (const GLubyte *) NULL + buffer_offset;
-        arrays[attr].Size = node_attrsz[src];
-        arrays[attr].StrideB = node->vertex_size * sizeof(GLfloat);
-        arrays[attr].Stride = node->vertex_size * sizeof(GLfloat);
-         arrays[attr].Type = node_attrtype[src];
-         arrays[attr].Integer =
-               vbo_attrtype_to_integer_flag(node_attrtype[src]);
-         arrays[attr].Format = GL_RGBA;
-        arrays[attr].Enabled = 1;
-         arrays[attr]._ElementSize = arrays[attr].Size * sizeof(GLfloat);
-         _mesa_reference_buffer_object(ctx,
-                                       &arrays[attr].BufferObj,
-                                       node->vertex_store->bufferobj);
-        arrays[attr]._MaxElement = node->count; /* ??? */
-        
-        assert(arrays[attr].BufferObj->Name);
-
-        buffer_offset += node_attrsz[src] * sizeof(GLfloat);
-         varying_inputs |= VERT_BIT(attr);
-      }
-   }
-
-   _mesa_set_varying_vp_inputs( ctx, varying_inputs );
-   ctx->NewDriverState |= ctx->DriverFlags.NewArray;
+   const gl_vertex_processing_mode mode = ctx->VertexProgram._VPMode;
+   _mesa_set_draw_vao(ctx, node->VAO[mode], _vbo_get_vao_filter(mode));
 }
 
 
 static void
-vbo_save_loopback_vertex_list(struct gl_context *ctx,
-                              const struct vbo_save_vertex_list *list)
+loopback_vertex_list(struct gl_context *ctx,
+                     const struct vbo_save_vertex_list *list)
 {
-   const char *buffer =
-      ctx->Driver.MapBufferRange(ctx, 0,
-                                list->vertex_store->bufferobj->Size,
-                                GL_MAP_READ_BIT, /* ? */
-                                list->vertex_store->bufferobj);
-
-   vbo_loopback_vertex_list(ctx,
-                            (const GLfloat *)(buffer + list->buffer_offset),
-                            list->attrsz,
-                            list->prim,
-                            list->prim_count,
-                            list->wrap_count,
-                            list->vertex_size);
-
-   ctx->Driver.UnmapBuffer(ctx, list->vertex_store->bufferobj);
+   struct gl_buffer_object *bo = list->VAO[0]->BufferBinding[0].BufferObj;
+   ctx->Driver.MapBufferRange(ctx, 0, bo->Size, GL_MAP_READ_BIT, /* ? */
+                              bo, MAP_INTERNAL);
+
+   /* Note that the range of referenced vertices must be mapped already */
+   _vbo_loopback_vertex_list(ctx, list);
+
+   ctx->Driver.UnmapBuffer(ctx, bo, MAP_INTERNAL);
 }
 
 
@@ -249,10 +154,11 @@ 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;
-   struct vbo_save_context *save = &vbo_context(ctx)->save;
+   struct vbo_context *vbo = vbo_context(ctx);
+   struct vbo_save_context *save = &vbo->save;
    GLboolean remap_vertex_store = GL_FALSE;
 
-   if (save->vertex_store && save->vertex_store->buffer) {
+   if (save->vertex_store && save->vertex_store->buffer_map) {
       /* The vertex store is currently mapped but we're about to replay
        * a display list.  This can happen when a nested display list is
        * being build with GL_COMPILE_AND_EXECUTE.
@@ -264,11 +170,11 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
       remap_vertex_store = GL_TRUE;
    }
 
-   FLUSH_CURRENT(ctx, 0);
+   FLUSH_FOR_DRAW(ctx);
 
    if (node->prim_count > 0) {
 
-      if (_mesa_inside_begin_end(ctx) && node->prim[0].begin) {
+      if (_mesa_inside_begin_end(ctx) && node->prims[0].begin) {
          /* Error: we're about to begin a new primitive but we're already
           * inside a glBegin/End pair.
           */
@@ -277,49 +183,43 @@ vbo_save_playback_vertex_list(struct gl_context *ctx, void *data)
          goto end;
       }
       else if (save->replay_flags) {
-        /* Various degnerate cases: translate into immediate mode
-         * calls rather than trying to execute in place.
-         */
-        vbo_save_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;
       }
-      
+
+      bind_vertex_list(ctx, node);
+
+      /* Need that at least one time. */
       if (ctx->NewState)
-        _mesa_update_state( ctx );
+         _mesa_update_state(ctx);
 
       /* XXX also need to check if shader enabled, but invalid */
-      if ((ctx->VertexProgram.Enabled && !ctx->VertexProgram._Enabled) ||
-          (ctx->FragmentProgram.Enabled && !ctx->FragmentProgram._Enabled)) {
+      if ((ctx->VertexProgram.Enabled &&
+           !_mesa_arb_vertex_program_enabled(ctx)) ||
+          (ctx->FragmentProgram.Enabled &&
+           !_mesa_arb_fragment_program_enabled(ctx))) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glBegin (invalid vertex/fragment program)");
          return;
       }
 
-      vbo_bind_vertex_list( ctx, node );
-
-      vbo_draw_method(vbo_context(ctx), DRAW_DISPLAY_LIST);
+      assert(ctx->NewState == 0);
 
-      /* Again...
-       */
-      if (ctx->NewState)
-        _mesa_update_state( ctx );
-
-      if (node->count > 0) {
-         vbo_context(ctx)->draw_prims(ctx, 
-                                      node->prim,
-                                      node->prim_count,
-                                      NULL,
-                                      GL_TRUE,
-                                      0,    /* Node is a VBO, so this is ok */
-                                      node->count - 1,
-                                      NULL, NULL);
+      if (node->vertex_count > 0) {
+         GLuint min_index = _vbo_save_get_min_index(node);
+         GLuint max_index = _vbo_save_get_max_index(node);
+         ctx->Driver.Draw(ctx, node->prims, node->prim_count, NULL, GL_TRUE,
+                          min_index, max_index, NULL, 0, NULL);
       }
    }
 
    /* Copy to current?
     */
-   _playback_copy_to_current( ctx, node );
+   playback_copy_to_current(ctx, node);
 
 end:
    if (remap_vertex_store) {