X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fstate_tracker%2Fst_cb_blit.c;h=a5a0d2d8d2649aab3ecabc9dfa5d92ba5c388585;hb=877128505431adaf817dc8069172ebe4a1cdf5d8;hp=1f73f503f6f004880c94dca32a5d540997840e85;hpb=bcc13b74443137043e8a34f8cb64a5add0d8af93;p=mesa.git diff --git a/src/mesa/state_tracker/st_cb_blit.c b/src/mesa/state_tracker/st_cb_blit.c index 1f73f503f6f..a5a0d2d8d26 100644 --- a/src/mesa/state_tracker/st_cb_blit.c +++ b/src/mesa/state_tracker/st_cb_blit.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2007 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. - * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. @@ -38,29 +38,41 @@ #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_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) +static void +st_adjust_blit_for_msaa_resolve(struct pipe_blit_info *blit) { - util_destroy_blit(st->blit); - st->blit = NULL; + /* Even though we do multisample resolves at the time of the blit, OpenGL + * specification defines them as if they happen at the time of rendering, + * which means that the type of averaging we do during the resolve should + * only depend on the source format; the destination format should be + * ignored. But, specification doesn't seem to be strict about it. + * + * It has been observed that mulitisample resolves produce slightly better + * looking images when averaging is done using destination format. NVIDIA's + * proprietary OpenGL driver also follows this approach. + * + * When multisampling, if the source and destination formats are equal + * (aside from the color space), we choose to blit in sRGB space to get + * this higher quality image. + */ + if (blit->src.resource->nr_samples > 1 && + blit->dst.resource->nr_samples <= 1) { + blit->dst.format = blit->dst.resource->format; + + if (util_format_is_srgb(blit->dst.resource->format)) + blit->src.format = util_format_srgb(blit->src.resource->format); + else + blit->src.format = util_format_linear(blit->src.resource->format); + } } - -#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) @@ -69,20 +81,62 @@ st_BlitFramebuffer(GLcontext *ctx, 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); + ? PIPE_TEX_FILTER_NEAREST + : PIPE_TEX_FILTER_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)) { + 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; + + /* 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) { @@ -105,46 +159,110 @@ st_BlitFramebuffer(GLcontext *ctx, 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 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; + blit.mask = PIPE_MASK_RGBA; - if (!srcObj->pt) + 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 = util_format_linear(dstSurf->format); - srcSub.face = srcAtt->CubeMapFace; - srcSub.level = srcAtt->TextureLevel; + 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); - util_blit_pixels(st->blit, srcObj->pt, srcSub, - srcX0, srcY0, srcX1, srcY1, srcAtt->Zoffset, - dstSurf, dstX0, dstY0, dstX1, dstY1, - 0.0, pFilter); + st_adjust_blit_for_msaa_resolve(&blit); + + 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_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); + 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_adjust_blit_for_msaa_resolve(&blit); + + st->pipe->blit(st->pipe, &blit); + } + } + } } } @@ -152,53 +270,73 @@ st_BlitFramebuffer(GLcontext *ctx, /* 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_subresource srcSub; - - srcSub.face = srcDepthRb->surface->face; - srcSub.level = srcDepthRb->surface->level; - - /* 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, srcSub, srcX0, srcY0, srcX1, srcY1, - srcDepthRb->surface->zslice, - 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); } } } @@ -210,5 +348,3 @@ st_init_blit_functions(struct dd_function_table *functions) { functions->BlitFramebuffer = st_BlitFramebuffer; } - -#endif /* FEATURE_EXT_framebuffer_blit */