#include "main/imports.h"
#include "main/image.h"
#include "main/macros.h"
-#include "shader/program.h"
#include "st_context.h"
#include "st_texture.h"
#include "st_cb_blit.h"
#include "st_cb_fbo.h"
+#include "st_atom.h"
-#include "util/u_blit.h"
-#include "util/u_inlines.h"
+#include "util/u_format.h"
-void
-st_init_blit(struct st_context *st)
-{
- st->blit = util_create_blit(st->pipe, st->cso_context);
-}
-
-
-void
-st_destroy_blit(struct st_context *st)
-{
- util_destroy_blit(st->blit);
- st->blit = NULL;
-}
-
-
-#if FEATURE_EXT_framebuffer_blit
static void
-st_BlitFramebuffer(GLcontext *ctx,
+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 = ctx->st;
- struct pipe_context *pipe = st->pipe;
+ struct st_context *st = st_context(ctx);
const uint pFilter = ((filter == GL_NEAREST)
- ? PIPE_TEX_MIPFILTER_NEAREST
- : PIPE_TEX_MIPFILTER_LINEAR);
+ ? PIPE_TEX_FILTER_NEAREST
+ : PIPE_TEX_FILTER_LINEAR);
struct gl_framebuffer *readFB = ctx->ReadBuffer;
struct gl_framebuffer *drawFB = ctx->DrawBuffer;
+ struct {
+ GLint srcX0, srcY0, srcX1, srcY1;
+ GLint dstX0, dstY0, dstX1, dstY1;
+ } clip;
+ struct pipe_blit_info blit;
+
+ st_validate_state(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;
- if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
- &dstX0, &dstY0, &dstX1, &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,
+ &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1,
+ &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) {
return; /* nothing to draw/blit */
}
+ 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) {
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;
+ }
+
+ blit.filter = pFilter;
+
if (mask & GL_COLOR_BUFFER_BIT) {
struct gl_renderbuffer_attachment *srcAtt =
&readFB->Attachment[readFB->_ColorReadBufferIndex];
- if(srcAtt->Type == GL_TEXTURE) {
- struct pipe_screen *screen = pipe->screen;
- struct st_texture_object *srcObj =
- st_texture_object(srcAtt->Texture);
- struct st_renderbuffer *dstRb =
- st_renderbuffer(drawFB->_ColorDrawBuffers[0]);
- struct pipe_surface *srcSurf;
- struct pipe_surface *dstSurf = dstRb->surface;
+ blit.mask = PIPE_MASK_RGBA;
- if (!srcObj->pt)
- return;
+ if (srcAtt->Type == GL_TEXTURE) {
+ struct st_texture_object *srcObj = st_texture_object(srcAtt->Texture);
+ GLuint i;
- srcSurf = screen->get_tex_surface(screen,
- srcObj->pt,
- srcAtt->CubeMapFace,
- srcAtt->TextureLevel,
- srcAtt->Zoffset,
- PIPE_BUFFER_USAGE_GPU_READ);
- if(!srcSurf)
+ 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;
- util_blit_pixels(st->blit,
- srcSurf, st_get_stobj_sampler_view(srcObj),
- srcX0, srcY0, srcX1, srcY1,
- dstSurf, dstX0, dstY0, dstX1, dstY1,
- 0.0, pFilter);
+ 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 = util_format_linear(dstSurf->format);
- pipe_surface_reference(&srcSurf, NULL);
+ blit.src.resource = srcObj->pt;
+ blit.src.level = srcAtt->TextureLevel;
+ blit.src.box.z = srcAtt->Zoffset + srcAtt->CubeMapFace;
+ blit.src.format = util_format_linear(srcObj->pt->format);
+
+ st->pipe->blit(st->pipe, &blit);
+ }
+ }
+ }
}
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_sampler_view *srcView = st_renderbuffer_get_sampler_view(srcRb, pipe);
- struct pipe_surface *dstSurf = dstRb->surface;
-
- util_blit_pixels(st->blit,
- srcSurf, srcView, srcX0, srcY0, srcX1, srcY1,
- dstSurf, dstX0, dstY0, dstX1, dstY1,
- 0.0, pFilter);
+ 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 = util_format_linear(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 = util_format_linear(srcSurf->format);
+
+ st->pipe->blit(st->pipe, &blit);
+ }
+ }
+ }
}
}
/* depth and/or stencil blit */
/* get src/dst depth surfaces */
- struct st_renderbuffer *srcDepthRb =
+ 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 =
+ struct st_renderbuffer *srcStencilRb =
st_renderbuffer(readFB->Attachment[BUFFER_STENCIL].Renderbuffer);
- struct st_renderbuffer *dstStencilRb =
+ 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) {
- struct pipe_sampler_view *srcView = st_renderbuffer_get_sampler_view(srcDepthRb, pipe);
-
- /* Blitting depth and stencil values between combined
- * depth/stencil buffers. This is the ideal case for such buffers.
- */
- util_blit_pixels(st->blit,
- srcDepthSurf, srcView, srcX0, srcY0, srcX1, srcY1,
- dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
- 0.0, pFilter);
+ 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 Z only */
- _mesa_problem(ctx, "st_BlitFramebuffer(DEPTH) not completed");
+ 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 stencil only */
- _mesa_problem(ctx, "st_BlitFramebuffer(STENCIL) not completed");
+ 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);
}
}
}
}
-#endif /* FEATURE_EXT_framebuffer_blit */
-
void
st_init_blit_functions(struct dd_function_table *functions)
{
-#if FEATURE_EXT_framebuffer_blit
functions->BlitFramebuffer = st_BlitFramebuffer;
-#endif
}