Esempio n. 1
0
void
vbo_save_NewList(struct gl_context *ctx, GLuint list, GLenum mode)
{
   struct vbo_save_context *save = &vbo_context(ctx)->save;

   (void) list;
   (void) mode;

   if (!save->prim_store)
      save->prim_store = alloc_prim_store(ctx);

   if (!save->vertex_store)
      save->vertex_store = alloc_vertex_store(ctx);

   save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);

   _save_reset_vertex(ctx);
   _save_reset_counters(ctx);
   ctx->Driver.SaveNeedFlush = 0;
}
Esempio n. 2
0
/**
 * Execute the buffer and save copied verts.
 * This is called from the display list code when executing
 * a drawing command.
 */
void
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;
   GLboolean remap_vertex_store = GL_FALSE;

   if (save->vertex_store && save->vertex_store->buffer) {
      /* 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.
       * We never want to have mapped vertex buffers when we're drawing.
       * Unmap the vertex store, execute the list, then remap the vertex
       * store.
       */
      vbo_save_unmap_vertex_store(ctx, save->vertex_store);
      remap_vertex_store = GL_TRUE;
   }

   FLUSH_CURRENT(ctx, 0);

   if (node->prim_count > 0) {

      if (_mesa_inside_begin_end(ctx) && node->prim[0].begin) {
         /* Error: we're about to begin a new primitive but we're already
          * inside a glBegin/End pair.
          */
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "draw operation inside glBegin/End");
         goto end;
      }
      else if (save->replay_flags) {
	 /* Various degenerate cases: translate into immediate mode
	  * calls rather than trying to execute in place.
	  */
	 vbo_save_loopback_vertex_list( ctx, node );

         goto end;
      }
      
      if (ctx->NewState)
	 _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)) {
         _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);

      /* 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, 0, NULL);
      }
   }

   /* Copy to current?
    */
   _playback_copy_to_current( ctx, node );

end:
   if (remap_vertex_store) {
      save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);
   }
}
Esempio n. 3
0
/**
 * Insert the active immediate struct onto the display list currently
 * being built.
 */
static void
_save_compile_vertex_list(struct gl_context *ctx)
{
   struct vbo_save_context *save = &vbo_context(ctx)->save;
   struct vbo_save_vertex_list *node;

   /* Allocate space for this structure in the display list currently
    * being compiled.
    */
   node = (struct vbo_save_vertex_list *)
      _mesa_dlist_alloc(ctx, save->opcode_vertex_list, sizeof(*node));

   if (!node)
      return;

   /* Duplicate our template, increment refcounts to the storage structs:
    */
   memcpy(node->attrsz, save->attrsz, sizeof(node->attrsz));
   node->vertex_size = save->vertex_size;
   node->buffer_offset =
      (save->buffer - save->vertex_store->buffer) * sizeof(GLfloat);
   node->count = save->vert_count;
   node->wrap_count = save->copied.nr;
   node->dangling_attr_ref = save->dangling_attr_ref;
   node->prim = save->prim;
   node->prim_count = save->prim_count;
   node->vertex_store = save->vertex_store;
   node->prim_store = save->prim_store;

   node->vertex_store->refcount++;
   node->prim_store->refcount++;

   if (node->prim[0].no_current_update) {
      node->current_size = 0;
      node->current_data = NULL;
   }
   else {
      node->current_size = node->vertex_size - node->attrsz[0];
      node->current_data = NULL;

      if (node->current_size) {
         /* If the malloc fails, we just pull the data out of the VBO
          * later instead.
          */
         node->current_data = MALLOC(node->current_size * sizeof(GLfloat));
         if (node->current_data) {
            const char *buffer = (const char *) save->vertex_store->buffer;
            unsigned attr_offset = node->attrsz[0] * sizeof(GLfloat);
            unsigned vertex_offset = 0;

            if (node->count)
               vertex_offset =
                  (node->count - 1) * node->vertex_size * sizeof(GLfloat);

            memcpy(node->current_data,
                   buffer + node->buffer_offset + vertex_offset + attr_offset,
                   node->current_size * sizeof(GLfloat));
         }
      }
   }

   assert(node->attrsz[VBO_ATTRIB_POS] != 0 || node->count == 0);

   if (save->dangling_attr_ref)
      ctx->ListState.CurrentList->Flags |= DLIST_DANGLING_REFS;

   save->vertex_store->used += save->vertex_size * node->count;
   save->prim_store->used += node->prim_count;

   /* Copy duplicated vertices 
    */
   save->copied.nr = _save_copy_vertices(ctx, node, save->buffer);

   /* Deal with GL_COMPILE_AND_EXECUTE:
    */
   if (ctx->ExecuteFlag) {
      struct _glapi_table *dispatch = GET_DISPATCH();

      _glapi_set_dispatch(ctx->Exec);

      vbo_loopback_vertex_list(ctx,
                               (const GLfloat *) ((const char *) save->
                                                  vertex_store->buffer +
                                                  node->buffer_offset),
                               node->attrsz, node->prim, node->prim_count,
                               node->wrap_count, node->vertex_size);

      _glapi_set_dispatch(dispatch);
   }

   /* Decide whether the storage structs are full, or can be used for
    * the next vertex lists as well.
    */
   if (save->vertex_store->used >
       VBO_SAVE_BUFFER_SIZE - 16 * (save->vertex_size + 4)) {

      /* Unmap old store:
       */
      vbo_save_unmap_vertex_store(ctx, save->vertex_store);

      /* Release old reference:
       */
      save->vertex_store->refcount--;
      assert(save->vertex_store->refcount != 0);
      save->vertex_store = NULL;

      /* Allocate and map new store:
       */
      save->vertex_store = alloc_vertex_store(ctx);
      save->buffer_ptr = vbo_save_map_vertex_store(ctx, save->vertex_store);
      save->out_of_memory = save->buffer_ptr == NULL;
   }

   if (save->prim_store->used > VBO_SAVE_PRIM_SIZE - 6) {
      save->prim_store->refcount--;
      assert(save->prim_store->refcount != 0);
      save->prim_store = alloc_prim_store(ctx);
   }

   /* Reset our structures for the next run of vertices:
    */
   _save_reset_counters(ctx);
}