X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fswrast%2Fs_blit.c;h=3e838a41d44b08149d0ee261a28fa8201d70ce1b;hb=192de3f051c70ff1404369f88ae2d55f1ffcf806;hp=08ec5e2d0e0cde8d16d0194b10e7aeaa59310dfa;hpb=b70b4862491121d5cc4444cea34f2f86a3aa5ded;p=mesa.git diff --git a/src/mesa/swrast/s_blit.c b/src/mesa/swrast/s_blit.c index 08ec5e2d0e0..3e838a41d44 100644 --- a/src/mesa/swrast/s_blit.c +++ b/src/mesa/swrast/s_blit.c @@ -1,6 +1,5 @@ /* * Mesa 3-D graphics library - * Version: 6.5 * * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. * @@ -17,9 +16,10 @@ * 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 NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL 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. + * THE AUTHORS OR COPYRIGHT HOLDERS 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. */ @@ -29,6 +29,7 @@ #include "main/macros.h" #include "main/format_unpack.h" #include "main/format_pack.h" +#include "main/condrender.h" #include "s_context.h" @@ -51,8 +52,8 @@ NAME(GLint srcWidth, GLint dstWidth, \ if (flip) { \ for (dstCol = 0; dstCol < dstWidth; dstCol++) { \ GLint srcCol = (dstCol * srcWidth) / dstWidth; \ - ASSERT(srcCol >= 0); \ - ASSERT(srcCol < srcWidth); \ + assert(srcCol >= 0); \ + assert(srcCol < srcWidth); \ srcCol = srcWidth - 1 - srcCol; /* flip */ \ if (SIZE == 1) { \ dst[dstCol] = src[srcCol]; \ @@ -72,8 +73,8 @@ NAME(GLint srcWidth, GLint dstWidth, \ else { \ for (dstCol = 0; dstCol < dstWidth; dstCol++) { \ GLint srcCol = (dstCol * srcWidth) / dstWidth; \ - ASSERT(srcCol >= 0); \ - ASSERT(srcCol < srcWidth); \ + assert(srcCol >= 0); \ + assert(srcCol < srcWidth); \ if (SIZE == 1) { \ dst[dstCol] = src[srcCol]; \ } \ @@ -106,14 +107,14 @@ RESAMPLE(resample_row_16, GLuint, 4) */ static void blit_nearest(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 buffer) { - struct gl_renderbuffer *readRb, *drawRb; - struct gl_renderbuffer_attachment *readAtt, *drawAtt; - struct gl_framebuffer *readFb = ctx->ReadBuffer; - struct gl_framebuffer *drawFb = ctx->DrawBuffer; + struct gl_renderbuffer *readRb, *drawRb = NULL; + struct gl_renderbuffer_attachment *readAtt = NULL, *drawAtt = NULL; GLuint numDrawBuffers = 0; GLuint i; @@ -135,12 +136,12 @@ blit_nearest(struct gl_context *ctx, UNPACK_Z_FLOAT, UNPACK_Z_INT, UNPACK_S, - } mode; + } mode = DIRECT; GLubyte *srcMap, *dstMap; GLint srcRowStride, dstRowStride; GLint dstRow; - GLint pixelSize; + GLint pixelSize = 0; GLvoid *srcBuffer, *dstBuffer; GLint prevY = -1; @@ -166,8 +167,8 @@ blit_nearest(struct gl_context *ctx, * using the core helpers for pack/unpack, we avoid needing to handle * masking for things like DEPTH copies of Z24S8. */ - if (readRb->Format == MESA_FORMAT_Z32_FLOAT || - readRb->Format == MESA_FORMAT_Z32_FLOAT_X24S8) { + if (readRb->Format == MESA_FORMAT_Z_FLOAT32 || + readRb->Format == MESA_FORMAT_Z32_FLOAT_S8X24_UINT) { mode = UNPACK_Z_FLOAT; } else { mode = UNPACK_Z_INT; @@ -188,6 +189,12 @@ blit_nearest(struct gl_context *ctx, return; } + /* allocate the src/dst row buffers */ + srcBuffer = malloc(MAX_PIXEL_BYTES * srcWidth); + dstBuffer = malloc(MAX_PIXEL_BYTES * dstWidth); + if (!srcBuffer || !dstBuffer) + goto fail_no_memory; + /* Blit to all the draw buffers */ for (i = 0; i < numDrawBuffers; i++) { if (buffer == GL_COLOR_BUFFER_BIT) { @@ -229,7 +236,7 @@ blit_nearest(struct gl_context *ctx, default: _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest", pixelSize); - return; + goto fail; } if ((readRb == drawRb) || @@ -248,8 +255,7 @@ blit_nearest(struct gl_context *ctx, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, &map, &rowStride); if (!map) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); - return; + goto fail_no_memory; } srcMap = map + srcYpos * rowStride + srcXpos * formatSize; @@ -276,8 +282,7 @@ blit_nearest(struct gl_context *ctx, srcWidth, srcHeight, GL_MAP_READ_BIT, &srcMap, &srcRowStride); if (!srcMap) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); - return; + goto fail_no_memory; } ctx->Driver.MapRenderbuffer(ctx, drawRb, dstXpos, dstYpos, @@ -285,30 +290,17 @@ blit_nearest(struct gl_context *ctx, GL_MAP_WRITE_BIT, &dstMap, &dstRowStride); if (!dstMap) { ctx->Driver.UnmapRenderbuffer(ctx, readRb); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); - return; + goto fail_no_memory; } } - /* allocate the src/dst row buffers */ - srcBuffer = malloc(pixelSize * srcWidth); - if (!srcBuffer) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); - return; - } - dstBuffer = malloc(pixelSize * dstWidth); - if (!dstBuffer) { - free(srcBuffer); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); - return; - } - for (dstRow = 0; dstRow < dstHeight; dstRow++) { - GLint srcRow = (dstRow * srcHeight) / dstHeight; + GLfloat srcRowF = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F; + GLint srcRow = IROUND(srcRowF); GLubyte *dstRowStart = dstMap + dstRowStride * dstRow; - ASSERT(srcRow >= 0); - ASSERT(srcRow < srcHeight); + assert(srcRow >= 0); + assert(srcRow < srcHeight); if (invertY) { srcRow = srcHeight - 1 - srcRow; @@ -368,14 +360,21 @@ blit_nearest(struct gl_context *ctx, } } - free(srcBuffer); - free(dstBuffer); - ctx->Driver.UnmapRenderbuffer(ctx, readRb); if (drawRb != readRb) { ctx->Driver.UnmapRenderbuffer(ctx, drawRb); } } + +fail: + free(srcBuffer); + free(dstBuffer); + return; + +fail_no_memory: + free(srcBuffer); + free(dstBuffer); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBuffer"); } @@ -404,19 +403,17 @@ resample_linear_row_ub(GLint srcWidth, GLint dstWidth, const GLubyte (*srcColor0)[4] = (const GLubyte (*)[4]) srcBuffer0; const GLubyte (*srcColor1)[4] = (const GLubyte (*)[4]) srcBuffer1; GLubyte (*dstColor)[4] = (GLubyte (*)[4]) dstBuffer; - const GLfloat dstWidthF = (GLfloat) dstWidth; GLint dstCol; for (dstCol = 0; dstCol < dstWidth; dstCol++) { - const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF; - GLint srcCol0 = IFLOOR(srcCol); + const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F; + GLint srcCol0 = MAX2(0, IFLOOR(srcCol)); GLint srcCol1 = srcCol0 + 1; GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */ GLfloat red, green, blue, alpha; - ASSERT(srcCol0 >= 0); - ASSERT(srcCol0 < srcWidth); - ASSERT(srcCol1 <= srcWidth); + assert(srcCol0 < srcWidth); + assert(srcCol1 <= srcWidth); if (srcCol1 == srcWidth) { /* last column fudge */ @@ -461,19 +458,17 @@ resample_linear_row_float(GLint srcWidth, GLint dstWidth, const GLfloat (*srcColor0)[4] = (const GLfloat (*)[4]) srcBuffer0; const GLfloat (*srcColor1)[4] = (const GLfloat (*)[4]) srcBuffer1; GLfloat (*dstColor)[4] = (GLfloat (*)[4]) dstBuffer; - const GLfloat dstWidthF = (GLfloat) dstWidth; GLint dstCol; for (dstCol = 0; dstCol < dstWidth; dstCol++) { - const GLfloat srcCol = (dstCol * srcWidth) / dstWidthF; - GLint srcCol0 = IFLOOR(srcCol); + const GLfloat srcCol = (dstCol + 0.5F) / dstWidth * srcWidth - 0.5F; + GLint srcCol0 = MAX2(0, IFLOOR(srcCol)); GLint srcCol1 = srcCol0 + 1; GLfloat colWeight = srcCol - srcCol0; /* fractional part of srcCol */ GLfloat red, green, blue, alpha; - ASSERT(srcCol0 >= 0); - ASSERT(srcCol0 < srcWidth); - ASSERT(srcCol1 <= srcWidth); + assert(srcCol0 < srcWidth); + assert(srcCol1 <= srcWidth); if (srcCol1 == srcWidth) { /* last column fudge */ @@ -513,11 +508,11 @@ resample_linear_row_float(GLint srcWidth, GLint dstWidth, */ static void blit_linear(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) { - struct gl_framebuffer *drawFb = ctx->DrawBuffer; - struct gl_framebuffer *readFb = ctx->ReadBuffer; struct gl_renderbuffer *readRb = readFb->_ColorReadBuffer; struct gl_renderbuffer_attachment *readAtt = &readFb->Attachment[readFb->_ColorReadBufferIndex]; @@ -526,7 +521,6 @@ blit_linear(struct gl_context *ctx, const GLint dstWidth = ABS(dstX1 - dstX0); const GLint srcHeight = ABS(srcY1 - srcY0); const GLint dstHeight = ABS(dstY1 - dstY0); - const GLfloat dstHeightF = (GLfloat) dstHeight; const GLint srcXpos = MIN2(srcX0, srcX1); const GLint srcYpos = MIN2(srcY0, srcY1); @@ -543,7 +537,7 @@ blit_linear(struct gl_context *ctx, GLint srcBufferY0 = -1, srcBufferY1 = -1; GLvoid *dstBuffer; - gl_format readFormat = _mesa_get_srgb_format_linear(readRb->Format); + mesa_format readFormat = _mesa_get_srgb_format_linear(readRb->Format); GLuint bpp = _mesa_get_format_bytes(readFormat); GLenum pixelType; @@ -568,29 +562,17 @@ blit_linear(struct gl_context *ctx, * Keep two adjacent src rows around for bilinear sampling. */ srcBuffer0 = malloc(pixelSize * srcWidth); - if (!srcBuffer0) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); - return; - } srcBuffer1 = malloc(pixelSize * srcWidth); - if (!srcBuffer1) { - free(srcBuffer0); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); - return; - } dstBuffer = malloc(pixelSize * dstWidth); - if (!dstBuffer) { - free(srcBuffer0); - free(srcBuffer1); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBufferEXT"); - return; + if (!srcBuffer0 || !srcBuffer1 || !dstBuffer) { + goto fail_no_memory; } for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) { GLint idx = drawFb->_ColorDrawBufferIndexes[i]; struct gl_renderbuffer_attachment *drawAtt; struct gl_renderbuffer *drawRb; - gl_format drawFormat; + mesa_format drawFormat; if (idx == -1) continue; @@ -614,11 +596,7 @@ blit_linear(struct gl_context *ctx, GL_MAP_READ_BIT | GL_MAP_WRITE_BIT, &srcMap, &srcRowStride); if (!srcMap) { - free(srcBuffer0); - free(srcBuffer1); - free(dstBuffer); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); - return; + goto fail_no_memory; } dstMap = srcMap; @@ -633,35 +611,24 @@ blit_linear(struct gl_context *ctx, 0, 0, readRb->Width, readRb->Height, GL_MAP_READ_BIT, &srcMap, &srcRowStride); if (!srcMap) { - free(srcBuffer0); - free(srcBuffer1); - free(dstBuffer); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); - return; + goto fail_no_memory; } ctx->Driver.MapRenderbuffer(ctx, drawRb, 0, 0, drawRb->Width, drawRb->Height, GL_MAP_WRITE_BIT, &dstMap, &dstRowStride); if (!dstMap) { ctx->Driver.UnmapRenderbuffer(ctx, readRb); - free(srcBuffer0); - free(srcBuffer1); - free(dstBuffer); - _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); - return; + goto fail_no_memory; } } for (dstRow = 0; dstRow < dstHeight; dstRow++) { const GLint dstY = dstYpos + dstRow; - const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF; - GLint srcRow0 = IFLOOR(srcRow); + GLfloat srcRow = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F; + GLint srcRow0 = MAX2(0, IFLOOR(srcRow)); GLint srcRow1 = srcRow0 + 1; GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */ - ASSERT(srcRow >= 0); - ASSERT(srcRow < srcHeight); - if (srcRow1 == srcHeight) { /* last row fudge */ srcRow1 = srcRow0; @@ -741,15 +708,22 @@ blit_linear(struct gl_context *ctx, } } - free(srcBuffer0); - free(srcBuffer1); - free(dstBuffer); - ctx->Driver.UnmapRenderbuffer(ctx, readRb); if (drawRb != readRb) { ctx->Driver.UnmapRenderbuffer(ctx, drawRb); } } + + free(srcBuffer0); + free(srcBuffer1); + free(dstBuffer); + return; + +fail_no_memory: + free(srcBuffer0); + free(srcBuffer1); + free(dstBuffer); + _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer"); } @@ -759,6 +733,8 @@ blit_linear(struct gl_context *ctx, */ 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) @@ -775,7 +751,14 @@ _swrast_BlitFramebuffer(struct gl_context *ctx, }; GLint i; - if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1, + /* 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; } @@ -794,33 +777,34 @@ _swrast_BlitFramebuffer(struct gl_context *ctx, 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 (swrast_fast_copy_pixels(ctx, + readFb, drawFb, + srcX0, srcY0, + srcX1 - srcX0, srcY1 - srcY0, + dstX0, dstY0, + buffer_enums[i])) { + mask &= ~buffers[i]; + } + } } if (!mask) - return; + 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]); - } + if (mask & buffers[i]) { + blit_nearest(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1, buffers[i]); + } } } else { - ASSERT(filter == GL_LINEAR); + 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); + blit_linear(ctx, readFb, drawFb, srcX0, srcY0, srcX1, srcY1, + dstX0, dstY0, dstX1, dstY1); } }