Refactored validation to glBlitFramebufferANGLE and implemented glBlitFramebuffer.
TRAC #23211
Signed-off-by: Jamie Madill
Signed-off-by: Shannon Woods
Author: Geoff Lang
diff --git a/src/libGLESv2/Context.cpp b/src/libGLESv2/Context.cpp
index 007e9f3..fae6008 100644
--- a/src/libGLESv2/Context.cpp
+++ b/src/libGLESv2/Context.cpp
@@ -3041,31 +3041,24 @@
return mRendererString;
}
-void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask)
+bool Context::clipBlitFramebufferCoordinates(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ gl::Rectangle *outSourceRect, gl::Rectangle *outDestRect,
+ bool *outPartialCopy)
{
Framebuffer *readFramebuffer = getReadFramebuffer();
Framebuffer *drawFramebuffer = getDrawFramebuffer();
-
if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
!drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
{
- return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION);
- }
-
- if (drawFramebuffer->getSamples() != 0)
- {
- return gl::error(GL_INVALID_OPERATION);
+ return false;
}
Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
-
- if (drawColorBuffer == NULL)
+ if (!readColorBuffer || !drawColorBuffer)
{
- ERR("Draw buffers formats don't match, which is not supported in this implementation of BlitFramebufferANGLE");
- return gl::error(GL_INVALID_OPERATION);
+ return false;
}
int readBufferWidth = readColorBuffer->getWidth();
@@ -3073,8 +3066,8 @@
int drawBufferWidth = drawColorBuffer->getWidth();
int drawBufferHeight = drawColorBuffer->getHeight();
- Rectangle sourceRect;
- Rectangle destRect;
+ gl::Rectangle sourceRect;
+ gl::Rectangle destRect;
if (srcX0 < srcX1)
{
@@ -3101,7 +3094,7 @@
else
{
sourceRect.height = srcY0 - srcY1;
- destRect.height = dstY0 - srcY1;
+ destRect.height = dstY0 - dstY1;
sourceRect.y = srcY1;
destRect.y = dstY1;
}
@@ -3119,7 +3112,6 @@
destScissoredRect.width -= xDiff;
sourceScissoredRect.x += xDiff;
sourceScissoredRect.width -= xDiff;
-
}
if (destRect.x + destRect.width > mState.scissor.x + mState.scissor.width)
@@ -3146,9 +3138,6 @@
}
}
- bool blitRenderTarget = false;
- bool blitDepthStencil = false;
-
Rectangle sourceTrimmedRect = sourceScissoredRect;
Rectangle destTrimmedRect = destScissoredRect;
@@ -3218,111 +3207,52 @@
sourceTrimmedRect.height -= yDiff;
}
- bool partialBufferCopy = false;
- if (sourceTrimmedRect.height < readBufferHeight ||
- sourceTrimmedRect.width < readBufferWidth ||
- destTrimmedRect.height < drawBufferHeight ||
- destTrimmedRect.width < drawBufferWidth ||
- sourceTrimmedRect.y != 0 || destTrimmedRect.y != 0 || sourceTrimmedRect.x != 0 || destTrimmedRect.x != 0)
+ *outSourceRect = sourceTrimmedRect;
+ *outDestRect = destTrimmedRect;
+
+ *outPartialCopy = sourceTrimmedRect.height < readBufferHeight ||
+ sourceTrimmedRect.width < readBufferWidth ||
+ destTrimmedRect.height < drawBufferHeight ||
+ destTrimmedRect.width < drawBufferWidth ||
+ sourceTrimmedRect.x != 0 || destTrimmedRect.x != 0 ||
+ sourceTrimmedRect.y != 0 || destTrimmedRect.y != 0;
+
+ return true;
+}
+
+void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ Framebuffer *readFramebuffer = getReadFramebuffer();
+ Framebuffer *drawFramebuffer = getDrawFramebuffer();
+
+ bool blitRenderTarget = false;
+ bool blitDepthStencil = false;
+ if ((mask & GL_COLOR_BUFFER_BIT) && readFramebuffer->getReadColorbuffer() && drawFramebuffer->getFirstColorbuffer())
{
- partialBufferCopy = true;
- }
-
- if (mask & GL_COLOR_BUFFER_BIT)
- {
- const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
- const bool validReadType = (readColorbufferType == GL_TEXTURE_2D) || (readColorbufferType == GL_RENDERBUFFER);
- bool validDrawType = true;
- bool validDrawFormat = true;
-
- for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
- {
- if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
- drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
- {
- validDrawType = false;
- }
-
- if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
- {
- validDrawFormat = false;
- }
- }
- }
-
- if (!validReadType || !validDrawType || !validDrawFormat)
- {
- ERR("Color buffer format conversion in BlitFramebufferANGLE not supported by this implementation");
- return gl::error(GL_INVALID_OPERATION);
- }
-
- if (partialBufferCopy && readFramebuffer->getSamples() != 0)
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
blitRenderTarget = true;
-
+ }
+ if ((mask & GL_STENCIL_BUFFER_BIT) && readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
+ {
+ blitDepthStencil = true;
+ }
+ if ((mask & GL_DEPTH_BUFFER_BIT) && readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
+ {
+ blitDepthStencil = true;
}
- if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
+ gl::Rectangle sourceClippedRect, destClippedRect;
+ bool partialCopy;
+ if (!clipBlitFramebufferCoordinates(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
+ &sourceClippedRect, &destClippedRect, &partialCopy))
{
- Renderbuffer *readDSBuffer = NULL;
- Renderbuffer *drawDSBuffer = NULL;
-
- // We support OES_packed_depth_stencil, and do not support a separately attached depth and stencil buffer, so if we have
- // both a depth and stencil buffer, it will be the same buffer.
-
- if (mask & GL_DEPTH_BUFFER_BIT)
- {
- if (readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
- {
- if (readFramebuffer->getDepthbufferType() != drawFramebuffer->getDepthbufferType() ||
- readFramebuffer->getDepthbuffer()->getActualFormat() != drawFramebuffer->getDepthbuffer()->getActualFormat())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- blitDepthStencil = true;
- readDSBuffer = readFramebuffer->getDepthbuffer();
- drawDSBuffer = drawFramebuffer->getDepthbuffer();
- }
- }
-
- if (mask & GL_STENCIL_BUFFER_BIT)
- {
- if (readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
- {
- if (readFramebuffer->getStencilbufferType() != drawFramebuffer->getStencilbufferType() ||
- readFramebuffer->getStencilbuffer()->getActualFormat() != drawFramebuffer->getStencilbuffer()->getActualFormat())
- {
- return gl::error(GL_INVALID_OPERATION);
- }
-
- blitDepthStencil = true;
- readDSBuffer = readFramebuffer->getStencilbuffer();
- drawDSBuffer = drawFramebuffer->getStencilbuffer();
- }
- }
-
- if (partialBufferCopy)
- {
- ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
- return gl::error(GL_INVALID_OPERATION); // only whole-buffer copies are permitted
- }
-
- if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) ||
- (readDSBuffer && readDSBuffer->getSamples() != 0))
- {
- return gl::error(GL_INVALID_OPERATION);
- }
+ return;
}
if (blitRenderTarget || blitDepthStencil)
{
- mRenderer->blitRect(readFramebuffer, sourceTrimmedRect, drawFramebuffer, destTrimmedRect, blitRenderTarget, blitDepthStencil);
+ mRenderer->blitRect(readFramebuffer, sourceClippedRect, drawFramebuffer, destClippedRect,
+ blitRenderTarget, blitDepthStencil, filter);
}
}
diff --git a/src/libGLESv2/Context.h b/src/libGLESv2/Context.h
index fbacb8f..f001905 100644
--- a/src/libGLESv2/Context.h
+++ b/src/libGLESv2/Context.h
@@ -462,9 +462,13 @@
float getTextureMaxAnisotropy() const;
- void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask);
+ bool clipBlitFramebufferCoordinates(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ gl::Rectangle *outSourceRect, gl::Rectangle *outDestRect,
+ bool *outPartialCopy);
+
+ void blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter);
void invalidateFrameBuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments,
GLint x, GLint y, GLsizei width, GLsizei height);
diff --git a/src/libGLESv2/libGLESv2.cpp b/src/libGLESv2/libGLESv2.cpp
index d5b5e5b..740c9b0 100644
--- a/src/libGLESv2/libGLESv2.cpp
+++ b/src/libGLESv2/libGLESv2.cpp
@@ -1680,6 +1680,238 @@
return true;
}
+bool validateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask,
+ GLenum filter, bool fromAngleExtension)
+{
+ switch (filter)
+ {
+ case GL_NEAREST:
+ break;
+ case GL_LINEAR:
+ if (fromAngleExtension)
+ {
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+ break;
+ default:
+ return gl::error(GL_INVALID_ENUM, false);
+ }
+
+ if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
+ {
+ return gl::error(GL_INVALID_VALUE, false);
+ }
+
+ if (mask == 0)
+ {
+ // ES3.0 spec, section 4.3.2 specifies that a mask of zero is valid and no
+ // buffers are copied.
+ return false;
+ }
+
+ if (fromAngleExtension && (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0))
+ {
+ ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation.");
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ // ES3.0 spec, section 4.3.2 states that linear filtering is only available for the
+ // color buffer, leaving only nearest being unfiltered from above
+ if ((mask & ~GL_COLOR_BUFFER_BIT) != 0 && filter != GL_NEAREST)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
+ {
+ if (fromAngleExtension)
+ {
+ ERR("Blits with the same source and destination framebuffer are not supported by this "
+ "implementation.");
+ }
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ gl::Framebuffer *readFramebuffer = context->getReadFramebuffer();
+ gl::Framebuffer *drawFramebuffer = context->getDrawFramebuffer();
+ if (!readFramebuffer || readFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE ||
+ !drawFramebuffer || drawFramebuffer->completeness() != GL_FRAMEBUFFER_COMPLETE)
+ {
+ return gl::error(GL_INVALID_FRAMEBUFFER_OPERATION, false);
+ }
+
+ if (drawFramebuffer->getSamples() != 0)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ gl::Rectangle sourceClippedRect, destClippedRect;
+ bool partialCopy;
+ if (!context->clipBlitFramebufferCoordinates(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
+ &sourceClippedRect, &destClippedRect, &partialCopy))
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ bool sameBounds = srcX0 == dstX0 && srcY0 == dstY0 && srcX1 == dstX1 && srcY1 == dstY1;
+
+ GLuint clientVersion = context->getClientVersion();
+
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ gl::Renderbuffer *readColorBuffer = readFramebuffer->getReadColorbuffer();
+ gl::Renderbuffer *drawColorBuffer = drawFramebuffer->getFirstColorbuffer();
+
+ if (readColorBuffer && drawColorBuffer)
+ {
+ GLint readInternalFormat = readColorBuffer->getActualFormat();
+ GLint drawInternalFormat = drawColorBuffer->getActualFormat();
+
+ for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
+ {
+ if (drawFramebuffer->isEnabledColorAttachment(i))
+ {
+ GLint drawbufferAttachmentFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat();
+
+ if (gl::IsNormalizedFixedPointFormat(readInternalFormat, clientVersion) &&
+ !gl::IsNormalizedFixedPointFormat(drawbufferAttachmentFormat, clientVersion))
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (gl::IsUnsignedIntegerFormat(readInternalFormat, clientVersion) &&
+ !gl::IsUnsignedIntegerFormat(drawbufferAttachmentFormat, clientVersion))
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (gl::IsSignedIntegerFormat(readInternalFormat, clientVersion) &&
+ !gl::IsSignedIntegerFormat(drawbufferAttachmentFormat, clientVersion))
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (readColorBuffer->getSamples() > 0 && (readInternalFormat != drawbufferAttachmentFormat || !sameBounds))
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+ }
+ }
+
+ if (gl::IsIntegerFormat(readInternalFormat, clientVersion) && filter == GL_LINEAR)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (fromAngleExtension)
+ {
+ const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
+ if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ {
+ if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
+ {
+ if (drawFramebuffer->getColorbufferType(colorAttachment) != GL_TEXTURE_2D &&
+ drawFramebuffer->getColorbufferType(colorAttachment) != GL_RENDERBUFFER)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+ }
+ }
+
+ if (partialCopy && readFramebuffer->getSamples() != 0)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+ }
+ }
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT)
+ {
+ gl::Renderbuffer *readDepthBuffer = readFramebuffer->getDepthbuffer();
+ gl::Renderbuffer *drawDepthBuffer = drawFramebuffer->getDepthbuffer();
+
+ if (readDepthBuffer && drawDepthBuffer)
+ {
+ if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat())
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (readDepthBuffer->getSamples() > 0 && !sameBounds)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (fromAngleExtension)
+ {
+ if (partialCopy)
+ {
+ ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
+ return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
+ }
+
+ if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+ }
+ }
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT)
+ {
+ gl::Renderbuffer *readStencilBuffer = readFramebuffer->getStencilbuffer();
+ gl::Renderbuffer *drawStencilBuffer = drawFramebuffer->getStencilbuffer();
+
+ if (fromAngleExtension && partialCopy)
+ {
+ ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
+ return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
+ }
+
+ if (readStencilBuffer && drawStencilBuffer)
+ {
+ if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat())
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (readStencilBuffer->getSamples() > 0 && !sameBounds)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+
+ if (fromAngleExtension)
+ {
+ if (partialCopy)
+ {
+ ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
+ return gl::error(GL_INVALID_OPERATION, false); // only whole-buffer copies are permitted
+ }
+
+ if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0)
+ {
+ return gl::error(GL_INVALID_OPERATION, false);
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
extern "C"
{
@@ -8796,7 +9028,15 @@
return gl::error(GL_INVALID_OPERATION);
}
- glBlitFramebufferANGLE(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+ if (!validateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter,
+ false))
+ {
+ return;
+ }
+
+ context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
}
}
catch(std::bad_alloc&)
@@ -11300,36 +11540,19 @@
try
{
- switch (filter)
- {
- case GL_NEAREST:
- break;
- default:
- return gl::error(GL_INVALID_ENUM);
- }
-
- if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)) != 0)
- {
- return gl::error(GL_INVALID_VALUE);
- }
-
- if (srcX1 - srcX0 != dstX1 - dstX0 || srcY1 - srcY0 != dstY1 - dstY0)
- {
- ERR("Scaling and flipping in BlitFramebufferANGLE not supported by this implementation");
- return gl::error(GL_INVALID_OPERATION);
- }
-
gl::Context *context = gl::getNonLostContext();
if (context)
{
- if (context->getReadFramebufferHandle() == context->getDrawFramebufferHandle())
+ if (!validateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter,
+ true))
{
- ERR("Blits with the same source and destination framebuffer are not supported by this implementation.");
- return gl::error(GL_INVALID_OPERATION);
+ return;
}
- context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask);
+ context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
}
}
catch(std::bad_alloc&)
diff --git a/src/libGLESv2/renderer/Renderer.h b/src/libGLESv2/renderer/Renderer.h
index eef8453..dadac4a 100644
--- a/src/libGLESv2/renderer/Renderer.h
+++ b/src/libGLESv2/renderer/Renderer.h
@@ -221,7 +221,7 @@
GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level) = 0;
virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
- bool blitRenderTarget, bool blitDepthStencil) = 0;
+ bool blitRenderTarget, bool blitDepthStencil, GLenum filter) = 0;
virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels) = 0;
diff --git a/src/libGLESv2/renderer/Renderer11.cpp b/src/libGLESv2/renderer/Renderer11.cpp
index 3f53111..05778f0 100644
--- a/src/libGLESv2/renderer/Renderer11.cpp
+++ b/src/libGLESv2/renderer/Renderer11.cpp
@@ -3004,7 +3004,7 @@
}
bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
- bool blitRenderTarget, bool blitDepthStencil)
+ bool blitRenderTarget, bool blitDepthStencil, GLenum filter)
{
if (blitRenderTarget)
{
@@ -3032,7 +3032,7 @@
RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget();
- if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false))
+ if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter))
{
return false;
}
@@ -3060,7 +3060,7 @@
RenderTarget *readRenderTarget = readBuffer->getDepthStencil();
RenderTarget *drawRenderTarget = drawBuffer->getDepthStencil();
- if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, true))
+ if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter))
{
return false;
}
@@ -3290,8 +3290,8 @@
stagingTex = NULL;
}
-bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
- RenderTarget *drawRenderTarget, bool wholeBufferCopy)
+bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
+ RenderTarget *drawRenderTarget, GLenum filter)
{
ASSERT(readRect.width == drawRect.width && readRect.height == drawRect.height);
@@ -3349,6 +3349,10 @@
readBox.front = 0;
readBox.back = 1;
+ bool wholeBufferCopy = readRect.x == 0 && readRect.y == 0 &&
+ readRect.width == readRenderTarget->getWidth() &&
+ readRect.height == readRenderTarget->getHeight();
+
// D3D11 needs depth-stencil CopySubresourceRegions to have a NULL pSrcBox
// We also require complete framebuffer copies for depth-stencil blit.
D3D11_BOX *pSrcBox = wholeBufferCopy ? NULL : &readBox;
diff --git a/src/libGLESv2/renderer/Renderer11.h b/src/libGLESv2/renderer/Renderer11.h
index 756324d..ab1afce 100644
--- a/src/libGLESv2/renderer/Renderer11.h
+++ b/src/libGLESv2/renderer/Renderer11.h
@@ -165,7 +165,7 @@
GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level);
virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
- bool blitRenderTarget, bool blitDepthStencil);
+ bool blitRenderTarget, bool blitDepthStencil, GLenum filter);
virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels);
@@ -222,7 +222,7 @@
rx::Range getViewportBounds() const;
bool blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
- RenderTarget *drawRenderTarget, bool wholeBufferCopy);
+ RenderTarget *drawRenderTarget, GLenum filter);
ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
HMODULE mD3d11Module;
diff --git a/src/libGLESv2/renderer/Renderer9.cpp b/src/libGLESv2/renderer/Renderer9.cpp
index 7b6d97f..ac8a10f 100644
--- a/src/libGLESv2/renderer/Renderer9.cpp
+++ b/src/libGLESv2/renderer/Renderer9.cpp
@@ -2663,8 +2663,10 @@
}
bool Renderer9::blitRect(gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect, gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect,
- bool blitRenderTarget, bool blitDepthStencil)
+ bool blitRenderTarget, bool blitDepthStencil, GLenum filter)
{
+ ASSERT(filter == GL_NEAREST);
+
endScene();
if (blitRenderTarget)
diff --git a/src/libGLESv2/renderer/Renderer9.h b/src/libGLESv2/renderer/Renderer9.h
index 77ea29c..f26d229 100644
--- a/src/libGLESv2/renderer/Renderer9.h
+++ b/src/libGLESv2/renderer/Renderer9.h
@@ -183,7 +183,7 @@
GLint xoffset, GLint yoffset, GLint zOffset, TextureStorageInterface2DArray *storage, GLint level);
virtual bool blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &readRect, gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
- bool blitRenderTarget, bool blitDepthStencil);
+ bool blitRenderTarget, bool blitDepthStencil, GLenum filter);
virtual void readPixels(gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type,
GLsizei outputPitch, bool packReverseRowOrder, GLint packAlignment, void* pixels);