Use winsys->user_buffer_create() to wrap user-space vertex arrays and element buffers.
authorBrian <brian.paul@tungstengraphics.com>
Thu, 11 Oct 2007 00:00:12 +0000 (18:00 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Thu, 11 Oct 2007 00:00:12 +0000 (18:00 -0600)
Now client-side vertex arrays and glDrawElements work.
More testing/debug/clean-up to come...

src/mesa/state_tracker/st_draw.c

index 7c836ba2c1357dce74a03263145f86c3f7dab34d..22f09c7a98275c693576c79d9622830302333e7d 100644 (file)
@@ -31,6 +31,7 @@
   */
 
 #include "main/imports.h"
+#include "main/image.h"
 
 #include "vbo/vbo.h"
 #include "vbo/vbo_context.h"
@@ -61,6 +62,12 @@ pipe_vertex_format(GLenum format, GLuint size)
       PIPE_FORMAT_R32G32B32_FLOAT,
       PIPE_FORMAT_R32G32B32A32_FLOAT,
    };
+   static const GLuint int_fmts[4] = {
+      PIPE_FORMAT_R32_SSCALED,
+      PIPE_FORMAT_R32G32_SSCALED,
+      PIPE_FORMAT_R32G32B32_SSCALED,
+      PIPE_FORMAT_R32G32B32A32_SSCALED,
+   };
 
    assert(format >= GL_BYTE);
    assert(format <= GL_DOUBLE);
@@ -70,6 +77,8 @@ pipe_vertex_format(GLenum format, GLuint size)
    switch (format) {
    case GL_FLOAT:
       return float_fmts[size - 1];
+   case GL_INT:
+      return int_fmts[size - 1];
    default:
       assert(0);
    }
@@ -215,6 +224,7 @@ st_draw_vbo(GLcontext *ctx,
       velement.src_format = 0;
 
       if (bufobj && bufobj->Name) {
+         /* attribute data is in a VBO */
          struct st_buffer_object *stobj = st_buffer_object(bufobj);
          /* Recall that for VBOs, the gl_client_array->Ptr field is
           * really an offset from the start of the VBO, not a pointer.
@@ -236,23 +246,30 @@ st_draw_vbo(GLcontext *ctx,
          assert(velement.src_format);
       }
       else {
-         /* use the default attribute buffer */
-         needDefaultAttribs = GL_TRUE;
+         /* attribute data is in user-space memory, not a VBO */
+         uint bytes = (arrays[mesaAttr]->Size
+                       * _mesa_sizeof_type(arrays[mesaAttr]->Type)
+                       * (max_index + 1));
+
+         /* wrap user data */
+         vbuffer.buffer
+            = pipe->winsys->user_buffer_create(pipe->winsys,
+                                               (void *) arrays[mesaAttr]->Ptr,
+                                               bytes);
+
+         /* XXX need to deref/free this buffer.vbuffer after drawing! */
 
-         vbuffer.buffer = ctx->st->default_attrib_buffer;
          vbuffer.buffer_offset = 0;
-         vbuffer.pitch = 0; /* must be zero! */
-         vbuffer.max_index = 1;
+         vbuffer.pitch = arrays[mesaAttr]->StrideB; /* in bytes */
+         vbuffer.max_index = 0;  /* need this? */
 
-         velement.src_offset = mesaAttr * 4 * sizeof(GLfloat);
+         velement.src_offset = 0;
          velement.vertex_buffer_index = attr;
-         velement.dst_offset = 0;
-         velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+         velement.dst_offset = 0; /* need this? */
+         velement.src_format = pipe_vertex_format(arrays[mesaAttr]->Type,
+                                                  arrays[mesaAttr]->Size);
       }
 
-      if (attr == 0)
-         assert(vbuffer.buffer);
-
       pipe->set_vertex_buffer(pipe, attr, &vbuffer);
       pipe->set_vertex_element(pipe, attr, &velement);
    }
@@ -268,30 +285,41 @@ st_draw_vbo(GLcontext *ctx,
       struct gl_buffer_object *bufobj = ib->obj;
       struct pipe_buffer_handle *bh = NULL;
       unsigned indexSize, i;
+      GLboolean userBuffer = GL_FALSE;
+
+      switch (ib->type) {
+      case GL_UNSIGNED_INT:
+         indexSize = 4;
+         break;
+      case GL_UNSIGNED_SHORT:
+         indexSize = 2;
+         break;
+      default:
+         assert(0);
+      }
 
       if (bufobj && bufobj->Name) {
          /* elements/indexes are in a real VBO */
          struct st_buffer_object *stobj = st_buffer_object(bufobj);
          bh = stobj->buffer;
-         switch (ib->type) {
-         case GL_UNSIGNED_INT:
-            indexSize = 4;
-            break;
-         case GL_UNSIGNED_SHORT:
-            indexSize = 2;
-            break;
-         default:
-            assert(0);
-         }
+         /* XXX reference buffer here, don't special case userBuffer below */
       }
       else {
-         assert(0);
+         /* element/indicies are in user space memory */
+         bh = pipe->winsys->user_buffer_create(pipe->winsys,
+                                               (void *) ib->ptr,
+                                               ib->count * indexSize);
+         userBuffer = GL_TRUE;
       }
 
       for (i = 0; i < nr_prims; i++) {
          pipe->draw_elements(pipe, bh, indexSize,
                               prims[i].mode, prims[i].start, prims[i].count);
       }
+
+      if (userBuffer) {
+         pipe->winsys->buffer_reference(pipe->winsys, &bh, NULL);
+      }
    }
    else {
       /* non-indexed */