Example #1
0
static void
svga_vbuf_render_draw_arrays( struct vbuf_render *render,
                              unsigned start,
                              uint nr )
{
   struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
   struct svga_context *svga = svga_render->svga;
   unsigned bias = (svga_render->vbuf_offset - svga_render->vdecl_offset) / svga_render->vertex_size;
   enum pipe_error ret = PIPE_OK;

   /* off to hardware */
   svga_vbuf_submit_state(svga_render);

   /* Need to call update_state() again as the draw module may have
    * altered some of our state behind our backs.  Testcase:
    * redbook/polys.c
    */
   svga_update_state_retry( svga, SVGA_STATE_HW_DRAW );

   ret = svga_hwtnl_draw_arrays(svga->hwtnl, svga_render->prim, start + bias, nr);
   if (ret != PIPE_OK) {
      svga_context_flush(svga, NULL);
      ret = svga_hwtnl_draw_arrays(svga->hwtnl, svga_render->prim, start + bias, nr);
      svga->swtnl.new_vbuf = TRUE;
      assert(ret == PIPE_OK);
   }
}
Example #2
0
static void
svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
   struct svga_context *svga = svga_context( pipe );
   unsigned reduced_prim = u_reduced_prim( info->mode );
   unsigned count = info->count;
   enum pipe_error ret = 0;
   boolean needed_swtnl;

   if (!u_trim_pipe_prim( info->mode, &count ))
      return;

   /*
    * Mark currently bound target surfaces as dirty
    * doesn't really matter if it is done before drawing.
    *
    * TODO If we ever normaly return something other then
    * true we should not mark it as dirty then.
    */
   svga_mark_surfaces_dirty(svga_context(pipe));

   if (svga->curr.reduced_prim != reduced_prim) {
      svga->curr.reduced_prim = reduced_prim;
      svga->dirty |= SVGA_NEW_REDUCED_PRIMITIVE;
   }
   
   needed_swtnl = svga->state.sw.need_swtnl;

   svga_update_state_retry( svga, SVGA_STATE_NEED_SWTNL );

#ifdef DEBUG
   if (svga->curr.vs->base.id == svga->debug.disable_shader ||
       svga->curr.fs->base.id == svga->debug.disable_shader)
      return;
#endif

   if (svga->state.sw.need_swtnl) {
      if (!needed_swtnl) {
         /*
          * We're switching from HW to SW TNL.  SW TNL will require mapping all
          * currently bound vertex buffers, some of which may already be
          * referenced in the current command buffer as result of previous HW
          * TNL. So flush now, to prevent the context to flush while a referred
          * vertex buffer is mapped.
          */

         svga_context_flush(svga, NULL);
      }

      /* Avoid leaking the previous hwtnl bias to swtnl */
      svga_hwtnl_set_index_bias( svga->hwtnl, 0 );
      ret = svga_swtnl_draw_vbo( svga, info );
   }
   else {
      if (info->indexed && svga->curr.ib.buffer) {
         unsigned offset;

         assert(svga->curr.ib.offset % svga->curr.ib.index_size == 0);
         offset = svga->curr.ib.offset / svga->curr.ib.index_size;

         ret = retry_draw_range_elements( svga,
                                          svga->curr.ib.buffer,
                                          svga->curr.ib.index_size,
                                          info->index_bias,
                                          info->min_index,
                                          info->max_index,
                                          info->mode,
                                          info->start + offset,
                                          info->count,
                                          info->instance_count,
                                          TRUE );
      }
      else {
         ret = retry_draw_arrays( svga,
                                  info->mode,
                                  info->start,
                                  info->count,
                                  info->instance_count,
                                  TRUE );
      }
   }

   /* XXX: Silence warnings, do something sensible here? */
   (void)ret;

   svga_release_user_upl_buffers( svga );

   if (SVGA_DEBUG & DEBUG_FLUSH) {
      svga_hwtnl_flush_retry( svga );
      svga_context_flush(svga, NULL);
   }
}
Example #3
0
static void
svga_vbuf_render_draw_elements( struct vbuf_render *render,
                                const ushort *indices,
                                uint nr_indices)
{
   struct svga_vbuf_render *svga_render = svga_vbuf_render(render);
   struct svga_context *svga = svga_render->svga;
   struct pipe_screen *screen = svga->pipe.screen;
   int bias = (svga_render->vbuf_offset - svga_render->vdecl_offset) / svga_render->vertex_size;
   boolean ret;
   size_t size = 2 * nr_indices;

   assert(( svga_render->vbuf_offset - svga_render->vdecl_offset) % svga_render->vertex_size == 0);
   
   if (svga_render->ibuf_size < svga_render->ibuf_offset + size)
      pipe_resource_reference(&svga_render->ibuf, NULL);

   if (!svga_render->ibuf) {
      svga_render->ibuf_size = MAX2(size, svga_render->ibuf_alloc_size);
      svga_render->ibuf = pipe_buffer_create(screen,
                                             PIPE_BIND_INDEX_BUFFER,
                                             PIPE_USAGE_STREAM,
                                             svga_render->ibuf_size);
      svga_render->ibuf_offset = 0;
   }

   pipe_buffer_write_nooverlap(&svga->pipe, svga_render->ibuf,
			       svga_render->ibuf_offset, 2 * nr_indices, indices);

   /* off to hardware */
   svga_vbuf_submit_state(svga_render);

   /* Need to call update_state() again as the draw module may have
    * altered some of our state behind our backs.  Testcase:
    * redbook/polys.c
    */
   svga_update_state_retry( svga, SVGA_STATE_HW_DRAW );

   ret = svga_hwtnl_draw_range_elements(svga->hwtnl,
                                        svga_render->ibuf,
                                        2,
                                        bias,
                                        svga_render->min_index,
                                        svga_render->max_index,
                                        svga_render->prim,
                                        svga_render->ibuf_offset / 2, nr_indices);
   if(ret != PIPE_OK) {
      svga_context_flush(svga, NULL);
      ret = svga_hwtnl_draw_range_elements(svga->hwtnl,
                                           svga_render->ibuf,
                                           2,
                                           bias,
                                           svga_render->min_index,
                                           svga_render->max_index,
                                           svga_render->prim,
                                           svga_render->ibuf_offset / 2, nr_indices);
      svga->swtnl.new_vbuf = TRUE;
      assert(ret == PIPE_OK);
   }

   svga_render->ibuf_offset += size;
}
Example #4
0
static void
svga_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info)
{
   struct svga_context *svga = svga_context( pipe );
   unsigned reduced_prim = u_reduced_prim( info->mode );
   unsigned count = info->count;
   enum pipe_error ret = 0;
   boolean needed_swtnl;

   SVGA_STATS_TIME_PUSH(svga_sws(svga), SVGA_STATS_TIME_DRAWVBO);

   svga->hud.num_draw_calls++;  /* for SVGA_QUERY_NUM_DRAW_CALLS */

   if (u_reduced_prim(info->mode) == PIPE_PRIM_TRIANGLES &&
       svga->curr.rast->templ.cull_face == PIPE_FACE_FRONT_AND_BACK)
      goto done;

   /*
    * Mark currently bound target surfaces as dirty
    * doesn't really matter if it is done before drawing.
    *
    * TODO If we ever normaly return something other then
    * true we should not mark it as dirty then.
    */
   svga_mark_surfaces_dirty(svga_context(pipe));

   if (svga->curr.reduced_prim != reduced_prim) {
      svga->curr.reduced_prim = reduced_prim;
      svga->dirty |= SVGA_NEW_REDUCED_PRIMITIVE;
   }

   if (need_fallback_prim_restart(svga, info)) {
      enum pipe_error r;
      r = util_draw_vbo_without_prim_restart(pipe, &svga->curr.ib, info);
      assert(r == PIPE_OK);
      (void) r;
      goto done;
   }

   if (!u_trim_pipe_prim( info->mode, &count ))
      goto done;

   needed_swtnl = svga->state.sw.need_swtnl;

   svga_update_state_retry( svga, SVGA_STATE_NEED_SWTNL );

   if (svga->state.sw.need_swtnl) {
      svga->hud.num_fallbacks++;  /* for SVGA_QUERY_NUM_FALLBACKS */
      if (!needed_swtnl) {
         /*
          * We're switching from HW to SW TNL.  SW TNL will require mapping all
          * currently bound vertex buffers, some of which may already be
          * referenced in the current command buffer as result of previous HW
          * TNL. So flush now, to prevent the context to flush while a referred
          * vertex buffer is mapped.
          */

         svga_context_flush(svga, NULL);
      }

      /* Avoid leaking the previous hwtnl bias to swtnl */
      svga_hwtnl_set_index_bias( svga->hwtnl, 0 );
      ret = svga_swtnl_draw_vbo( svga, info );
   }
   else {
      if (info->indexed && svga->curr.ib.buffer) {
         unsigned offset;

         assert(svga->curr.ib.offset % svga->curr.ib.index_size == 0);
         offset = svga->curr.ib.offset / svga->curr.ib.index_size;

         ret = retry_draw_range_elements( svga,
                                          svga->curr.ib.buffer,
                                          svga->curr.ib.index_size,
                                          info->index_bias,
                                          info->min_index,
                                          info->max_index,
                                          info->mode,
                                          info->start + offset,
                                          count,
                                          info->start_instance,
                                          info->instance_count,
                                          TRUE );
      }
      else {
         ret = retry_draw_arrays(svga, info->mode, info->start, count,
                                 info->start_instance, info->instance_count,
                                 TRUE);
      }
   }

   /* XXX: Silence warnings, do something sensible here? */
   (void)ret;

   if (SVGA_DEBUG & DEBUG_FLUSH) {
      svga_hwtnl_flush_retry( svga );
      svga_context_flush(svga, NULL);
   }

done:
   SVGA_STATS_TIME_POP(svga_sws(svga));
;
}
Example #5
0
static boolean
svga_draw_range_elements( struct pipe_context *pipe,
                          struct pipe_buffer *index_buffer,
                          unsigned index_size,
                          unsigned min_index,
                          unsigned max_index,
                          unsigned prim, unsigned start, unsigned count)
{
    struct svga_context *svga = svga_context( pipe );
    unsigned reduced_prim = u_reduced_prim(prim);
    enum pipe_error ret = 0;

    if (!u_trim_pipe_prim( prim, &count ))
        return TRUE;

    /*
     * Mark currently bound target surfaces as dirty
     * doesn't really matter if it is done before drawing.
     *
     * TODO If we ever normaly return something other then
     * true we should not mark it as dirty then.
     */
    svga_mark_surfaces_dirty(svga_context(pipe));

    if (svga->curr.reduced_prim != reduced_prim) {
        svga->curr.reduced_prim = reduced_prim;
        svga->dirty |= SVGA_NEW_REDUCED_PRIMITIVE;
    }

    svga_update_state_retry( svga, SVGA_STATE_NEED_SWTNL );

#ifdef DEBUG
    if (svga->curr.vs->base.id == svga->debug.disable_shader ||
            svga->curr.fs->base.id == svga->debug.disable_shader)
        return 0;
#endif

    if (svga->state.sw.need_swtnl)
    {
        ret = svga_swtnl_draw_range_elements( svga,
                                              index_buffer,
                                              index_size,
                                              min_index, max_index,
                                              prim,
                                              start, count );
    }
    else {
        if (index_buffer) {
            ret = retry_draw_range_elements( svga,
                                             index_buffer,
                                             index_size,
                                             min_index,
                                             max_index,
                                             prim,
                                             start,
                                             count,
                                             TRUE );
        }
        else {
            ret = retry_draw_arrays( svga,
                                     prim,
                                     start,
                                     count,
                                     TRUE );
        }
    }

    if (SVGA_DEBUG & DEBUG_FLUSH) {
        static unsigned id;
        debug_printf("%s %d\n", __FUNCTION__, id++);
        svga_hwtnl_flush_retry( svga );
        svga_context_flush(svga, NULL);
    }

    return ret == PIPE_OK;
}