Fix masked ClearBuffer.
We were not properly setting the masked channels for these APIs.
Since we use a std::vector for tracking the render targets for
a particular ClearBuffer call, we lose the indexing into the
clear parameters. Fix this by storing the information in the
std::vector along with the Render Target.
BUG=angle:702
Change-Id: Ie3b1e870aa04054411c4f155682b86a340ec00cf
Reviewed-on: https://chromium-review.googlesource.com/209103
Tested-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
index 1100656..656cd94 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
+++ b/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
@@ -200,7 +200,7 @@
clearParams.scissor.x + clearParams.scissor.width < framebufferSize.width ||
clearParams.scissor.y + clearParams.scissor.height < framebufferSize.height);
- std::vector<RenderTarget11*> maskedClearRenderTargets;
+ std::vector<MaskedRenderTarget> maskedClearRenderTargets;
RenderTarget11* maskedClearDepthStencil = NULL;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
@@ -249,7 +249,14 @@
(internalAlphaBits > 0 && !clearParams.colorMaskAlpha))
{
// A scissored or masked clear is required
- maskedClearRenderTargets.push_back(renderTarget);
+ MaskedRenderTarget maskAndRt;
+ bool clearColor = clearParams.clearColor[colorAttachment];
+ maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed);
+ maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen);
+ maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue);
+ maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha);
+ maskAndRt.renderTarget = renderTarget;
+ maskedClearRenderTargets.push_back(maskAndRt);
}
else
{
@@ -353,18 +360,19 @@
std::vector<ID3D11RenderTargetView*> rtvs(maskedClearRenderTargets.size());
for (unsigned int i = 0; i < maskedClearRenderTargets.size(); i++)
{
- ID3D11RenderTargetView *renderTarget = maskedClearRenderTargets[i]->getRenderTargetView();
- if (!renderTarget)
+ RenderTarget11 *renderTarget = maskedClearRenderTargets[i].renderTarget;
+ ID3D11RenderTargetView *rtv = renderTarget->getRenderTargetView();
+ if (!rtv)
{
- ERR("Render target pointer unexpectedly null.");
+ ERR("Render target view unexpectedly null.");
return;
}
- rtvs[i] = renderTarget;
+ rtvs[i] = rtv;
}
ID3D11DepthStencilView *dsv = maskedClearDepthStencil ? maskedClearDepthStencil->getDepthStencilView() : NULL;
- ID3D11BlendState *blendState = getBlendState(clearParams, maskedClearRenderTargets);
+ ID3D11BlendState *blendState = getBlendState(maskedClearRenderTargets);
const FLOAT blendFactors[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
const UINT sampleMask = 0xFFFFFFFF;
@@ -447,19 +455,20 @@
}
}
-ID3D11BlendState *Clear11::getBlendState(const gl::ClearParameters &clearParams, const std::vector<RenderTarget11*>& rts)
+ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>& rts)
{
ClearBlendInfo blendKey = { 0 };
for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
{
if (i < rts.size())
{
- GLint internalFormat = rts[i]->getInternalFormat();
+ RenderTarget11 *rt = rts[i].renderTarget;
+ GLint internalFormat = rt->getInternalFormat();
- blendKey.maskChannels[i][0] = clearParams.clearColor ? (clearParams.colorMaskRed && gl::GetRedBits(internalFormat) > 0) : false;
- blendKey.maskChannels[i][1] = clearParams.clearColor ? (clearParams.colorMaskGreen && gl::GetGreenBits(internalFormat) > 0) : false;
- blendKey.maskChannels[i][2] = clearParams.clearColor ? (clearParams.colorMaskBlue && gl::GetBlueBits(internalFormat) > 0) : false;
- blendKey.maskChannels[i][3] = clearParams.clearColor ? (clearParams.colorMaskAlpha && gl::GetAlphaBits(internalFormat) > 0) : false;
+ blendKey.maskChannels[i][0] = (rts[i].colorMask[0] && gl::GetRedBits(internalFormat) > 0);
+ blendKey.maskChannels[i][1] = (rts[i].colorMask[1] && gl::GetGreenBits(internalFormat) > 0);
+ blendKey.maskChannels[i][2] = (rts[i].colorMask[2] && gl::GetBlueBits(internalFormat) > 0);
+ blendKey.maskChannels[i][3] = (rts[i].colorMask[3] && gl::GetAlphaBits(internalFormat) > 0);
}
else
{
diff --git a/src/libGLESv2/renderer/d3d/d3d11/Clear11.h b/src/libGLESv2/renderer/d3d/d3d11/Clear11.h
index e8e4c9e..0cb9a85 100644
--- a/src/libGLESv2/renderer/d3d/d3d11/Clear11.h
+++ b/src/libGLESv2/renderer/d3d/d3d11/Clear11.h
@@ -41,7 +41,13 @@
typedef std::map<ClearBlendInfo, ID3D11BlendState*, ClearBlendInfoComparisonFunction> ClearBlendStateMap;
ClearBlendStateMap mClearBlendStates;
- ID3D11BlendState *getBlendState(const gl::ClearParameters &clearParams, const std::vector<RenderTarget11*>& rts);
+ struct MaskedRenderTarget
+ {
+ bool colorMask[4];
+ RenderTarget11 *renderTarget;
+ };
+
+ ID3D11BlendState *getBlendState(const std::vector<MaskedRenderTarget> &rts);
struct ClearShader
{
diff --git a/tests/angle_tests/ClearTest.cpp b/tests/angle_tests/ClearTest.cpp
index 7da3337..50af0bf 100644
--- a/tests/angle_tests/ClearTest.cpp
+++ b/tests/angle_tests/ClearTest.cpp
@@ -12,6 +12,7 @@
setConfigBlueBits(8);
setConfigAlphaBits(8);
setConfigDepthBits(24);
+ setClientVersion(3);
}
virtual void SetUp()
@@ -44,22 +45,26 @@
{
FAIL() << "shader compilation failed.";
}
+
+ glGenFramebuffers(1, &mFBO);
+
+ ASSERT_GL_NO_ERROR();
}
virtual void TearDown()
{
glDeleteProgram(mProgram);
+ glDeleteFramebuffers(1, &mFBO);
ANGLETest::TearDown();
}
GLuint mProgram;
+ GLuint mFBO;
};
TEST_F(ClearTest, ClearIssue)
{
- EXPECT_GL_NO_ERROR();
-
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
@@ -69,9 +74,7 @@
EXPECT_GL_NO_ERROR();
- GLuint fbo;
- glGenFramebuffers(1, &fbo);
- glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
GLuint rbo;
glGenRenderbuffers(1, &rbo);
@@ -97,3 +100,41 @@
EXPECT_PIXEL_EQ(0, 0, 0, 255, 0, 255);
}
+
+// Requires ES3
+// This tests a bug where in a masked clear when calling "ClearBuffer", we would
+// mistakenly clear every channel (including the masked-out ones)
+TEST_F(ClearTest, MaskedClearBufferBug)
+{
+ unsigned char pixelData[] = { 255, 255, 255, 255 };
+
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
+
+ GLuint textures[2];
+ glGenTextures(2, &textures[0]);
+
+ glBindTexture(GL_TEXTURE_2D, textures[0]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelData);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[0], 0);
+
+ glBindTexture(GL_TEXTURE_2D, textures[1]);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixelData);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, textures[1], 0);
+
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_EQ(0, 0, 255, 255, 255, 255);
+
+ float clearValue[] = { 0, 0.5f, 0.5f, 1.0f };
+ GLenum drawBuffers[] = { GL_NONE, GL_COLOR_ATTACHMENT1 };
+ glDrawBuffers(2, drawBuffers);
+ glColorMask(GL_TRUE, GL_TRUE, GL_FALSE, GL_TRUE);
+ glClearBufferfv(GL_COLOR, 1, clearValue);
+
+ ASSERT_GL_NO_ERROR();
+ EXPECT_PIXEL_EQ(0, 0, 255, 255, 255, 255);
+
+ // TODO: glReadBuffer support
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, 0, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[1], 0);
+ EXPECT_PIXEL_EQ(0, 0, 0, 127, 255, 255);
+}