Exemplo n.º 1
0
enum pipe_error
SVGA3D_vgpu10_SetRenderTargets(struct svga_winsys_context *swc,
                               unsigned color_count,
                               struct pipe_surface **color_surfs,
                               struct pipe_surface *depth_stencil_surf)
{
   const unsigned surf_count = color_count + 1;
   SVGA3dCmdDXSetRenderTargets *cmd;
   SVGA3dRenderTargetViewId *ctarget;
   struct svga_surface *ss;
   unsigned i;

   assert(surf_count > 0);

   cmd = SVGA3D_FIFOReserve(swc,
                            SVGA_3D_CMD_DX_SET_RENDERTARGETS,
                            sizeof(SVGA3dCmdDXSetRenderTargets) +
                            color_count * sizeof(SVGA3dRenderTargetViewId),
                            surf_count); /* 'surf_count' relocations */
   if (!cmd)
      return PIPE_ERROR_OUT_OF_MEMORY;

   /* NOTE: See earlier comment about the tricky handling of the ViewIds.
    */

   /* Depth / Stencil buffer */
   if (depth_stencil_surf) {
      ss = svga_surface(depth_stencil_surf);
      view_relocation(swc, depth_stencil_surf, &cmd->depthStencilViewId,
                      SVGA_RELOC_WRITE);
      cmd->depthStencilViewId = ss->view_id;
   }
   else {
      /* no depth/stencil buffer - still need a relocation */
      view_relocation(swc, NULL, &cmd->depthStencilViewId,
                      SVGA_RELOC_WRITE);
      cmd->depthStencilViewId = SVGA3D_INVALID_ID;
   }

   /* Color buffers */
   ctarget = (SVGA3dRenderTargetViewId *) &cmd[1];
   for (i = 0; i < color_count; i++) {
      if (color_surfs[i]) {
         ss = svga_surface(color_surfs[i]);
         view_relocation(swc, color_surfs[i], ctarget + i, SVGA_RELOC_WRITE);
         ctarget[i] = ss->view_id;
      }
      else {
         view_relocation(swc, NULL, ctarget + i, SVGA_RELOC_WRITE);
         ctarget[i] = SVGA3D_INVALID_ID;
      }
   }

   swc->commit(swc);
   return PIPE_OK;
}
Exemplo n.º 2
0
/**
 * Clear the given surface to the specified value.
 * No masking, no scissor (clear entire buffer).
 */
void
svga_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba,
	   double depth, unsigned stencil)
{
   struct svga_context *svga = svga_context( pipe );
   int ret;

   if (buffers & PIPE_CLEAR_COLOR)
      SVGA_DBG(DEBUG_DMA, "clear sid %p\n",
               svga_surface(svga->curr.framebuffer.cbufs[0])->handle);

   ret = try_clear( svga, buffers, rgba, depth, stencil );

   if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
      /* Flush command buffer and retry:
       */
      svga_context_flush( svga, NULL );

      ret = try_clear( svga, buffers, rgba, depth, stencil );
   }

   /*
    * Mark target surfaces as dirty
    * TODO Mark only cleared surfaces.
    */
   svga_mark_surfaces_dirty(svga);

   assert (ret == PIPE_OK);
}
Exemplo n.º 3
0
/**
 * Clear the given surface to the specified value.
 * No masking, no scissor (clear entire buffer).
 */
void
svga_clear(struct pipe_context *pipe, unsigned buffers,
           const union pipe_color_union *color,
	   double depth, unsigned stencil)
{
   struct svga_context *svga = svga_context( pipe );
   enum pipe_error ret;

   if (buffers & PIPE_CLEAR_COLOR)
      SVGA_DBG(DEBUG_DMA, "clear sid %p\n",
               svga_surface(svga->curr.framebuffer.cbufs[0])->handle);

   /* flush any queued prims (don't want them to appear after the clear!) */
   svga_hwtnl_flush_retry(svga);

   ret = try_clear( svga, buffers, color, depth, stencil );

   if (ret == PIPE_ERROR_OUT_OF_MEMORY) {
      /* Flush command buffer and retry:
       */
      svga_context_flush( svga, NULL );

      ret = try_clear( svga, buffers, color, depth, stencil );
   }

   /*
    * Mark target surfaces as dirty
    * TODO Mark only cleared surfaces.
    */
   svga_mark_surfaces_dirty(svga);

   assert (ret == PIPE_OK);
}
Exemplo n.º 4
0
enum pipe_error
SVGA3D_vgpu10_ClearDepthStencilView(struct svga_winsys_context *swc,
                                    struct pipe_surface *ds_surf,
                                    uint16 flags,
                                    uint16 stencil,
                                    float depth)
{
   SVGA3dCmdDXClearDepthStencilView *cmd;
   struct svga_surface *ss = svga_surface(ds_surf);

   cmd = SVGA3D_FIFOReserve(swc,
                            SVGA_3D_CMD_DX_CLEAR_DEPTHSTENCIL_VIEW,
                            sizeof(SVGA3dCmdDXClearDepthStencilView),
                            1); /* one relocation */
   if (!cmd)
      return PIPE_ERROR_OUT_OF_MEMORY;

   /* NOTE: The following is pretty tricky.  We need to emit a view/surface
    * relocation and we have to provide a pointer to an ID which lies in
    * the bounds of the command space which we just allocated.  However,
    * we then need to overwrite it with the original DepthStencilViewId.
    */
   view_relocation(swc, ds_surf, &cmd->depthStencilViewId,
                   SVGA_RELOC_WRITE);
   cmd->depthStencilViewId = ss->view_id;
   cmd->flags = flags;
   cmd->stencil = stencil;
   cmd->depth = depth;

   swc->commit(swc);
   return PIPE_OK;
}
Exemplo n.º 5
0
static INLINE void 
svga_mark_surface_dirty(struct pipe_surface *surf)
{
   struct svga_surface *s = svga_surface(surf);

   if (!s->dirty) {
      struct svga_texture *tex = svga_texture(surf->texture);

      s->dirty = TRUE;

      if (s->handle == tex->handle) {
         /* hmm so 3d textures always have all their slices marked ? */
         if (surf->texture->target == PIPE_TEXTURE_CUBE)
            svga_define_texture_level(tex, surf->u.tex.first_layer,
                                      surf->u.tex.level);
         else
            svga_define_texture_level(tex, 0, surf->u.tex.level);
      }
      else {
         /* this will happen later in svga_propagate_surface */
      }

      /* Increment the view_age and texture age for this surface's mipmap
       * level so that any sampler views into the texture are re-validated too.
       */
      svga_age_texture_view(tex, surf->u.tex.level);
   }
}
Exemplo n.º 6
0
enum pipe_error
SVGA3D_vgpu10_ClearRenderTargetView(struct svga_winsys_context *swc,
                                    struct pipe_surface *color_surf,
                                    const float *rgba)
{
   SVGA3dCmdDXClearRenderTargetView *cmd;
   struct svga_surface *ss = svga_surface(color_surf);

   cmd = SVGA3D_FIFOReserve(swc,
                            SVGA_3D_CMD_DX_CLEAR_RENDERTARGET_VIEW,
                            sizeof(SVGA3dCmdDXClearRenderTargetView),
                            1); /* one relocation */
   if (!cmd)
      return PIPE_ERROR_OUT_OF_MEMORY;


   /* NOTE: The following is pretty tricky.  We need to emit a view/surface
    * relocation and we have to provide a pointer to an ID which lies in
    * the bounds of the command space which we just allocated.  However,
    * we then need to overwrite it with the original RenderTargetViewId.
    */
   view_relocation(swc, color_surf, &cmd->renderTargetViewId,
                   SVGA_RELOC_WRITE);
   cmd->renderTargetViewId = ss->view_id;

   COPY_4V(cmd->rgba.value, rgba);

   swc->commit(swc);
   return PIPE_OK;
}
Exemplo n.º 7
0
/**
 * Check if we should call svga_propagate_surface on the surface.
 */
boolean
svga_surface_needs_propagation(struct pipe_surface *surf)
{
   struct svga_surface *s = svga_surface(surf);
   struct svga_texture *tex = svga_texture(surf->texture);

   return s->dirty && s->handle != tex->handle;
}
/**
 * \brief  Clear the whole render target using vgpu10 functionality
 *
 * \param svga[in]  The svga context
 * \param dst[in]  The surface to clear
 * \param color[in]  Clear color
 * \return PIPE_OK if all well, PIPE_ERROR_OUT_OF_MEMORY if ran out of
 * command submission resources.
 */
static enum pipe_error
svga_try_clear_render_target(struct svga_context *svga,
                             struct pipe_surface *dst,
                             const union pipe_color_union *color)
{
   struct pipe_surface *rtv =
      svga_validate_surface_view(svga, svga_surface(dst));

   if (!rtv)
      return PIPE_ERROR_OUT_OF_MEMORY;

   return SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv, color->f);
 }
Exemplo n.º 9
0
/*
 * Send a private allocation command to page in rendertargets resource.
 */
enum pipe_error
svga_rebind_framebuffer_bindings(struct svga_context *svga)
{
   const struct svga_screen *ss = svga_screen(svga->pipe.screen);
   struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
   unsigned i;
   enum pipe_error ret;

   assert(svga_have_vgpu10(svga));

   if (!svga->rebind.flags.rendertargets)
      return PIPE_OK;

   for (i = 0; i < ss->max_color_buffers; i++) {
      if (hw->cbufs[i]) {
         ret = svga->swc->resource_rebind(svga->swc,
                                          svga_surface(hw->cbufs[i])->handle,
                                          NULL,
                                          SVGA_RELOC_WRITE);
         if (ret != PIPE_OK)
            return ret;
      }
   }

   if (hw->zsbuf) {
      ret = svga->swc->resource_rebind(svga->swc,
                                       svga_surface(hw->zsbuf)->handle,
                                       NULL,
                                       SVGA_RELOC_WRITE);
      if (ret != PIPE_OK)
         return ret;
   }

   svga->rebind.flags.rendertargets = 0;

   return PIPE_OK;
}
Exemplo n.º 10
0
/**
 * Check if there are any resources that are both bound to a render target
 * and bound as a shader resource for the given type of shader.
 */
boolean
svga_check_sampler_framebuffer_resource_collision(struct svga_context *svga,
                                                  enum pipe_shader_type shader)
{
   struct svga_surface *surf;
   unsigned i;

   for (i = 0; i < svga->curr.framebuffer.nr_cbufs; i++) {
      surf = svga_surface(svga->curr.framebuffer.cbufs[i]);
      if (surf &&
          svga_check_sampler_view_resource_collision(svga, surf->handle,
                                                     shader)) {
         return TRUE;
      }
   }

   surf = svga_surface(svga->curr.framebuffer.zsbuf);
   if (surf &&
       svga_check_sampler_view_resource_collision(svga, surf->handle, shader)) {
      return TRUE;
   }

   return FALSE;
}
Exemplo n.º 11
0
/*
 * Send a private allocation command to page in rendertargets resource.
 */
enum pipe_error
svga_rebind_framebuffer_bindings(struct svga_context *svga)
{
   struct svga_hw_draw_state *hw = &svga->state.hw_draw;
   unsigned i;
   enum pipe_error ret;

   assert(svga_have_vgpu10(svga));

   if (!svga->rebind.flags.rendertargets)
      return PIPE_OK;

   for (i = 0; i < hw->num_rendertargets; i++) {
      if (hw->rtv[i]) {
         ret = svga->swc->resource_rebind(svga->swc,
                                          svga_surface(hw->rtv[i])->handle,
                                          NULL,
                                          SVGA_RELOC_WRITE);
         if (ret != PIPE_OK)
            return ret;
      }
   }

   if (hw->dsv) {
      ret = svga->swc->resource_rebind(svga->swc,
                                       svga_surface(hw->dsv)->handle,
                                       NULL,
                                       SVGA_RELOC_WRITE);
      if (ret != PIPE_OK)
         return ret;
   }

   svga->rebind.flags.rendertargets = 0;

   return PIPE_OK;
}
Exemplo n.º 12
0
static void
svga_tex_surface_destroy(struct pipe_surface *surf)
{
   struct svga_surface *s = svga_surface(surf);
   struct svga_texture *t = svga_texture(surf->texture);
   struct svga_screen *ss = svga_screen(surf->texture->screen);

   if(s->handle != t->handle) {
      SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
      svga_screen_surface_destroy(ss, &s->key, &s->handle);
   }

   pipe_resource_reference(&surf->texture, NULL);
   FREE(surf);
}
Exemplo n.º 13
0
/**
 * Emit a surface relocation for RenderTargetViewId
 */
static void
view_relocation(struct svga_winsys_context *swc, // IN
                struct pipe_surface *surface,    // IN
                SVGA3dRenderTargetViewId *id,    // OUT
                unsigned flags)
{
   if (surface) {
      struct svga_surface *s = svga_surface(surface);
      assert(s->handle);
      swc->surface_relocation(swc, id, NULL, s->handle, flags);
   }
   else {
      swc->surface_relocation(swc, id, NULL, NULL, flags);
   }
}
Exemplo n.º 14
0
static INLINE void 
svga_mark_surface_dirty(struct pipe_surface *surf)
{
   struct svga_surface *s = svga_surface(surf);

   if(!s->dirty) {
      struct svga_texture *tex = svga_texture(surf->texture);

      s->dirty = TRUE;

      if (s->handle == tex->handle)
         tex->defined[surf->face][surf->level] = TRUE;
      else {
         /* this will happen later in svga_propagate_surface */
      }
   }
}
Exemplo n.º 15
0
static INLINE
void surface_to_surfaceid(struct svga_winsys_context *swc, // IN
                          struct pipe_surface *surface,    // IN
                          SVGA3dSurfaceImageId *id,        // OUT
                          unsigned flags)                  // IN
{
   if(surface) {
      struct svga_surface *s = svga_surface(surface);
      swc->surface_relocation(swc, &id->sid, s->handle, flags);
      id->face = s->real_face; /* faces have the same order */
      id->mipmap = s->real_level;
   }
   else {
      id->sid = SVGA3D_INVALID_ID;
      id->face = 0;
      id->mipmap = 0;
   }
}
Exemplo n.º 16
0
/**
 * Progagate any changes from surfaces to texture.
 * pipe is optional context to inline the blit command in.
 */
void
svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf)
{
   struct svga_surface *s = svga_surface(surf);
   struct svga_texture *tex = svga_texture(surf->texture);
   struct svga_screen *ss = svga_screen(surf->texture->screen);
   unsigned zslice, face;

   if (!s->dirty)
      return;

   if (surf->texture->target == PIPE_TEXTURE_CUBE) {
      zslice = 0;
      face = surf->u.tex.first_layer;
   }
   else {
      zslice = surf->u.tex.first_layer;
      face = 0;
   }

   s->dirty = FALSE;
   ss->texture_timestamp++;
   svga_age_texture_view(tex, surf->u.tex.level);

   if (s->handle != tex->handle) {
      SVGA_DBG(DEBUG_VIEWS,
               "svga: Surface propagate: tex %p, level %u, from %p\n",
               tex, surf->u.tex.level, surf);
      svga_texture_copy_handle(svga,
                               s->handle, 0, 0, 0, s->real_level, s->real_face,
                               tex->handle, 0, 0, zslice, surf->u.tex.level, face,
                               u_minify(tex->b.b.width0, surf->u.tex.level),
                               u_minify(tex->b.b.height0, surf->u.tex.level), 1);
      svga_define_texture_level(tex, face, surf->u.tex.level);
   }
}
Exemplo n.º 17
0
/**
 * Progagate any changes from surfaces to texture.
 * pipe is optional context to inline the blit command in.
 */
void
svga_propagate_surface(struct pipe_context *pipe, struct pipe_surface *surf)
{
   struct svga_surface *s = svga_surface(surf);
   struct svga_texture *tex = svga_texture(surf->texture);
   struct svga_screen *ss = svga_screen(surf->texture->screen);

   if (!s->dirty)
      return;

   s->dirty = FALSE;
   ss->texture_timestamp++;
   tex->view_age[surf->level] = ++(tex->age);

   if (s->handle != tex->handle) {
      SVGA_DBG(DEBUG_VIEWS, "svga: Surface propagate: tex %p, level %u, from %p\n", tex, surf->level, surf);
      svga_texture_copy_handle(svga_context(pipe),
                               s->handle, 0, 0, 0, s->real_level, s->real_face,
                               tex->handle, 0, 0, surf->zslice, surf->level, surf->face,
                               u_minify(tex->b.b.width0, surf->level),
                               u_minify(tex->b.b.height0, surf->level), 1);
      tex->defined[surf->face][surf->level] = TRUE;
   }
}
Exemplo n.º 18
0
/**
 * Clone the surface view and its associated resource.
 */
static struct svga_surface *
create_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
{
   struct svga_surface *bs = s->backed;

   if (!bs) {
      struct svga_texture *tex = svga_texture(s->base.texture);
      struct pipe_surface *backed_view;

      backed_view = svga_create_surface_view(&svga->pipe,
                                             &tex->b.b,
                                             &s->base,
                                             TRUE);
      if (!backed_view)
         return NULL;

      bs = svga_surface(backed_view);
      s->backed = bs;
   }

   svga_mark_surface_dirty(&bs->base);

   return bs;
}
Exemplo n.º 19
0
static enum pipe_error
emit_fb_vgpu10(struct svga_context *svga)
{
   const struct svga_screen *ss = svga_screen(svga->pipe.screen);
   struct pipe_surface *rtv[SVGA3D_MAX_RENDER_TARGETS];
   struct pipe_surface *dsv;
   struct pipe_framebuffer_state *curr = &svga->curr.framebuffer;
   struct pipe_framebuffer_state *hw = &svga->state.hw_clear.framebuffer;
   const unsigned num_color = MAX2(curr->nr_cbufs, hw->nr_cbufs);
   unsigned i;
   enum pipe_error ret;

   assert(svga_have_vgpu10(svga));

   /* Setup render targets array.  Note that we loop over the max of the
    * number of previously bound buffers and the new buffers to unbind
    * any previously bound buffers when the new number of buffers is less
    * than the old number of buffers.
    */
   for (i = 0; i < num_color; i++) {
      if (curr->cbufs[i]) {
         rtv[i] = svga_validate_surface_view(svga,
                                             svga_surface(curr->cbufs[i]));
         if (rtv[i] == NULL) {
            return PIPE_ERROR_OUT_OF_MEMORY;
         }

         assert(svga_surface(rtv[i])->view_id != SVGA3D_INVALID_ID);
      }
      else {
         rtv[i] = NULL;
      }
   }

   /* Setup depth stencil view */
   if (curr->zsbuf) {
      dsv = svga_validate_surface_view(svga, svga_surface(curr->zsbuf));
      if (!dsv) {
         return PIPE_ERROR_OUT_OF_MEMORY;
      }
   }
   else {
      dsv = NULL;
   }

   ret = SVGA3D_vgpu10_SetRenderTargets(svga->swc, num_color, rtv, dsv);
   if (ret != PIPE_OK)
      return ret;

   for (i = 0; i < ss->max_color_buffers; i++) {
      if (hw->cbufs[i] != curr->cbufs[i]) {
         /* propagate the backed view surface before unbinding it */
         if (hw->cbufs[i] && svga_surface(hw->cbufs[i])->backed) {
            svga_propagate_surface(svga,
                                   &svga_surface(hw->cbufs[i])->backed->base);
         }
         pipe_surface_reference(&hw->cbufs[i], curr->cbufs[i]);
      }
   }
   hw->nr_cbufs = curr->nr_cbufs;

   if (hw->zsbuf != curr->zsbuf) {
      /* propagate the backed view surface before unbinding it */
      if (hw->zsbuf && svga_surface(hw->zsbuf)->backed) {
         svga_propagate_surface(svga, &svga_surface(hw->zsbuf)->backed->base);
      }
      pipe_surface_reference(&hw->zsbuf, curr->zsbuf);
   }

   return ret;
}
Exemplo n.º 20
0
static enum pipe_error
draw_vgpu9(struct svga_hwtnl *hwtnl)
{
   struct svga_winsys_context *swc = hwtnl->cmd.swc;
   struct svga_context *svga = hwtnl->svga;
   enum pipe_error ret;
   struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
   struct svga_winsys_surface *ib_handle[QSZ];
   struct svga_winsys_surface *handle;
   SVGA3dVertexDecl *vdecl;
   SVGA3dPrimitiveRange *prim;
   unsigned i;

   for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
      unsigned j = hwtnl->cmd.vdecl_buffer_index[i];
      handle = svga_buffer_handle(svga, hwtnl->cmd.vbufs[j].buffer);
      if (handle == NULL)
         return PIPE_ERROR_OUT_OF_MEMORY;

      vb_handle[i] = handle;
   }

   for (i = 0; i < hwtnl->cmd.prim_count; i++) {
      if (hwtnl->cmd.prim_ib[i]) {
         handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i]);
         if (handle == NULL)
            return PIPE_ERROR_OUT_OF_MEMORY;
      }
      else
         handle = NULL;

      ib_handle[i] = handle;
   }

   if (svga->rebind.flags.rendertargets) {
      ret = svga_reemit_framebuffer_bindings(svga);
      if (ret != PIPE_OK) {
         return ret;
      }
   }

   if (svga->rebind.flags.texture_samplers) {
      ret = svga_reemit_tss_bindings(svga);
      if (ret != PIPE_OK) {
         return ret;
      }
   }

   if (svga->rebind.flags.vs) {
      ret = svga_reemit_vs_bindings(svga);
      if (ret != PIPE_OK) {
         return ret;
      }
   }

   if (svga->rebind.flags.fs) {
      ret = svga_reemit_fs_bindings(svga);
      if (ret != PIPE_OK) {
         return ret;
      }
   }

   SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n",
            svga->curr.framebuffer.cbufs[0] ?
            svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL,
            hwtnl->cmd.prim_count);

   ret = SVGA3D_BeginDrawPrimitives(swc,
                                    &vdecl,
                                    hwtnl->cmd.vdecl_count,
                                    &prim, hwtnl->cmd.prim_count);
   if (ret != PIPE_OK)
      return ret;

   memcpy(vdecl,
          hwtnl->cmd.vdecl,
          hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);

   for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
      /* check for 4-byte alignment */
      assert(vdecl[i].array.offset % 4 == 0);
      assert(vdecl[i].array.stride % 4 == 0);

      /* Given rangeHint is considered to be relative to indexBias, and
       * indexBias varies per primitive, we cannot accurately supply an
       * rangeHint when emitting more than one primitive per draw command.
       */
      if (hwtnl->cmd.prim_count == 1) {
         vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0];
         vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1;
      }
      else {
         vdecl[i].rangeHint.first = 0;
         vdecl[i].rangeHint.last = 0;
      }

      swc->surface_relocation(swc,
                              &vdecl[i].array.surfaceId,
                              NULL, vb_handle[i], SVGA_RELOC_READ);
   }

   memcpy(prim,
          hwtnl->cmd.prim, hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);

   for (i = 0; i < hwtnl->cmd.prim_count; i++) {
      swc->surface_relocation(swc,
                              &prim[i].indexArray.surfaceId,
                              NULL, ib_handle[i], SVGA_RELOC_READ);
      pipe_resource_reference(&hwtnl->cmd.prim_ib[i], NULL);
   }

   SVGA_FIFOCommitAll(swc);

   hwtnl->cmd.prim_count = 0;

   return PIPE_OK;
}
Exemplo n.º 21
0
static void
svga_surface_destroy(struct pipe_context *pipe,
                     struct pipe_surface *surf)
{
   struct svga_context *svga = svga_context(pipe);
   struct svga_surface *s = svga_surface(surf);
   struct svga_texture *t = svga_texture(surf->texture);
   struct svga_screen *ss = svga_screen(surf->texture->screen);
   enum pipe_error ret = PIPE_OK;

   /* Destroy the backed view surface if it exists */
   if (s->backed) {
      svga_surface_destroy(pipe, &s->backed->base);
      s->backed = NULL;
   }

   if (s->handle != t->handle) {
      SVGA_DBG(DEBUG_DMA, "unref sid %p (tex surface)\n", s->handle);
      svga_screen_surface_destroy(ss, &s->key, &s->handle);
   }

   if (s->view_id != SVGA3D_INVALID_ID) {
      unsigned try;

      assert(svga_have_vgpu10(svga));
      for (try = 0; try < 2; try++) {
         if (util_format_is_depth_or_stencil(s->base.format)) {
            ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id);
         }
         else {
            ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id);
         }
         if (ret == PIPE_OK)
            break;
         svga_context_flush(svga, NULL);
      }
      assert(ret == PIPE_OK);
      util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
   }

   pipe_resource_reference(&surf->texture, NULL);
   FREE(surf);

   svga->hud.num_surface_views--;
}


static void 
svga_mark_surface_dirty(struct pipe_surface *surf)
{
   struct svga_surface *s = svga_surface(surf);
   struct svga_texture *tex = svga_texture(surf->texture);

   if (!s->dirty) {
      s->dirty = TRUE;

      if (s->handle == tex->handle) {
         /* hmm so 3d textures always have all their slices marked ? */
         svga_define_texture_level(tex, surf->u.tex.first_layer,
                                   surf->u.tex.level);
      }
      else {
         /* this will happen later in svga_propagate_surface */
      }
   }

   /* Increment the view_age and texture age for this surface's mipmap
    * level so that any sampler views into the texture are re-validated too.
    */
   svga_age_texture_view(tex, surf->u.tex.level);
}


void
svga_mark_surfaces_dirty(struct svga_context *svga)
{
   struct svga_screen *svgascreen = svga_screen(svga->pipe.screen);
   unsigned i;

   for (i = 0; i < svgascreen->max_color_buffers; i++) {
      if (svga->curr.framebuffer.cbufs[i])
         svga_mark_surface_dirty(svga->curr.framebuffer.cbufs[i]);
   }
   if (svga->curr.framebuffer.zsbuf)
      svga_mark_surface_dirty(svga->curr.framebuffer.zsbuf);
}


/**
 * Progagate any changes from surfaces to texture.
 * pipe is optional context to inline the blit command in.
 */
void
svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf)
{
   struct svga_surface *s = svga_surface(surf);
   struct svga_texture *tex = svga_texture(surf->texture);
   struct svga_screen *ss = svga_screen(surf->texture->screen);
   unsigned zslice, layer;
   unsigned nlayers = 1;
   unsigned i;

   if (!s->dirty)
      return;

   if (surf->texture->target == PIPE_TEXTURE_CUBE) {
      zslice = 0;
      layer = surf->u.tex.first_layer;
   }
   else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY ||
            surf->texture->target == PIPE_TEXTURE_2D_ARRAY) {
      zslice = 0;
      layer = surf->u.tex.first_layer;
      nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1;
   }
   else {
      zslice = surf->u.tex.first_layer;
      layer = 0;
   }

   s->dirty = FALSE;
   ss->texture_timestamp++;
   svga_age_texture_view(tex, surf->u.tex.level);

   if (s->handle != tex->handle) {
      SVGA_DBG(DEBUG_VIEWS,
               "svga: Surface propagate: tex %p, level %u, from %p\n",
               tex, surf->u.tex.level, surf);
      for (i = 0; i < nlayers; i++) {
         svga_texture_copy_handle(svga,
                                  s->handle, 0, 0, 0, s->real_level, s->real_layer + i,
                                  tex->handle, 0, 0, zslice, surf->u.tex.level, layer + i,
                                  u_minify(tex->b.b.width0, surf->u.tex.level),
                                  u_minify(tex->b.b.height0, surf->u.tex.level), 1);
         svga_define_texture_level(tex, layer + i, surf->u.tex.level);
      }
   }
}


/**
 * Check if we should call svga_propagate_surface on the surface.
 */
boolean
svga_surface_needs_propagation(const struct pipe_surface *surf)
{
   const struct svga_surface *s = svga_surface_const(surf);
   struct svga_texture *tex = svga_texture(surf->texture);

   return s->dirty && s->handle != tex->handle;
}


static void
svga_get_sample_position(struct pipe_context *context,
                         unsigned sample_count, unsigned sample_index,
                         float *pos_out)
{
   /* We can't actually query the device to learn the sample positions.
    * These were grabbed from nvidia's driver.
    */
   static const float pos1[1][2] = {
      { 0.5, 0.5 }
   };
   static const float pos4[4][2] = {
      { 0.375000, 0.125000 },
      { 0.875000, 0.375000 },
      { 0.125000, 0.625000 },
      { 0.625000, 0.875000 }
   };
   static const float pos8[8][2] = {
      { 0.562500, 0.312500 },
      { 0.437500, 0.687500 },
      { 0.812500, 0.562500 },
      { 0.312500, 0.187500 },
      { 0.187500, 0.812500 },
      { 0.062500, 0.437500 },
      { 0.687500, 0.937500 },
      { 0.937500, 0.062500 }
   };
   static const float pos16[16][2] = {
      { 0.187500, 0.062500 },
      { 0.437500, 0.187500 },
      { 0.062500, 0.312500 },
      { 0.312500, 0.437500 },
      { 0.687500, 0.062500 },
      { 0.937500, 0.187500 },
      { 0.562500, 0.312500 },
      { 0.812500, 0.437500 },
      { 0.187500, 0.562500 },
      { 0.437500, 0.687500 },
      { 0.062500, 0.812500 },
      { 0.312500, 0.937500 },
      { 0.687500, 0.562500 },
      { 0.937500, 0.687500 },
      { 0.562500, 0.812500 },
      { 0.812500, 0.937500 }
   };
   const float (*positions)[2];

   switch (sample_count) {
   case 4:
      positions = pos4;
      break;
   case 8:
      positions = pos8;
      break;
   case 16:
      positions = pos16;
      break;
   default:
      positions = pos1;
   }

   pos_out[0] = positions[sample_index][0];
   pos_out[1] = positions[sample_index][1];
}


void
svga_init_surface_functions(struct svga_context *svga)
{
   svga->pipe.create_surface = svga_create_surface;
   svga->pipe.surface_destroy = svga_surface_destroy;
   svga->pipe.get_sample_position = svga_get_sample_position;
}
static void
svga_clear_texture(struct pipe_context *pipe,
                   struct pipe_resource *res,
                   unsigned level,
                   const struct pipe_box *box,
                   const void *data)
{
   struct svga_context *svga = svga_context(pipe);
   struct svga_surface *svga_surface_dst;
   enum pipe_error ret;
   struct pipe_surface tmpl;
   struct pipe_surface *surface;

   memset(&tmpl, 0, sizeof(tmpl));
   tmpl.format = res->format;
   tmpl.u.tex.first_layer = box->z;
   tmpl.u.tex.last_layer = box->z + box->depth - 1;
   tmpl.u.tex.level = level;

   surface = pipe->create_surface(pipe, res, &tmpl);
   if (surface == NULL) {
      debug_printf("failed to create surface\n");
      return;
   }
   svga_surface_dst = svga_surface(surface);

   union pipe_color_union color;
   const struct util_format_description *desc =
      util_format_description(surface->format);

   if (util_format_is_depth_or_stencil(surface->format)) {
      float depth;
      uint8_t stencil;
      unsigned clear_flags = 0;

      /* If data is NULL, then set depthValue and stencilValue to zeros */
      if (data == NULL) {
         depth = 0.0;
         stencil = 0;
      }
      else {
         desc->unpack_z_float(&depth, 0, data, 0, 1, 1);
         desc->unpack_s_8uint(&stencil, 0, data, 0, 1, 1);
      }

      if (util_format_has_depth(desc)) {
         clear_flags |= PIPE_CLEAR_DEPTH;
      }
      if (util_format_has_stencil(desc)) {
         clear_flags |= PIPE_CLEAR_STENCIL;
      }

      /* Setup depth stencil view */
      struct pipe_surface *dsv =
         svga_validate_surface_view(svga, svga_surface_dst);

      if (!dsv) {
         pipe_surface_reference(&surface, NULL);
         return;
      }

      if (box->x == 0 && box->y == 0 && box->width == surface->width &&
          box->height == surface->height) {
         /* clearing whole surface, use direct VGPU10 command */


         ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv,
                                                   clear_flags,
                                                   stencil, depth);
         if (ret != PIPE_OK) {
            /* flush and try again */
            svga_context_flush(svga, NULL);
            ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv,
                                                      clear_flags,
                                                      stencil, depth);
            assert(ret == PIPE_OK);
         }
      }
      else {
         /* To clear subtexture use software fallback */

         util_blitter_save_framebuffer(svga->blitter,
                                       &svga->curr.framebuffer);
         begin_blit(svga);
         util_blitter_clear_depth_stencil(svga->blitter,
                                          dsv, clear_flags,
                                          depth,stencil,
                                          box->x, box->y,
                                          box->width, box->height);
      }
   }
   else {
      /* non depth-stencil formats */

      if (data == NULL) {
         /* If data is NULL, the texture image is filled with zeros */
         color.f[0] = color.f[1] = color.f[2] = color.f[3] = 0;
      }
      else {
         if (util_format_is_pure_sint(surface->format)) {
            /* signed integer */
            desc->unpack_rgba_sint(color.i, 0, data, 0, 1, 1);
         }
         else if (util_format_is_pure_uint(surface->format)) {
            /* unsigned integer */
            desc->unpack_rgba_uint(color.ui, 0, data, 0, 1, 1);
         }
         else {
            /* floating point */
            desc->unpack_rgba_float(color.f, 0, data, 0, 1, 1);
         }
      }

      /* Setup render target view */
      struct pipe_surface *rtv =
         svga_validate_surface_view(svga, svga_surface_dst);

      if (!rtv) {
         pipe_surface_reference(&surface, NULL);
         return;
      }

      if (box->x == 0 && box->y == 0 && box->width == surface->width &&
          box->height == surface->height) {
         struct pipe_framebuffer_state *curr =  &svga->curr.framebuffer;

         if (is_integer_target(curr, PIPE_CLEAR_COLOR) &&
             !ints_fit_in_floats(&color)) {
            /* To clear full texture with integer format */
            clear_buffers_with_quad(svga, PIPE_CLEAR_COLOR, &color, 0.0, 0);
         }
         else {
            /* clearing whole surface using VGPU10 command */
            ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv,
                                                      color.f);
            if (ret != PIPE_OK) {
               svga_context_flush(svga,NULL);
               ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc, rtv,
                                                         color.f);
               assert(ret == PIPE_OK);
            }
         }
      }
      else {
         /* To clear subtexture use software fallback */

         /**
          * util_blitter_clear_render_target doesn't support PIPE_TEXTURE_3D
          * It tries to draw quad with depth 0 for PIPE_TEXTURE_3D so use
          * util_clear_render_target() for PIPE_TEXTURE_3D.
          */
         if (rtv->texture->target != PIPE_TEXTURE_3D &&
             pipe->screen->is_format_supported(pipe->screen, rtv->format,
                                               rtv->texture->target,
                                               rtv->texture->nr_samples,
                                               PIPE_BIND_RENDER_TARGET)) {
            /* clear with quad drawing */
            util_blitter_save_framebuffer(svga->blitter,
                                          &svga->curr.framebuffer);
            begin_blit(svga);
            util_blitter_clear_render_target(svga->blitter,
                                             rtv,
                                             &color,
                                             box->x, box->y,
                                             box->width, box->height);
         }
         else {
            /* clear with map/write/unmap */

            /* store layer values */
            unsigned first_layer = rtv->u.tex.first_layer;
            unsigned last_layer = rtv->u.tex.last_layer;
            unsigned box_depth = last_layer - first_layer + 1;

            for (unsigned i = 0; i < box_depth; i++) {
               rtv->u.tex.first_layer = rtv->u.tex.last_layer =
                  first_layer + i;
               util_clear_render_target(pipe, rtv, &color, box->x, box->y,
                                        box->width, box->height);
            }
            /* restore layer values */
            rtv->u.tex.first_layer = first_layer;
            rtv->u.tex.last_layer = last_layer;
         }
      }
   }
   pipe_surface_reference(&surface, NULL);
}
Exemplo n.º 23
0
enum pipe_error
svga_hwtnl_flush( struct svga_hwtnl *hwtnl )
{
    struct svga_winsys_context *swc = hwtnl->cmd.swc;
    struct svga_context *svga = hwtnl->svga;
    enum pipe_error ret;

    if (hwtnl->cmd.prim_count) {
        struct svga_winsys_surface *vb_handle[SVGA3D_INPUTREG_MAX];
        struct svga_winsys_surface *ib_handle[QSZ];
        struct svga_winsys_surface *handle;
        SVGA3dVertexDecl *vdecl;
        SVGA3dPrimitiveRange *prim;
        unsigned i;

        for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
            handle = svga_buffer_handle(svga, hwtnl->cmd.vdecl_vb[i]);
            if (handle == NULL)
                return PIPE_ERROR_OUT_OF_MEMORY;

            vb_handle[i] = handle;
        }

        for (i = 0; i < hwtnl->cmd.prim_count; i++) {
            if (hwtnl->cmd.prim_ib[i]) {
                handle = svga_buffer_handle(svga, hwtnl->cmd.prim_ib[i]);
                if (handle == NULL)
                    return PIPE_ERROR_OUT_OF_MEMORY;
            }
            else
                handle = NULL;

            ib_handle[i] = handle;
        }

        SVGA_DBG(DEBUG_DMA, "draw to sid %p, %d prims\n",
                 svga->curr.framebuffer.cbufs[0] ?
                 svga_surface(svga->curr.framebuffer.cbufs[0])->handle : NULL,
                 hwtnl->cmd.prim_count);

        ret = SVGA3D_BeginDrawPrimitives(swc,
                                         &vdecl,
                                         hwtnl->cmd.vdecl_count,
                                         &prim,
                                         hwtnl->cmd.prim_count);
        if (ret != PIPE_OK)
            return ret;


        memcpy( vdecl,
                hwtnl->cmd.vdecl,
                hwtnl->cmd.vdecl_count * sizeof hwtnl->cmd.vdecl[0]);

        for (i = 0; i < hwtnl->cmd.vdecl_count; i++) {
            /* Given rangeHint is considered to be relative to indexBias, and
             * indexBias varies per primitive, we cannot accurately supply an
             * rangeHint when emitting more than one primitive per draw command.
             */
            if (hwtnl->cmd.prim_count == 1) {
                vdecl[i].rangeHint.first = hwtnl->cmd.min_index[0];
                vdecl[i].rangeHint.last = hwtnl->cmd.max_index[0] + 1;
            }
            else {
                vdecl[i].rangeHint.first = 0;
                vdecl[i].rangeHint.last = 0;
            }

            swc->surface_relocation(swc,
                                    &vdecl[i].array.surfaceId,
                                    vb_handle[i],
                                    PIPE_BUFFER_USAGE_GPU_READ);
        }

        memcpy( prim,
                hwtnl->cmd.prim,
                hwtnl->cmd.prim_count * sizeof hwtnl->cmd.prim[0]);

        for (i = 0; i < hwtnl->cmd.prim_count; i++) {
            swc->surface_relocation(swc,
                                    &prim[i].indexArray.surfaceId,
                                    ib_handle[i],
                                    PIPE_BUFFER_USAGE_GPU_READ);
            pipe_buffer_reference(&hwtnl->cmd.prim_ib[i], NULL);
        }

        SVGA_FIFOCommitAll( swc );
        hwtnl->cmd.prim_count = 0;
    }

    return PIPE_OK;
}
Exemplo n.º 24
0
/* XXX still have doubts about this... */
static void svga_surface_copy(struct pipe_context *pipe,
                              struct pipe_resource* dst_tex,
                              unsigned dst_level,
                              unsigned dstx, unsigned dsty, unsigned dstz,
                              struct pipe_resource* src_tex,
                              unsigned src_level,
                              const struct pipe_box *src_box)
 {
   struct svga_context *svga = svga_context(pipe);
   struct svga_texture *stex, *dtex;
/*   struct pipe_screen *screen = pipe->screen;
   SVGA3dCopyBox *box;
   enum pipe_error ret;
   struct pipe_surface *srcsurf, *dstsurf;*/
   unsigned dst_face, dst_z, src_face, src_z;

   /* Emit buffered drawing commands, and any back copies.
    */
   svga_surfaces_flush( svga );

   /* Fallback for buffers. */
   if (dst_tex->target == PIPE_BUFFER && src_tex->target == PIPE_BUFFER) {
      util_resource_copy_region(pipe, dst_tex, dst_level, dstx, dsty, dstz,
                                src_tex, src_level, src_box);
      return;
   }

   stex = svga_texture(src_tex);
   dtex = svga_texture(dst_tex);

#if 0
   srcsurf = screen->get_tex_surface(screen, src_tex,
                                     src_level, src_box->z, src_box->z,
                                     PIPE_BIND_SAMPLER_VIEW);

   dstsurf = screen->get_tex_surface(screen, dst_tex,
                                     dst_level, dst_box->z, dst_box->z,
                                     PIPE_BIND_RENDER_TARGET);

   SVGA_DBG(DEBUG_DMA, "blit to sid %p (%d,%d), from sid %p (%d,%d) sz %dx%d\n",
            svga_surface(dstsurf)->handle,
            dstx, dsty,
            svga_surface(srcsurf)->handle,
            src_box->x, src_box->y,
            width, height);

   ret = SVGA3D_BeginSurfaceCopy(svga->swc,
                                 srcsurf,
                                 dstsurf,
                                 &box,
                                 1);
   if(ret != PIPE_OK) {

      svga_context_flush(svga, NULL);

      ret = SVGA3D_BeginSurfaceCopy(svga->swc,
                                    srcsurf,
                                    dstsurf,
                                    &box,
                                    1);
      assert(ret == PIPE_OK);
   }

   box->x = dstx;
   box->y = dsty;
   box->z = 0;
   box->w = width;
   box->h = height;
   box->d = 1;
   box->srcx = src_box->x;
   box->srcy = src_box->y;
   box->srcz = 0;

   SVGA_FIFOCommitAll(svga->swc);

   svga_surface(dstsurf)->dirty = TRUE;
   svga_propagate_surface(pipe, dstsurf);

   pipe_surface_reference(&srcsurf, NULL);
   pipe_surface_reference(&dstsurf, NULL);

#else
   if (src_tex->target == PIPE_TEXTURE_CUBE) {
      src_face = src_box->z;
      src_z = 0;
      assert(src_box->depth == 1);
   }
   else {
      src_face = 0;
      src_z = src_box->z;
   }
   /* different src/dst type???*/
   if (dst_tex->target == PIPE_TEXTURE_CUBE) {
      dst_face = dstz;
      dst_z = 0;
      assert(src_box->depth == 1);
   }
   else {
      dst_face = 0;
      dst_z = dstz;
   }
   svga_texture_copy_handle(svga,
                            stex->handle,
                            src_box->x, src_box->y, src_z,
                            src_level, src_face,
                            dtex->handle,
                            dstx, dsty, dst_z,
                            dst_level, dst_face,
                            src_box->width, src_box->height, src_box->depth);

#endif

}
static enum pipe_error
try_clear(struct svga_context *svga, 
          unsigned buffers,
          const union pipe_color_union *color,
          double depth,
          unsigned stencil)
{
   enum pipe_error ret = PIPE_OK;
   SVGA3dRect rect = { 0, 0, 0, 0 };
   boolean restore_viewport = FALSE;
   SVGA3dClearFlag flags = 0;
   struct pipe_framebuffer_state *fb = &svga->curr.framebuffer;
   union util_color uc = {0};

   ret = svga_update_state(svga, SVGA_STATE_HW_CLEAR);
   if (ret != PIPE_OK)
      return ret;

   if (svga->rebind.flags.rendertargets) {
      ret = svga_reemit_framebuffer_bindings(svga);
      if (ret != PIPE_OK) {
         return ret;
      }
   }

   if (buffers & PIPE_CLEAR_COLOR) {
      flags |= SVGA3D_CLEAR_COLOR;
      util_pack_color(color->f, PIPE_FORMAT_B8G8R8A8_UNORM, &uc);

      rect.w = fb->width;
      rect.h = fb->height;
   }

   if ((buffers & PIPE_CLEAR_DEPTHSTENCIL) && fb->zsbuf) {
      if (buffers & PIPE_CLEAR_DEPTH)
         flags |= SVGA3D_CLEAR_DEPTH;

      if (buffers & PIPE_CLEAR_STENCIL)
         flags |= SVGA3D_CLEAR_STENCIL;

      rect.w = MAX2(rect.w, fb->zsbuf->width);
      rect.h = MAX2(rect.h, fb->zsbuf->height);
   }

   if (!svga_have_vgpu10(svga) &&
       !svga_rects_equal(&rect, &svga->state.hw_clear.viewport)) {
      restore_viewport = TRUE;
      ret = SVGA3D_SetViewport(svga->swc, &rect);
      if (ret != PIPE_OK)
         return ret;
   }

   if (svga_have_vgpu10(svga)) {
      if (flags & SVGA3D_CLEAR_COLOR) {
         unsigned i;

         if (is_integer_target(fb, buffers) && !ints_fit_in_floats(color)) {
            clear_buffers_with_quad(svga, buffers, color, depth, stencil);
            /* We also cleared depth/stencil, so that's done */
            flags &= ~(SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL);
         }
         else {
            struct pipe_surface *rtv;

            /* Issue VGPU10 Clear commands */
            for (i = 0; i < fb->nr_cbufs; i++) {
               if ((fb->cbufs[i] == NULL) ||
                   !(buffers & (PIPE_CLEAR_COLOR0 << i)))
                  continue;

               rtv = svga_validate_surface_view(svga,
                                                svga_surface(fb->cbufs[i]));
               if (!rtv)
                  return PIPE_ERROR_OUT_OF_MEMORY;

               ret = SVGA3D_vgpu10_ClearRenderTargetView(svga->swc,
                                                         rtv, color->f);
               if (ret != PIPE_OK)
                  return ret;
            }
         }
      }
      if (flags & (SVGA3D_CLEAR_DEPTH | SVGA3D_CLEAR_STENCIL)) {
         struct pipe_surface *dsv =
            svga_validate_surface_view(svga, svga_surface(fb->zsbuf));
         if (!dsv)
            return PIPE_ERROR_OUT_OF_MEMORY;

         ret = SVGA3D_vgpu10_ClearDepthStencilView(svga->swc, dsv, flags,
                                                   stencil, (float) depth);
         if (ret != PIPE_OK)
            return ret;
      }
   }
   else {
      ret = SVGA3D_ClearRect(svga->swc, flags, uc.ui[0], (float) depth, stencil,
                             rect.x, rect.y, rect.w, rect.h);
      if (ret != PIPE_OK)
         return ret;
   }

   if (restore_viewport) {
      ret = SVGA3D_SetViewport(svga->swc, &svga->state.hw_clear.viewport);
   }
   
   return ret;
}