Create a default vertex attribute buffer which mirrors ctx->Current.Attrrib[]
authorBrian <brian.paul@tungstengraphics.com>
Sat, 18 Aug 2007 15:05:49 +0000 (16:05 +0100)
committerBrian <brian.paul@tungstengraphics.com>
Sat, 18 Aug 2007 15:05:49 +0000 (16:05 +0100)
Used when the vertex shader references attributes which aren't present in VBOs.

src/mesa/state_tracker/st_context.h
src/mesa/state_tracker/st_draw.c

index 25ed20a5f841a9b745b15e4b36d03d474d459d93..35774a790e232556df0e2dec82d82e1f7b829cf9 100644 (file)
@@ -104,6 +104,8 @@ struct st_context
    struct st_state_flags dirty;
 
    GLfloat polygon_offset_scale; /* ?? */
+
+   struct pipe_buffer_handle *default_attrib_buffer;
 };
 
 
index 425076d6537f81e1417afb08fbbc33bb2b902bcb..db24b24fa7e967cf78159e77baa5ecd5017ec5f0 100644 (file)
@@ -44,6 +44,7 @@
 #include "st_cb_bufferobjects.h"
 #include "pipe/p_context.h"
 #include "pipe/p_defines.h"
+#include "pipe/p_winsys.h"
 
 #include "vbo/vbo_context.h"
 
@@ -52,7 +53,7 @@
  * bypassing the T&L module.  This only works with VBO-based demos,
  * such as progs/test/bufferobj.c
  */
-#define USE_NEW_DRAW 0
+#define USE_NEW_DRAW 01
 
 
 /*
@@ -134,6 +135,38 @@ pipe_vertex_format(GLenum format, GLuint size)
 
 
 
+/**
+ * The default attribute buffer is basically a copy of the
+ * ctx->Current.Attrib[] array.  It's used when the vertex program
+ * references an attribute for which we don't have a VBO/array.
+ */
+static void
+create_default_attribs_buffer(struct st_context *st)
+{
+   struct pipe_context *pipe = st->pipe;
+   st->default_attrib_buffer = pipe->winsys->buffer_create( pipe->winsys, 32 );
+}
+
+
+static void
+destroy_default_attribs_buffer(struct st_context *st)
+{
+   struct pipe_context *pipe = st->pipe;
+   pipe->winsys->buffer_unreference(pipe->winsys, &st->default_attrib_buffer);
+}
+
+
+static void
+update_default_attribs_buffer(GLcontext *ctx)
+{
+   struct pipe_context *pipe = ctx->st->pipe;
+   struct pipe_buffer_handle *buf = ctx->st->default_attrib_buffer;
+   const unsigned size = sizeof(ctx->Current.Attrib);
+   const void *data = ctx->Current.Attrib;
+   pipe->winsys->buffer_data(pipe->winsys, buf, size, data);
+}
+
+
 /**
  * This function gets plugged into the VBO module and is called when
  * we have something to render.
@@ -150,41 +183,66 @@ draw_vbo(GLcontext *ctx,
 {
    struct pipe_context *pipe = ctx->st->pipe;
    GLuint attr, i;
+   GLbitfield attrsNeeded;
+   const unsigned attr0_offset = (unsigned) arrays[0]->Ptr;
 
    st_validate_state(ctx->st);
+   update_default_attribs_buffer(ctx);
 
+   /* this must be after state validation */
+   attrsNeeded = ctx->st->state.vs.inputs_read;
 
    /* tell pipe about the vertex array element/attributes */
    for (attr = 0; attr < 16; attr++) {
-      struct gl_buffer_object *bufobj = arrays[attr]->BufferObj;
       struct pipe_vertex_buffer vbuffer;
       struct pipe_vertex_element velement;
 
-      if (bufobj && bufobj->Name) {
-         struct st_buffer_object *stobj = st_buffer_object(bufobj);
-
-         assert(stobj->buffer);
-
-         vbuffer.pitch = arrays[attr]->StrideB; /* in bytes */
-         vbuffer.max_index = 0;
-         vbuffer.buffer = stobj->buffer;
-         vbuffer.buffer_offset = 0;
-
-         /* Recall that for VBOs, the gl_client_array->Ptr field is
-          * really an offset from the start of the VBO, not a pointer.
-          */
-         velement.src_offset = (unsigned) arrays[attr]->Ptr;
-         velement.vertex_buffer_index = attr;
-         velement.dst_offset = 0;
-         velement.src_format = pipe_vertex_format(arrays[attr]->Type,
-                                                  arrays[attr]->Size);
+      vbuffer.buffer = NULL;
+      vbuffer.pitch = 0;
+      velement.src_offset = 0;
+      velement.vertex_buffer_index = 0;
+      velement.src_format = 0;
+
+      if (attrsNeeded & (1 << attr)) {
+         struct gl_buffer_object *bufobj = arrays[attr]->BufferObj;
+
+         if (bufobj && bufobj->Name) {
+            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.
+             */
+            unsigned offset = (unsigned) arrays[attr]->Ptr;
+
+            assert(stobj->buffer);
+
+            vbuffer.buffer = stobj->buffer;
+            vbuffer.buffer_offset = attr0_offset;  /* in bytes */
+            vbuffer.pitch = arrays[attr]->StrideB; /* in bytes */
+            vbuffer.max_index = 0;  /* need this? */
+
+            velement.src_offset = offset - attr0_offset; /* bytes */
+            velement.vertex_buffer_index = attr;
+            velement.dst_offset = 0; /* need this? */
+            velement.src_format = pipe_vertex_format(arrays[attr]->Type,
+                                                     arrays[attr]->Size);
+            assert(velement.src_format);
+         }
+         else {
+            /* use the default attribute buffer */
+            vbuffer.buffer = ctx->st->default_attrib_buffer;
+            vbuffer.buffer_offset = 0;
+            vbuffer.pitch = 0; /* must be zero! */
+            vbuffer.max_index = 1;
+
+            velement.src_offset = attr * 4 * sizeof(GLfloat);
+            velement.vertex_buffer_index = attr;
+            velement.dst_offset = 0;
+            velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+         }
       }
-      else {
-         /* vertex attribute data is not an a real buffer! */
-         /* XXX we'll want to handle that someday... */
 
-         vbuffer.buffer = NULL;
-      }
+      if (attr == 0)
+         assert(vbuffer.buffer);
 
       pipe->set_vertex_buffer(pipe, attr, &vbuffer);
       pipe->set_vertex_element(pipe, attr, &velement);
@@ -209,6 +267,8 @@ void st_init_draw( struct st_context *st )
 #if USE_NEW_DRAW
    struct vbo_context *vbo = (struct vbo_context *) ctx->swtnl_im;
 
+   create_default_attribs_buffer(st);
+
    assert(vbo);
    assert(vbo->draw_prims);
    vbo->draw_prims = draw_vbo;
@@ -224,8 +284,7 @@ void st_init_draw( struct st_context *st )
 
 void st_destroy_draw( struct st_context *st )
 {
-   /* Nothing to do. 
-    */
+   destroy_default_attribs_buffer(st);
 }