Commit 78df3362 by Olli Etuaho Committed by Commit Bot

Fix clearing out-of-range default FB drawbuffer

The default framebuffer is initialized with just one drawbuffer slot so the number of drawbuffers needs to be validated before checking if a buffer is attached. BUG=angleproject:2831 TEST=angle_end2end_tests Change-Id: I960c39357853d1cd4575b06a992cff33223ab3df Reviewed-on: https://chromium-review.googlesource.com/c/1264518 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 8efa3418
......@@ -3547,49 +3547,67 @@ void Context::clear(GLbitfield mask)
void Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values)
{
// It's not an error to try to clear a non-existent buffer, but it's a no-op. We early out so
// that the backend doesn't need to take this case into account.
if (buffer == GL_DEPTH && !getGLState().getDrawFramebuffer()->getDepthbuffer())
Framebuffer *framebufferObject = mGLState.getDrawFramebuffer();
const FramebufferAttachment *attachment = nullptr;
if (buffer == GL_DEPTH)
{
return;
attachment = framebufferObject->getDepthbuffer();
}
if (buffer == GL_COLOR &&
static_cast<size_t>(drawbuffer) < framebufferObject->getNumColorBuffers())
{
attachment = framebufferObject->getColorbuffer(drawbuffer);
}
if (buffer == GL_COLOR && !getGLState().getDrawFramebuffer()->getColorbuffer(drawbuffer))
// It's not an error to try to clear a non-existent buffer, but it's a no-op. We early out so
// that the backend doesn't need to take this case into account.
if (!attachment)
{
return;
}
ANGLE_CONTEXT_TRY(prepareForClearBuffer(buffer, drawbuffer));
ANGLE_CONTEXT_TRY(
mGLState.getDrawFramebuffer()->clearBufferfv(this, buffer, drawbuffer, values));
ANGLE_CONTEXT_TRY(framebufferObject->clearBufferfv(this, buffer, drawbuffer, values));
}
void Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values)
{
Framebuffer *framebufferObject = mGLState.getDrawFramebuffer();
const FramebufferAttachment *attachment = nullptr;
if (buffer == GL_COLOR &&
static_cast<size_t>(drawbuffer) < framebufferObject->getNumColorBuffers())
{
attachment = framebufferObject->getColorbuffer(drawbuffer);
}
// It's not an error to try to clear a non-existent buffer, but it's a no-op. We early out so
// that the backend doesn't need to take this case into account.
if (buffer == GL_COLOR && !getGLState().getDrawFramebuffer()->getColorbuffer(drawbuffer))
if (!attachment)
{
return;
}
ANGLE_CONTEXT_TRY(prepareForClearBuffer(buffer, drawbuffer));
ANGLE_CONTEXT_TRY(
mGLState.getDrawFramebuffer()->clearBufferuiv(this, buffer, drawbuffer, values));
ANGLE_CONTEXT_TRY(framebufferObject->clearBufferuiv(this, buffer, drawbuffer, values));
}
void Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values)
{
// It's not an error to try to clear a non-existent buffer, but it's a no-op. We early out so
// that the backend doesn't need to take this case into account.
if (buffer == GL_STENCIL && !getGLState().getDrawFramebuffer()->getStencilbuffer())
Framebuffer *framebufferObject = mGLState.getDrawFramebuffer();
const FramebufferAttachment *attachment = nullptr;
if (buffer == GL_STENCIL)
{
return;
attachment = framebufferObject->getStencilbuffer();
}
if (buffer == GL_COLOR && !getGLState().getDrawFramebuffer()->getColorbuffer(drawbuffer))
if (buffer == GL_COLOR &&
static_cast<size_t>(drawbuffer) < framebufferObject->getNumColorBuffers())
{
attachment = framebufferObject->getColorbuffer(drawbuffer);
}
// It's not an error to try to clear a non-existent buffer, but it's a no-op. We early out so
// that the backend doesn't need to take this case into account.
if (!attachment)
{
return;
}
ANGLE_CONTEXT_TRY(prepareForClearBuffer(buffer, drawbuffer));
ANGLE_CONTEXT_TRY(
mGLState.getDrawFramebuffer()->clearBufferiv(this, buffer, drawbuffer, values));
ANGLE_CONTEXT_TRY(framebufferObject->clearBufferiv(this, buffer, drawbuffer, values));
}
void Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
......
......@@ -629,6 +629,19 @@ TEST_P(ClearTest, MaskedColorAndDepthClear)
ASSERT_GL_NO_ERROR();
}
// Test that just clearing a nonexistent drawbuffer of the default framebuffer doesn't cause an
// assert.
TEST_P(ClearTestES3, ClearBuffer1OnDefaultFramebufferNoAssert)
{
std::vector<GLuint> testUint(4);
glClearBufferuiv(GL_COLOR, 1, testUint.data());
std::vector<GLint> testInt(4);
glClearBufferiv(GL_COLOR, 1, testInt.data());
std::vector<GLfloat> testFloat(4);
glClearBufferfv(GL_COLOR, 1, testFloat.data());
EXPECT_GL_NO_ERROR();
}
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
// tests should be run against. Vulkan support disabled because of incomplete implementation.
ANGLE_INSTANTIATE_TEST(ClearTest,
......
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