static void
finalize_index_buffer(struct ilo_context *ilo)
{
   struct ilo_state_vector *vec = &ilo->state_vector;
   const bool need_upload = (vec->draw->indexed &&
         (vec->ib.user_buffer || vec->ib.offset % vec->ib.index_size));
   struct pipe_resource *current_hw_res = NULL;

   if (!(vec->dirty & ILO_DIRTY_IB) && !need_upload)
      return;

   pipe_resource_reference(&current_hw_res, vec->ib.hw_resource);

   if (need_upload) {
      const unsigned offset = vec->ib.index_size * vec->draw->start;
      const unsigned size = vec->ib.index_size * vec->draw->count;
      unsigned hw_offset;

      if (vec->ib.user_buffer) {
         u_upload_data(ilo->uploader, 0, size,
               vec->ib.user_buffer + offset, &hw_offset, &vec->ib.hw_resource);
      }
      else {
         u_upload_buffer(ilo->uploader, 0, vec->ib.offset + offset, size,
               vec->ib.buffer, &hw_offset, &vec->ib.hw_resource);
      }

      /* the HW offset should be aligned */
      assert(hw_offset % vec->ib.index_size == 0);
      vec->ib.draw_start_offset = hw_offset / vec->ib.index_size;

      /*
       * INDEX[vec->draw->start] in the original buffer is INDEX[0] in the HW
       * resource
       */
      vec->ib.draw_start_offset -= vec->draw->start;
   }
   else {
      pipe_resource_reference(&vec->ib.hw_resource, vec->ib.buffer);

      /* note that index size may be zero when the draw is not indexed */
      if (vec->draw->indexed)
         vec->ib.draw_start_offset = vec->ib.offset / vec->ib.index_size;
      else
         vec->ib.draw_start_offset = 0;
   }

   /* treat the IB as clean if the HW states do not change */
   if (vec->ib.hw_resource == current_hw_res &&
       vec->ib.hw_index_size == vec->ib.index_size)
      vec->dirty &= ~ILO_DIRTY_IB;
   else
      vec->ib.hw_index_size = vec->ib.index_size;

   pipe_resource_reference(&current_hw_res, NULL);
}
Beispiel #2
0
static int
svga_upload_user_buffers(struct svga_context *svga,
                         unsigned start,
                         unsigned count,
                         unsigned instance_count)
{
   const struct pipe_vertex_element *ve = svga->curr.velems->velem;
   unsigned i;
   int ret;

   svga_user_buffer_range(svga, start, count, instance_count);

   for (i=0; i < svga->curr.velems->count; i++) {
      struct pipe_vertex_buffer *vb =
         &svga->curr.vb[ve[i].vertex_buffer_index];

      if (vb->buffer && svga_buffer_is_user_buffer(vb->buffer)) {
         struct svga_buffer *buffer = svga_buffer(vb->buffer);

         /*
          * Check if already uploaded. Otherwise go ahead and upload.
          */

         if (buffer->uploaded.buffer)
            continue;

         ret = u_upload_buffer( svga->upload_vb,
                                0,
                                buffer->uploaded.start,
                                buffer->uploaded.end - buffer->uploaded.start,
                                &buffer->b.b,
                                &buffer->uploaded.offset,
                                &buffer->uploaded.buffer);

         if (ret)
            return ret;

         if (0)
            debug_printf("%s: %d: orig buf %p upl buf %p ofs %d sofs %d"
                         " sz %d\n",
                         __FUNCTION__,
                         i,
                         buffer,
                         buffer->uploaded.buffer,
                         buffer->uploaded.offset,
                         buffer->uploaded.start,
                         buffer->uploaded.end - buffer->uploaded.start);

         vb->buffer_offset = buffer->uploaded.offset;
      }
   }

   return PIPE_OK;
}
static int
upload_user_buffers( struct svga_context *svga )
{
   enum pipe_error ret = PIPE_OK;
   int i;
   int nr;

   if (0) 
      debug_printf("%s: %d\n", __FUNCTION__, svga->curr.num_vertex_buffers);

   nr = svga->curr.num_vertex_buffers;

   for (i = 0; i < nr; i++) 
   {
      if (svga_buffer_is_user_buffer(svga->curr.vb[i].buffer))
      {
         struct svga_buffer *buffer = svga_buffer(svga->curr.vb[i].buffer);

         if (!buffer->uploaded.buffer) {
            ret = u_upload_buffer( svga->upload_vb,
                                   0,
                                   buffer->base.size,
                                   &buffer->base,
                                   &buffer->uploaded.offset,
                                   &buffer->uploaded.buffer );
            if (ret)
               return ret;

            if (0)
               debug_printf("%s: %d: orig buf %p upl buf %p ofs %d sz %d\n",
                            __FUNCTION__,
                            i,
                            buffer,
                            buffer->uploaded.buffer,
                            buffer->uploaded.offset,
                            buffer->base.size);
         }

         pipe_buffer_reference( &svga->curr.vb[i].buffer, buffer->uploaded.buffer );
         svga->curr.vb[i].buffer_offset = buffer->uploaded.offset;
      }
   }

   if (0)
      debug_printf("%s: DONE\n", __FUNCTION__);

   return ret;
}
enum pipe_error
svga_hwtnl_simple_draw_range_elements( struct svga_hwtnl *hwtnl,
                                       struct pipe_resource *index_buffer,
                                       unsigned index_size,
                                       int index_bias,
                                       unsigned min_index,
                                       unsigned max_index,
                                       unsigned prim,
                                       unsigned start,
                                       unsigned count )
{
   struct pipe_resource *upload_buffer = NULL;
   SVGA3dPrimitiveRange range;
   unsigned hw_prim;
   unsigned hw_count;
   unsigned index_offset = start * index_size;
   enum pipe_error ret = PIPE_OK;

   hw_prim = svga_translate_prim(prim, count, &hw_count);
   if (hw_count == 0)
      goto done;

   if (index_buffer &&
       svga_buffer_is_user_buffer(index_buffer))
   {
      assert( index_buffer->width0 >= index_offset + count * index_size );

      ret = u_upload_buffer( hwtnl->upload_ib,
                             0,
                             index_offset,
                             count * index_size,
                             index_buffer,
                             &index_offset,
                             &upload_buffer);
      if (ret != PIPE_OK)
         goto done;

      /* Don't need to worry about refcounting index_buffer as this is
       * just a stack variable without a counted reference of its own.
       * The caller holds the reference.
       */
      index_buffer = upload_buffer;
   }

   range.primType = hw_prim;
   range.primitiveCount = hw_count;
   range.indexArray.offset = index_offset;
   range.indexArray.stride = index_size;
   range.indexWidth = index_size;
   range.indexBias = index_bias;

   ret = svga_hwtnl_prim( hwtnl, &range, min_index, max_index, index_buffer );
   if (ret != PIPE_OK)
      goto done;

done:
   if (upload_buffer)
      pipe_resource_reference( &upload_buffer, NULL );

   return ret;
}