Пример #1
0
static void
st_indirect_draw_vbo(struct gl_context *ctx,
                     GLuint mode,
                     struct gl_buffer_object *indirect_data,
                     GLsizeiptr indirect_offset,
                     unsigned draw_count,
                     unsigned stride,
                     struct gl_buffer_object *indirect_params,
                     GLsizeiptr indirect_params_offset,
                     const struct _mesa_index_buffer *ib)
{
   struct st_context *st = st_context(ctx);
   struct pipe_index_buffer ibuffer = {0};
   struct pipe_draw_info info;

   /* Mesa core state should have been validated already */
   assert(ctx->NewState == 0x0);
   assert(stride);

   /* Validate state. */
   if ((st->dirty | ctx->NewDriverState) & ST_PIPELINE_RENDER_STATE_MASK ||
       st->gfx_shaders_may_be_dirty) {
      st_validate_state(st, ST_PIPELINE_RENDER);
   }

   if (st->vertex_array_out_of_memory) {
      return;
   }

   util_draw_init_info(&info);

   if (ib) {
      if (!setup_index_buffer(st, ib, &ibuffer)) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "gl%sDrawElementsIndirect%s",
                     (draw_count > 1) ? "Multi" : "",
                     indirect_params ? "CountARB" : "");
         return;
      }

      info.indexed = TRUE;

      /* Primitive restart is not handled by the VBO module in this case. */
      setup_primitive_restart(ctx, ib, &info);
   }

   info.mode = translate_prim(ctx, mode);
   info.vertices_per_patch = ctx->TessCtrlProgram.patch_vertices;
   info.indirect = st_buffer_object(indirect_data)->buffer;
   info.indirect_offset = indirect_offset;

   if (ST_DEBUG & DEBUG_DRAW) {
      debug_printf("st/draw indirect: mode %s drawcount %d indexed %d\n",
                   u_prim_name(info.mode),
                   draw_count,
                   info.indexed);
   }

   if (!st->has_multi_draw_indirect) {
      int i;

      assert(!indirect_params);
      info.indirect_count = 1;
      for (i = 0; i < draw_count; i++) {
         info.drawid = i;
         cso_draw_vbo(st->cso_context, &info);
         info.indirect_offset += stride;
      }
   } else {
      info.indirect_count = draw_count;
      info.indirect_stride = stride;
      if (indirect_params) {
         info.indirect_params = st_buffer_object(indirect_params)->buffer;
         info.indirect_params_offset = indirect_params_offset;
      }
      cso_draw_vbo(st->cso_context, &info);
   }
}
Пример #2
0
/**
 * This function gets plugged into the VBO module and is called when
 * we have something to render.
 * Basically, translate the information into the format expected by gallium.
 */
void
st_draw_vbo(struct gl_context *ctx,
            const struct _mesa_prim *prims,
            GLuint nr_prims,
            const struct _mesa_index_buffer *ib,
	    GLboolean index_bounds_valid,
            GLuint min_index,
            GLuint max_index,
            struct gl_transform_feedback_object *tfb_vertcount,
            struct gl_buffer_object *indirect)
{
   struct st_context *st = st_context(ctx);
   struct pipe_index_buffer ibuffer = {0};
   struct pipe_draw_info info;
   const struct gl_client_array **arrays = ctx->Array._DrawArrays;
   unsigned i;

   /* Mesa core state should have been validated already */
   assert(ctx->NewState == 0x0);

   /* Validate state. */
   if (st->dirty.st || ctx->NewDriverState) {
      st_validate_state(st);

#if 0
      if (MESA_VERBOSE & VERBOSE_GLSL) {
         check_uniforms(ctx);
      }
#else
      (void) check_uniforms;
#endif
   }

   if (st->vertex_array_out_of_memory) {
      return;
   }

   util_draw_init_info(&info);

   if (ib) {
      /* Get index bounds for user buffers. */
      if (!index_bounds_valid)
         if (!all_varyings_in_vbos(arrays))
            vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
                                   nr_prims);

      if (!setup_index_buffer(st, ib, &ibuffer)) {
         _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBegin/DrawElements/DrawArray");
         return;
      }

      info.indexed = TRUE;
      if (min_index != ~0 && max_index != ~0) {
         info.min_index = min_index;
         info.max_index = max_index;
      }

      /* The VBO module handles restart for the non-indexed GLDrawArrays
       * so we only set these fields for indexed drawing:
       */
      info.primitive_restart = ctx->Array._PrimitiveRestart;
      info.restart_index = ctx->Array.RestartIndex;
   }
   else {
      /* Transform feedback drawing is always non-indexed. */
      /* Set info.count_from_stream_output. */
      if (tfb_vertcount) {
         st_transform_feedback_draw_init(tfb_vertcount, &info);
      }
   }

   /* do actual drawing */
   for (i = 0; i < nr_prims; i++) {
      info.mode = translate_prim(ctx, prims[i].mode);
      info.start = prims[i].start;
      info.count = prims[i].count;
      info.start_instance = prims[i].base_instance;
      info.instance_count = prims[i].num_instances;
      info.index_bias = prims[i].basevertex;
      if (!ib) {
         info.min_index = info.start;
         info.max_index = info.start + info.count - 1;
      }

      if (ST_DEBUG & DEBUG_DRAW) {
         debug_printf("st/draw: mode %s  start %u  count %u  indexed %d\n",
                      u_prim_name(info.mode),
                      info.start,
                      info.count,
                      info.indexed);
      }

      if (info.count_from_stream_output) {
         cso_draw_vbo(st->cso_context, &info);
      }
      else if (info.primitive_restart) {
         /* don't trim, restarts might be inside index list */
         cso_draw_vbo(st->cso_context, &info);
      }
      else if (u_trim_pipe_prim(prims[i].mode, &info.count)) {
         cso_draw_vbo(st->cso_context, &info);
      }
   }

   if (ib && st->indexbuf_uploader && !_mesa_is_bufferobj(ib->obj)) {
      pipe_resource_reference(&ibuffer.buffer, NULL);
   }
}
Пример #3
0
/**
 * This function gets plugged into the VBO module and is called when
 * we have something to render.
 * Basically, translate the information into the format expected by gallium.
 */
void
st_draw_vbo(struct gl_context *ctx,
            const struct _mesa_prim *prims,
            GLuint nr_prims,
            const struct _mesa_index_buffer *ib,
	    GLboolean index_bounds_valid,
            GLuint min_index,
            GLuint max_index,
            struct gl_transform_feedback_object *tfb_vertcount)
{
   struct st_context *st = st_context(ctx);
   struct pipe_index_buffer ibuffer = {0};
   struct pipe_draw_info info;
   const struct gl_client_array **arrays = ctx->Array._DrawArrays;
   unsigned i;
   GLboolean new_array;

   /* Mesa core state should have been validated already */
   assert(ctx->NewState == 0x0);

   /* Get Mesa driver state. */
   st->dirty.st |= ctx->NewDriverState;
   ctx->NewDriverState = 0;

   new_array =
      (st->dirty.st & (ST_NEW_VERTEX_ARRAYS | ST_NEW_VERTEX_PROGRAM)) ||
      (st->dirty.mesa & (_NEW_PROGRAM | _NEW_BUFFER_OBJECT)) != 0;

   /* Validate state. */
   if (st->dirty.st) {
      GLboolean vertDataEdgeFlags;

      vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj &&
                          arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name;
      if (vertDataEdgeFlags != st->vertdata_edgeflags) {
         st->vertdata_edgeflags = vertDataEdgeFlags;
         st->dirty.st |= ST_NEW_EDGEFLAGS_DATA;
      }

      st_validate_state(st);

      if (new_array) {
         if (!st_validate_varrays(ctx, arrays)) {
            /* probably out of memory, no-op the draw call */
            return;
         }
      }

#if 0
      if (MESA_VERBOSE & VERBOSE_GLSL) {
         check_uniforms(ctx);
      }
#else
      (void) check_uniforms;
#endif
   }

   util_draw_init_info(&info);
   if (ib) {
      /* Get index bounds for user buffers. */
      if (!index_bounds_valid)
         if (!all_varyings_in_vbos(arrays))
            vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index,
                                   nr_prims);

      setup_index_buffer(st, ib, &ibuffer);

      info.indexed = TRUE;
      if (min_index != ~0 && max_index != ~0) {
         info.min_index = min_index;
         info.max_index = max_index;
      }

      /* The VBO module handles restart for the non-indexed GLDrawArrays
       * so we only set these fields for indexed drawing:
       */
      info.primitive_restart = ctx->Array.PrimitiveRestart;
      info.restart_index = ctx->Array.RestartIndex;
   }
   else {
      /* Transform feedback drawing is always non-indexed. */
      /* Set info.count_from_stream_output. */
      if (tfb_vertcount) {
         st_transform_feedback_draw_init(tfb_vertcount, &info);
      }
   }

   /* do actual drawing */
   for (i = 0; i < nr_prims; i++) {
      info.mode = translate_prim( ctx, prims[i].mode );
      info.start = prims[i].start;
      info.count = prims[i].count;
      info.instance_count = prims[i].num_instances;
      info.index_bias = prims[i].basevertex;
      if (!ib) {
         info.min_index = info.start;
         info.max_index = info.start + info.count - 1;
      }

      if (info.count_from_stream_output) {
         cso_draw_vbo(st->cso_context, &info);
      }
      else if (info.primitive_restart) {
         /* don't trim, restarts might be inside index list */
         cso_draw_vbo(st->cso_context, &info);
      }
      else if (u_trim_pipe_prim(info.mode, &info.count))
         cso_draw_vbo(st->cso_context, &info);
   }

   if (ib && st->indexbuf_uploader && !_mesa_is_bufferobj(ib->obj)) {
      pipe_resource_reference(&ibuffer.buffer, NULL);
   }
}