| // |
| // Copyright 2015 The ANGLE Project Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| // |
| // Framebuffer tests: |
| // Various tests related for Frambuffers. |
| // |
| |
| #include "test_utils/ANGLETest.h" |
| #include "test_utils/gl_raii.h" |
| |
| using namespace angle; |
| |
| class FramebufferFormatsTest : public ANGLETest |
| { |
| protected: |
| FramebufferFormatsTest() : mFramebuffer(0), mTexture(0), mRenderbuffer(0), mProgram(0) |
| { |
| setWindowWidth(128); |
| setWindowHeight(128); |
| setConfigRedBits(8); |
| setConfigGreenBits(8); |
| setConfigBlueBits(8); |
| setConfigAlphaBits(8); |
| } |
| |
| void checkBitCount(GLuint fbo, GLenum channel, GLint minBits) |
| { |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| |
| GLint bits = 0; |
| glGetIntegerv(channel, &bits); |
| |
| if (minBits == 0) |
| { |
| EXPECT_EQ(minBits, bits); |
| } |
| else |
| { |
| EXPECT_GE(bits, minBits); |
| } |
| } |
| |
| void testBitCounts(GLuint fbo, |
| GLint minRedBits, |
| GLint minGreenBits, |
| GLint minBlueBits, |
| GLint minAlphaBits, |
| GLint minDepthBits, |
| GLint minStencilBits) |
| { |
| checkBitCount(fbo, GL_RED_BITS, minRedBits); |
| checkBitCount(fbo, GL_GREEN_BITS, minGreenBits); |
| checkBitCount(fbo, GL_BLUE_BITS, minBlueBits); |
| checkBitCount(fbo, GL_ALPHA_BITS, minAlphaBits); |
| checkBitCount(fbo, GL_DEPTH_BITS, minDepthBits); |
| checkBitCount(fbo, GL_STENCIL_BITS, minStencilBits); |
| } |
| |
| void testTextureFormat(GLenum internalFormat, |
| GLint minRedBits, |
| GLint minGreenBits, |
| GLint minBlueBits, |
| GLint minAlphaBits) |
| { |
| glGenTextures(1, &mTexture); |
| glBindTexture(GL_TEXTURE_2D, mTexture); |
| |
| if (getClientMajorVersion() >= 3) |
| { |
| glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 1, 1); |
| } |
| else |
| { |
| glTexStorage2DEXT(GL_TEXTURE_2D, 1, internalFormat, 1, 1); |
| } |
| |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTexture, 0); |
| |
| testBitCounts(mFramebuffer, minRedBits, minGreenBits, minBlueBits, minAlphaBits, 0, 0); |
| } |
| |
| void testRenderbufferMultisampleFormat(int minESVersion, |
| GLenum attachmentType, |
| GLenum internalFormat) |
| { |
| // TODO(geofflang): Figure out why this is broken on Intel OpenGL |
| if (IsIntel() && getPlatformRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE) |
| { |
| std::cout << "Test skipped on Intel OpenGL." << std::endl; |
| return; |
| } |
| |
| int clientVersion = getClientMajorVersion(); |
| if (clientVersion < minESVersion) |
| { |
| return; |
| } |
| |
| // Check that multisample is supported with at least two samples (minimum required is 1) |
| bool supports2Samples = false; |
| |
| if (clientVersion == 2) |
| { |
| if (extensionEnabled("ANGLE_framebuffer_multisample")) |
| { |
| int maxSamples; |
| glGetIntegerv(GL_MAX_SAMPLES_ANGLE, &maxSamples); |
| supports2Samples = maxSamples >= 2; |
| } |
| } |
| else |
| { |
| assert(clientVersion >= 3); |
| int maxSamples; |
| glGetIntegerv(GL_MAX_SAMPLES, &maxSamples); |
| supports2Samples = maxSamples >= 2; |
| } |
| |
| if (!supports2Samples) |
| { |
| return; |
| } |
| |
| glGenRenderbuffers(1, &mRenderbuffer); |
| glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer); |
| |
| EXPECT_GL_NO_ERROR(); |
| glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 2, internalFormat, 128, 128); |
| EXPECT_GL_NO_ERROR(); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachmentType, GL_RENDERBUFFER, mRenderbuffer); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void testZeroHeightRenderbuffer() |
| { |
| glGenRenderbuffers(1, &mRenderbuffer); |
| glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer); |
| glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1, 0); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, |
| mRenderbuffer); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| void SetUp() override |
| { |
| ANGLETest::SetUp(); |
| |
| glGenFramebuffers(1, &mFramebuffer); |
| glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); |
| } |
| |
| void TearDown() override |
| { |
| 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) |
| { |
| if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_texture_storage")) |
| { |
| std::cout << "Test skipped due to missing ES3 or GL_EXT_texture_storage." << std::endl; |
| return; |
| } |
| |
| testTextureFormat(GL_RGBA4, 4, 4, 4, 4); |
| } |
| |
| TEST_P(FramebufferFormatsTest, RGB565) |
| { |
| if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_texture_storage")) |
| { |
| std::cout << "Test skipped due to missing ES3 or GL_EXT_texture_storage." << std::endl; |
| return; |
| } |
| |
| testTextureFormat(GL_RGB565, 5, 6, 5, 0); |
| } |
| |
| TEST_P(FramebufferFormatsTest, RGB8) |
| { |
| if (getClientMajorVersion() < 3 && |
| (!extensionEnabled("GL_OES_rgb8_rgba8") || !extensionEnabled("GL_EXT_texture_storage"))) |
| { |
| std::cout |
| << "Test skipped due to missing ES3 or GL_OES_rgb8_rgba8 and GL_EXT_texture_storage." |
| << std::endl; |
| return; |
| } |
| |
| testTextureFormat(GL_RGB8_OES, 8, 8, 8, 0); |
| } |
| |
| TEST_P(FramebufferFormatsTest, BGRA8) |
| { |
| if (!extensionEnabled("GL_EXT_texture_format_BGRA8888") || |
| (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_texture_storage"))) |
| { |
| std::cout << "Test skipped due to missing GL_EXT_texture_format_BGRA8888 or " |
| "GL_EXT_texture_storage." |
| << std::endl; |
| return; |
| } |
| |
| testTextureFormat(GL_BGRA8_EXT, 8, 8, 8, 8); |
| } |
| |
| TEST_P(FramebufferFormatsTest, RGBA8) |
| { |
| if (getClientMajorVersion() < 3 && |
| (!extensionEnabled("GL_OES_rgb8_rgba8") || !extensionEnabled("GL_EXT_texture_storage"))) |
| { |
| std::cout |
| << "Test skipped due to missing ES3 or GL_OES_rgb8_rgba8 and GL_EXT_texture_storage." |
| << std::endl; |
| return; |
| } |
| |
| testTextureFormat(GL_RGBA8_OES, 8, 8, 8, 8); |
| } |
| |
| TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH16) |
| { |
| testRenderbufferMultisampleFormat(2, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT16); |
| } |
| |
| TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24) |
| { |
| testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT24); |
| } |
| |
| TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F) |
| { |
| if (getClientMajorVersion() < 3) |
| { |
| std::cout << "Test skipped due to missing ES3." << std::endl; |
| return; |
| } |
| |
| testRenderbufferMultisampleFormat(3, GL_DEPTH_ATTACHMENT, GL_DEPTH_COMPONENT32F); |
| } |
| |
| TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH24_STENCIL8) |
| { |
| testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH24_STENCIL8); |
| } |
| |
| TEST_P(FramebufferFormatsTest, RenderbufferMultisample_DEPTH32F_STENCIL8) |
| { |
| if (getClientMajorVersion() < 3) |
| { |
| std::cout << "Test skipped due to missing ES3." << std::endl; |
| return; |
| } |
| |
| testRenderbufferMultisampleFormat(3, GL_DEPTH_STENCIL_ATTACHMENT, GL_DEPTH32F_STENCIL8); |
| } |
| |
| TEST_P(FramebufferFormatsTest, RenderbufferMultisample_STENCIL_INDEX8) |
| { |
| // TODO(geofflang): Figure out how to support GLSTENCIL_INDEX8 on desktop GL |
| if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE) |
| { |
| std::cout << "Test skipped on Desktop OpenGL." << std::endl; |
| return; |
| } |
| |
| 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); |
| } |
| |
| // Test that a renderbuffer with zero height but nonzero width is handled without crashes/asserts. |
| TEST_P(FramebufferFormatsTest, ZeroHeightRenderbuffer) |
| { |
| if (getClientMajorVersion() < 3) |
| { |
| std::cout << "Test skipped due to missing ES3" << std::endl; |
| return; |
| } |
| |
| testZeroHeightRenderbuffer(); |
| } |
| |
| // 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(), |
| ES2_OPENGLES(), |
| ES3_OPENGLES()); |
| |
| class FramebufferTest_ES3 : public ANGLETest |
| { |
| protected: |
| FramebufferTest_ES3() : mFramebuffer(0), mRenderbuffer(0) {} |
| |
| void SetUp() override |
| { |
| ANGLETest::SetUp(); |
| |
| glGenFramebuffers(1, &mFramebuffer); |
| glGenRenderbuffers(1, &mRenderbuffer); |
| } |
| |
| void TearDown() override |
| { |
| glDeleteFramebuffers(1, &mFramebuffer); |
| glDeleteRenderbuffers(1, &mRenderbuffer); |
| ANGLETest::TearDown(); |
| } |
| |
| GLuint mFramebuffer; |
| GLuint mRenderbuffer; |
| }; |
| |
| // Covers invalidating an incomplete framebuffer. This should be a no-op, but should not error. |
| TEST_P(FramebufferTest_ES3, InvalidateIncomplete) |
| { |
| glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); |
| glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mRenderbuffer); |
| EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT, |
| glCheckFramebufferStatus(GL_FRAMEBUFFER)); |
| |
| std::vector<GLenum> attachments; |
| attachments.push_back(GL_COLOR_ATTACHMENT0); |
| |
| glInvalidateFramebuffer(GL_FRAMEBUFFER, 1, attachments.data()); |
| EXPECT_GL_NO_ERROR(); |
| } |
| |
| // Test that the framebuffer state tracking robustly handles a depth-only attachment being set |
| // as a depth-stencil attachment. It is equivalent to detaching the depth-stencil attachment. |
| TEST_P(FramebufferTest_ES3, DepthOnlyAsDepthStencil) |
| { |
| glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer); |
| glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer); |
| glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 4, 4); |
| |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, |
| mRenderbuffer); |
| EXPECT_GLENUM_NE(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); |
| } |
| |
| ANGLE_INSTANTIATE_TEST(FramebufferTest_ES3, ES3_D3D11(), ES3_OPENGL(), ES3_OPENGLES()); |
| |
| class FramebufferTest_ES31 : public ANGLETest |
| { |
| }; |
| |
| // Test that without attachment, if either the value of FRAMEBUFFER_DEFAULT_WIDTH or |
| // FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is incomplete. |
| TEST_P(FramebufferTest_ES31, IncompleteMissingAttachmentDefaultParam) |
| { |
| GLFramebuffer mFramebuffer; |
| glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get()); |
| |
| glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1); |
| glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1); |
| EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); |
| |
| glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0); |
| glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0); |
| EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT, |
| glCheckFramebufferStatus(GL_FRAMEBUFFER)); |
| |
| glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 1); |
| glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 0); |
| EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT, |
| glCheckFramebufferStatus(GL_FRAMEBUFFER)); |
| |
| glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH, 0); |
| glFramebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT, 1); |
| EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT, |
| glCheckFramebufferStatus(GL_FRAMEBUFFER)); |
| |
| ASSERT_GL_NO_ERROR(); |
| } |
| |
| // Test that the sample count of a mix of texture and renderbuffer should be same. |
| TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountMix) |
| { |
| GLFramebuffer mFramebuffer; |
| glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get()); |
| |
| GLTexture mTexture; |
| glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get()); |
| glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, true); |
| |
| GLRenderbuffer mRenderbuffer; |
| glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get()); |
| glRenderbufferStorageMultisample(GL_RENDERBUFFER, 2, GL_RGBA8, 1, 1); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, |
| mTexture.get(), 0); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, |
| mRenderbuffer.get()); |
| EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, |
| glCheckFramebufferStatus(GL_FRAMEBUFFER)); |
| |
| ASSERT_GL_NO_ERROR(); |
| } |
| |
| // Test that the sample count of texture attachments should be same. |
| TEST_P(FramebufferTest_ES31, IncompleteMultisampleSampleCountTex) |
| { |
| GLFramebuffer mFramebuffer; |
| glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get()); |
| |
| GLTexture mTextures[2]; |
| glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get()); |
| glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, true); |
| glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get()); |
| glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 2, GL_RGBA8, 1, 1, true); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, |
| mTextures[0].get(), 0); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, |
| mTextures[1].get(), 0); |
| EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, |
| glCheckFramebufferStatus(GL_FRAMEBUFFER)); |
| |
| ASSERT_GL_NO_ERROR(); |
| } |
| |
| // Test that if the attached images are a mix of renderbuffers and textures, the value of |
| // TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures. |
| TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsMix) |
| { |
| GLFramebuffer mFramebuffer; |
| glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get()); |
| |
| GLTexture mTexture; |
| glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTexture.get()); |
| glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false); |
| |
| GLRenderbuffer mRenderbuffer; |
| glBindRenderbuffer(GL_RENDERBUFFER, mRenderbuffer.get()); |
| glRenderbufferStorageMultisample(GL_RENDERBUFFER, 1, GL_RGBA8, 1, 1); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, |
| mTexture.get(), 0); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, |
| mRenderbuffer.get()); |
| EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, |
| glCheckFramebufferStatus(GL_FRAMEBUFFER)); |
| |
| ASSERT_GL_NO_ERROR(); |
| } |
| |
| // Test that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS is the same for all attached textures. |
| TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex) |
| { |
| GLFramebuffer mFramebuffer; |
| glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer.get()); |
| |
| GLTexture mTextures[2]; |
| glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[0].get()); |
| glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGBA8, 1, 1, false); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, |
| mTextures[0].get(), 0); |
| glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, mTextures[1].get()); |
| glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 1, GL_RGB8, 1, 1, true); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D_MULTISAMPLE, |
| mTextures[1].get(), 0); |
| EXPECT_GLENUM_EQ(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, |
| glCheckFramebufferStatus(GL_FRAMEBUFFER)); |
| |
| ASSERT_GL_NO_ERROR(); |
| } |
| |
| ANGLE_INSTANTIATE_TEST(FramebufferTest_ES31, ES31_OPENGL(), ES31_OPENGLES()); |