Disallow glCopyTex* with multi-view read framebuffers
According to the ANGLE_multiview spec, glCopyTex* functions must
generate an INVALID_FRAMEBUFFER_OPERATION error if the active read
framebuffer has a multi-view layout.
BUG=angleproject:2062
TEST=angle_end2end_tests
Change-Id: Icadc4ac79843986076594da25a90ba807e511d1e
Reviewed-on: https://chromium-review.googlesource.com/589447
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Commit-Queue: Martin Radev <mradev@nvidia.com>
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
index 5e7806b..206762a 100644
--- a/src/libANGLE/validationES.cpp
+++ b/src/libANGLE/validationES.cpp
@@ -2624,12 +2624,24 @@
// In OpenGL ES it is undefined what happens when an operation tries to read from a missing
// attachment and WebGL defines it to be an error. We do the check unconditionally as the
// situation is an application error that would lead to a crash in ANGLE.
- if (readFramebuffer->getReadColorbuffer() == nullptr)
+ const FramebufferAttachment *source = readFramebuffer->getReadColorbuffer();
+ if (source == nullptr)
{
ANGLE_VALIDATION_ERR(context, InvalidOperation(), MissingReadAttachment);
return false;
}
+ // ANGLE_multiview spec, Revision 1:
+ // Calling CopyTexSubImage3D, CopyTexImage2D, or CopyTexSubImage2D will result in an
+ // INVALID_FRAMEBUFFER_OPERATION error if the multi-view layout of the current read framebuffer
+ // is not NONE.
+ if (source->getMultiviewLayout() != GL_NONE)
+ {
+ context->handleError(InvalidFramebufferOperation()
+ << "The active read framebuffer object has multiview attachments.");
+ return false;
+ }
+
const gl::Caps &caps = context->getCaps();
GLuint maxDimension = 0;
diff --git a/src/tests/gl_tests/FramebufferMultiviewTest.cpp b/src/tests/gl_tests/FramebufferMultiviewTest.cpp
index 7304b05..c605099 100644
--- a/src/tests/gl_tests/FramebufferMultiviewTest.cpp
+++ b/src/tests/gl_tests/FramebufferMultiviewTest.cpp
@@ -379,4 +379,48 @@
glDeleteTextures(1, &otherTexture);
}
+// Test that the active read framebuffer cannot be read from through glCopyTex* if it has multi-view
+// attachments.
+TEST_P(FramebufferMultiviewTest, InvalidCopyTex)
+{
+ if (!requestMultiviewExtension())
+ {
+ return;
+ }
+
+ mTexture2D = CreateTexture2D(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
+ ASSERT_GL_NO_ERROR();
+
+ const GLint viewportOffsets[2] = {0};
+ glFramebufferTextureMultiviewSideBySideANGLE(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, mTexture2D,
+ 0, 1, &viewportOffsets[0]);
+ ASSERT_GL_NO_ERROR();
+
+ // Test glCopyTexImage2D and glCopyTexSubImage2D.
+ {
+ GLuint tex = CreateTexture2D(GL_RGBA8, GL_RGBA, GL_UNSIGNED_BYTE);
+
+ glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 1, 1, 0);
+ EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
+
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1);
+ EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
+
+ glDeleteTextures(1, &tex);
+ }
+
+ // Test glCopyTexSubImage3D.
+ {
+ GLuint tex = 0u;
+ glGenTextures(1, &tex);
+ glBindTexture(GL_TEXTURE_3D, tex);
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA8, 1, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
+ glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 0, 0, 0, 1, 1);
+ EXPECT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
+
+ glDeleteTextures(1, &tex);
+ }
+}
+
ANGLE_INSTANTIATE_TEST(FramebufferMultiviewTest, ES3_OPENGL());
\ No newline at end of file