diff options
Diffstat (limited to 'tests/angle_tests/DrawBuffersTest.cpp')
-rw-r--r-- | tests/angle_tests/DrawBuffersTest.cpp | 329 |
1 files changed, 329 insertions, 0 deletions
diff --git a/tests/angle_tests/DrawBuffersTest.cpp b/tests/angle_tests/DrawBuffersTest.cpp new file mode 100644 index 00000000..fdf2bdbb --- /dev/null +++ b/tests/angle_tests/DrawBuffersTest.cpp @@ -0,0 +1,329 @@ +#include "ANGLETest.h" + +class DrawBuffersTest : public ANGLETest +{ + protected: + DrawBuffersTest(int clientVersion) + { + setWindowWidth(128); + setWindowHeight(128); + setConfigRedBits(8); + setConfigGreenBits(8); + setConfigBlueBits(8); + setConfigAlphaBits(8); + setConfigDepthBits(24); + setClientVersion(clientVersion); + } + + virtual void SetUp() + { + ANGLETest::SetUp(); + + glGenFramebuffers(1, &mFBO); + glBindFramebuffer(GL_FRAMEBUFFER, mFBO); + + glGenTextures(4, mTextures); + + for (size_t texIndex = 0; texIndex < ArraySize(mTextures); texIndex++) + { + glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]); + glTexStorage2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, getWindowWidth(), getWindowHeight()); + } + + GLfloat data[] = + { + -1.0f, 1.0f, + -1.0f, -2.0f, + 2.0f, 1.0f + }; + + glGenBuffers(1, &mBuffer); + glBindBuffer(GL_ARRAY_BUFFER, mBuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 6, data, GL_STATIC_DRAW); + + GLint maxDrawBuffers; + glGetIntegerv(GL_MAX_DRAW_BUFFERS, &maxDrawBuffers); + ASSERT_EQ(maxDrawBuffers, 8); + + ASSERT_GL_NO_ERROR(); + } + + virtual void TearDown() + { + glDeleteFramebuffers(1, &mFBO); + glDeleteTextures(4, mTextures); + glDeleteBuffers(1, &mBuffer); + + ANGLETest::TearDown(); + } + + void setupMRTProgramESSL3(bool bufferEnabled[8], GLuint *programOut) + { + const std::string vertexShaderSource = + "#version 300 es\n" + "in vec4 position;\n" + "void main() {\n" + " gl_Position = position;\n" + "}\n"; + + std::stringstream strstr; + + strstr << "#version 300 es\n" + "precision highp float;\n"; + + for (unsigned int index = 0; index < 8; index++) + { + if (bufferEnabled[index]) + { + strstr << "layout(location = " << index << ") " + "out vec4 value" << index << ";\n"; + } + } + + strstr << "void main()\n" + "{\n"; + + for (unsigned int index = 0; index < 8; index++) + { + if (bufferEnabled[index]) + { + unsigned int r = (index + 1) & 1; + unsigned int g = (index + 1) & 2; + unsigned int b = (index + 1) & 4; + + strstr << " value" << index << " = vec4(" + << r << ".0, " << g << ".0, " + << b << ".0, 1.0);\n"; + } + } + + strstr << "}\n"; + + *programOut = CompileProgram(vertexShaderSource, strstr.str()); + if (*programOut == 0) + { + FAIL() << "shader compilation failed."; + } + + glUseProgram(*programOut); + + GLint location = glGetAttribLocation(*programOut, "position"); + ASSERT_NE(location, -1); + glBindBuffer(GL_ARRAY_BUFFER, mBuffer); + glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 8, NULL); + glEnableVertexAttribArray(location); + } + + void setupMRTProgramESSL1(bool bufferEnabled[8], GLuint *programOut) + { + const std::string vertexShaderSource = + "attribute vec4 position;\n" + "void main() {\n" + " gl_Position = position;\n" + "}\n"; + + std::stringstream strstr; + + strstr << "#extension GL_EXT_draw_buffers : enable\n" + "precision highp float;\n" + "void main()\n" + "{\n"; + + for (unsigned int index = 0; index < 8; index++) + { + if (bufferEnabled[index]) + { + unsigned int r = (index + 1) & 1; + unsigned int g = (index + 1) & 2; + unsigned int b = (index + 1) & 4; + + strstr << " gl_FragData[" << index << "] = vec4(" + << r << ".0, " << g << ".0, " + << b << ".0, 1.0);\n"; + } + } + + strstr << "}\n"; + + *programOut = CompileProgram(vertexShaderSource, strstr.str()); + if (*programOut == 0) + { + FAIL() << "shader compilation failed."; + } + + glUseProgram(*programOut); + + GLint location = glGetAttribLocation(*programOut, "position"); + ASSERT_NE(location, -1); + glBindBuffer(GL_ARRAY_BUFFER, mBuffer); + glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 8, NULL); + glEnableVertexAttribArray(location); + } + + void setupMRTProgram(bool bufferEnabled[8], GLuint *programOut) + { + if (getClientVersion() == 3) + { + setupMRTProgramESSL3(bufferEnabled, programOut); + } + else + { + ASSERT_EQ(getClientVersion(), 2); + setupMRTProgramESSL1(bufferEnabled, programOut); + } + } + + void verifyAttachment(unsigned int index, GLuint textureName) + { + for (unsigned int colorAttachment = 0; colorAttachment < 8; colorAttachment++) + { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + colorAttachment, GL_TEXTURE_2D, 0, 0); + } + + glBindTexture(GL_TEXTURE_2D, textureName); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureName, 0); + + unsigned int r = (((index + 1) & 1) > 0) ? 255 : 0; + unsigned int g = (((index + 1) & 2) > 0) ? 255 : 0; + unsigned int b = (((index + 1) & 4) > 0) ? 255 : 0; + + EXPECT_PIXEL_EQ(getWindowWidth() / 2, getWindowHeight() / 2, r, g, b, 255); + } + + void gapsTest() + { + glBindTexture(GL_TEXTURE_2D, mTextures[0]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_TEXTURE_2D, mTextures[0], 0); + + bool flags[8] = { false, true }; + + GLuint program; + setupMRTProgram(flags, &program); + + const GLenum bufs[] = + { + GL_NONE, + GL_COLOR_ATTACHMENT1 + }; + glUseProgram(program); + glDrawBuffersEXT(2, bufs); + glDrawArrays(GL_TRIANGLES, 0, 3); + + verifyAttachment(1, mTextures[0]); + + glDeleteProgram(program); + } + + void firstAndLastTest() + { + glBindTexture(GL_TEXTURE_2D, mTextures[0]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextures[0], 0); + + glBindTexture(GL_TEXTURE_2D, mTextures[1]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT3, GL_TEXTURE_2D, mTextures[1], 0); + + bool flags[8] = { true, false, false, true }; + + GLuint program; + setupMRTProgram(flags, &program); + + const GLenum bufs[] = + { + GL_COLOR_ATTACHMENT0, + GL_NONE, + GL_NONE, + GL_COLOR_ATTACHMENT3 + }; + + glUseProgram(program); + glDrawBuffersEXT(4, bufs); + glDrawArrays(GL_TRIANGLES, 0, 3); + + verifyAttachment(0, mTextures[0]); + verifyAttachment(3, mTextures[1]); + + EXPECT_GL_NO_ERROR(); + + glDeleteProgram(program); + } + + void firstHalfNULLTest() + { + bool flags[8] = { false }; + GLenum bufs[8] = { GL_NONE }; + + for (unsigned int texIndex = 0; texIndex < 4; texIndex++) + { + glBindTexture(GL_TEXTURE_2D, mTextures[texIndex]); + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT4 + texIndex, GL_TEXTURE_2D, mTextures[texIndex], 0); + flags[texIndex + 4] = true; + bufs[texIndex + 4] = GL_COLOR_ATTACHMENT4 + texIndex; + } + + GLuint program; + setupMRTProgram(flags, &program); + + glUseProgram(program); + glDrawBuffersEXT(8, bufs); + glDrawArrays(GL_TRIANGLES, 0, 3); + + for (unsigned int texIndex = 0; texIndex < 4; texIndex++) + { + verifyAttachment(texIndex + 4, mTextures[texIndex]); + } + + EXPECT_GL_NO_ERROR(); + + glDeleteProgram(program); + } + + GLuint mFBO; + GLuint mTextures[4]; + GLuint mBuffer; +}; + +class DrawBuffersTestESSL3 : public DrawBuffersTest +{ + protected: + DrawBuffersTestESSL3() + : DrawBuffersTest(3) + {} +}; + +class DrawBuffersTestESSL1 : public DrawBuffersTest +{ + protected: + DrawBuffersTestESSL1() + : DrawBuffersTest(2) + {} +}; + +TEST_F(DrawBuffersTestESSL3, Gaps) +{ + gapsTest(); +} + +TEST_F(DrawBuffersTestESSL1, Gaps) +{ + gapsTest(); +} + +TEST_F(DrawBuffersTestESSL3, FirstAndLast) +{ + firstAndLastTest(); +} + +TEST_F(DrawBuffersTestESSL1, FirstAndLast) +{ + firstAndLastTest(); +} + +TEST_F(DrawBuffersTestESSL3, FirstHalfNULL) +{ + firstHalfNULLTest(); +} + +TEST_F(DrawBuffersTestESSL1, FirstHalfNULL) +{ + firstHalfNULLTest(); +} |