Commit 758d5b21 by Geoff Lang Committed by Shannon Woods

Refactored validation to glBlitFramebufferANGLE and implemented glBlitFramebuffer.

TRAC #23211 Signed-off-by: Jamie Madill Signed-off-by: Shannon Woods Author: Geoff Lang
parent a2d97f13
......@@ -3041,31 +3041,24 @@ const char *Context::getRendererString() const
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 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
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 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
else
{
sourceRect.height = srcY0 - srcY1;
destRect.height = dstY0 - srcY1;
destRect.height = dstY0 - dstY1;
sourceRect.y = srcY1;
destRect.y = dstY1;
}
......@@ -3119,7 +3112,6 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
destScissoredRect.width -= xDiff;
sourceScissoredRect.x += xDiff;
sourceScissoredRect.width -= xDiff;
}
if (destRect.x + destRect.width > mState.scissor.x + mState.scissor.width)
......@@ -3146,9 +3138,6 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
}
}
bool blitRenderTarget = false;
bool blitDepthStencil = false;
Rectangle sourceTrimmedRect = sourceScissoredRect;
Rectangle destTrimmedRect = destScissoredRect;
......@@ -3218,111 +3207,52 @@ void Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1
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)
{
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;
*outSourceRect = sourceTrimmedRect;
*outDestRect = destTrimmedRect;
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;
}
*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;
if (drawFramebuffer->getColorbuffer(colorAttachment)->getActualFormat() != readColorBuffer->getActualFormat())
{
validDrawFormat = false;
}
}
}
return true;
}
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);
}
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())
{
blitRenderTarget = true;
}
if (mask & (GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT))
if ((mask & GL_STENCIL_BUFFER_BIT) && readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
{
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
}
blitDepthStencil = true;
}
if ((mask & GL_DEPTH_BUFFER_BIT) && readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
{
blitDepthStencil = true;
}
if ((drawDSBuffer && drawDSBuffer->getSamples() != 0) ||
(readDSBuffer && readDSBuffer->getSamples() != 0))
{
return gl::error(GL_INVALID_OPERATION);
}
gl::Rectangle sourceClippedRect, destClippedRect;
bool partialCopy;
if (!clipBlitFramebufferCoordinates(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
&sourceClippedRect, &destClippedRect, &partialCopy))
{
return;
}
if (blitRenderTarget || blitDepthStencil)
{
mRenderer->blitRect(readFramebuffer, sourceTrimmedRect, drawFramebuffer, destTrimmedRect, blitRenderTarget, blitDepthStencil);
mRenderer->blitRect(readFramebuffer, sourceClippedRect, drawFramebuffer, destClippedRect,
blitRenderTarget, blitDepthStencil, filter);
}
}
......
......@@ -462,9 +462,13 @@ class Context
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);
......
......@@ -221,7 +221,7 @@ class Renderer
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;
......
......@@ -3004,7 +3004,7 @@ bool Renderer11::getRenderTargetResource(gl::Renderbuffer *colorbuffer, unsigned
}
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 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read
RenderTarget *drawRenderTarget = drawBuffer->getRenderTarget();
if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, false))
if (!blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter))
{
return false;
}
......@@ -3060,7 +3060,7 @@ bool Renderer11::blitRect(gl::Framebuffer *readTarget, const gl::Rectangle &read
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 @@ void Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResou
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 @@ bool Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::R
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;
......
......@@ -165,7 +165,7 @@ class Renderer11 : public Renderer
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 @@ class Renderer11 : public Renderer
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;
......
......@@ -2663,8 +2663,10 @@ bool Renderer9::copyImage(gl::Framebuffer *framebuffer, const gl::Rectangle &sou
}
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)
......
......@@ -183,7 +183,7 @@ class Renderer9 : public Renderer
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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment