зеркало из https://github.com/AvaloniaUI/angle.git
Validation cube completeness for FBO attachments.
ES3 adds a clause that cube map FBO attachments must be cube complete to produce complete framebuffers. ES2 doesn't have this clause, but some (if not all, unverified) OpenGL back-ends don't support these incomplete cube map attachments. BUG=angleproject:1259 Change-Id: Idd4564488375b8646dde712e6ce4a158c23020ee Reviewed-on: https://chromium-review.googlesource.com/318264 Tryjob-Request: Jamie Madill <jmadill@chromium.org> Reviewed-by: Rafael Cintron <rafael.cintron@microsoft.com> Reviewed-by: Kenneth Russell <kbr@chromium.org> Tested-by: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
Родитель
4bc76d07e8
Коммит
3215b207b2
|
@ -390,6 +390,17 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
|
||||||
{
|
{
|
||||||
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ES3 specifies that cube map texture attachments must be cube complete.
|
||||||
|
// This language is missing from the ES2 spec, but we enforce it here because some
|
||||||
|
// desktop OpenGL drivers also enforce this validation.
|
||||||
|
// TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
|
||||||
|
const Texture *texture = colorAttachment.getTexture();
|
||||||
|
ASSERT(texture);
|
||||||
|
if (texture->getTarget() == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete())
|
||||||
|
{
|
||||||
|
return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (colorAttachment.type() == GL_RENDERBUFFER)
|
else if (colorAttachment.type() == GL_RENDERBUFFER)
|
||||||
{
|
{
|
||||||
|
|
|
@ -11,7 +11,7 @@ using namespace angle;
|
||||||
class FramebufferFormatsTest : public ANGLETest
|
class FramebufferFormatsTest : public ANGLETest
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
FramebufferFormatsTest()
|
FramebufferFormatsTest() : mFramebuffer(0), mTexture(0), mRenderbuffer(0), mProgram(0)
|
||||||
{
|
{
|
||||||
setWindowWidth(128);
|
setWindowWidth(128);
|
||||||
setWindowHeight(128);
|
setWindowHeight(128);
|
||||||
|
@ -52,20 +52,13 @@ class FramebufferFormatsTest : public ANGLETest
|
||||||
void testTextureFormat(GLenum internalFormat, GLint minRedBits, GLint minGreenBits, GLint minBlueBits,
|
void testTextureFormat(GLenum internalFormat, GLint minRedBits, GLint minGreenBits, GLint minBlueBits,
|
||||||
GLint minAlphaBits)
|
GLint minAlphaBits)
|
||||||
{
|
{
|
||||||
GLuint tex = 0;
|
glGenTextures(1, &mTexture);
|
||||||
glGenTextures(1, &tex);
|
glBindTexture(GL_TEXTURE_2D, mTexture);
|
||||||
glBindTexture(GL_TEXTURE_2D, tex);
|
|
||||||
glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
|
glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1);
|
||||||
|
|
||||||
GLuint fbo = 0;
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0);
|
||||||
glGenFramebuffers(1, &fbo);
|
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
|
|
||||||
|
|
||||||
testBitCounts(fbo, minRedBits, minGreenBits, minBlueBits, minAlphaBits, 0, 0);
|
testBitCounts(mFramebuffer, minRedBits, minGreenBits, minBlueBits, minAlphaBits, 0, 0);
|
||||||
|
|
||||||
glDeleteTextures(1, &tex);
|
|
||||||
glDeleteFramebuffers(1, &fbo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void testRenderbufferMultisampleFormat(int minESVersion, GLenum attachmentType, GLenum internalFormat)
|
void testRenderbufferMultisampleFormat(int minESVersion, GLenum attachmentType, GLenum internalFormat)
|
||||||
|
@ -108,33 +101,57 @@ class FramebufferFormatsTest : public ANGLETest
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint framebufferID;
|
glGenRenderbuffers(1, &mRenderbuffer);
|
||||||
glGenFramebuffers(1, &framebufferID);
|
glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer);
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
|
|
||||||
|
|
||||||
GLuint renderbufferID;
|
|
||||||
glGenRenderbuffers(1, &renderbufferID);
|
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID);
|
|
||||||
|
|
||||||
EXPECT_GL_NO_ERROR();
|
EXPECT_GL_NO_ERROR();
|
||||||
glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, internalFormat, 128, 128);
|
glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, internalFormat, 128, 128);
|
||||||
EXPECT_GL_NO_ERROR();
|
EXPECT_GL_NO_ERROR();
|
||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentType, GL_RENDERBUFFER, renderbufferID);
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentType, GL_RENDERBUFFER, mRenderbuffer);
|
||||||
EXPECT_GL_NO_ERROR();
|
EXPECT_GL_NO_ERROR();
|
||||||
|
|
||||||
glDeleteRenderbuffers(1, &renderbufferID);
|
|
||||||
glDeleteFramebuffers(1, &framebufferID);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void SetUp()
|
void SetUp() override
|
||||||
{
|
{
|
||||||
ANGLETest::SetUp();
|
ANGLETest::SetUp();
|
||||||
|
|
||||||
|
glGenFramebuffers(1, &mFramebuffer);
|
||||||
|
glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void TearDown()
|
void TearDown() override
|
||||||
{
|
{
|
||||||
ANGLETest::TearDown();
|
ANGLETest::TearDown();
|
||||||
|
|
||||||
|
if (mTexture != 0)
|
||||||
|
{
|
||||||
|
glDeleteTextures(1, &mTexture);
|
||||||
|
mTexture = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mRenderbuffer != 0)
|
||||||
|
{
|
||||||
|
glDeleteRenderbuffers(1, &mRenderbuffer);
|
||||||
|
mRenderbuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mFramebuffer != 0)
|
||||||
|
{
|
||||||
|
glDeleteFramebuffers(1, &mFramebuffer);
|
||||||
|
mFramebuffer = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mProgram != 0)
|
||||||
|
{
|
||||||
|
glDeleteProgram(mProgram);
|
||||||
|
mProgram = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GLuint mFramebuffer;
|
||||||
|
GLuint mTexture;
|
||||||
|
GLuint mRenderbuffer;
|
||||||
|
GLuint mProgram;
|
||||||
};
|
};
|
||||||
|
|
||||||
TEST_P(FramebufferFormatsTest, RGBA4)
|
TEST_P(FramebufferFormatsTest, RGBA4)
|
||||||
|
@ -229,5 +246,49 @@ TEST_P(FramebufferFormatsTest, RenderbufferMultisample_STENCIL_INDEX8)
|
||||||
testRenderbufferMultisampleFormat(2, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
|
testRenderbufferMultisampleFormat(2, GL_STENCIL_ATTACHMENT, GL_STENCIL_INDEX8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that binding an incomplete cube map is rejected by ANGLE.
|
||||||
|
TEST_P(FramebufferFormatsTest, IncompleteCubeMap)
|
||||||
|
{
|
||||||
|
// First make a complete CubeMap.
|
||||||
|
glGenTextures(1, &mTexture);
|
||||||
|
glBindTexture(GL_TEXTURE_CUBE_MAP, mTexture);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
nullptr);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
nullptr);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
nullptr);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
nullptr);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
nullptr);
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 8, 8, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
nullptr);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||||
|
|
||||||
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_CUBE_MAP_POSITIVE_X,
|
||||||
|
mTexture, 0);
|
||||||
|
|
||||||
|
// Verify the framebuffer is complete.
|
||||||
|
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
|
||||||
|
|
||||||
|
// Make the CubeMap cube-incomplete.
|
||||||
|
glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, GL_RGBA, 16, 16, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||||
|
nullptr);
|
||||||
|
|
||||||
|
// Verify the framebuffer is incomplete.
|
||||||
|
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT,
|
||||||
|
glCheckFramebufferStatus(GL_FRAMEBUFFER));
|
||||||
|
|
||||||
|
// Verify drawing with the incomplete framebuffer produces a GL error
|
||||||
|
const std::string &vs = "attribute vec4 position; void main() { gl_Position = position; }";
|
||||||
|
const std::string &ps = "void main() { gl_FragColor = vec4(1, 0, 0, 1); }";
|
||||||
|
mProgram = CompileProgram(vs, ps);
|
||||||
|
ASSERT_NE(0u, mProgram);
|
||||||
|
drawQuad(mProgram, "position", 0.5f);
|
||||||
|
ASSERT_GL_ERROR(GL_INVALID_FRAMEBUFFER_OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
|
// Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
|
||||||
ANGLE_INSTANTIATE_TEST(FramebufferFormatsTest, ES2_D3D9(), ES2_D3D11(), ES3_D3D11(), ES2_OPENGL(), ES3_OPENGL());
|
ANGLE_INSTANTIATE_TEST(FramebufferFormatsTest, ES2_D3D9(), ES2_D3D11(), ES3_D3D11(), ES2_OPENGL(), ES3_OPENGL());
|
||||||
|
|
Загрузка…
Ссылка в новой задаче