mesa: Add support to allow blitting to multiple color draw buffers
This patch fixes a blitting case when drawAttachment->Texture ==
readAttachment->Texture. It was causing an assertion failure in
intel_miptree_attach_map() with gles3 conformance test case:
framebuffer_blit_functionality_minifying_blit
Number of changes in this file look scary. But most of them are caused
by introducing a big for loop to support rendering to multiple color
draw buffers.
V2: Fixed a case when number of draw buffer attachments are zero.
V3: Put a for loop in blit_nearest() and blit_linear() functions in to
support blitting to multiple color draw buffers.
V4: Remove variable declaration in for loop to avoid MSVC compilation
issues.
Signed-off-by: Anuj Phogat <anuj.phogat@gmail.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
This commit is contained in:
committed by
Ian Romanick
parent
ab36ca0614
commit
bed997daba
+316
-277
@@ -111,6 +111,11 @@ blit_nearest(struct gl_context *ctx,
|
||||
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;
|
||||
GLint NumDrawBuffers = 0;
|
||||
GLuint i;
|
||||
|
||||
const GLint srcWidth = ABS(srcX1 - srcX0);
|
||||
const GLint dstWidth = ABS(dstX1 - dstX0);
|
||||
@@ -146,21 +151,16 @@ blit_nearest(struct gl_context *ctx,
|
||||
|
||||
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
|
||||
@@ -175,8 +175,11 @@ blit_nearest(struct gl_context *ctx,
|
||||
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;
|
||||
@@ -208,146 +211,167 @@ blit_nearest(struct gl_context *ctx,
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
/* 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;
|
||||
|
||||
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;
|
||||
if (readRb->Format == drawRb->Format) {
|
||||
mode = DIRECT;
|
||||
pixelSize = _mesa_get_format_bytes(readRb->Format);
|
||||
} else {
|
||||
mode = UNPACK_RGBA_FLOAT;
|
||||
pixelSize = 16;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
/* 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;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
else {
|
||||
/* copy in normal (bottom->up) order */
|
||||
srcRowStride = rowStride;
|
||||
dstRowStride = rowStride;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* copy in normal (bottom->up) order */
|
||||
srcRowStride = rowStride;
|
||||
dstRowStride = rowStride;
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
|
||||
|
||||
ASSERT(srcRow >= 0);
|
||||
ASSERT(srcRow < srcHeight);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
(*resampleRow)(srcWidth, dstWidth, srcBuffer, dstBuffer, invertX);
|
||||
prevY = srcRow;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
free(dstBuffer);
|
||||
|
||||
for (dstRow = 0; dstRow < dstHeight; dstRow++) {
|
||||
GLint srcRow = (dstRow * srcHeight) / dstHeight;
|
||||
GLubyte *dstRowStart = dstMap + dstRowStride * dstRow;
|
||||
|
||||
ASSERT(srcRow >= 0);
|
||||
ASSERT(srcRow < srcHeight);
|
||||
|
||||
if (invertY) {
|
||||
srcRow = srcHeight - 1 - srcRow;
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, readRb);
|
||||
if (drawRb != readRb) {
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
free(srcBuffer);
|
||||
free(dstBuffer);
|
||||
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, readRb);
|
||||
if (drawRb != readRb) {
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -489,8 +513,13 @@ blit_linear(struct gl_context *ctx,
|
||||
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_framebuffer *drawFb = ctx->DrawBuffer;
|
||||
struct gl_renderbuffer *drawRb = NULL;
|
||||
struct gl_renderbuffer_attachment *drawAtt = NULL;
|
||||
struct gl_framebuffer *readFb = ctx->ReadBuffer;
|
||||
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);
|
||||
@@ -521,6 +550,7 @@ blit_linear(struct gl_context *ctx,
|
||||
|
||||
GLubyte *srcMap, *dstMap;
|
||||
GLint srcRowStride, dstRowStride;
|
||||
GLuint i;
|
||||
|
||||
|
||||
/* Determine datatype for resampling */
|
||||
@@ -556,150 +586,159 @@ blit_linear(struct gl_context *ctx,
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
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.
|
||||
for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) {
|
||||
int idx = drawFb->_ColorDrawBufferIndexes[i];
|
||||
if (idx == -1)
|
||||
continue;
|
||||
drawAtt = &drawFb->Attachment[idx];
|
||||
drawRb = drawAtt->Renderbuffer;
|
||||
/*
|
||||
* Map src / dst renderbuffers
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
ASSERT(srcRow >= 0);
|
||||
ASSERT(srcRow < srcHeight);
|
||||
|
||||
if (srcRow1 == srcHeight) {
|
||||
/* last row fudge */
|
||||
srcRow1 = srcRow0;
|
||||
rowWeight = 0.0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
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) {
|
||||
free(srcBuffer0);
|
||||
free(srcBuffer1);
|
||||
free(dstBuffer);
|
||||
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glBlitFramebuffer");
|
||||
return;
|
||||
}
|
||||
srcBufferY0 = srcY0;
|
||||
srcBufferY1 = srcY1;
|
||||
}
|
||||
|
||||
if (pixelType == GL_UNSIGNED_BYTE) {
|
||||
resample_linear_row_ub(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
|
||||
dstBuffer, invertX, rowWeight);
|
||||
dstMap = srcMap;
|
||||
dstRowStride = srcRowStride;
|
||||
}
|
||||
else {
|
||||
resample_linear_row_float(srcWidth, dstWidth, srcBuffer0, srcBuffer1,
|
||||
dstBuffer, invertX, rowWeight);
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* 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);
|
||||
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 */
|
||||
|
||||
ASSERT(srcRow >= 0);
|
||||
ASSERT(srcRow < srcHeight);
|
||||
|
||||
if (srcRow1 == srcHeight) {
|
||||
/* last row fudge */
|
||||
srcRow1 = srcRow0;
|
||||
rowWeight = 0.0;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
srcBufferY0 = srcY0;
|
||||
srcBufferY1 = srcY1;
|
||||
}
|
||||
else {
|
||||
_mesa_pack_float_rgba_row(drawFormat, dstWidth, dstBuffer, dst);
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(srcBuffer0);
|
||||
free(srcBuffer1);
|
||||
free(dstBuffer);
|
||||
free(srcBuffer0);
|
||||
free(srcBuffer1);
|
||||
free(dstBuffer);
|
||||
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, readRb);
|
||||
if (drawRb != readRb) {
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, readRb);
|
||||
if (drawRb != readRb) {
|
||||
ctx->Driver.UnmapRenderbuffer(ctx, drawRb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user