/*
* Mesa 3-D graphics library
- * Version: 6.5
*
* Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
*
* 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.
*/
#include "main/macros.h"
#include "main/format_unpack.h"
#include "main/format_pack.h"
+#include "main/condrender.h"
#include "s_context.h"
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]; \
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]; \
} \
*/
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 *readRb, *drawRb = NULL;
+ struct gl_renderbuffer_attachment *readAtt = NULL, *drawAtt = NULL;
+ GLuint numDrawBuffers = 0;
+ GLuint i;
const GLint srcWidth = ABS(srcX1 - srcX0);
const GLint dstWidth = ABS(dstX1 - dstX0);
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;
switch (buffer) {
case GL_COLOR_BUFFER_BIT:
- readRb = ctx->ReadBuffer->_ColorReadBuffer;
- drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
-
- if (readRb->Format == drawRb->Format) {
- mode = DIRECT;
- pixelSize = _mesa_get_format_bytes(readRb->Format);
- } else {
- mode = UNPACK_RGBA_FLOAT;
- pixelSize = 16;
- }
-
+ readAtt = &readFb->Attachment[readFb->_ColorReadBufferIndex];
+ readRb = readFb->_ColorReadBuffer;
+ numDrawBuffers = drawFb->_NumColorDrawBuffers;
break;
case GL_DEPTH_BUFFER_BIT:
- readRb = ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
- drawRb = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
+ readAtt = &readFb->Attachment[BUFFER_DEPTH];
+ drawAtt = &drawFb->Attachment[BUFFER_DEPTH];
+ readRb = readAtt->Renderbuffer;
+ drawRb = drawAtt->Renderbuffer;
+ numDrawBuffers = 1;
/* Note that for depth/stencil, the formats of src/dst must match. By
* 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;
pixelSize = 4;
break;
case GL_STENCIL_BUFFER_BIT:
- readRb = ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
- drawRb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
+ readAtt = &readFb->Attachment[BUFFER_STENCIL];
+ drawAtt = &drawFb->Attachment[BUFFER_STENCIL];
+ readRb = readAtt->Renderbuffer;
+ drawRb = drawAtt->Renderbuffer;
+ numDrawBuffers = 1;
mode = UNPACK_S;
pixelSize = 1;
break;
return;
}
- /* choose row resampler */
- switch (pixelSize) {
- case 1:
- resampleRow = resample_row_1;
- break;
- case 2:
- resampleRow = resample_row_2;
- break;
- case 4:
- resampleRow = resample_row_4;
- break;
- case 8:
- resampleRow = resample_row_8;
- break;
- case 16:
- resampleRow = resample_row_16;
- break;
- default:
- _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
- pixelSize);
- 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) {
+ int idx = drawFb->_ColorDrawBufferIndexes[i];
+ if (idx == -1)
+ continue;
+ drawAtt = &drawFb->Attachment[idx];
+ drawRb = drawAtt->Renderbuffer;
+
+ if (!drawRb)
+ continue;
+
+ if (readRb->Format == drawRb->Format) {
+ mode = DIRECT;
+ pixelSize = _mesa_get_format_bytes(readRb->Format);
+ } else {
+ mode = UNPACK_RGBA_FLOAT;
+ pixelSize = 16;
+ }
+ }
- if (readRb == drawRb) {
- /* map whole buffer for read/write */
- /* XXX we could be clever and just map the union region of the
- * source and dest rects.
- */
- GLubyte *map;
- GLint rowStride;
- GLint formatSize = _mesa_get_format_bytes(readRb->Format);
-
- ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0,
- readRb->Width, readRb->Height,
- GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
- &map, &rowStride);
- if (!map) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
- return;
+ /* choose row resampler */
+ switch (pixelSize) {
+ case 1:
+ resampleRow = resample_row_1;
+ break;
+ case 2:
+ resampleRow = resample_row_2;
+ break;
+ case 4:
+ resampleRow = resample_row_4;
+ break;
+ case 8:
+ resampleRow = resample_row_8;
+ break;
+ case 16:
+ resampleRow = resample_row_16;
+ break;
+ default:
+ _mesa_problem(ctx, "unexpected pixel size (%d) in blit_nearest",
+ pixelSize);
+ goto fail;
}
- srcMap = map + srcYpos * rowStride + srcXpos * formatSize;
- dstMap = map + dstYpos * rowStride + dstXpos * formatSize;
+ if ((readRb == drawRb) ||
+ (readAtt->Texture && drawAtt->Texture &&
+ (readAtt->Texture == drawAtt->Texture))) {
+ /* map whole buffer for read/write */
+ /* XXX we could be clever and just map the union region of the
+ * source and dest rects.
+ */
+ GLubyte *map;
+ GLint rowStride;
+ GLint formatSize = _mesa_get_format_bytes(readRb->Format);
+
+ ctx->Driver.MapRenderbuffer(ctx, readRb, 0, 0,
+ readRb->Width, readRb->Height,
+ GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
+ &map, &rowStride);
+ if (!map) {
+ goto fail_no_memory;
+ }
+
+ srcMap = map + srcYpos * rowStride + srcXpos * formatSize;
+ dstMap = map + dstYpos * rowStride + dstXpos * formatSize;
- /* this handles overlapping copies */
- if (srcY0 < dstY0) {
- /* copy in reverse (top->down) order */
- srcMap += rowStride * (readRb->Height - 1);
- dstMap += rowStride * (readRb->Height - 1);
- srcRowStride = -rowStride;
- dstRowStride = -rowStride;
+ /* this handles overlapping copies */
+ if (srcY0 < dstY0) {
+ /* copy in reverse (top->down) order */
+ srcMap += rowStride * (readRb->Height - 1);
+ dstMap += rowStride * (readRb->Height - 1);
+ srcRowStride = -rowStride;
+ dstRowStride = -rowStride;
+ }
+ else {
+ /* copy in normal (bottom->up) order */
+ srcRowStride = rowStride;
+ dstRowStride = rowStride;
+ }
}
else {
- /* copy in normal (bottom->up) order */
- srcRowStride = rowStride;
- dstRowStride = rowStride;
- }
- }
- else {
- /* different src/dst buffers */
- ctx->Driver.MapRenderbuffer(ctx, readRb,
- srcXpos, srcYpos,
- srcWidth, srcHeight,
- GL_MAP_READ_BIT, &srcMap, &srcRowStride);
- if (!srcMap) {
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
- return;
- }
- ctx->Driver.MapRenderbuffer(ctx, drawRb,
- dstXpos, dstYpos,
- dstWidth, dstHeight,
- GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
- if (!dstMap) {
- ctx->Driver.UnmapRenderbuffer(ctx, readRb);
- _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
- return;
+ /* different src/dst buffers */
+ ctx->Driver.MapRenderbuffer(ctx, readRb,
+ srcXpos, srcYpos,
+ srcWidth, srcHeight,
+ GL_MAP_READ_BIT, &srcMap, &srcRowStride);
+ if (!srcMap) {
+ goto fail_no_memory;
+ }
+ ctx->Driver.MapRenderbuffer(ctx, drawRb,
+ dstXpos, dstYpos,
+ dstWidth, dstHeight,
+ GL_MAP_WRITE_BIT, &dstMap, &dstRowStride);
+ if (!dstMap) {
+ ctx->Driver.UnmapRenderbuffer(ctx, readRb);
+ 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++) {
+ GLfloat srcRowF = (dstRow + 0.5F) / dstHeight * srcHeight - 0.5F;
+ GLint srcRow = IROUND(srcRowF);
+ GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
- for (dstRow = 0; dstRow < dstHeight; dstRow++) {
- GLint srcRow = (dstRow * srcHeight) / dstHeight;
- GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
+ assert(srcRow >= 0);
+ assert(srcRow < srcHeight);
- ASSERT(srcRow >= 0);
- ASSERT(srcRow < srcHeight);
+ if (invertY) {
+ srcRow = srcHeight - 1 - srcRow;
+ }
- if (invertY) {
- srcRow = srcHeight - 1 - srcRow;
- }
+ /* get pixel row from source and resample to match dest width */
+ if (prevY != srcRow) {
+ GLubyte *srcRowStart = srcMap + srcRowStride * srcRow;
+
+ switch (mode) {
+ case DIRECT:
+ memcpy(srcBuffer, srcRowStart, pixelSize * srcWidth);
+ break;
+ case UNPACK_RGBA_FLOAT:
+ _mesa_unpack_rgba_row(readRb->Format, srcWidth, srcRowStart,
+ srcBuffer);
+ break;
+ case UNPACK_Z_FLOAT:
+ _mesa_unpack_float_z_row(readRb->Format, srcWidth, srcRowStart,
+ srcBuffer);
+ break;
+ case UNPACK_Z_INT:
+ _mesa_unpack_uint_z_row(readRb->Format, srcWidth, srcRowStart,
+ srcBuffer);
+ break;
+ case UNPACK_S:
+ _mesa_unpack_ubyte_stencil_row(readRb->Format, srcWidth,
+ srcRowStart, srcBuffer);
+ break;
+ }
- /* get pixel row from source and resample to match dest width */
- if (prevY != srcRow) {
- GLubyte *srcRowStart = srcMap + srcRowStride * srcRow;
-
- switch (mode) {
- case DIRECT:
- memcpy(srcBuffer, srcRowStart, pixelSize * srcWidth);
- break;
- case UNPACK_RGBA_FLOAT:
- _mesa_unpack_rgba_row(readRb->Format, srcWidth, srcRowStart,
- srcBuffer);
- break;
- case UNPACK_Z_FLOAT:
- _mesa_unpack_float_z_row(readRb->Format, srcWidth, srcRowStart,
- srcBuffer);
- break;
- case UNPACK_Z_INT:
- _mesa_unpack_uint_z_row(readRb->Format, srcWidth, srcRowStart,
- srcBuffer);
- break;
- case UNPACK_S:
- _mesa_unpack_ubyte_stencil_row(readRb->Format, srcWidth,
- srcRowStart, srcBuffer);
- break;
- }
-
- (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
- prevY = srcRow;
+ (*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
+ prevY = srcRow;
+ }
+
+ /* store pixel row in destination */
+ switch (mode) {
+ case DIRECT:
+ memcpy(dstRowStart, dstBuffer, pixelSize * dstWidth);
+ break;
+ case UNPACK_RGBA_FLOAT:
+ _mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer,
+ dstRowStart);
+ break;
+ case UNPACK_Z_FLOAT:
+ _mesa_pack_float_z_row(drawRb->Format, dstWidth, dstBuffer,
+ dstRowStart);
+ break;
+ case UNPACK_Z_INT:
+ _mesa_pack_uint_z_row(drawRb->Format, dstWidth, dstBuffer,
+ dstRowStart);
+ break;
+ case UNPACK_S:
+ _mesa_pack_ubyte_stencil_row(drawRb->Format, dstWidth, dstBuffer,
+ dstRowStart);
+ break;
+ }
}
- /* store pixel row in destination */
- switch (mode) {
- case DIRECT:
- memcpy(dstRowStart, dstBuffer, pixelSize * srcWidth);
- break;
- case UNPACK_RGBA_FLOAT:
- _mesa_pack_float_rgba_row(drawRb->Format, dstWidth, dstBuffer,
- dstRowStart);
- break;
- case UNPACK_Z_FLOAT:
- _mesa_pack_float_z_row(drawRb->Format, dstWidth, dstBuffer,
- dstRowStart);
- break;
- case UNPACK_Z_INT:
- _mesa_pack_uint_z_row(drawRb->Format, dstWidth, dstBuffer,
- dstRowStart);
- break;
- case UNPACK_S:
- _mesa_pack_ubyte_stencil_row(drawRb->Format, dstWidth, dstBuffer,
- dstRowStart);
- break;
+ ctx->Driver.UnmapRenderbuffer(ctx, readRb);
+ if (drawRb != readRb) {
+ ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
}
}
+fail:
free(srcBuffer);
free(dstBuffer);
+ return;
- ctx->Driver.UnmapRenderbuffer(ctx, readRb);
- if (drawRb != readRb) {
- ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
- }
+fail_no_memory:
+ free(srcBuffer);
+ free(dstBuffer);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFrameBuffer");
}
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 */
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 */
*/
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_renderbuffer *readRb = ctx->ReadBuffer->_ColorReadBuffer;
- struct gl_renderbuffer *drawRb = ctx->DrawBuffer->_ColorDrawBuffers[0];
+ struct gl_renderbuffer *readRb = readFb->_ColorReadBuffer;
+ struct gl_renderbuffer_attachment *readAtt =
+ &readFb->Attachment[readFb->_ColorReadBufferIndex];
const GLint srcWidth = ABS(srcX1 - srcX0);
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);
GLint srcBufferY0 = -1, srcBufferY1 = -1;
GLvoid *dstBuffer;
- gl_format readFormat = _mesa_get_srgb_format_linear(readRb->Format);
- gl_format drawFormat = _mesa_get_srgb_format_linear(drawRb->Format);
+ mesa_format readFormat = _mesa_get_srgb_format_linear(readRb->Format);
GLuint bpp = _mesa_get_format_bytes(readFormat);
GLenum pixelType;
GLubyte *srcMap, *dstMap;
GLint srcRowStride, dstRowStride;
+ GLuint i;
/* Determine datatype for resampling */
* 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;
}
- /*
- * Map src / dst renderbuffers
- */
- if (readRb == drawRb) {
- /* map whole buffer for read/write */
- ctx->Driver.MapRenderbuffer(ctx, readRb,
- 0, 0, readRb->Width, readRb->Height,
- 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;
- }
+ for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
+ GLint idx = drawFb->_ColorDrawBufferIndexes[i];
+ struct gl_renderbuffer_attachment *drawAtt;
+ struct gl_renderbuffer *drawRb;
+ mesa_format drawFormat;
- dstMap = srcMap;
- dstRowStride = srcRowStride;
- }
- else {
- /* different src/dst buffers */
- /* XXX with a bit of work we could just map the regions to be
- * read/written instead of the whole buffers.
- */
- ctx->Driver.MapRenderbuffer(ctx, readRb,
- 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;
- }
- 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;
- }
- }
+ if (idx == -1)
+ continue;
- for (dstRow = 0; dstRow < dstHeight; dstRow++) {
- const GLint dstY = dstYpos + dstRow;
- const GLfloat srcRow = (dstRow * srcHeight) / dstHeightF;
- GLint srcRow0 = IFLOOR(srcRow);
- GLint srcRow1 = srcRow0 + 1;
- GLfloat rowWeight = srcRow - srcRow0; /* fractional part of srcRow */
+ drawAtt = &drawFb->Attachment[idx];
+ drawRb = drawAtt->Renderbuffer;
+ if (!drawRb)
+ continue;
- ASSERT(srcRow >= 0);
- ASSERT(srcRow < srcHeight);
+ drawFormat = _mesa_get_srgb_format_linear(drawRb->Format);
- if (srcRow1 == srcHeight) {
- /* last row fudge */
- srcRow1 = srcRow0;
- rowWeight = 0.0;
- }
+ /*
+ * Map src / dst renderbuffers
+ */
+ if ((readRb == drawRb) ||
+ (readAtt->Texture && drawAtt->Texture &&
+ (readAtt->Texture == drawAtt->Texture))) {
+ /* map whole buffer for read/write */
+ ctx->Driver.MapRenderbuffer(ctx, readRb,
+ 0, 0, readRb->Width, readRb->Height,
+ GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
+ &srcMap, &srcRowStride);
+ if (!srcMap) {
+ goto fail_no_memory;
+ }
- if (invertY) {
- srcRow0 = srcHeight - 1 - srcRow0;
- srcRow1 = srcHeight - 1 - srcRow1;
+ dstMap = srcMap;
+ dstRowStride = srcRowStride;
+ }
+ else {
+ /* different src/dst buffers */
+ /* XXX with a bit of work we could just map the regions to be
+ * read/written instead of the whole buffers.
+ */
+ ctx->Driver.MapRenderbuffer(ctx, readRb,
+ 0, 0, readRb->Width, readRb->Height,
+ GL_MAP_READ_BIT, &srcMap, &srcRowStride);
+ if (!srcMap) {
+ 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);
+ goto fail_no_memory;
+ }
}
- srcY0 = srcYpos + srcRow0;
- srcY1 = srcYpos + srcRow1;
+ for (dstRow = 0; dstRow < dstHeight; dstRow++) {
+ const GLint dstY = dstYpos + dstRow;
+ 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 */
+
+ if (srcRow1 == srcHeight) {
+ /* last row fudge */
+ srcRow1 = srcRow0;
+ rowWeight = 0.0;
+ }
- /* get the two source rows */
- if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
- /* use same source row buffers again */
- }
- else if (srcY0 == srcBufferY1) {
- /* move buffer1 into buffer0 by swapping pointers */
- GLvoid *tmp = srcBuffer0;
- srcBuffer0 = srcBuffer1;
- srcBuffer1 = tmp;
- /* get y1 row */
- {
- GLubyte *src = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
- if (pixelType == GL_UNSIGNED_BYTE) {
- _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
- src, srcBuffer1);
+ if (invertY) {
+ srcRow0 = srcHeight - 1 - srcRow0;
+ srcRow1 = srcHeight - 1 - srcRow1;
+ }
+
+ srcY0 = srcYpos + srcRow0;
+ srcY1 = srcYpos + srcRow1;
+
+ /* get the two source rows */
+ if (srcY0 == srcBufferY0 && srcY1 == srcBufferY1) {
+ /* use same source row buffers again */
+ }
+ else if (srcY0 == srcBufferY1) {
+ /* move buffer1 into buffer0 by swapping pointers */
+ GLvoid *tmp = srcBuffer0;
+ srcBuffer0 = srcBuffer1;
+ srcBuffer1 = tmp;
+ /* get y1 row */
+ {
+ GLubyte *src = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
+ if (pixelType == GL_UNSIGNED_BYTE) {
+ _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
+ src, srcBuffer1);
+ }
+ else {
+ _mesa_unpack_rgba_row(readFormat, srcWidth,
+ src, srcBuffer1);
+ }
}
- else {
- _mesa_unpack_rgba_row(readFormat, srcWidth,
- src, srcBuffer1);
+ srcBufferY0 = srcY0;
+ srcBufferY1 = srcY1;
+ }
+ else {
+ /* get both new rows */
+ {
+ GLubyte *src0 = srcMap + srcY0 * srcRowStride + srcXpos * bpp;
+ GLubyte *src1 = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
+ if (pixelType == GL_UNSIGNED_BYTE) {
+ _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
+ src0, srcBuffer0);
+ _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
+ src1, srcBuffer1);
+ }
+ else {
+ _mesa_unpack_rgba_row(readFormat, srcWidth, src0, srcBuffer0);
+ _mesa_unpack_rgba_row(readFormat, srcWidth, src1, srcBuffer1);
+ }
}
- }
- srcBufferY0 = srcY0;
- srcBufferY1 = srcY1;
- }
- else {
- /* get both new rows */
+ srcBufferY0 = srcY0;
+ srcBufferY1 = srcY1;
+ }
+
+ if (pixelType == GL_UNSIGNED_BYTE) {
+ resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
+ dstBuffer, invertX, rowWeight);
+ }
+ else {
+ resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
+ dstBuffer, invertX, rowWeight);
+ }
+
+ /* store pixel row in destination */
{
- GLubyte *src0 = srcMap + srcY0 * srcRowStride + srcXpos * bpp;
- GLubyte *src1 = srcMap + srcY1 * srcRowStride + srcXpos * bpp;
+ GLubyte *dst = dstMap + dstY * dstRowStride + dstXpos * bpp;
if (pixelType == GL_UNSIGNED_BYTE) {
- _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
- src0, srcBuffer0);
- _mesa_unpack_ubyte_rgba_row(readFormat, srcWidth,
- src1, srcBuffer1);
+ _mesa_pack_ubyte_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
}
else {
- _mesa_unpack_rgba_row(readFormat, srcWidth, src0, srcBuffer0);
- _mesa_unpack_rgba_row(readFormat, srcWidth, src1, srcBuffer1);
+ _mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
}
}
- srcBufferY0 = srcY0;
- srcBufferY1 = srcY1;
}
- if (pixelType == GL_UNSIGNED_BYTE) {
- resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
- dstBuffer, invertX, rowWeight);
- }
- else {
- resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
- dstBuffer, invertX, rowWeight);
- }
-
- /* store pixel row in destination */
- {
- GLubyte *dst = dstMap + dstY * dstRowStride + dstXpos * bpp;
- if (pixelType == GL_UNSIGNED_BYTE) {
- _mesa_pack_ubyte_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
- }
- else {
- _mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
- }
+ ctx->Driver.UnmapRenderbuffer(ctx, readRb);
+ if (drawRb != readRb) {
+ ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
}
}
free(srcBuffer0);
free(srcBuffer1);
free(dstBuffer);
+ return;
- ctx->Driver.UnmapRenderbuffer(ctx, readRb);
- if (drawRb != readRb) {
- ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
- }
+fail_no_memory:
+ free(srcBuffer0);
+ free(srcBuffer1);
+ free(dstBuffer);
+ _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
}
*/
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)
};
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;
}
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);
}
}