Exemplo n.º 1
0
/**
 * Software fallback for glBlitFramebufferEXT().
 */
void
_swrast_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)
{
   static const GLbitfield buffers[3] = {
      GL_COLOR_BUFFER_BIT,
      GL_DEPTH_BUFFER_BIT,
      GL_STENCIL_BUFFER_BIT
   };
   GLint i;

   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
                        &dstX0, &dstY0, &dstX1, &dstY1)) {
      return;
   }

   if (SWRAST_CONTEXT(ctx)->NewState)
      _swrast_validate_derived(ctx);

   swrast_render_start(ctx);

   if (srcX1 - srcX0 == dstX1 - dstX0 &&
       srcY1 - srcY0 == dstY1 - dstY0 &&
       srcX0 < srcX1 &&
       srcY0 < srcY1 &&
       dstX0 < dstX1 &&
       dstY0 < dstY1) {
      /* no stretching or flipping.
       * filter doesn't matter.
       */
      for (i = 0; i < 3; i++) {
         if (mask & buffers[i]) {
            simple_blit(ctx, srcX0, srcY0, srcX1, srcY1,
                        dstX0, dstY0, dstX1, dstY1, buffers[i]);
         }
      }
   }
   else {
      if (filter == GL_NEAREST) {
         for (i = 0; i < 3; i++) {
            if (mask & buffers[i]) {
               blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
                            dstX0, dstY0, dstX1, dstY1, buffers[i]);
            }
         }
      }
      else {
         ASSERT(filter == GL_LINEAR);
         if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
            blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
                        dstX0, dstY0, dstX1, dstY1);
         }
      }
   }

   swrast_render_finish(ctx);
}
Exemplo n.º 2
0
static void
st_BlitFramebuffer(struct gl_context *ctx,
                   struct gl_framebuffer *readFB,
                   struct gl_framebuffer *drawFB,
                   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_FILTER_NEAREST
                         : PIPE_TEX_FILTER_LINEAR);
   struct {
      GLint srcX0, srcY0, srcX1, srcY1;
      GLint dstX0, dstY0, dstX1, dstY1;
   } clip;
   struct pipe_blit_info blit;

   st_manager_validate_framebuffers(st);

   /* Make sure bitmap rendering has landed in the framebuffers */
   st_flush_bitmap_cache(st);
   st_invalidate_readpix_cache(st);

   clip.srcX0 = srcX0;
   clip.srcY0 = srcY0;
   clip.srcX1 = srcX1;
   clip.srcY1 = srcY1;
   clip.dstX0 = dstX0;
   clip.dstY0 = dstY0;
   clip.dstX1 = dstX1;
   clip.dstY1 = dstY1;

   /* NOTE: If the src and dst dimensions don't match, we cannot simply adjust
    * the integer coordinates to account for clipping (or scissors) because that
    * would make us cut off fractional parts, affecting the result of the blit.
    *
    * XXX: This should depend on mask !
    */
   if (!_mesa_clip_blit(ctx, readFB, drawFB,
                        &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
                        &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
      return; /* nothing to draw/blit */
   }
   memset(&blit, 0, sizeof(struct pipe_blit_info));
   blit.scissor_enable =
      (dstX0 != clip.dstX0) ||
      (dstY0 != clip.dstY0) ||
      (dstX1 != clip.dstX1) ||
      (dstY1 != clip.dstY1);

   if (st_fb_orientation(drawFB) == Y_0_TOP) {
      /* invert Y for dest */
      dstY0 = drawFB->Height - dstY0;
      dstY1 = drawFB->Height - dstY1;
      /* invert Y for clip */
      clip.dstY0 = drawFB->Height - clip.dstY0;
      clip.dstY1 = drawFB->Height - clip.dstY1;
   }
   if (blit.scissor_enable) {
      blit.scissor.minx = MIN2(clip.dstX0, clip.dstX1);
      blit.scissor.miny = MIN2(clip.dstY0, clip.dstY1);
      blit.scissor.maxx = MAX2(clip.dstX0, clip.dstX1);
      blit.scissor.maxy = MAX2(clip.dstY0, clip.dstY1);
#if 0
      debug_printf("scissor = (%i,%i)-(%i,%i)\n",
                   blit.scissor.minx,blit.scissor.miny,
                   blit.scissor.maxx,blit.scissor.maxy);
#endif
   }

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

   blit.src.box.depth = 1;
   blit.dst.box.depth = 1;

   /* Destination dimensions have to be positive: */
   if (dstX0 < dstX1) {
      blit.dst.box.x = dstX0;
      blit.src.box.x = srcX0;
      blit.dst.box.width = dstX1 - dstX0;
      blit.src.box.width = srcX1 - srcX0;
   } else {
      blit.dst.box.x = dstX1;
      blit.src.box.x = srcX1;
      blit.dst.box.width = dstX0 - dstX1;
      blit.src.box.width = srcX0 - srcX1;
   }
   if (dstY0 < dstY1) {
      blit.dst.box.y = dstY0;
      blit.src.box.y = srcY0;
      blit.dst.box.height = dstY1 - dstY0;
      blit.src.box.height = srcY1 - srcY0;
   } else {
      blit.dst.box.y = dstY1;
      blit.src.box.y = srcY1;
      blit.dst.box.height = dstY0 - dstY1;
      blit.src.box.height = srcY0 - srcY1;
   }

   if (drawFB != ctx->WinSysDrawBuffer)
      st_window_rectangles_to_blit(ctx, &blit);

   blit.filter = pFilter;
   blit.render_condition_enable = TRUE;
   blit.alpha_blend = FALSE;

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

      blit.mask = PIPE_MASK_RGBA;

      if (srcAtt->Type == GL_TEXTURE) {
         struct st_texture_object *srcObj = st_texture_object(srcAtt->Texture);
         GLuint i;

         if (!srcObj || !srcObj->pt) {
            return;
         }

         for (i = 0; i < drawFB->_NumColorDrawBuffers; i++) {
            struct st_renderbuffer *dstRb =
               st_renderbuffer(drawFB->_ColorDrawBuffers[i]);

            if (dstRb) {
               struct pipe_surface *dstSurf = dstRb->surface;

               if (dstSurf) {
                  blit.dst.resource = dstSurf->texture;
                  blit.dst.level = dstSurf->u.tex.level;
                  blit.dst.box.z = dstSurf->u.tex.first_layer;
                  blit.dst.format = dstSurf->format;

                  blit.src.resource = srcObj->pt;
                  blit.src.level = srcAtt->TextureLevel;
                  blit.src.box.z = srcAtt->Zoffset + srcAtt->CubeMapFace;
                  blit.src.format = srcObj->pt->format;

                  st_adjust_blit_for_srgb(&blit, ctx->Color.sRGBEnabled);

                  st->pipe->blit(st->pipe, &blit);
                  dstRb->defined = true; /* front buffer tracking */
               }
            }
         }
      }
      else {
         struct st_renderbuffer *srcRb =
            st_renderbuffer(readFB->_ColorReadBuffer);
         struct pipe_surface *srcSurf;
         GLuint i;

         if (!srcRb || !srcRb->surface) {
            return;
         }

         srcSurf = srcRb->surface;

         for (i = 0; i < drawFB->_NumColorDrawBuffers; i++) {
            struct st_renderbuffer *dstRb =
               st_renderbuffer(drawFB->_ColorDrawBuffers[i]);

            if (dstRb) {
               struct pipe_surface *dstSurf = dstRb->surface;

               if (dstSurf) {
                  blit.dst.resource = dstSurf->texture;
                  blit.dst.level = dstSurf->u.tex.level;
                  blit.dst.box.z = dstSurf->u.tex.first_layer;
                  blit.dst.format = dstSurf->format;

                  blit.src.resource = srcSurf->texture;
                  blit.src.level = srcSurf->u.tex.level;
                  blit.src.box.z = srcSurf->u.tex.first_layer;
                  blit.src.format = srcSurf->format;

                  st_adjust_blit_for_srgb(&blit, ctx->Color.sRGBEnabled);

                  st->pipe->blit(st->pipe, &blit);
                  dstRb->defined = true; /* front buffer tracking */
               }
            }
         }
      }
   }

   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 *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 (_mesa_has_depthstencil_combined(readFB) &&
          _mesa_has_depthstencil_combined(drawFB)) {
         blit.mask = 0;
         if (mask & GL_DEPTH_BUFFER_BIT)
            blit.mask |= PIPE_MASK_Z;
         if (mask & GL_STENCIL_BUFFER_BIT)
            blit.mask |= PIPE_MASK_S;

         blit.dst.resource = dstDepthSurf->texture;
         blit.dst.level = dstDepthSurf->u.tex.level;
         blit.dst.box.z = dstDepthSurf->u.tex.first_layer;
         blit.dst.format = dstDepthSurf->format;

         blit.src.resource = srcDepthRb->texture;
         blit.src.level = srcDepthRb->surface->u.tex.level;
         blit.src.box.z = srcDepthRb->surface->u.tex.first_layer;
         blit.src.format = srcDepthRb->surface->format;

         st->pipe->blit(st->pipe, &blit);
      }
      else {
         /* blitting depth and stencil separately */

         if (mask & GL_DEPTH_BUFFER_BIT) {
            blit.mask = PIPE_MASK_Z;

            blit.dst.resource = dstDepthSurf->texture;
            blit.dst.level = dstDepthSurf->u.tex.level;
            blit.dst.box.z = dstDepthSurf->u.tex.first_layer;
            blit.dst.format = dstDepthSurf->format;

            blit.src.resource = srcDepthRb->texture;
            blit.src.level = srcDepthRb->surface->u.tex.level;
            blit.src.box.z = srcDepthRb->surface->u.tex.first_layer;
            blit.src.format = srcDepthRb->surface->format;

            st->pipe->blit(st->pipe, &blit);
         }

         if (mask & GL_STENCIL_BUFFER_BIT) {
            blit.mask = PIPE_MASK_S;

            blit.dst.resource = dstStencilSurf->texture;
            blit.dst.level = dstStencilSurf->u.tex.level;
            blit.dst.box.z = dstStencilSurf->u.tex.first_layer;
            blit.dst.format = dstStencilSurf->format;

            blit.src.resource = srcStencilRb->texture;
            blit.src.level = srcStencilRb->surface->u.tex.level;
            blit.src.box.z = srcStencilRb->surface->u.tex.first_layer;
            blit.src.format = srcStencilRb->surface->format;

            st->pipe->blit(st->pipe, &blit);
         }
      }
   }
}
Exemplo n.º 3
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");
         }
      }
   }
}
Exemplo n.º 4
0
/**
 * Software fallback for glBlitFramebufferEXT().
 */
void
_swrast_BlitFramebuffer(GLcontext *ctx,
                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                        GLbitfield mask, GLenum filter)
{
   static const GLbitfield buffers[3] = {
      GL_COLOR_BUFFER_BIT,
      GL_DEPTH_BUFFER_BIT,
      GL_STENCIL_BUFFER_BIT
   };
   GLint i;

   if (!_mesa_check_conditional_render(ctx))
      return; /* don't clear */

   if (!ctx->DrawBuffer->_NumColorDrawBuffers)
      return;

   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
                        &dstX0, &dstY0, &dstX1, &dstY1)) {
      return;
   }

   swrast_render_start(ctx);

   if (srcX1 - srcX0 == dstX1 - dstX0 &&
       srcY1 - srcY0 == dstY1 - dstY0 &&
       srcX0 < srcX1 &&
       srcY0 < srcY1 &&
       dstX0 < dstX1 &&
       dstY0 < dstY1) {
      /* no stretching or flipping.
       * filter doesn't matter.
       */
      for (i = 0; i < 3; i++) {
         if (mask & buffers[i]) {
            simple_blit(ctx, srcX0, srcY0, srcX1, srcY1,
                        dstX0, dstY0, dstX1, dstY1, buffers[i]);
         }
      }
   }
   else {
      if (filter == GL_NEAREST) {
         for (i = 0; i < 3; i++) {
            if (mask & buffers[i]) {
               blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
                            dstX0, dstY0, dstX1, dstY1, buffers[i]);
            }
         }
      }
      else {
         ASSERT(filter == GL_LINEAR);
         if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
            blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
                        dstX0, dstY0, dstX1, dstY1);
         }
      }
   }

   swrast_render_finish(ctx);
}
/**
 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms
 * of texture mapping and polygon rendering.
 */
GLbitfield
_mesa_meta_BlitFramebuffer(struct gl_context *ctx,
                           const struct gl_framebuffer *readFb,
                           const struct gl_framebuffer *drawFb,
                           GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                           GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                           GLbitfield mask, GLenum filter)
{
   const GLint dstW = abs(dstX1 - dstX0);
   const GLint dstH = abs(dstY1 - dstY0);
   const GLint dstFlipX = (dstX1 - dstX0) / dstW;
   const GLint dstFlipY = (dstY1 - dstY0) / dstH;

   struct {
      GLint srcX0, srcY0, srcX1, srcY1;
      GLint dstX0, dstY0, dstX1, dstY1;
   } clip = {
      srcX0, srcY0, srcX1, srcY1,
      dstX0, dstY0, dstX1, dstY1
   };

   const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader &&
                                      ctx->Extensions.ARB_fragment_shader;

   /* Multisample texture blit support requires texture multisample. */
   if (readFb->Visual.samples > 0 &&
       !ctx->Extensions.ARB_texture_multisample) {
      return mask;
   }

   /* Clip a copy of the blit coordinates. If these differ from the input
    * coordinates, then we'll set the scissor.
    */
   if (!_mesa_clip_blit(ctx, readFb, drawFb,
                        &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
                        &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
      /* clipped/scissored everything away */
      return 0;
   }

   /* Only scissor affects blit, but we're doing to set a custom scissor if
    * necessary anyway, so save/clear state.
    */
   _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS);

   /* Dithering shouldn't be performed for glBlitFramebuffer */
   _mesa_set_enable(ctx, GL_DITHER, GL_FALSE);

   /* If the clipping earlier changed the destination rect at all, then
    * enable the scissor to clip to it.
    */
   if (clip.dstX0 != dstX0 || clip.dstY0 != dstY0 ||
       clip.dstX1 != dstX1 || clip.dstY1 != dstY1) {
      _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE);
      _mesa_Scissor(MIN2(clip.dstX0, clip.dstX1),
                    MIN2(clip.dstY0, clip.dstY1),
                    abs(clip.dstX0 - clip.dstX1),
                    abs(clip.dstY0 - clip.dstY1));
   }

   /* Try faster, direct texture approach first */
   if (mask & GL_COLOR_BUFFER_BIT) {
      if (blitframebuffer_texture(ctx, readFb, drawFb,
                                  srcX0, srcY0, srcX1, srcY1,
                                  dstX0, dstY0, dstX1, dstY1,
                                  filter, dstFlipX, dstFlipY,
                                  use_glsl_version, false)) {
         mask &= ~GL_COLOR_BUFFER_BIT;
      }
   }

   if (mask & GL_DEPTH_BUFFER_BIT && use_glsl_version) {
      if (blitframebuffer_texture(ctx, readFb, drawFb,
                                  srcX0, srcY0, srcX1, srcY1,
                                  dstX0, dstY0, dstX1, dstY1,
                                  filter, dstFlipX, dstFlipY,
                                  use_glsl_version, true)) {
         mask &= ~GL_DEPTH_BUFFER_BIT;
      }
   }

   if (mask & GL_STENCIL_BUFFER_BIT) {
      /* XXX can't easily do stencil */
   }

   _mesa_meta_end(ctx);

   return mask;
}
Exemplo n.º 6
0
/**
 * Software fallback for glBlitFramebufferEXT().
 */
void
_swrast_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)
{
   static const GLbitfield buffers[3] = {
      GL_COLOR_BUFFER_BIT,
      GL_DEPTH_BUFFER_BIT,
      GL_STENCIL_BUFFER_BIT
   };
   static const GLenum buffer_enums[3] = {
      GL_COLOR,
      GL_DEPTH,
      GL_STENCIL,
   };
   GLint i;

   if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
                        &dstX0, &dstY0, &dstX1, &dstY1)) {
      return;
   }

   if (SWRAST_CONTEXT(ctx)->NewState)
      _swrast_validate_derived(ctx);

   /* First, try covering whatever buffers possible using the fast 1:1 copy
    * path.
    */
   if (srcX1 - srcX0 == dstX1 - dstX0 &&
       srcY1 - srcY0 == dstY1 - dstY0 &&
       srcX0 < srcX1 &&
       srcY0 < srcY1 &&
       dstX0 < dstX1 &&
       dstY0 < dstY1) {
      for (i = 0; i < 3; i++) {
         if (mask & buffers[i]) {
	    if (swrast_fast_copy_pixels(ctx,
					srcX0, srcY0,
					srcX1 - srcX0, srcY1 - srcY0,
					dstX0, dstY0,
					buffer_enums[i])) {
	       mask &= ~buffers[i];
	    }
	 }
      }

      if (!mask)
	 return;
   }

   if (filter == GL_NEAREST) {
      for (i = 0; i < 3; i++) {
	 if (mask & buffers[i]) {
	    blit_nearest(ctx,  srcX0, srcY0, srcX1, srcY1,
			 dstX0, dstY0, dstX1, dstY1, buffers[i]);
	 }
      }
   }
   else {
      ASSERT(filter == GL_LINEAR);
      if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
	 blit_linear(ctx,  srcX0, srcY0, srcX1, srcY1,
		     dstX0, dstY0, dstX1, dstY1);
      }
   }

}
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");
         }
      }
   }
}
Exemplo n.º 8
0
/**
 * Software fallback for glBlitFramebufferEXT().
 */
void
_swrast_BlitFramebuffer(struct gl_context *ctx,
                        struct gl_framebuffer *readFb,
                        struct gl_framebuffer *drawFb,
                        GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
                        GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
                        GLbitfield mask, GLenum filter)
{
   static const GLbitfield buffers[3] = {
      GL_COLOR_BUFFER_BIT,
      GL_DEPTH_BUFFER_BIT,
      GL_STENCIL_BUFFER_BIT
   };
   static const GLenum buffer_enums[3] = {
      GL_COLOR,
      GL_DEPTH,
      GL_STENCIL,
   };
   GLint i;

   /* Page 679 of OpenGL 4.4 spec says:
    *    "Added BlitFramebuffer to commands affected by conditional rendering in
    *     section 10.10 (Bug 9562)."
    */
   if (!_mesa_check_conditional_render(ctx))
      return; /* Do not blit */

   if (!_mesa_clip_blit(ctx, readFb, drawFb, &srcX0, &srcY0, &srcX1, &srcY1,
                        &dstX0, &dstY0, &dstX1, &dstY1)) {
      return;
   }

   if (SWRAST_CONTEXT(ctx)->NewState)
      _swrast_validate_derived(ctx);

   /* First, try covering whatever buffers possible using the fast 1:1 copy
    * path.
    */
   if (srcX1 - srcX0 == dstX1 - dstX0 &&
       srcY1 - srcY0 == dstY1 - dstY0 &&
       srcX0 < srcX1 &&
       srcY0 < srcY1 &&
       dstX0 < dstX1 &&
       dstY0 < dstY1) {
      for (i = 0; i < 3; i++) {
         if (mask & buffers[i]) {
            if (swrast_fast_copy_pixels(ctx,
                                        readFb, drawFb,
                                        srcX0, srcY0,
                                        srcX1 - srcX0, srcY1 - srcY0,
                                        dstX0, dstY0,
                                        buffer_enums[i])) {
               mask &= ~buffers[i];
            }
         }
      }

      if (!mask)
         return;
   }

   if (filter == GL_NEAREST) {
      for (i = 0; i < 3; i++) {
          if (mask & buffers[i]) {
             blit_nearest(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1,
                          dstX0, dstY0, dstX1, dstY1, buffers[i]);
          }
      }
   }
   else {
      assert(filter == GL_LINEAR);
      if (mask & GL_COLOR_BUFFER_BIT) {  /* depth/stencil not allowed */
         blit_linear(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1,
                     dstX0, dstY0, dstX1, dstY1);
      }
   }

}
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);
   }
}