// // 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. // #include "test_utils/ANGLETest.h" using namespace angle; class BlendMinMaxTest : public ANGLETest { protected: BlendMinMaxTest() { setWindowWidth(128); setWindowHeight(128); setConfigRedBits(8); setConfigGreenBits(8); setConfigBlueBits(8); setConfigAlphaBits(8); setConfigDepthBits(24); mProgram = 0; mColorLocation = -1; mFramebuffer = 0; mColorRenderbuffer = 0; } struct Color { float values[4]; }; static GLubyte getExpected(bool blendMin, float curColor, GLubyte prevColor) { GLubyte curAsUbyte = static_cast((curColor * std::numeric_limits::max()) + 0.5f); return blendMin ? std::min(curAsUbyte, prevColor) : std::max(curAsUbyte, prevColor); } void runTest(GLenum colorFormat) { if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_blend_minmax")) { std::cout << "Test skipped because ES3 or GL_EXT_blend_minmax is not available." << std::endl; return; } // TODO(geofflang): figure out why this fails if (IsIntel() && GetParam() == ES2_OPENGL()) { std::cout << "Test skipped on OpenGL Intel due to flakyness." << std::endl; return; } SetUpFramebuffer(colorFormat); const size_t colorCount = 1024; Color colors[colorCount]; for (size_t i = 0; i < colorCount; i++) { for (size_t j = 0; j < 4; j++) { colors[i].values[j] = (rand() % 255) / 255.0f; } } GLubyte prevColor[4]; for (size_t i = 0; i < colorCount; i++) { const Color &color = colors[i]; glUseProgram(mProgram); glUniform4f(mColorLocation, color.values[0], color.values[1], color.values[2], color.values[3]); bool blendMin = (rand() % 2 == 0); glBlendEquation(blendMin ? GL_MIN : GL_MAX); drawQuad(mProgram, "aPosition", 0.5f); if (i > 0) { EXPECT_PIXEL_EQ(0, 0, getExpected(blendMin, color.values[0], prevColor[0]), getExpected(blendMin, color.values[1], prevColor[1]), getExpected(blendMin, color.values[2], prevColor[2]), getExpected(blendMin, color.values[3], prevColor[3])); } glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, prevColor); } } virtual void SetUp() { ANGLETest::SetUp(); const std::string testVertexShaderSource = SHADER_SOURCE ( attribute highp vec4 aPosition; void main(void) { gl_Position = aPosition; } ); const std::string testFragmentShaderSource = SHADER_SOURCE ( uniform highp vec4 color; void main(void) { gl_FragColor = color; } ); mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource); if (mProgram == 0) { FAIL() << "shader compilation failed."; } mColorLocation = glGetUniformLocation(mProgram, "color"); glUseProgram(mProgram); glClearColor(0, 0, 0, 0); glClearDepthf(0.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glEnable(GL_BLEND); glDisable(GL_DEPTH_TEST); } void SetUpFramebuffer(GLenum colorFormat) { glGenFramebuffers(1, &mFramebuffer); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer); glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer); glGenRenderbuffers(1, &mColorRenderbuffer); glBindRenderbuffer(GL_RENDERBUFFER, mColorRenderbuffer); glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, getWindowWidth(), getWindowHeight()); glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mColorRenderbuffer); ASSERT_GL_NO_ERROR(); } virtual void TearDown() { glDeleteProgram(mProgram); glDeleteFramebuffers(1, &mFramebuffer); glDeleteRenderbuffers(1, &mColorRenderbuffer); ANGLETest::TearDown(); } GLuint mProgram; GLint mColorLocation; GLuint mFramebuffer; GLuint mColorRenderbuffer; }; TEST_P(BlendMinMaxTest, RGBA8) { runTest(GL_RGBA8); } TEST_P(BlendMinMaxTest, RGBA32f) { if (getClientMajorVersion() < 3 || !extensionEnabled("GL_EXT_color_buffer_float")) { std::cout << "Test skipped because ES3 and GL_EXT_color_buffer_float are not available." << std::endl; return; } // TODO(jmadill): Figure out why this is broken on Intel if (IsIntel() && (GetParam() == ES2_D3D11() || GetParam() == ES2_D3D9())) { std::cout << "Test skipped on Intel OpenGL." << std::endl; return; } // TODO (bug 1284): Investigate RGBA32f D3D SDK Layers messages on D3D11_FL9_3 if (IsD3D11_FL93()) { std::cout << "Test skipped on Feature Level 9_3." << std::endl; return; } runTest(GL_RGBA32F); } TEST_P(BlendMinMaxTest, RGBA16F) { if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_color_buffer_half_float")) { std::cout << "Test skipped because ES3 or GL_EXT_color_buffer_half_float is not available." << std::endl; return; } // TODO(jmadill): figure out why this fails if (IsIntel() && (GetParam() == ES2_D3D11() || GetParam() == ES2_D3D9())) { std::cout << "Test skipped on Intel due to failures." << std::endl; return; } // TODO(geofflang): This fails because readpixels with UNSIGNED_BYTE/RGBA does not work with // half float buffers (http://anglebug.com/1288) if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE) { std::cout << "Test skipped on OpenGL ES targets." << std::endl; return; } runTest(GL_RGBA16F); } // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against. ANGLE_INSTANTIATE_TEST(BlendMinMaxTest, ES2_D3D9(), ES2_D3D11(), ES2_D3D11_FL9_3(), ES2_OPENGL(), ES2_OPENGLES());