Example #1
0
static void
init_array(struct gl_context *ctx,
           struct gl_vertex_array_object *obj, GLuint index, GLint size, GLint type)
{
   struct gl_vertex_attrib_array *array = &obj->VertexAttrib[index];
   struct gl_vertex_buffer_binding *binding = &obj->VertexBinding[index];

   array->Size = size;
   array->Type = type;
   array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */
   array->Stride = 0;
   array->Ptr = NULL;
   array->RelativeOffset = 0;
   array->Enabled = GL_FALSE;
   array->Normalized = GL_FALSE;
   array->Integer = GL_FALSE;
   array->Doubles = GL_FALSE;
   array->_ElementSize = size * _mesa_sizeof_type(type);
   array->VertexBinding = index;

   binding->Offset = 0;
   binding->Stride = array->_ElementSize;
   binding->BufferObj = NULL;
   binding->_BoundArrays = BITFIELD64_BIT(index);

   /* Vertex array buffers */
   _mesa_reference_buffer_object(ctx, &binding->BufferObj,
                                 ctx->Shared->NullBufferObj);
}
Example #2
0
/**
 * Do error checking and update state for glVertex/Color/TexCoord/...Pointer
 * functions.
 *
 * \param func  name of calling function used for error reporting
 * \param attrib  the attribute array index to update
 * \param legalTypes  bitmask of *_BIT above indicating legal datatypes
 * \param sizeMin  min allowable size value
 * \param sizeMax  max allowable size value
 * \param size  components per element (1, 2, 3 or 4)
 * \param type  datatype of each component (GL_FLOAT, GL_INT, etc)
 * \param stride  stride between elements, in elements
 * \param normalized  are integer types converted to floats in [-1, 1]?
 * \param integer  integer-valued values (will not be normalized to [-1,1])
 * \param ptr  the address (or offset inside VBO) of the array data
 */
static void
update_array(struct gl_context *ctx,
             const char *func,
             GLuint attrib, GLbitfield legalTypesMask,
             GLint sizeMin, GLint sizeMax,
             GLint size, GLenum type, GLsizei stride,
             GLboolean normalized, GLboolean integer,
             const GLvoid *ptr)
{
   struct gl_client_array *array;
   GLbitfield typeBit;
   GLsizei elementSize;

   typeBit = type_to_bit(ctx, type);
   if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) {
      _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)",
                  func, _mesa_lookup_enum_by_nr(type));
      return;
   }

   /* Do size parameter checking. */
   if (size < sizeMin || size > sizeMax || size > 4) {
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size);
      return;
   }

   ASSERT(size <= 4);

   if (stride < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride );
      return;
   }

   if (ctx->Array.ArrayObj->ARBsemantics &&
       !_mesa_is_bufferobj(ctx->Array.ArrayBufferObj)) {
      /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
       * Generate GL_INVALID_OPERATION if that's not true.
       */
      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-VBO array)", func);
      return;
   }

   elementSize = _mesa_sizeof_type(type) * size;

   array = &ctx->Array.ArrayObj->VertexAttrib[attrib];
   array->Size = size;
   array->Type = type;
   array->Stride = stride;
   array->StrideB = stride ? stride : elementSize;
   array->Normalized = normalized;
   array->Integer = integer;
   array->Ptr = (const GLubyte *) ptr;
   array->_ElementSize = elementSize;

   _mesa_reference_buffer_object(ctx, &array->BufferObj,
                                 ctx->Array.ArrayBufferObj);

   ctx->NewState |= _NEW_ARRAY;
   ctx->Array.NewState |= VERT_BIT(attrib);
}
Example #3
0
static void flush_vertex( struct split_context *split )
{
   struct _mesa_index_buffer ib;
   GLuint i;

   if (!split->dstprim_nr) 
      return;

   if (split->ib) {
      ib = *split->ib;

      ib.count = split->max_index - split->min_index + 1;
      ib.ptr = (const void *)((const char *)ib.ptr + 
                              split->min_index * _mesa_sizeof_type(ib.type));

      /* Rebase the primitives to save index buffer entries. */
      for (i = 0; i < split->dstprim_nr; i++)
	 split->dstprim[i].start -= split->min_index;
   }

   assert(split->max_index >= split->min_index);

   split->draw(split->ctx,
	       split->array,
	       split->dstprim,
	       split->dstprim_nr,
	       split->ib ? &ib : NULL,
	       !split->ib,
	       split->min_index,
	       split->max_index);

   split->dstprim_nr = 0;
   split->min_index = ~0;
   split->max_index = 0;
}
Example #4
0
static int
get_array_stride(struct gl_context *ctx, const struct gl_client_array *a)
{
	struct nouveau_render_state *render = to_render_state(ctx);

	if (render->mode == VBO && !_mesa_is_bufferobj(a->BufferObj))
		/* Pack client buffers. */
		return align(_mesa_sizeof_type(a->Type) * a->Size, 4);
	else
		return a->StrideB;
}
Example #5
0
/**
 * Do error checking and update state for glVertex/Color/TexCoord/...Pointer
 * functions.
 *
 * \param func  name of calling function used for error reporting
 * \param attrib  the attribute array index to update
 * \param legalTypes  bitmask of *_BIT above indicating legal datatypes
 * \param sizeMin  min allowable size value
 * \param sizeMax  max allowable size value
 * \param size  components per element (1, 2, 3 or 4)
 * \param type  datatype of each component (GL_FLOAT, GL_INT, etc)
 * \param stride  stride between elements, in elements
 * \param normalized  are integer types converted to floats in [-1, 1]?
 * \param integer  integer-valued values (will not be normalized to [-1,1])
 * \param ptr  the address (or offset inside VBO) of the array data
 */
static void
update_array(struct gl_context *ctx,
             const char *func,
             GLuint attrib, GLbitfield legalTypesMask,
             GLint sizeMin, GLint sizeMax,
             GLint size, GLenum type, GLsizei stride,
             GLboolean normalized, GLboolean integer,
             const GLvoid *ptr)
{
   struct gl_client_array *array;
   GLbitfield typeBit;
   GLsizei elementSize;

   typeBit = type_to_bit(ctx, type);
   if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) {
      _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)",
                  func, _mesa_lookup_enum_by_nr(type));
      return;
   }

   /* Do size parameter checking. */
   if (size < sizeMin || size > sizeMax || size > 4) {
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size);
      return;
   }

   ASSERT(size <= 4);

   if (stride < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride );
      return;
   }

   elementSize = _mesa_sizeof_type(type) * size;

   array = &ctx->Array.VertexAttrib[attrib];
   array->Size = size;
   array->Type = type;
   array->Stride = stride;
   array->StrideB = stride ? stride : elementSize;
   array->Normalized = normalized;
   array->Integer = integer;
   array->Ptr = (const GLubyte *) ptr;
   array->_ElementSize = elementSize;

   ctx->NewState |= _NEW_ARRAY;
   ctx->Array.NewState |= VERT_BIT(attrib);
}
Example #6
0
static void
init_array(struct gl_context *ctx,
           struct gl_client_array *array, GLint size, GLint type)
{
   array->Size = size;
   array->Type = type;
   array->Stride = 0;
   array->StrideB = 0;
   array->Ptr = NULL;
   array->Enabled = GL_FALSE;
   array->Normalized = GL_FALSE;
   array->Integer = GL_FALSE;
   array->_ElementSize = size * _mesa_sizeof_type(type);
   /* Vertex array buffers */
   _mesa_reference_buffer_object(ctx, &array->BufferObj,
                                 ctx->Shared->NullBufferObj);
}
Example #7
0
static void flush_vertex( struct split_context *split )
{
   struct gl_context *ctx = split->ctx;
   const struct gl_vertex_array **saved_arrays = ctx->Array._DrawArrays;
   struct _mesa_index_buffer ib;
   GLuint i;

   if (!split->dstprim_nr) 
      return;

   if (split->ib) {
      ib = *split->ib;

      ib.count = split->max_index - split->min_index + 1;
      ib.ptr = (const void *)((const char *)ib.ptr + 
                              split->min_index * _mesa_sizeof_type(ib.type));

      /* Rebase the primitives to save index buffer entries. */
      for (i = 0; i < split->dstprim_nr; i++)
	 split->dstprim[i].start -= split->min_index;
   }

   assert(split->max_index >= split->min_index);

   ctx->Array._DrawArrays = split->array;
   ctx->NewDriverState |= ctx->DriverFlags.NewArray;

   split->draw(ctx,
	       split->dstprim,
	       split->dstprim_nr,
	       split->ib ? &ib : NULL,
	       !split->ib,
	       split->min_index,
	       split->max_index,
	       NULL, 0, NULL);

   ctx->Array._DrawArrays = saved_arrays;
   ctx->NewDriverState |= ctx->DriverFlags.NewArray;

   split->dstprim_nr = 0;
   split->min_index = ~0;
   split->max_index = 0;
}
Example #8
0
static void
init_array(struct gl_context *ctx,
           struct gl_client_array *array, GLint size, GLint type)
{
   array->Size = size;
   array->Type = type;
   array->Format = GL_RGBA; /* only significant for GL_EXT_vertex_array_bgra */
   array->Stride = 0;
   array->StrideB = 0;
   array->Ptr = NULL;
   array->Enabled = GL_FALSE;
   array->Normalized = GL_FALSE;
   array->_ElementSize = size * _mesa_sizeof_type(type);
#if FEATURE_ARB_vertex_buffer_object
   /* Vertex array buffers */
   _mesa_reference_buffer_object(ctx, &array->BufferObj,
                                 ctx->Shared->NullBufferObj);
#endif
}
Example #9
0
static GLuint attr_size( const struct gl_client_array *array )
{
   return array->Size * _mesa_sizeof_type(array->Type);
}
Example #10
0
static void brw_upload_indices(struct brw_context *brw)
{
   struct gl_context *ctx = &brw->ctx;
   const struct _mesa_index_buffer *index_buffer = brw->ib.ib;
   GLuint ib_size;
   drm_intel_bo *old_bo = brw->ib.bo;
   struct gl_buffer_object *bufferobj;
   GLuint offset;
   GLuint ib_type_size;

   if (index_buffer == NULL)
      return;

   ib_type_size = _mesa_sizeof_type(index_buffer->type);
   ib_size = ib_type_size * index_buffer->count;
   bufferobj = index_buffer->obj;

   /* Turn into a proper VBO:
    */
   if (!_mesa_is_bufferobj(bufferobj)) {
      /* Get new bufferobj, offset:
       */
      intel_upload_data(brw, index_buffer->ptr, ib_size, ib_type_size,
			&brw->ib.bo, &offset);
   } else {
      offset = (GLuint) (unsigned long) index_buffer->ptr;

      /* If the index buffer isn't aligned to its element size, we have to
       * rebase it into a temporary.
       */
      if ((ib_type_size - 1) & offset) {
         perf_debug("copying index buffer to a temporary to work around "
                    "misaligned offset %d\n", offset);

         GLubyte *map = ctx->Driver.MapBufferRange(ctx,
                                                   offset,
                                                   ib_size,
                                                   GL_MAP_READ_BIT,
                                                   bufferobj,
                                                   MAP_INTERNAL);

         intel_upload_data(brw, map, ib_size, ib_type_size,
                           &brw->ib.bo, &offset);

         ctx->Driver.UnmapBuffer(ctx, bufferobj, MAP_INTERNAL);
      } else {
         drm_intel_bo *bo =
            intel_bufferobj_buffer(brw, intel_buffer_object(bufferobj),
                                   offset, ib_size);
         if (bo != brw->ib.bo) {
            drm_intel_bo_unreference(brw->ib.bo);
            brw->ib.bo = bo;
            drm_intel_bo_reference(bo);
         }
      }
   }

   /* Use 3DPRIMITIVE's start_vertex_offset to avoid re-uploading
    * the index buffer state when we're just moving the start index
    * of our drawing.
    */
   brw->ib.start_vertex_offset = offset / ib_type_size;

   if (brw->ib.bo != old_bo)
      brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER;

   if (index_buffer->type != brw->ib.type) {
      brw->ib.type = index_buffer->type;
      brw->state.dirty.brw |= BRW_NEW_INDEX_BUFFER;
   }
}
Example #11
0
/**
 * Called by VBO to draw arrays when in selection or feedback mode and
 * to implement glRasterPos.
 * 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,
		     GLboolean index_bounds_valid,
                     GLuint min_index,
                     GLuint max_index)
{
   struct st_context *st = ctx->st;
   struct pipe_context *pipe = st->pipe;
   struct draw_context *draw = st->draw;
   const struct st_vertex_program *vp;
   const struct pipe_shader_state *vs;
   struct pipe_buffer *index_buffer_handle = 0;
   struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
   GLuint attr, i;
   ubyte *mapped_constants;

   assert(draw);

   st_validate_state(ctx->st);

   if (!index_bounds_valid)
      vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);

   /* must get these after state validation! */
   vp = ctx->st->vp;
   vs = &st->vp->state;

   if (!st->vp->draw_shader) {
      st->vp->draw_shader = draw_create_vertex_shader(draw, vs);
   }

   /*
    * 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_rasterizer_state(draw, &st->state.rasterizer);
   draw_bind_vertex_shader(draw, st->vp->draw_shader);
   set_feedback_vertex_format(ctx);

   /* loop over TGSI shader inputs to determine vertex buffer
    * and attribute info
    */
   for (attr = 0; attr < vp->num_inputs; attr++) {
      const GLuint mesaAttr = vp->index_to_input[attr];
      struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
      void *map;

      if (bufobj && bufobj->Name) {
         /* Attribute data is in a VBO.
          * Recall that for VBOs, the gl_client_array->Ptr field is
          * really an offset from the start of the VBO, not a pointer.
          */
         struct st_buffer_object *stobj = st_buffer_object(bufobj);
         assert(stobj->buffer);

         vbuffers[attr].buffer = NULL;
         pipe_buffer_reference(&vbuffers[attr].buffer, stobj->buffer);
         vbuffers[attr].buffer_offset = pointer_to_offset(arrays[0]->Ptr);
         velements[attr].src_offset = arrays[mesaAttr]->Ptr - arrays[0]->Ptr;
      }
      else {
         /* 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 */
         vbuffers[attr].buffer
            = pipe_user_buffer_create(pipe->screen, (void *) arrays[mesaAttr]->Ptr,
                                      bytes);
         vbuffers[attr].buffer_offset = 0;
         velements[attr].src_offset = 0;
      }

      /* common-case setup */
      vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */
      vbuffers[attr].max_index = max_index;
      velements[attr].vertex_buffer_index = attr;
      velements[attr].nr_components = arrays[mesaAttr]->Size;
      velements[attr].src_format = 
         st_pipe_vertex_format(arrays[mesaAttr]->Type,
                               arrays[mesaAttr]->Size,
                               arrays[mesaAttr]->Format,
                               arrays[mesaAttr]->Normalized);
      assert(velements[attr].src_format);

      /* tell draw about this attribute */
#if 0
      draw_set_vertex_buffer(draw, attr, &vbuffer[attr]);
#endif

      /* map the attrib buffer */
      map = pipe_buffer_map(pipe->screen, vbuffers[attr].buffer,
                            PIPE_BUFFER_USAGE_CPU_READ);
      draw_set_mapped_vertex_buffer(draw, attr, map);
   }

   draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
   draw_set_vertex_elements(draw, vp->num_inputs, velements);

   if (ib) {
      struct gl_buffer_object *bufobj = ib->obj;
      unsigned indexSize;
      void *map;

      switch (ib->type) {
      case GL_UNSIGNED_INT:
         indexSize = 4;
         break;
      case GL_UNSIGNED_SHORT:
         indexSize = 2;
         break;
      default:
         assert(0);
	 return;
      }

      if (bufobj && bufobj->Name) {
         struct st_buffer_object *stobj = st_buffer_object(bufobj);

         index_buffer_handle = stobj->buffer;

         map = pipe_buffer_map(pipe->screen, index_buffer_handle,
                               PIPE_BUFFER_USAGE_CPU_READ);

         draw_set_mapped_element_buffer(draw, indexSize, map);
      }
      else {
         draw_set_mapped_element_buffer(draw, indexSize, (void *) ib->ptr);
      }
   }
   else {
      /* no index/element buffer */
      draw_set_mapped_element_buffer(draw, 0, NULL);
   }


   /* map constant buffers */
   mapped_constants = pipe_buffer_map(pipe->screen,
                                      st->state.constants[PIPE_SHADER_VERTEX].buffer,
                                      PIPE_BUFFER_USAGE_CPU_READ);
   draw_set_mapped_constant_buffer(st->draw, mapped_constants,
                                   st->state.constants[PIPE_SHADER_VERTEX].buffer->size);


   /* draw here */
   for (i = 0; i < nr_prims; i++) {
      draw_arrays(draw, prims[i].mode, prims[i].start, prims[i].count);
   }


   /* unmap constant buffers */
   pipe_buffer_unmap(pipe->screen, st->state.constants[PIPE_SHADER_VERTEX].buffer);

   /*
    * unmap vertex/index buffers
    */
   for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
      if (draw->pt.vertex_buffer[i].buffer) {
         pipe_buffer_unmap(pipe->screen, draw->pt.vertex_buffer[i].buffer);
         pipe_buffer_reference(&draw->pt.vertex_buffer[i].buffer, NULL);
         draw_set_mapped_vertex_buffer(draw, i, NULL);
      }
   }
   if (index_buffer_handle) {
      pipe_buffer_unmap(pipe->screen, index_buffer_handle);
      draw_set_mapped_element_buffer(draw, 0, NULL);
   }
}
Example #12
0
/**
 * Called by VBO to draw arrays when in selection or feedback mode and
 * to implement glRasterPos.
 * This is very much like the normal draw_vbo() function above.
 * Look at code refactoring some day.
 */
void
st_feedback_draw_vbo(struct gl_context *ctx,
                     const struct gl_client_array **arrays,
                     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_context *pipe = st->pipe;
   struct draw_context *draw = st->draw;
   const struct st_vertex_program *vp;
   const struct pipe_shader_state *vs;
   struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
   struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
   struct pipe_index_buffer ibuffer;
   struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
   struct pipe_transfer *ib_transfer = NULL;
   GLuint attr, i;
   const GLubyte *low_addr = NULL;
   const void *mapped_indices = NULL;

   assert(draw);

   st_validate_state(st);

   if (!index_bounds_valid)
      vbo_get_minmax_indices(ctx, prims, ib, &min_index, &max_index, nr_prims);

   /* must get these after state validation! */
   vp = st->vp;
   vs = &st->vp_variant->tgsi;

   if (!st->vp_variant->draw_shader) {
      st->vp_variant->draw_shader = draw_create_vertex_shader(draw, vs);
   }

   /*
    * 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_rasterizer_state(draw, &st->state.rasterizer, NULL);
   draw_bind_vertex_shader(draw, st->vp_variant->draw_shader);
   set_feedback_vertex_format(ctx);

   /* Find the lowest address of the arrays we're drawing */
   if (vp->num_inputs) {
      low_addr = arrays[vp->index_to_input[0]]->Ptr;

      for (attr = 1; attr < vp->num_inputs; attr++) {
         const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr;
         low_addr = MIN2(low_addr, start);
      }
   }

   /* loop over TGSI shader inputs to determine vertex buffer
    * and attribute info
    */
   for (attr = 0; attr < vp->num_inputs; attr++) {
      const GLuint mesaAttr = vp->index_to_input[attr];
      struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
      void *map;

      if (bufobj && bufobj->Name) {
         /* Attribute data is in a VBO.
          * Recall that for VBOs, the gl_client_array->Ptr field is
          * really an offset from the start of the VBO, not a pointer.
          */
         struct st_buffer_object *stobj = st_buffer_object(bufobj);
         assert(stobj->buffer);

         vbuffers[attr].buffer = NULL;
         pipe_resource_reference(&vbuffers[attr].buffer, stobj->buffer);
         vbuffers[attr].buffer_offset = pointer_to_offset(low_addr);
         velements[attr].src_offset = arrays[mesaAttr]->Ptr - low_addr;
      }
      else {
         /* 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 */
         vbuffers[attr].buffer
            = pipe_user_buffer_create(pipe->screen, (void *) arrays[mesaAttr]->Ptr,
                                      bytes,
				      PIPE_BIND_VERTEX_BUFFER);
         vbuffers[attr].buffer_offset = 0;
         velements[attr].src_offset = 0;
      }

      /* common-case setup */
      vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */
      velements[attr].instance_divisor = 0;
      velements[attr].vertex_buffer_index = attr;
      velements[attr].src_format = 
         st_pipe_vertex_format(arrays[mesaAttr]->Type,
                               arrays[mesaAttr]->Size,
                               arrays[mesaAttr]->Format,
                               arrays[mesaAttr]->Normalized,
                               arrays[mesaAttr]->Integer);
      assert(velements[attr].src_format);

      /* tell draw about this attribute */
#if 0
      draw_set_vertex_buffer(draw, attr, &vbuffer[attr]);
#endif

      /* map the attrib buffer */
      map = pipe_buffer_map(pipe, vbuffers[attr].buffer,
                            PIPE_TRANSFER_READ,
			    &vb_transfer[attr]);
      draw_set_mapped_vertex_buffer(draw, attr, map);
   }

   draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
   draw_set_vertex_elements(draw, vp->num_inputs, velements);

   memset(&ibuffer, 0, sizeof(ibuffer));
   if (ib) {
      struct gl_buffer_object *bufobj = ib->obj;

      ibuffer.index_size = vbo_sizeof_ib_type(ib->type);
      if (ibuffer.index_size == 0)
         goto out_unref_vertex;

      if (bufobj && bufobj->Name) {
         struct st_buffer_object *stobj = st_buffer_object(bufobj);

         pipe_resource_reference(&ibuffer.buffer, stobj->buffer);
         ibuffer.offset = pointer_to_offset(ib->ptr);

         mapped_indices = pipe_buffer_map(pipe, stobj->buffer,
                                          PIPE_TRANSFER_READ, &ib_transfer);
      }
      else {
         /* skip setting ibuffer.buffer as the draw module does not use it */
         mapped_indices = ib->ptr;
      }

      draw_set_index_buffer(draw, &ibuffer);
      draw_set_mapped_index_buffer(draw, mapped_indices);
   }

   /* set the constant buffer */
   draw_set_mapped_constant_buffer(st->draw, PIPE_SHADER_VERTEX, 0,
                                   st->state.constants[PIPE_SHADER_VERTEX].ptr,
                                   st->state.constants[PIPE_SHADER_VERTEX].size);


   /* 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
    */
   if (ib) {
      draw_set_mapped_index_buffer(draw, NULL);
      draw_set_index_buffer(draw, NULL);

      if (ib_transfer)
         pipe_buffer_unmap(pipe, ib_transfer);
      pipe_resource_reference(&ibuffer.buffer, NULL);
   }

 out_unref_vertex:
   for (attr = 0; attr < vp->num_inputs; attr++) {
      pipe_buffer_unmap(pipe, vb_transfer[attr]);
      draw_set_mapped_vertex_buffer(draw, attr, NULL);
      pipe_resource_reference(&vbuffers[attr].buffer, NULL);
   }
   draw_set_vertex_buffers(draw, 0, NULL);
}
Example #13
0
/**
 * Do error checking and update state for glVertex/Color/TexCoord/...Pointer
 * functions.
 *
 * \param func  name of calling function used for error reporting
 * \param attrib  the attribute array index to update
 * \param legalTypes  bitmask of *_BIT above indicating legal datatypes
 * \param sizeMin  min allowable size value
 * \param sizeMax  max allowable size value (may also be BGRA_OR_4)
 * \param size  components per element (1, 2, 3 or 4)
 * \param type  datatype of each component (GL_FLOAT, GL_INT, etc)
 * \param stride  stride between elements, in elements
 * \param normalized  are integer types converted to floats in [-1, 1]?
 * \param integer  integer-valued values (will not be normalized to [-1,1])
 * \param ptr  the address (or offset inside VBO) of the array data
 */
static void
update_array(struct gl_context *ctx,
             const char *func,
             GLuint attrib, GLbitfield legalTypesMask,
             GLint sizeMin, GLint sizeMax,
             GLint size, GLenum type, GLsizei stride,
             GLboolean normalized, GLboolean integer,
             const GLvoid *ptr)
{
   struct gl_client_array *array;
   GLbitfield typeBit;
   GLsizei elementSize;
   GLenum format = GL_RGBA;

   if (_mesa_is_gles(ctx)) {
      /* Once Mesa gets support for GL_OES_vertex_half_float this mask will
       * change.  Adding support for this extension isn't quite as trivial as
       * we'd like because ES uses a different enum value for GL_HALF_FLOAT.
       */
      legalTypesMask &= ~(FIXED_GL_BIT | HALF_BIT | DOUBLE_BIT);

      /* GL_INT and GL_UNSIGNED_INT data is not allowed in OpenGL ES until
       * 3.0.  The 2_10_10_10 types are added in OpenGL ES 3.0 or
       * GL_OES_vertex_type_10_10_10_2.
       */
      if (ctx->Version < 30) {
         legalTypesMask &= ~(UNSIGNED_INT_BIT
                             | INT_BIT
                             | UNSIGNED_INT_2_10_10_10_REV_BIT
                             | INT_2_10_10_10_REV_BIT);
      }

      /* BGRA ordering is not supported in ES contexts.
       */
      if (sizeMax == BGRA_OR_4)
         sizeMax = 4;
   } else {
      legalTypesMask &= ~FIXED_ES_BIT;

      if (!ctx->Extensions.ARB_ES2_compatibility)
         legalTypesMask &= ~FIXED_GL_BIT;

      if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev)
         legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT |
                             INT_2_10_10_10_REV_BIT);
   }

   typeBit = type_to_bit(ctx, type);
   if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) {
      _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)",
                  func, _mesa_lookup_enum_by_nr(type));
      return;
   }

   /* Do size parameter checking.
    * If sizeMax = BGRA_OR_4 it means that size = GL_BGRA is legal and
    * must be handled specially.
    */
   if (ctx->Extensions.EXT_vertex_array_bgra &&
       sizeMax == BGRA_OR_4 &&
       size == GL_BGRA) {
      GLboolean bgra_error = GL_FALSE;

      if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) {
         if (type != GL_UNSIGNED_INT_2_10_10_10_REV &&
             type != GL_INT_2_10_10_10_REV &&
             type != GL_UNSIGNED_BYTE)
            bgra_error = GL_TRUE;
      } else if (type != GL_UNSIGNED_BYTE)
         bgra_error = GL_TRUE;

      if (bgra_error) {
         _mesa_error(ctx, GL_INVALID_VALUE, "%s(GL_BGRA/GLubyte)", func);
         return;
      }
      format = GL_BGRA;
      size = 4;
   }
   else if (size < sizeMin || size > sizeMax || size > 4) {
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size);
      return;
   }

   if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev &&
       (type == GL_UNSIGNED_INT_2_10_10_10_REV ||
        type == GL_INT_2_10_10_10_REV) && size != 4) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size);
      return;
   }

   ASSERT(size <= 4);

   if (stride < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride );
      return;
   }

   if (ctx->Array.ArrayObj->ARBsemantics &&
       !_mesa_is_bufferobj(ctx->Array.ArrayBufferObj)) {
      /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
       * Generate GL_INVALID_OPERATION if that's not true.
       */
      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-VBO array)", func);
      return;
   }

   elementSize = _mesa_sizeof_type(type) * size;

   array = &ctx->Array.ArrayObj->VertexAttrib[attrib];
   array->Size = size;
   array->Type = type;
   array->Format = format;
   array->Stride = stride;
   array->StrideB = stride ? stride : elementSize;
   array->Normalized = normalized;
   array->Integer = integer;
   array->Ptr = (const GLubyte *) ptr;
   array->_ElementSize = elementSize;

   _mesa_reference_buffer_object(ctx, &array->BufferObj,
                                 ctx->Array.ArrayBufferObj);

   ctx->NewState |= _NEW_ARRAY;
   ctx->Array.ArrayObj->NewArrays |= VERT_BIT(attrib);
}
Example #14
0
/**
 * Set up a separate pipe_vertex_buffer and pipe_vertex_element for each
 * vertex attribute.
 * \param vbuffer  returns vertex buffer info
 * \param velements  returns vertex element info
 */
static boolean
setup_non_interleaved_attribs(struct st_context *st,
                              const struct st_vertex_program *vp,
                              const struct st_vp_variant *vpv,
                              const struct gl_client_array **arrays,
                              struct pipe_vertex_buffer vbuffer[],
                              struct pipe_vertex_element velements[])
{
   struct gl_context *ctx = st->ctx;
   GLuint attr;

   for (attr = 0; attr < vpv->num_inputs; attr++) {
      const GLuint mesaAttr = vp->index_to_input[attr];
      const struct gl_client_array *array = arrays[mesaAttr];
      struct gl_buffer_object *bufobj = array->BufferObj;
      GLsizei stride = array->StrideB;

      assert(array->_ElementSize == array->Size * _mesa_sizeof_type(array->Type));

      if (_mesa_is_bufferobj(bufobj)) {
         /* Attribute data is in a VBO.
          * Recall that for VBOs, the gl_client_array->Ptr field is
          * really an offset from the start of the VBO, not a pointer.
          */
         struct st_buffer_object *stobj = st_buffer_object(bufobj);

         if (!stobj || !stobj->buffer) {
            return FALSE; /* out-of-memory error probably */
         }

         vbuffer[attr].buffer = stobj->buffer;
         vbuffer[attr].user_buffer = NULL;
         vbuffer[attr].buffer_offset = pointer_to_offset(array->Ptr);
      }
      else {
         /* wrap user data */
         void *ptr;

         if (array->Ptr) {
            ptr = (void *) array->Ptr;
         }
         else {
            /* no array, use ctx->Current.Attrib[] value */
            ptr = (void *) ctx->Current.Attrib[mesaAttr];
            stride = 0;
         }

         assert(ptr);

         vbuffer[attr].buffer = NULL;
         vbuffer[attr].user_buffer = ptr;
         vbuffer[attr].buffer_offset = 0;
      }

      /* common-case setup */
      vbuffer[attr].stride = stride; /* in bytes */

      velements[attr].src_offset = 0;
      velements[attr].instance_divisor = array->InstanceDivisor;
      velements[attr].vertex_buffer_index = attr;
      velements[attr].src_format = st_pipe_vertex_format(array->Type,
                                                         array->Size,
                                                         array->Format,
                                                         array->Normalized,
                                                         array->Integer);
      assert(velements[attr].src_format);
   }
   return TRUE;
}
Example #15
0
/**
 * Set up for drawing interleaved arrays that all live in one VBO
 * or all live in user space.
 * \param vbuffer  returns vertex buffer info
 * \param velements  returns vertex element info
 */
static boolean
setup_interleaved_attribs(const struct st_vertex_program *vp,
                          const struct st_vp_variant *vpv,
                          const struct gl_client_array **arrays,
                          struct pipe_vertex_buffer *vbuffer,
                          struct pipe_vertex_element velements[])
{
   GLuint attr;
   const GLubyte *low_addr = NULL;
   GLboolean usingVBO;      /* all arrays in a VBO? */
   struct gl_buffer_object *bufobj;
   GLsizei stride;

   /* Find the lowest address of the arrays we're drawing,
    * Init bufobj and stride.
    */
   if (vpv->num_inputs) {
      const GLuint mesaAttr0 = vp->index_to_input[0];
      const struct gl_client_array *array = arrays[mesaAttr0];

      /* Since we're doing interleaved arrays, we know there'll be at most
       * one buffer object and the stride will be the same for all arrays.
       * Grab them now.
       */
      bufobj = array->BufferObj;
      stride = array->StrideB;

      low_addr = arrays[vp->index_to_input[0]]->Ptr;

      for (attr = 1; attr < vpv->num_inputs; attr++) {
         const GLubyte *start = arrays[vp->index_to_input[attr]]->Ptr;
         low_addr = MIN2(low_addr, start);
      }
   }
   else {
      /* not sure we'll ever have zero inputs, but play it safe */
      bufobj = NULL;
      stride = 0;
      low_addr = 0;
   }

   /* are the arrays in user space? */
   usingVBO = _mesa_is_bufferobj(bufobj);

   for (attr = 0; attr < vpv->num_inputs; attr++) {
      const GLuint mesaAttr = vp->index_to_input[attr];
      const struct gl_client_array *array = arrays[mesaAttr];
      unsigned src_offset = (unsigned) (array->Ptr - low_addr);
      GLuint element_size = array->_ElementSize;

      assert(element_size == array->Size * _mesa_sizeof_type(array->Type));

      velements[attr].src_offset = src_offset;
      velements[attr].instance_divisor = array->InstanceDivisor;
      velements[attr].vertex_buffer_index = 0;
      velements[attr].src_format = st_pipe_vertex_format(array->Type,
                                                         array->Size,
                                                         array->Format,
                                                         array->Normalized,
                                                         array->Integer);
      assert(velements[attr].src_format);
   }

   /*
    * Return the vbuffer info and setup user-space attrib info, if needed.
    */
   if (vpv->num_inputs == 0) {
      /* just defensive coding here */
      vbuffer->buffer = NULL;
      vbuffer->user_buffer = NULL;
      vbuffer->buffer_offset = 0;
      vbuffer->stride = 0;
   }
   else if (usingVBO) {
      /* all interleaved arrays in a VBO */
      struct st_buffer_object *stobj = st_buffer_object(bufobj);

      if (!stobj || !stobj->buffer) {
         return FALSE; /* out-of-memory error probably */
      }

      vbuffer->buffer = stobj->buffer;
      vbuffer->user_buffer = NULL;
      vbuffer->buffer_offset = pointer_to_offset(low_addr);
      vbuffer->stride = stride;
   }
   else {
      /* all interleaved arrays in user memory */
      vbuffer->buffer = NULL;
      vbuffer->user_buffer = low_addr;
      vbuffer->buffer_offset = 0;
      vbuffer->stride = stride;
   }
   return TRUE;
}
Example #16
0
/**
 * Do error checking and update state for glVertex/Color/TexCoord/...Pointer
 * functions.
 *
 * \param func  name of calling function used for error reporting
 * \param attrib  the attribute array index to update
 * \param legalTypes  bitmask of *_BIT above indicating legal datatypes
 * \param sizeMin  min allowable size value
 * \param sizeMax  max allowable size value (may also be BGRA_OR_4)
 * \param size  components per element (1, 2, 3 or 4)
 * \param type  datatype of each component (GL_FLOAT, GL_INT, etc)
 * \param stride  stride between elements, in elements
 * \param normalized  are integer types converted to floats in [-1, 1]?
 * \param integer  integer-valued values (will not be normalized to [-1,1])
 * \param ptr  the address (or offset inside VBO) of the array data
 */
static void
update_array(struct gl_context *ctx,
             const char *func,
             GLuint attrib, GLbitfield legalTypesMask,
             GLint sizeMin, GLint sizeMax,
             GLint size, GLenum type, GLsizei stride,
             GLboolean normalized, GLboolean integer,
             const GLvoid *ptr)
{
   struct gl_client_array *array;
   GLbitfield typeBit;
   GLsizei elementSize;
   GLenum format = GL_RGBA;

   if (ctx->API != API_OPENGLES && ctx->API != API_OPENGLES2) {
      /* fixed point arrays / data is only allowed with OpenGL ES 1.x/2.0 */
      legalTypesMask &= ~FIXED_ES_BIT;
   }
   if (!ctx->Extensions.ARB_ES2_compatibility) {
      legalTypesMask &= ~FIXED_GL_BIT;
   }
   if (!ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) {
      legalTypesMask &= ~(UNSIGNED_INT_2_10_10_10_REV_BIT |
                          INT_2_10_10_10_REV_BIT);
   }

   typeBit = type_to_bit(ctx, type);
   if (typeBit == 0x0 || (typeBit & legalTypesMask) == 0x0) {
      _mesa_error(ctx, GL_INVALID_ENUM, "%s(type = %s)",
                  func, _mesa_lookup_enum_by_nr(type));
      return;
   }

   /* Do size parameter checking.
    * If sizeMax = BGRA_OR_4 it means that size = GL_BGRA is legal and
    * must be handled specially.
    */
   if (ctx->Extensions.EXT_vertex_array_bgra &&
       sizeMax == BGRA_OR_4 &&
       size == GL_BGRA) {
      GLboolean bgra_error = GL_FALSE;

      if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev) {
         if (type != GL_UNSIGNED_INT_2_10_10_10_REV &&
             type != GL_INT_2_10_10_10_REV &&
             type != GL_UNSIGNED_BYTE)
            bgra_error = GL_TRUE;
      } else if (type != GL_UNSIGNED_BYTE)
         bgra_error = GL_TRUE;

      if (bgra_error) {
         _mesa_error(ctx, GL_INVALID_VALUE, "%s(GL_BGRA/GLubyte)", func);
         return;
      }
      format = GL_BGRA;
      size = 4;
   }
   else if (size < sizeMin || size > sizeMax || size > 4) {
      _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", func, size);
      return;
   }

   if (ctx->Extensions.ARB_vertex_type_2_10_10_10_rev &&
       (type == GL_UNSIGNED_INT_2_10_10_10_REV ||
        type == GL_INT_2_10_10_10_REV) && size != 4) {
      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(size=%d)", func, size);
   }

   ASSERT(size <= 4);

   if (stride < 0) {
      _mesa_error( ctx, GL_INVALID_VALUE, "%s(stride=%d)", func, stride );
      return;
   }

   if (ctx->Array.ArrayObj->ARBsemantics &&
       !_mesa_is_bufferobj(ctx->Array.ArrayBufferObj)) {
      /* GL_ARB_vertex_array_object requires that all arrays reside in VBOs.
       * Generate GL_INVALID_OPERATION if that's not true.
       */
      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-VBO array)", func);
      return;
   }

   elementSize = _mesa_sizeof_type(type) * size;

   array = &ctx->Array.ArrayObj->VertexAttrib[attrib];
   array->Size = size;
   array->Type = type;
   array->Format = format;
   array->Stride = stride;
   array->StrideB = stride ? stride : elementSize;
   array->Normalized = normalized;
   array->Integer = integer;
   array->Ptr = (const GLubyte *) ptr;
   array->_ElementSize = elementSize;

   _mesa_reference_buffer_object(ctx, &array->BufferObj,
                                 ctx->Array.ArrayBufferObj);

   ctx->NewState |= _NEW_ARRAY;
   ctx->Array.NewState |= VERT_BIT(attrib);
}