#include "test_utils/ANGLETest.h" #include "test_utils/gl_raii.h" using namespace angle; constexpr int kPixelColorThreshhold = 8; class AdvancedBlendTest : public ANGLETest<> { protected: AdvancedBlendTest() { setWindowWidth(128); setWindowHeight(128); setConfigRedBits(8); setConfigGreenBits(8); setConfigBlueBits(8); setConfigAlphaBits(8); } }; // Test that when blending is disabled, advanced blend is not applied. // Regression test for a bug in the emulation path in the Vulkan backend. TEST_P(AdvancedBlendTest, advancedBlendNotAppliedWhenBlendIsDisabled) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced")); const char *vertSrc = R"(#version 320 es in highp vec4 a_position; in mediump vec4 a_color; out mediump vec4 v_color; void main() { gl_Position = a_position; v_color = a_color; } )"; const char *fragSrc = R"(#version 320 es in mediump vec4 v_color; layout(blend_support_colorburn) out; layout(location = 0) out mediump vec4 o_color; void main() { o_color = v_color; } )"; ANGLE_GL_PROGRAM(program, vertSrc, fragSrc); glUseProgram(program); std::array attribPosData = {1, 1, 0.5, 1, -1, 1, 0.5, 1, 1, -1, 0.5, 1, -1, -1, 0.5, 1}; GLint attribPosLoc = glGetAttribLocation(1, "a_position"); ASSERT(attribPosLoc >= 0); glEnableVertexAttribArray(attribPosLoc); glVertexAttribPointer(attribPosLoc, 4, GL_FLOAT, GL_FALSE, 0, attribPosData.data()); std::array attribColorData1 = {1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1}; GLint attribColorLoc = glGetAttribLocation(1, "a_color"); ASSERT(attribColorLoc >= 0); glEnableVertexAttribArray(attribColorLoc); glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData1.data()); glBlendEquation(GL_COLORBURN); const uint16_t indices[] = {0, 1, 2, 2, 1, 3}; glClearColor(0.5, 0.5, 0.5, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Disable the blend. The next glDrawElements() should not blend the a_color with clear color glDisable(GL_BLEND); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]); EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(255, 51, 128, 255), kPixelColorThreshhold); } // Test that when blending is disabled, advanced blend is not applied, but is applied after // it is enabled. // Regression test for a bug in the emulation path in the Vulkan backend. TEST_P(AdvancedBlendTest, advancedBlendDisabledAndThenEnabled) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced")); const char *vertSrc = R"(#version 320 es in highp vec4 a_position; in mediump vec4 a_color; out mediump vec4 v_color; void main() { gl_Position = a_position; v_color = a_color; } )"; const char *fragSrc = R"(#version 320 es in mediump vec4 v_color; layout(blend_support_colorburn) out; layout(location = 0) out mediump vec4 o_color; void main() { o_color = v_color; } )"; ANGLE_GL_PROGRAM(program, vertSrc, fragSrc); glUseProgram(program); std::array attribPosData = {1, 1, 0.5, 1, -1, 1, 0.5, 1, 1, -1, 0.5, 1, -1, -1, 0.5, 1}; GLint attribPosLoc = glGetAttribLocation(1, "a_position"); ASSERT(attribPosLoc >= 0); glEnableVertexAttribArray(attribPosLoc); glVertexAttribPointer(attribPosLoc, 4, GL_FLOAT, GL_FALSE, 0, attribPosData.data()); std::array attribColorData1 = {1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1}; GLint attribColorLoc = glGetAttribLocation(1, "a_color"); ASSERT(attribColorLoc >= 0); glEnableVertexAttribArray(attribColorLoc); glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData1.data()); glBlendEquation(GL_COLORBURN); const uint16_t indices[] = {0, 1, 2, 2, 1, 3}; glClearColor(0.5, 0.5, 0.5, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Disable the blend. The next glDrawElements() should not blend the a_color with clear color glDisable(GL_BLEND); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]); // Enable the blend. The next glDrawElements() should blend a_color // with the the existing framebuffer output with GL_COLORBURN blend mode glEnable(GL_BLEND); // Test the blend with coherent blend disabled. This make the test cover both devices that // support / do not support GL_KHR_blend_equation_advanced_coherent if (IsGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent")) { glDisable(GL_BLEND_ADVANCED_COHERENT_KHR); } glBlendBarrier(); std::array attribColorData2 = {0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1}; glEnableVertexAttribArray(attribColorLoc); glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData2.data()); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]); EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(255, 0, 0, 255), kPixelColorThreshhold); } // Test that when blending is enabled, advanced blend is applied, but is not applied after // it is disabled. // Regression test for a bug in the emulation path in the Vulkan backend. TEST_P(AdvancedBlendTest, advancedBlendEnabledAndThenDisabled) { ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced")); const char *vertSrc = R"(#version 320 es in highp vec4 a_position; in mediump vec4 a_color; out mediump vec4 v_color; void main() { gl_Position = a_position; v_color = a_color; } )"; const char *fragSrc = R"(#version 320 es in mediump vec4 v_color; layout(blend_support_colorburn) out; layout(location = 0) out mediump vec4 o_color; void main() { o_color = v_color; } )"; ANGLE_GL_PROGRAM(program, vertSrc, fragSrc); glUseProgram(program); std::array attribPosData = {1, 1, 0.5, 1, -1, 1, 0.5, 1, 1, -1, 0.5, 1, -1, -1, 0.5, 1}; GLint attribPosLoc = glGetAttribLocation(1, "a_position"); ASSERT(attribPosLoc >= 0); glEnableVertexAttribArray(attribPosLoc); glVertexAttribPointer(attribPosLoc, 4, GL_FLOAT, GL_FALSE, 0, attribPosData.data()); std::array attribColorData1 = {1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1}; GLint attribColorLoc = glGetAttribLocation(1, "a_color"); ASSERT(attribColorLoc >= 0); glEnableVertexAttribArray(attribColorLoc); glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData1.data()); glBlendEquation(GL_COLORBURN); const uint16_t indices[] = {0, 1, 2, 2, 1, 3}; glClearColor(0.5, 0.5, 0.5, 1.0); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); // Enable the blend. The next glDrawElements() should blend the a_color with clear color // using the GL_COLORBURN blend mode glEnable(GL_BLEND); // Test the blend with coherent blend disabled. This make the test cover both devices that // support / do not support GL_KHR_blend_equation_advanced_coherent if (IsGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent")) { glDisable(GL_BLEND_ADVANCED_COHERENT_KHR); } glBlendBarrier(); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]); // Disable the blend. The next glDrawElements() should not blend the a_color with // the existing framebuffer output with GL_COLORBURN blend mode glDisable(GL_BLEND); std::array attribColorData2 = {0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1}; glEnableVertexAttribArray(attribColorLoc); glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData2.data()); glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]); EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(128, 128, 0, 255), kPixelColorThreshhold); } GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AdvancedBlendTest); ANGLE_INSTANTIATE_TEST_ES32(AdvancedBlendTest);