Plug in selection/feedback code.
authorBrian <brian.paul@tungstengraphics.com>
Mon, 17 Sep 2007 20:24:11 +0000 (14:24 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Mon, 17 Sep 2007 20:24:11 +0000 (14:24 -0600)
Not quite finished yet.
Selection/feedback are done with a private instance of the 'draw' module
in the state tracker.  Not quite all the draw context's state is set yet,
namely vertex format info.  Hold off on that for a bit...

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

index a672ad2fcffcbb11fc11f03fbb1de15cafb5b033..ec561294c5a9ef3f1f284b26b1d434faf2696792 100644 (file)
@@ -210,6 +210,7 @@ STATETRACKER_SOURCES = \
        state_tracker/st_cb_flush.c \
        state_tracker/st_cb_drawpixels.c \
        state_tracker/st_cb_fbo.c \
+       state_tracker/st_cb_feedback.c \
        state_tracker/st_cb_program.c \
        state_tracker/st_cb_queryobj.c \
        state_tracker/st_cb_rasterpos.c \
index e66e65e2dd6ac90c133beaee8f2e214bc0eec961..6ab643f1feff8340ab15defd7b1246b8edba9b12 100644 (file)
@@ -33,6 +33,7 @@
 #include "st_cb_clear.h"
 #include "st_cb_drawpixels.h"
 #include "st_cb_fbo.h"
+#include "st_cb_feedback.h"
 #include "st_cb_queryobj.h"
 #include "st_cb_rasterpos.h"
 #include "st_cb_readpixels.h"
@@ -43,6 +44,7 @@
 #include "st_draw.h"
 #include "st_program.h"
 #include "pipe/p_context.h"
+#include "pipe/draw/draw_context.h"
 
 
 void st_invalidate_state(GLcontext * ctx, GLuint new_state)
@@ -64,6 +66,8 @@ struct st_context *st_create_context( GLcontext *ctx,
    st->ctx = ctx;
    st->pipe = pipe;
 
+   st->draw = draw_create(); /* for selection/feedback */
+
    st->dirty.mesa = ~0;
    st->dirty.st = ~0;
 
@@ -97,6 +101,7 @@ struct st_context *st_create_context( GLcontext *ctx,
 
 void st_destroy_context( struct st_context *st )
 {
+   draw_destroy(st->draw);
    st_destroy_atoms( st );
    st_destroy_draw( st );
 
@@ -120,6 +125,7 @@ void st_init_driver_functions(struct dd_function_table *functions)
    st_init_clear_functions(functions);
    st_init_drawpixels_functions(functions);
    st_init_fbo_functions(functions);
+   st_init_feedback_functions(functions);
    st_init_program_functions(functions);
    st_init_query_functions(functions);
    st_init_rasterpos_functions(functions);
index 98b78af7c5b86c13f63e1d4d0a1059495a7f39bc..56cae7d9734ca45d2885f3b18af4d5563b32e977 100644 (file)
@@ -37,6 +37,9 @@ struct st_region;
 struct st_texture_object;
 struct st_texture_image;
 struct st_fragment_program;
+struct draw_context;
+struct draw_stage;
+
 
 #define ST_NEW_MESA                    0x1 /* Mesa state has changed */
 #define ST_NEW_FRAGMENT_PROGRAM        0x2
@@ -62,6 +65,10 @@ struct st_context
 
    struct pipe_context *pipe;
 
+   struct draw_context *draw;  /**< For selection/feedback */
+   struct draw_stage *feedback_stage;  /**< For FL_FEEDBACK rendermode */
+   struct draw_stage *selection_stage;  /**< For GL_SELECT rendermode */
+
    /* Eventually will use a cache to feed the pipe with
     * create/bind/delete calls to constant state objects.  Not yet
     * though, we just shove random objects across the interface.  
index 1facc14ccd41ea33d4ce383b259013cf2fd549d8..69f4b7fa5b025eba73cedbec633b3f359b7eb64e 100644 (file)
@@ -46,6 +46,8 @@
 #include "pipe/p_winsys.h"
 #include "pipe/tgsi/exec/tgsi_attribs.h"
 
+#include "pipe/draw/draw_private.h"
+#include "pipe/draw/draw_context.h"
 
 
 static GLuint
@@ -173,14 +175,14 @@ update_default_attribs_buffer(GLcontext *ctx)
  * we have something to render.
  * Basically, translate the information into the format expected by pipe.
  */
-static void
-draw_vbo(GLcontext *ctx,
-         const struct gl_client_array **arrays,
-         const struct _mesa_prim *prims,
-         GLuint nr_prims,
-         const struct _mesa_index_buffer *ib,
-         GLuint min_index,
-         GLuint max_index)
+void
+st_draw_vbo(GLcontext *ctx,
+            const struct gl_client_array **arrays,
+            const struct _mesa_prim *prims,
+            GLuint nr_prims,
+            const struct _mesa_index_buffer *ib,
+            GLuint min_index,
+            GLuint max_index)
 {
    struct pipe_context *pipe = ctx->st->pipe;
    GLuint attr, i;
@@ -356,6 +358,166 @@ st_draw_vertices(GLcontext *ctx, unsigned prim,
 
 
 
+/**
+ * Called by VBO to draw arrays when in selection or feedback mode.
+ * This is very much like the normal draw_vbo() function above.
+ * Look at code refactoring some day.
+ * Might move this into the failover module some day.
+ */
+void
+st_feedback_draw_vbo(GLcontext *ctx,
+                     const struct gl_client_array **arrays,
+                     const struct _mesa_prim *prims,
+                     GLuint nr_prims,
+                     const struct _mesa_index_buffer *ib,
+                     GLuint min_index,
+                     GLuint max_index)
+{
+   struct st_context *st = ctx->st;
+   struct pipe_context *pipe = st->pipe;
+   struct draw_context *draw = st->draw;
+   GLuint attr, i;
+   GLbitfield attrsNeeded;
+   const unsigned attr0_offset = (unsigned) arrays[0]->Ptr;
+   struct pipe_buffer_handle *index_buffer_handle = 0;
+
+   assert(ctx->RenderMode == GL_SELECT ||
+          ctx->RenderMode == GL_FEEDBACK);
+   assert(draw);
+
+   /*
+    * Set up the draw module's state.
+    *
+    * We'd like to do this less frequently, but the normal state-update
+    * code sends state updates to the pipe, not to our private draw module.
+    */
+   assert(draw);
+   draw_set_viewport_state(draw, &st->state.viewport);
+   draw_set_clip_state(draw, &st->state.clip);
+   draw_set_setup_state(draw, &st->state.setup);
+   draw_set_vertex_shader(draw, &st->state.vs);
+   /* XXX need to set vertex info too */
+
+
+   update_default_attribs_buffer(ctx);
+
+   /* this must be after state validation */
+   attrsNeeded = ctx->st->state.vs.inputs_read;
+
+   /* tell draw module about the vertex array element/attributes */
+   for (attr = 0; attr < 16; attr++) {
+      struct pipe_vertex_buffer vbuffer;
+      struct pipe_vertex_element velement;
+      void *map;
+
+      vbuffer.buffer = NULL;
+      vbuffer.pitch = 0;
+      velement.src_offset = 0;
+      velement.vertex_buffer_index = 0;
+      velement.src_format = 0;
+
+      if (attrsNeeded & (1 << attr)) {
+         const GLuint mesaAttr = tgsi_attrib_to_mesa_attrib(attr);
+         struct gl_buffer_object *bufobj = arrays[mesaAttr]->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[mesaAttr]->Ptr;
+
+            assert(stobj->buffer);
+
+            vbuffer.buffer = stobj->buffer;
+            vbuffer.buffer_offset = attr0_offset;  /* in bytes */
+            vbuffer.pitch = arrays[mesaAttr]->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[mesaAttr]->Type,
+                                                     arrays[mesaAttr]->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;
+         }
+      }
+
+      if (attr == 0)
+         assert(vbuffer.buffer);
+
+      draw_set_vertex_buffer(draw, attr, &vbuffer);
+      draw_set_vertex_element(draw, attr, &velement);
+
+      /* map the attrib buffer */
+      if (vbuffer.buffer) {
+         map = pipe->winsys->buffer_map(pipe->winsys,
+                                        vbuffer.buffer,
+                                        PIPE_BUFFER_FLAG_READ);
+         draw_set_mapped_vertex_buffer(draw, attr, map);
+      }
+   }
+
+
+   if (ib) {
+      unsigned indexSize;
+      struct gl_buffer_object *bufobj = ib->obj;
+      struct st_buffer_object *stobj = st_buffer_object(bufobj);
+      index_buffer_handle = stobj->buffer;
+      void *map;
+
+      switch (ib->type) {
+      case GL_UNSIGNED_INT:
+         indexSize = 4;
+         break;
+      case GL_UNSIGNED_SHORT:
+         indexSize = 2;
+         break;
+      default:
+         assert(0);
+      }
+
+      map = pipe->winsys->buffer_map(pipe->winsys,
+                                     index_buffer_handle,
+                                     PIPE_BUFFER_FLAG_READ);
+      draw_set_mapped_element_buffer(draw, indexSize, map);
+   }
+
+
+   /* draw here */
+   for (i = 0; i < nr_prims; i++) {
+      draw_arrays(draw, prims[i].mode, prims[i].start, prims[i].count);
+   }
+
+
+   /*
+    * unmap vertex/index buffers
+    */
+   for (i = 0; i < PIPE_ATTRIB_MAX; i++) {
+      if (draw->vertex_buffer[i].buffer) {
+         pipe->winsys->buffer_unmap(pipe->winsys,
+                                    draw->vertex_buffer[i].buffer);
+         draw_set_mapped_vertex_buffer(draw, i, NULL);
+      }
+   }
+   if (ib) {
+      pipe->winsys->buffer_unmap(pipe->winsys, index_buffer_handle);
+      draw_set_mapped_element_buffer(draw, 0, NULL);
+   }
+}
+
 
 
 /* This is all a hack to keep using tnl until we have vertex programs
@@ -370,7 +532,7 @@ void st_init_draw( struct st_context *st )
 
    assert(vbo);
    assert(vbo->draw_prims);
-   vbo->draw_prims = draw_vbo;
+   vbo->draw_prims = st_draw_vbo;
 
    _tnl_ProgramCacheInit( ctx );
 }
index 0005fbc51f388a684492509a9bccf58facb8b163..1fcd1b7e6b04c5cd3401600649a75bc1d883bb2f 100644 (file)
 #ifndef ST_DRAW_H
 #define ST_DRAW_H
 
+struct _mesa_prim;
+struct _mesa_index_buffer;
 
 void st_init_draw( struct st_context *st );
 
 void st_destroy_draw( struct st_context *st );
 
+extern void
+st_draw_vbo(GLcontext *ctx,
+            const struct gl_client_array **arrays,
+            const struct _mesa_prim *prims,
+            GLuint nr_prims,
+            const struct _mesa_index_buffer *ib,
+            GLuint min_index,
+            GLuint max_index);
+
+extern void
+st_feedback_draw_vbo(GLcontext *ctx,
+                     const struct gl_client_array **arrays,
+                     const struct _mesa_prim *prims,
+                     GLuint nr_prims,
+                     const struct _mesa_index_buffer *ib,
+                     GLuint min_index,
+                     GLuint max_index);
+
 void 
 st_draw_vertices(GLcontext *ctx, unsigned prim,
                  unsigned numVertex, float *verts,