Esempio n. 1
0
void
st_setup_current_user(struct st_context *st,
                      const struct st_vertex_program *vp,
                      const struct st_vp_variant *vp_variant,
                      struct pipe_vertex_element *velements,
                      struct pipe_vertex_buffer *vbuffer, unsigned *num_vbuffers)
{
   struct gl_context *ctx = st->ctx;
   const GLbitfield inputs_read = vp_variant->vert_attrib_mask;
   const ubyte *input_to_index = vp->input_to_index;

   /* Process values that should have better been uniforms in the application */
   GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx);
   /* For each attribute, make an own user buffer binding. */
   while (curmask) {
      const gl_vert_attrib attr = u_bit_scan(&curmask);
      const struct gl_array_attributes *const attrib
         = _mesa_draw_current_attrib(ctx, attr);
      const unsigned bufidx = (*num_vbuffers)++;

      init_velement_lowered(vp, velements, &attrib->Format, 0, 0,
                            bufidx, input_to_index[attr]);

      vbuffer[bufidx].is_user_buffer = true;
      vbuffer[bufidx].buffer.user = attrib->Ptr;
      vbuffer[bufidx].buffer_offset = 0;
      vbuffer[bufidx].stride = 0;
   }
}
Esempio n. 2
0
void
st_setup_arrays(struct st_context *st,
                const struct st_vertex_program *vp,
                const struct st_vp_variant *vp_variant,
                struct pipe_vertex_element *velements,
                struct pipe_vertex_buffer *vbuffer, unsigned *num_vbuffers)
{
   struct gl_context *ctx = st->ctx;
   const struct gl_vertex_array_object *vao = ctx->Array._DrawVAO;
   const GLbitfield inputs_read = vp_variant->vert_attrib_mask;
   const ubyte *input_to_index = vp->input_to_index;

   /* Process attribute array data. */
   GLbitfield mask = inputs_read & _mesa_draw_array_bits(ctx);
   while (mask) {
      /* The attribute index to start pulling a binding */
      const gl_vert_attrib i = ffs(mask) - 1;
      const struct gl_vertex_buffer_binding *const binding
         = _mesa_draw_buffer_binding(vao, i);
      const unsigned bufidx = (*num_vbuffers)++;

      if (_mesa_is_bufferobj(binding->BufferObj)) {
         /* Set the binding */
         struct st_buffer_object *stobj = st_buffer_object(binding->BufferObj);
         vbuffer[bufidx].buffer.resource = stobj ? stobj->buffer : NULL;
         vbuffer[bufidx].is_user_buffer = false;
         vbuffer[bufidx].buffer_offset = _mesa_draw_binding_offset(binding);
      } else {
         /* Set the binding */
         const void *ptr = (const void *)_mesa_draw_binding_offset(binding);
         vbuffer[bufidx].buffer.user = ptr;
         vbuffer[bufidx].is_user_buffer = true;
         vbuffer[bufidx].buffer_offset = 0;

         if (!binding->InstanceDivisor)
            st->draw_needs_minmax_index = true;
      }
      vbuffer[bufidx].stride = binding->Stride; /* in bytes */

      const GLbitfield boundmask = _mesa_draw_bound_attrib_bits(binding);
      GLbitfield attrmask = mask & boundmask;
      /* Mark the those attributes as processed */
      mask &= ~boundmask;
      /* We can assume that we have array for the binding */
      assert(attrmask);
      /* Walk attributes belonging to the binding */
      while (attrmask) {
         const gl_vert_attrib attr = u_bit_scan(&attrmask);
         const struct gl_array_attributes *const attrib
            = _mesa_draw_array_attrib(vao, attr);
         const GLuint off = _mesa_draw_attributes_relative_offset(attrib);
         init_velement_lowered(vp, velements, &attrib->Format, off,
                               binding->InstanceDivisor, bufidx,
                               input_to_index[attr]);
      }
   }
}
Esempio n. 3
0
void
st_setup_current(struct st_context *st,
                 const struct st_vertex_program *vp,
                 const struct st_vp_variant *vp_variant,
                 struct pipe_vertex_element *velements,
                 struct pipe_vertex_buffer *vbuffer, unsigned *num_vbuffers)
{
   struct gl_context *ctx = st->ctx;
   const GLbitfield inputs_read = vp_variant->vert_attrib_mask;

   /* Process values that should have better been uniforms in the application */
   GLbitfield curmask = inputs_read & _mesa_draw_current_bits(ctx);
   if (curmask) {
      /* vertex program validation must be done before this */
      const struct st_vertex_program *vp = st->vp;
      const ubyte *input_to_index = vp->input_to_index;
      /* For each attribute, upload the maximum possible size. */
      GLubyte data[VERT_ATTRIB_MAX * sizeof(GLdouble) * 4];
      GLubyte *cursor = data;
      const unsigned bufidx = (*num_vbuffers)++;
      unsigned max_alignment = 1;

      while (curmask) {
         const gl_vert_attrib attr = u_bit_scan(&curmask);
         const struct gl_array_attributes *const attrib
            = _mesa_draw_current_attrib(ctx, attr);
         const unsigned size = attrib->Format._ElementSize;
         const unsigned alignment = util_next_power_of_two(size);
         max_alignment = MAX2(max_alignment, alignment);
         memcpy(cursor, attrib->Ptr, size);
         if (alignment != size)
            memset(cursor + size, 0, alignment - size);

         init_velement_lowered(vp, velements, &attrib->Format, cursor - data, 0,
                               bufidx, input_to_index[attr]);

         cursor += alignment;
      }

      vbuffer[bufidx].is_user_buffer = false;
      vbuffer[bufidx].buffer.resource = NULL;
      /* vbuffer[bufidx].buffer_offset is set below */
      vbuffer[bufidx].stride = 0;

      /* Use const_uploader for zero-stride vertex attributes, because
       * it may use a better memory placement than stream_uploader.
       * The reason is that zero-stride attributes can be fetched many
       * times (thousands of times), so a better placement is going to
       * perform better.
       */
      struct u_upload_mgr *uploader = st->can_bind_const_buffer_as_vertex ?
                                      st->pipe->const_uploader :
                                      st->pipe->stream_uploader;
      u_upload_data(uploader,
                    0, cursor - data, max_alignment, data,
                    &vbuffer[bufidx].buffer_offset,
                    &vbuffer[bufidx].buffer.resource);
      /* Always unmap. The uploader might use explicit flushes. */
      u_upload_unmap(uploader);
   }
}
Esempio n. 4
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[],
                              unsigned *num_velements)
{
   struct gl_context *ctx = st->ctx;
   GLuint attr, attr_idx = 0;

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

      array = get_client_array(vp, arrays, attr);
      if (!array) {
         vbuffer[attr].buffer = NULL;
         vbuffer[attr].user_buffer = NULL;
         vbuffer[attr].buffer_offset = 0;
         continue;
      }

      stride = array->StrideB;
      bufobj = array->BufferObj;
      assert(array->_ElementSize ==
             _mesa_bytes_per_vertex_attrib(array->Size, 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 */

      src_format = st_pipe_vertex_format(array->Type,
                                         array->Size,
                                         array->Format,
                                         array->Normalized,
                                         array->Integer);

      init_velement_lowered(st, velements, 0, src_format,
                            array->InstanceDivisor, attr,
                            array->Size, array->Doubles, &attr_idx);

   }

   *num_velements = attr_idx;
   return TRUE;
}
Esempio n. 5
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(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[],
                          unsigned *num_velements)
{
   GLuint attr, attr_idx;
   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 struct gl_client_array *array;

      array = get_client_array(vp, arrays, 0);
      assert(array);

      /* 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;
         array = get_client_array(vp, arrays, attr);
         if (!array)
            continue;
         start = array->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);

   attr_idx = 0;
   for (attr = 0; attr < vpv->num_inputs; attr++) {
      const struct gl_client_array *array;
      unsigned src_offset;
      unsigned src_format;

      array = get_client_array(vp, arrays, attr);
      if (!array)
         continue;

      src_offset = (unsigned) (array->Ptr - low_addr);
      assert(array->_ElementSize ==
             _mesa_bytes_per_vertex_attrib(array->Size, array->Type));

      src_format = st_pipe_vertex_format(array->Type,
                                         array->Size,
                                         array->Format,
                                         array->Normalized,
                                         array->Integer);

      init_velement_lowered(st, velements, src_offset, src_format,
                            array->InstanceDivisor, 0,
                            array->Size, array->Doubles, &attr_idx);
   }

   *num_velements = attr_idx;

   /*
    * 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;
}