Exemplo n.º 1
0
static void
st_BlitFramebuffer(GLcontext *ctx,
                   GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                   GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                   GLbitfield mask, GLenum filter)
{
   struct st_context *st = ctx->st;

   const uint pFilter = ((filter == GL_NEAREST)
                         ? PIPE_TEX_MIPFILTER_NEAREST
                         : PIPE_TEX_MIPFILTER_LINEAR);

   if (mask & GL_COLOR_BUFFER_BIT) {
      struct st_renderbuffer *srcRb = 
         st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
      struct st_renderbuffer *dstRb = 
         st_renderbuffer(ctx->DrawBuffer->_ColorDrawBuffers[0][0]);
      struct pipe_surface *srcSurf = srcRb->surface;
      struct pipe_surface *dstSurf = dstRb->surface;

      if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
         /* invert Y */
         srcY0 = srcRb->Base.Height - srcY0;
         srcY1 = srcRb->Base.Height - srcY1;

         dstY0 = dstRb->Base.Height - dstY0;
         dstY1 = dstRb->Base.Height - dstY1;
      }

      util_blit_pixels(st->blit,
                       srcSurf, srcX0, srcY0, srcX1, srcY1,
                       dstSurf, dstX0, dstY0, dstX1, dstY1,
                       0.0, pFilter);

   }
}
Exemplo n.º 2
0
static void
st_BlitFramebuffer(GLcontext *ctx,
                   GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                   GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                   GLbitfield mask, GLenum filter)
{
   const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT |
                                    GL_STENCIL_BUFFER_BIT);
   struct st_context *st = ctx->st;
   const uint pFilter = ((filter == GL_NEAREST)
                         ? PIPE_TEX_MIPFILTER_NEAREST
                         : PIPE_TEX_MIPFILTER_LINEAR);
   struct gl_framebuffer *readFB = ctx->ReadBuffer;
   struct gl_framebuffer *drawFB = ctx->DrawBuffer;

   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
                        &dstX0, &dstY0, &dstX1, &dstY1)) {
      return; /* nothing to draw/blit */
   }

   if (st_fb_orientation(drawFB) == Y_0_TOP) {
      /* invert Y for dest */
      dstY0 = drawFB->Height - dstY0;
      dstY1 = drawFB->Height - dstY1;
   }

   if (st_fb_orientation(readFB) == Y_0_TOP) {
      /* invert Y for src */
      srcY0 = readFB->Height - srcY0;
      srcY1 = readFB->Height - srcY1;
   }

   if (srcY0 > srcY1 && dstY0 > dstY1) {
      /* Both src and dst are upside down.  Swap Y to make it
       * right-side up to increase odds of using a fast path.
       * Recall that all Gallium raster coords have Y=0=top.
       */
      GLint tmp;
      tmp = srcY0;
      srcY0 = srcY1;
      srcY1 = tmp;
      tmp = dstY0;
      dstY0 = dstY1;
      dstY1 = tmp;
   }

   if (mask & GL_COLOR_BUFFER_BIT) {
      struct st_renderbuffer *srcRb = 
         st_renderbuffer(readFB->_ColorReadBuffer);
      struct st_renderbuffer *dstRb = 
         st_renderbuffer(drawFB->_ColorDrawBuffers[0]);
      struct pipe_surface *srcSurf = srcRb->surface;
      struct pipe_surface *dstSurf = dstRb->surface;

      util_blit_pixels(st->blit,
                       srcSurf, srcX0, srcY0, srcX1, srcY1,
                       dstSurf, dstX0, dstY0, dstX1, dstY1,
                       0.0, pFilter);
   }

   if (mask & depthStencil) {
      /* depth and/or stencil blit */

      /* get src/dst depth surfaces */
      struct st_renderbuffer *srcDepthRb = 
         st_renderbuffer(readFB->Attachment[BUFFER_DEPTH].Renderbuffer);
      struct st_renderbuffer *dstDepthRb = 
         st_renderbuffer(drawFB->Attachment[BUFFER_DEPTH].Renderbuffer);
      struct pipe_surface *srcDepthSurf =
         srcDepthRb ? srcDepthRb->surface : NULL;
      struct pipe_surface *dstDepthSurf =
         dstDepthRb ? dstDepthRb->surface : NULL;

      /* get src/dst stencil surfaces */
      struct st_renderbuffer *srcStencilRb = 
         st_renderbuffer(readFB->Attachment[BUFFER_STENCIL].Renderbuffer);
      struct st_renderbuffer *dstStencilRb = 
         st_renderbuffer(drawFB->Attachment[BUFFER_STENCIL].Renderbuffer);
      struct pipe_surface *srcStencilSurf =
         srcStencilRb ? srcStencilRb->surface : NULL;
      struct pipe_surface *dstStencilSurf =
         dstStencilRb ? dstStencilRb->surface : NULL;

      if ((mask & depthStencil) == depthStencil &&
          srcDepthSurf == srcStencilSurf &&
          dstDepthSurf == dstStencilSurf) {
         /* Blitting depth and stencil values between combined
          * depth/stencil buffers.  This is the ideal case for such buffers.
          */
         util_blit_pixels(st->blit,
                          srcDepthSurf, srcX0, srcY0, srcX1, srcY1,
                          dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
                          0.0, pFilter);
      }
      else {
         /* blitting depth and stencil separately */

         if (mask & GL_DEPTH_BUFFER_BIT) {
            /* blit Z only */
            _mesa_problem(ctx, "st_BlitFramebuffer(DEPTH) not completed");
         }

         if (mask & GL_STENCIL_BUFFER_BIT) {
            /* blit stencil only */
            _mesa_problem(ctx, "st_BlitFramebuffer(STENCIL) not completed");
         }
      }
   }
}
/**
*	Main run function of the PP queue. Called on swapbuffers/flush.
*
*	Runs all requested filters in order and handles shuffling the temp
*	buffers in between.
*/
void
pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
       struct pipe_resource *out, struct pipe_resource *indepth)
{
   struct pipe_resource *refin = NULL, *refout = NULL;
   unsigned int i;

   if (in->width0 != ppq->p->framebuffer.width ||
       in->height0 != ppq->p->framebuffer.height) {
      pp_debug("Resizing the temp pp buffers\n");
      pp_free_fbos(ppq);
      pp_init_fbos(ppq, in->width0, in->height0);
   }

   if (in == out && ppq->n_filters == 1) {
      /* Make a copy of in to tmp[0] in this case. */
      unsigned int w = ppq->p->framebuffer.width;
      unsigned int h = ppq->p->framebuffer.height;

      util_blit_pixels(ppq->p->blitctx, in, 0, 0, 0,
                       w, h, 0, ppq->tmps[0],
                       0, 0, w, h, 0, PIPE_TEX_MIPFILTER_NEAREST,
                       TGSI_WRITEMASK_XYZW, 0);

      in = ppq->tmp[0];
   }

   // Kept only for this frame.
   pipe_resource_reference(&ppq->depth, indepth);
   pipe_resource_reference(&refin, in);
   pipe_resource_reference(&refout, out);

   switch (ppq->n_filters) {
   case 1:                     /* No temp buf */
      ppq->pp_queue[0] (ppq, in, out, 0);
      break;
   case 2:                     /* One temp buf */

      ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);
      ppq->pp_queue[1] (ppq, ppq->tmp[0], out, 1);

      break;
   default:                    /* Two temp bufs */
      ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);

      for (i = 1; i < (ppq->n_filters - 1); i++) {
         if (i % 2 == 0)
            ppq->pp_queue[i] (ppq, ppq->tmp[1], ppq->tmp[0], i);

         else
            ppq->pp_queue[i] (ppq, ppq->tmp[0], ppq->tmp[1], i);
      }

      if (i % 2 == 0)
         ppq->pp_queue[i] (ppq, ppq->tmp[1], out, i);

      else
         ppq->pp_queue[i] (ppq, ppq->tmp[0], out, i);

      break;
   }

   pipe_resource_reference(&ppq->depth, NULL);
   pipe_resource_reference(&refin, NULL);
   pipe_resource_reference(&refout, NULL);
}
Exemplo n.º 4
0
/** Run function of the MLAA filter. */
static void
pp_jimenezmlaa_run(struct pp_queue_t *ppq, struct pipe_resource *in,
                   struct pipe_resource *out, unsigned int n, bool iscolor)
{

    struct program *p = ppq->p;

    struct pipe_depth_stencil_alpha_state mstencil;
    struct pipe_sampler_view v_tmp, *arr[3];

    unsigned int w = p->framebuffer.width;
    unsigned int h = p->framebuffer.height;

    const struct pipe_stencil_ref ref = { {1} };
    memset(&mstencil, 0, sizeof(mstencil));
    cso_set_stencil_ref(p->cso, &ref);

    /* Init the pixel size constant */
    if (dimensions[0] != p->framebuffer.width ||
            dimensions[1] != p->framebuffer.height) {
        constants[0] = 1.0 / p->framebuffer.width;
        constants[1] = 1.0 / p->framebuffer.height;

        up_consts(p->pipe);
        dimensions[0] = p->framebuffer.width;
        dimensions[1] = p->framebuffer.height;
    }

    p->pipe->set_constant_buffer(p->pipe, PIPE_SHADER_VERTEX, 0, constbuf);
    p->pipe->set_constant_buffer(p->pipe, PIPE_SHADER_FRAGMENT, 0, constbuf);

    mstencil.stencil[0].enabled = 1;
    mstencil.stencil[0].valuemask = mstencil.stencil[0].writemask = ~0;
    mstencil.stencil[0].func = PIPE_FUNC_ALWAYS;
    mstencil.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
    mstencil.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
    mstencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;

    p->framebuffer.zsbuf = ppq->stencils;

    /* First pass: depth edge detection */
    if (iscolor)
        pp_filter_setup_in(p, in);
    else
        pp_filter_setup_in(p, ppq->depth);

    pp_filter_setup_out(p, ppq->inner_tmp[0]);

    pp_filter_set_fb(p);
    pp_filter_misc_state(p);
    cso_set_depth_stencil_alpha(p->cso, &mstencil);
    p->pipe->clear(p->pipe, PIPE_CLEAR_STENCIL | PIPE_CLEAR_COLOR,
                   &p->clear_color, 0, 0);

    cso_single_sampler(p->cso, 0, &p->sampler_point);
    cso_single_sampler_done(p->cso);
    cso_set_fragment_sampler_views(p->cso, 1, &p->view);

    cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][1]);    /* offsetvs */
    cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][2]);

    pp_filter_draw(p);
    pp_filter_end_pass(p);


    /* Second pass: blend weights */
    /* Sampler order: areamap, edgesmap, edgesmapL (reversed, thx compiler) */
    mstencil.stencil[0].func = PIPE_FUNC_EQUAL;
    mstencil.stencil[0].zpass_op = PIPE_STENCIL_OP_KEEP;
    cso_set_depth_stencil_alpha(p->cso, &mstencil);

    pp_filter_setup_in(p, areamaptex);
    pp_filter_setup_out(p, ppq->inner_tmp[1]);

    u_sampler_view_default_template(&v_tmp, ppq->inner_tmp[0],
                                    ppq->inner_tmp[0]->format);
    arr[1] = arr[2] = p->pipe->create_sampler_view(p->pipe,
                      ppq->inner_tmp[0], &v_tmp);

    pp_filter_set_clear_fb(p);

    cso_single_sampler(p->cso, 0, &p->sampler_point);
    cso_single_sampler(p->cso, 1, &p->sampler_point);
    cso_single_sampler(p->cso, 2, &p->sampler);
    cso_single_sampler_done(p->cso);

    arr[0] = p->view;
    cso_set_fragment_sampler_views(p->cso, 3, arr);

    cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][0]);    /* passvs */
    cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][3]);

    pp_filter_draw(p);
    pp_filter_end_pass(p);
    pipe_sampler_view_reference(&arr[1], NULL);


    /* Third pass: smoothed edges */
    /* Sampler order: colormap, blendmap (wtf compiler) */
    pp_filter_setup_in(p, ppq->inner_tmp[1]);
    pp_filter_setup_out(p, out);

    pp_filter_set_fb(p);

    /* Blit the input to the output */
    util_blit_pixels(p->blitctx, in, 0, 0, 0,
                     w, h, 0, p->framebuffer.cbufs[0],
                     0, 0, w, h, 0, PIPE_TEX_MIPFILTER_NEAREST);

    u_sampler_view_default_template(&v_tmp, in, in->format);
    arr[0] = p->pipe->create_sampler_view(p->pipe, in, &v_tmp);

    cso_single_sampler(p->cso, 0, &p->sampler_point);
    cso_single_sampler(p->cso, 1, &p->sampler_point);
    cso_single_sampler_done(p->cso);

    arr[1] = p->view;
    cso_set_fragment_sampler_views(p->cso, 2, arr);

    cso_set_vertex_shader_handle(p->cso, ppq->shaders[n][1]);    /* offsetvs */
    cso_set_fragment_shader_handle(p->cso, ppq->shaders[n][4]);

    p->blend.rt[0].blend_enable = 1;
    cso_set_blend(p->cso, &p->blend);

    pp_filter_draw(p);
    pp_filter_end_pass(p);
    pipe_sampler_view_reference(&arr[0], NULL);

    p->blend.rt[0].blend_enable = 0;
    p->framebuffer.zsbuf = NULL;
}
Exemplo n.º 5
0
/**
 * Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
 * Note that the region to copy has already been clipped so we know we
 * won't read from outside the source renderbuffer's bounds.
 *
 * Note: srcY=0=Bottom of renderbuffer (GL convention)
 */
static void
st_CopyTexSubImage(struct gl_context *ctx, GLuint dims,
                   struct gl_texture_image *texImage,
                   GLint destX, GLint destY, GLint destZ,
                   struct gl_renderbuffer *rb,
                   GLint srcX, GLint srcY, GLsizei width, GLsizei height)
{
   struct st_texture_image *stImage = st_texture_image(texImage);
   const GLenum texBaseFormat = texImage->_BaseFormat;
   struct st_renderbuffer *strb = st_renderbuffer(rb);
   struct st_context *st = st_context(ctx);
   struct pipe_context *pipe = st->pipe;
   struct pipe_screen *screen = pipe->screen;
   enum pipe_format dest_format, src_format;
   GLboolean matching_base_formats;
   GLuint color_writemask, zs_writemask, sample_count;
   struct pipe_surface *dest_surface = NULL;
   GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
   struct pipe_surface surf_tmpl;
   unsigned int dst_usage;
   GLint srcY0, srcY1;

   /* make sure finalize_textures has been called? 
    */
   if (0) st_validate_state(st);

   if (!strb || !strb->surface || !stImage->pt) {
      debug_printf("%s: null strb or stImage\n", __FUNCTION__);
      return;
   }

   sample_count = strb->surface->texture->nr_samples;
   /* I believe this would be legal, presumably would need to do a resolve
      for color, and for depth/stencil spec says to just use one of the
      depth/stencil samples per pixel? Need some transfer clarifications. */
   assert(sample_count < 2);

   assert(strb);
   assert(strb->surface);
   assert(stImage->pt);

   src_format = strb->surface->format;
   dest_format = stImage->pt->format;

   /*
    * Determine if the src framebuffer and dest texture have the same
    * base format.  We need this to detect a case such as the framebuffer
    * being GL_RGBA but the texture being GL_RGB.  If the actual hardware
    * texture format stores RGBA we need to set A=1 (overriding the
    * framebuffer's alpha values).  We can't do that with the blit or
    * textured-quad paths.
    */
   matching_base_formats =
      (_mesa_get_format_base_format(strb->Base.Format) ==
       _mesa_get_format_base_format(texImage->TexFormat));

   if (ctx->_ImageTransferState) {
      goto fallback;
   }

   if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
      /* 1D arrays might be thought of as 2D images but the actual layout
       * might not be that way.  At some points, we convert OpenGL's 1D
       * array 'height' into gallium 'layers' and that prevents the blit
       * utility code from doing the right thing.  Simpy use the memcpy-based
       * fallback.
       */
      goto fallback;
   }

   if (matching_base_formats &&
       src_format == dest_format &&
       !do_flip) {
      /* use surface_copy() / blit */
      struct pipe_box src_box;
      unsigned dstLevel;

      u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer,
                      width, height, &src_box);

      /* If stImage->pt is an independent image (not a pointer into a full
       * mipmap) stImage->pt.last_level will be zero and we need to use that
       * as the dest level.
       */
      dstLevel = MIN2(stImage->base.Level, stImage->pt->last_level);

      /* for resource_copy_region(), y=0=top, always */
      pipe->resource_copy_region(pipe,
                                 /* dest */
                                 stImage->pt,
                                 dstLevel,
                                 destX, destY, destZ + stImage->base.Face,
                                 /* src */
                                 strb->texture,
                                 strb->surface->u.tex.level,
                                 &src_box);
      return;
   }

   if (texBaseFormat == GL_DEPTH_STENCIL) {
      goto fallback;
   }

   if (texBaseFormat == GL_DEPTH_COMPONENT) {
      color_writemask = 0;
      zs_writemask = BLIT_WRITEMASK_Z;
      dst_usage = PIPE_BIND_DEPTH_STENCIL;
   }
   else {
      color_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
      zs_writemask = 0;
      dst_usage = PIPE_BIND_RENDER_TARGET;
   }

   if ((!color_writemask && !zs_writemask) ||
       !screen->is_format_supported(screen, src_format,
                                    PIPE_TEXTURE_2D, sample_count,
                                    PIPE_BIND_SAMPLER_VIEW) ||
       !screen->is_format_supported(screen, dest_format,
                                    PIPE_TEXTURE_2D, 0,
                                    dst_usage)) {
      goto fallback;
   }

   if (do_flip) {
      srcY1 = strb->Base.Height - srcY - height;
      srcY0 = srcY1 + height;
   }
   else {
      srcY0 = srcY;
      srcY1 = srcY0 + height;
   }

   /* Disable conditional rendering. */
   if (st->render_condition) {
      pipe->render_condition(pipe, NULL, 0);
   }

   memset(&surf_tmpl, 0, sizeof(surf_tmpl));
   surf_tmpl.format = util_format_linear(stImage->pt->format);
   surf_tmpl.usage = dst_usage;
   surf_tmpl.u.tex.level = stImage->base.Level;
   surf_tmpl.u.tex.first_layer = stImage->base.Face + destZ;
   surf_tmpl.u.tex.last_layer = stImage->base.Face + destZ;

   dest_surface = pipe->create_surface(pipe, stImage->pt,
                                       &surf_tmpl);
   util_blit_pixels(st->blit,
                    strb->texture,
                    strb->surface->u.tex.level,
                    srcX, srcY0,
                    srcX + width, srcY1,
                    strb->surface->u.tex.first_layer,
                    dest_surface,
                    destX, destY,
                    destX + width, destY + height,
                    0.0, PIPE_TEX_MIPFILTER_NEAREST,
                    color_writemask, zs_writemask);
   pipe_surface_reference(&dest_surface, NULL);

   /* Restore conditional rendering state. */
   if (st->render_condition) {
      pipe->render_condition(pipe, st->render_condition,
                             st->condition_mode);
   }

   return;

fallback:
   /* software fallback */
   fallback_copy_texsubimage(ctx,
                             strb, stImage, texBaseFormat,
                             destX, destY, destZ,
                             srcX, srcY, width, height);
}
Exemplo n.º 6
0
/**
*	Main run function of the PP queue. Called on swapbuffers/flush.
*
*	Runs all requested filters in order and handles shuffling the temp
*	buffers in between.
*/
void
pp_run(struct pp_queue_t *ppq, struct pipe_resource *in,
       struct pipe_resource *out, struct pipe_resource *indepth)
{
   struct pipe_resource *refin = NULL, *refout = NULL;
   unsigned int i;
   struct cso_context *cso = ppq->p->cso;

   if (in->width0 != ppq->p->framebuffer.width ||
       in->height0 != ppq->p->framebuffer.height) {
      pp_debug("Resizing the temp pp buffers\n");
      pp_free_fbos(ppq);
      pp_init_fbos(ppq, in->width0, in->height0);
   }

   if (in == out && ppq->n_filters == 1) {
      /* Make a copy of in to tmp[0] in this case. */
      unsigned int w = ppq->p->framebuffer.width;
      unsigned int h = ppq->p->framebuffer.height;

      util_blit_pixels(ppq->p->blitctx, in, 0, 0, 0,
                       w, h, 0, ppq->tmps[0],
                       0, 0, w, h, 0, PIPE_TEX_MIPFILTER_NEAREST,
                       TGSI_WRITEMASK_XYZW, 0);

      in = ppq->tmp[0];
   }

   /* save state (restored below) */
   cso_save_blend(cso);
   cso_save_depth_stencil_alpha(cso);
   cso_save_fragment_shader(cso);
   cso_save_framebuffer(cso);
   cso_save_geometry_shader(cso);
   cso_save_rasterizer(cso);
   cso_save_sample_mask(cso);
   cso_save_samplers(cso, PIPE_SHADER_FRAGMENT);
   cso_save_sampler_views(cso, PIPE_SHADER_FRAGMENT);
   cso_save_stencil_ref(cso);
   cso_save_stream_outputs(cso);
   cso_save_vertex_elements(cso);
   cso_save_vertex_shader(cso);
   cso_save_viewport(cso);
   cso_save_aux_vertex_buffer_slot(cso);
   cso_save_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX);
   cso_save_constant_buffer_slot0(cso, PIPE_SHADER_FRAGMENT);
   cso_save_render_condition(cso);

   /* set default state */
   cso_set_sample_mask(cso, ~0);
   cso_set_stream_outputs(cso, 0, NULL, 0);
   cso_set_geometry_shader_handle(cso, NULL);
   cso_set_render_condition(cso, NULL, 0);

   // Kept only for this frame.
   pipe_resource_reference(&ppq->depth, indepth);
   pipe_resource_reference(&refin, in);
   pipe_resource_reference(&refout, out);

   switch (ppq->n_filters) {
   case 1:                     /* No temp buf */
      ppq->pp_queue[0] (ppq, in, out, 0);
      break;
   case 2:                     /* One temp buf */

      ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);
      ppq->pp_queue[1] (ppq, ppq->tmp[0], out, 1);

      break;
   default:                    /* Two temp bufs */
      ppq->pp_queue[0] (ppq, in, ppq->tmp[0], 0);

      for (i = 1; i < (ppq->n_filters - 1); i++) {
         if (i % 2 == 0)
            ppq->pp_queue[i] (ppq, ppq->tmp[1], ppq->tmp[0], i);

         else
            ppq->pp_queue[i] (ppq, ppq->tmp[0], ppq->tmp[1], i);
      }

      if (i % 2 == 0)
         ppq->pp_queue[i] (ppq, ppq->tmp[1], out, i);

      else
         ppq->pp_queue[i] (ppq, ppq->tmp[0], out, i);

      break;
   }

   /* restore state we changed */
   cso_restore_blend(cso);
   cso_restore_depth_stencil_alpha(cso);
   cso_restore_fragment_shader(cso);
   cso_restore_framebuffer(cso);
   cso_restore_geometry_shader(cso);
   cso_restore_rasterizer(cso);
   cso_restore_sample_mask(cso);
   cso_restore_samplers(cso, PIPE_SHADER_FRAGMENT);
   cso_restore_sampler_views(cso, PIPE_SHADER_FRAGMENT);
   cso_restore_stencil_ref(cso);
   cso_restore_stream_outputs(cso);
   cso_restore_vertex_elements(cso);
   cso_restore_vertex_shader(cso);
   cso_restore_viewport(cso);
   cso_restore_aux_vertex_buffer_slot(cso);
   cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_VERTEX);
   cso_restore_constant_buffer_slot0(cso, PIPE_SHADER_FRAGMENT);
   cso_restore_render_condition(cso);

   pipe_resource_reference(&ppq->depth, NULL);
   pipe_resource_reference(&refin, NULL);
   pipe_resource_reference(&refout, NULL);
}
Exemplo n.º 7
0
static void
st_BlitFramebuffer(GLcontext *ctx,
                   GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                   GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                   GLbitfield mask, GLenum filter)
{
   const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT |
                                    GL_STENCIL_BUFFER_BIT);
   struct st_context *st = st_context(ctx);
   const uint pFilter = ((filter == GL_NEAREST)
                         ? PIPE_TEX_MIPFILTER_NEAREST
                         : PIPE_TEX_MIPFILTER_LINEAR);
   struct gl_framebuffer *readFB = ctx->ReadBuffer;
   struct gl_framebuffer *drawFB = ctx->DrawBuffer;

   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
                        &dstX0, &dstY0, &dstX1, &dstY1)) {
      return; /* nothing to draw/blit */
   }

   if (st_fb_orientation(drawFB) == Y_0_TOP) {
      /* invert Y for dest */
      dstY0 = drawFB->Height - dstY0;
      dstY1 = drawFB->Height - dstY1;
   }

   if (st_fb_orientation(readFB) == Y_0_TOP) {
      /* invert Y for src */
      srcY0 = readFB->Height - srcY0;
      srcY1 = readFB->Height - srcY1;
   }

   if (srcY0 > srcY1 && dstY0 > dstY1) {
      /* Both src and dst are upside down.  Swap Y to make it
       * right-side up to increase odds of using a fast path.
       * Recall that all Gallium raster coords have Y=0=top.
       */
      GLint tmp;
      tmp = srcY0;
      srcY0 = srcY1;
      srcY1 = tmp;
      tmp = dstY0;
      dstY0 = dstY1;
      dstY1 = tmp;
   }

   if (mask & GL_COLOR_BUFFER_BIT) {
      struct gl_renderbuffer_attachment *srcAtt =
         &readFB->Attachment[readFB->_ColorReadBufferIndex];

      if(srcAtt->Type == GL_TEXTURE) {
         struct st_texture_object *srcObj =
            st_texture_object(srcAtt->Texture);
         struct st_renderbuffer *dstRb =
            st_renderbuffer(drawFB->_ColorDrawBuffers[0]);
         struct pipe_subresource srcSub;
         struct pipe_surface *dstSurf = dstRb->surface;

         if (!srcObj->pt)
            return;

         srcSub.face = srcAtt->CubeMapFace;
         srcSub.level = srcAtt->TextureLevel;

         util_blit_pixels(st->blit, srcObj->pt, srcSub,
                          srcX0, srcY0, srcX1, srcY1, srcAtt->Zoffset,
                          dstSurf, dstX0, dstY0, dstX1, dstY1,
                          0.0, pFilter);
      }
      else {
         struct st_renderbuffer *srcRb =
            st_renderbuffer(readFB->_ColorReadBuffer);
         struct st_renderbuffer *dstRb =
            st_renderbuffer(drawFB->_ColorDrawBuffers[0]);
         struct pipe_surface *srcSurf = srcRb->surface;
         struct pipe_surface *dstSurf = dstRb->surface;
         struct pipe_subresource srcSub;

         srcSub.face = srcSurf->face;
         srcSub.level = srcSurf->level;

         util_blit_pixels(st->blit,
                          srcRb->texture, srcSub, srcX0, srcY0, srcX1, srcY1,
                          srcSurf->zslice,
                          dstSurf, dstX0, dstY0, dstX1, dstY1,
                          0.0, pFilter);
      }
   }

   if (mask & depthStencil) {
      /* depth and/or stencil blit */

      /* get src/dst depth surfaces */
      struct gl_renderbuffer_attachment *srcDepth =
         &readFB->Attachment[BUFFER_DEPTH];
      struct gl_renderbuffer_attachment *dstDepth =
         &drawFB->Attachment[BUFFER_DEPTH];
      struct gl_renderbuffer_attachment *srcStencil =
         &readFB->Attachment[BUFFER_STENCIL];
      struct gl_renderbuffer_attachment *dstStencil =
         &drawFB->Attachment[BUFFER_STENCIL];

      struct st_renderbuffer *srcDepthRb =
         st_renderbuffer(readFB->Attachment[BUFFER_DEPTH].Renderbuffer);
      struct st_renderbuffer *dstDepthRb = 
         st_renderbuffer(drawFB->Attachment[BUFFER_DEPTH].Renderbuffer);
      struct pipe_surface *dstDepthSurf =
         dstDepthRb ? dstDepthRb->surface : NULL;

      if ((mask & depthStencil) == depthStencil &&
          st_is_depth_stencil_combined(srcDepth, srcStencil) &&
          st_is_depth_stencil_combined(dstDepth, dstStencil)) {

         /* Blitting depth and stencil values between combined
          * depth/stencil buffers.  This is the ideal case for such buffers.
          */
         util_blit_pixels(st->blit, srcDepthRb->texture,
                          u_subresource(srcDepthRb->surface->face,
                                        srcDepthRb->surface->level),
                          srcX0, srcY0, srcX1, srcY1,
                          srcDepthRb->surface->zslice,
                          dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
                          0.0, pFilter);
      }
      else {
         /* blitting depth and stencil separately */

         if (mask & GL_DEPTH_BUFFER_BIT) {
            util_blit_pixels(st->blit, srcDepthRb->texture,
                             u_subresource(srcDepthRb->surface->face,
                                           srcDepthRb->surface->level),
                             srcX0, srcY0, srcX1, srcY1,
                             srcDepthRb->surface->zslice,
                             dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
                             0.0, pFilter);
         }

         if (mask & GL_STENCIL_BUFFER_BIT) {
            /* blit stencil only */
            _mesa_problem(ctx, "st_BlitFramebuffer(STENCIL) not completed");
         }
      }
   }
}
static void
st_BlitFramebuffer(struct gl_context *ctx,
                   GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                   GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                   GLbitfield mask, GLenum filter)
{
   const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT |
                                    GL_STENCIL_BUFFER_BIT);
   struct st_context *st = st_context(ctx);
   const uint pFilter = ((filter == GL_NEAREST)
                         ? PIPE_TEX_MIPFILTER_NEAREST
                         : PIPE_TEX_MIPFILTER_LINEAR);
   struct gl_framebuffer *readFB = ctx->ReadBuffer;
   struct gl_framebuffer *drawFB = ctx->DrawBuffer;

   st_validate_state(st);

   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
                        &dstX0, &dstY0, &dstX1, &dstY1)) {
      return; /* nothing to draw/blit */
   }

   if (st_fb_orientation(drawFB) == Y_0_TOP) {
      /* invert Y for dest */
      dstY0 = drawFB->Height - dstY0;
      dstY1 = drawFB->Height - dstY1;
   }

   if (st_fb_orientation(readFB) == Y_0_TOP) {
      /* invert Y for src */
      srcY0 = readFB->Height - srcY0;
      srcY1 = readFB->Height - srcY1;
   }

   /* Disable conditional rendering. */
   if (st->render_condition) {
      st->pipe->render_condition(st->pipe, NULL, 0);
   }

   if (readFB->Visual.sampleBuffers > drawFB->Visual.sampleBuffers &&
       readFB->Visual.samples > 1) {
      struct pipe_resolve_info info;

      if (dstX0 < dstX1) {
         info.dst.x0 = dstX0;
         info.dst.x1 = dstX1;
         info.src.x0 = srcX0;
         info.src.x1 = srcX1;
      } else {
         info.dst.x0 = dstX1;
         info.dst.x1 = dstX0;
         info.src.x0 = srcX1;
         info.src.x1 = srcX0;
      }
      if (dstY0 < dstY1) {
         info.dst.y0 = dstY0;
         info.dst.y1 = dstY1;
         info.src.y0 = srcY0;
         info.src.y1 = srcY1;
      } else {
         info.dst.y0 = dstY1;
         info.dst.y1 = dstY0;
         info.src.y0 = srcY1;
         info.src.y1 = srcY0;
      }

      st_BlitFramebuffer_resolve(ctx, mask, &info); /* filter doesn't apply */

      goto done;
   }

   if (srcY0 > srcY1 && dstY0 > dstY1) {
      /* Both src and dst are upside down.  Swap Y to make it
       * right-side up to increase odds of using a fast path.
       * Recall that all Gallium raster coords have Y=0=top.
       */
      GLint tmp;
      tmp = srcY0;
      srcY0 = srcY1;
      srcY1 = tmp;
      tmp = dstY0;
      dstY0 = dstY1;
      dstY1 = tmp;
   }

   if (mask & GL_COLOR_BUFFER_BIT) {
      struct gl_renderbuffer_attachment *srcAtt =
         &readFB->Attachment[readFB->_ColorReadBufferIndex];

      if(srcAtt->Type == GL_TEXTURE) {
         struct st_texture_object *srcObj =
            st_texture_object(srcAtt->Texture);
         struct st_renderbuffer *dstRb =
            st_renderbuffer(drawFB->_ColorDrawBuffers[0]);
         struct pipe_surface *dstSurf = dstRb->surface;

         if (!srcObj->pt)
            goto done;

         util_blit_pixels(st->blit, srcObj->pt, srcAtt->TextureLevel,
                          srcX0, srcY0, srcX1, srcY1,
                          srcAtt->Zoffset + srcAtt->CubeMapFace,
                          dstSurf, dstX0, dstY0, dstX1, dstY1,
                          0.0, pFilter, TGSI_WRITEMASK_XYZW, 0);
      }
      else {
         struct st_renderbuffer *srcRb =
            st_renderbuffer(readFB->_ColorReadBuffer);
         struct st_renderbuffer *dstRb =
            st_renderbuffer(drawFB->_ColorDrawBuffers[0]);
         struct pipe_surface *srcSurf = srcRb->surface;
         struct pipe_surface *dstSurf = dstRb->surface;

         util_blit_pixels(st->blit,
                          srcRb->texture, srcSurf->u.tex.level,
                          srcX0, srcY0, srcX1, srcY1,
                          srcSurf->u.tex.first_layer,
                          dstSurf, dstX0, dstY0, dstX1, dstY1,
                          0.0, pFilter, TGSI_WRITEMASK_XYZW, 0);
      }
   }

   if (mask & depthStencil) {
      /* depth and/or stencil blit */

      /* get src/dst depth surfaces */
      struct gl_renderbuffer_attachment *srcDepth =
         &readFB->Attachment[BUFFER_DEPTH];
      struct gl_renderbuffer_attachment *dstDepth =
         &drawFB->Attachment[BUFFER_DEPTH];
      struct gl_renderbuffer_attachment *srcStencil =
         &readFB->Attachment[BUFFER_STENCIL];
      struct gl_renderbuffer_attachment *dstStencil =
         &drawFB->Attachment[BUFFER_STENCIL];

      struct st_renderbuffer *srcDepthRb =
         st_renderbuffer(readFB->Attachment[BUFFER_DEPTH].Renderbuffer);
      struct st_renderbuffer *dstDepthRb = 
         st_renderbuffer(drawFB->Attachment[BUFFER_DEPTH].Renderbuffer);
      struct pipe_surface *dstDepthSurf =
         dstDepthRb ? dstDepthRb->surface : NULL;

      struct st_renderbuffer *srcStencilRb =
         st_renderbuffer(readFB->Attachment[BUFFER_STENCIL].Renderbuffer);
      struct st_renderbuffer *dstStencilRb =
         st_renderbuffer(drawFB->Attachment[BUFFER_STENCIL].Renderbuffer);
      struct pipe_surface *dstStencilSurf =
         dstStencilRb ? dstStencilRb->surface : NULL;

      if ((mask & depthStencil) == depthStencil &&
          st_is_depth_stencil_combined(srcDepth, srcStencil) &&
          st_is_depth_stencil_combined(dstDepth, dstStencil)) {

         /* Blitting depth and stencil values between combined
          * depth/stencil buffers.  This is the ideal case for such buffers.
          */
         util_blit_pixels(st->blit,
                          srcDepthRb->texture,
                          srcDepthRb->surface->u.tex.level,
                          srcX0, srcY0, srcX1, srcY1,
                          srcDepthRb->surface->u.tex.first_layer,
                          dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
                          0.0, pFilter, 0,
                          BLIT_WRITEMASK_Z |
                          (st->has_stencil_export ? BLIT_WRITEMASK_STENCIL
                                                  : 0));

         if (!st->has_stencil_export) {
            _mesa_problem(ctx, "st_BlitFramebuffer(STENCIL) "
                               "software fallback not implemented");
         }
      }
      else {
         /* blitting depth and stencil separately */

         if (mask & GL_DEPTH_BUFFER_BIT) {
            util_blit_pixels(st->blit, srcDepthRb->texture,
                             srcDepthRb->surface->u.tex.level,
                             srcX0, srcY0, srcX1, srcY1,
                             srcDepthRb->surface->u.tex.first_layer,
                             dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
                             0.0, pFilter, 0, BLIT_WRITEMASK_Z);
         }

         if (mask & GL_STENCIL_BUFFER_BIT) {
            if (st->has_stencil_export) {
               util_blit_pixels(st->blit, srcStencilRb->texture,
                                srcStencilRb->surface->u.tex.level,
                                srcX0, srcY0, srcX1, srcY1,
                                srcStencilRb->surface->u.tex.first_layer,
                                dstStencilSurf, dstX0, dstY0, dstX1, dstY1,
                                0.0, pFilter, 0, BLIT_WRITEMASK_STENCIL);
            }
            else {
               _mesa_problem(ctx, "st_BlitFramebuffer(STENCIL) "
                                  "software fallback not implemented");
            }
         }
      }
   }

done:
   /* Restore conditional rendering state. */
   if (st->render_condition) {
      st->pipe->render_condition(st->pipe, st->render_condition,
                                 st->condition_mode);
   }
}