xref: /aosp_15_r20/external/angle/src/tests/gl_tests/AdvancedBlendTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2024 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 
7 #include "test_utils/ANGLETest.h"
8 #include "test_utils/gl_raii.h"
9 
10 using namespace angle;
11 
12 constexpr int kPixelColorThreshhold = 8;
13 
14 class AdvancedBlendTest : public ANGLETest<>
15 {
16   protected:
AdvancedBlendTest()17     AdvancedBlendTest()
18     {
19         setWindowWidth(128);
20         setWindowHeight(128);
21         setConfigRedBits(8);
22         setConfigGreenBits(8);
23         setConfigBlueBits(8);
24         setConfigAlphaBits(8);
25     }
26 
27     void callBlendBarrier(APIExtensionVersion usedExtension);
28     void testAdvancedBlendNotAppliedWhenBlendIsDisabled(APIExtensionVersion usedExtension);
29     void testAdvancedBlendDisabledAndThenEnabled(APIExtensionVersion usedExtension);
30     void testAdvancedBlendEnabledAndThenDisabled(APIExtensionVersion usedExtension);
31 };
32 
33 class AdvancedBlendTestES32 : public AdvancedBlendTest
34 {};
35 
callBlendBarrier(APIExtensionVersion usedExtension)36 void AdvancedBlendTest::callBlendBarrier(APIExtensionVersion usedExtension)
37 {
38     ASSERT(usedExtension == APIExtensionVersion::Core || usedExtension == APIExtensionVersion::KHR);
39     if (usedExtension == APIExtensionVersion::KHR)
40     {
41         glBlendBarrierKHR();
42     }
43     else
44     {
45         glBlendBarrier();
46     }
47 }
48 
testAdvancedBlendNotAppliedWhenBlendIsDisabled(APIExtensionVersion usedExtension)49 void AdvancedBlendTest::testAdvancedBlendNotAppliedWhenBlendIsDisabled(
50     APIExtensionVersion usedExtension)
51 {
52     ASSERT(usedExtension == APIExtensionVersion::Core || usedExtension == APIExtensionVersion::KHR);
53 
54     constexpr char kGLSLVersion31[] = R"(#version 310 es
55 )";
56     constexpr char kGLSLVersion32[] = R"(#version 320 es
57 )";
58     constexpr char kBlendKHR[]      = R"(#extension GL_KHR_blend_equation_advanced : require
59 )";
60 
61     std::string vertSrc;
62     std::string fragSrc;
63 
64     if (usedExtension == APIExtensionVersion::KHR)
65     {
66         vertSrc.append(kGLSLVersion31);
67         fragSrc.append(kGLSLVersion31);
68         fragSrc.append(kBlendKHR);
69     }
70     else
71     {
72         vertSrc.append(kGLSLVersion32);
73         fragSrc.append(kGLSLVersion32);
74     }
75 
76     constexpr char kVertSrcBody[] = R"(
77         in highp vec4 a_position;
78         in mediump vec4 a_color;
79         out mediump vec4 v_color;
80         void main()
81         {
82             gl_Position = a_position;
83             v_color = a_color;
84         }
85     )";
86     vertSrc.append(kVertSrcBody);
87 
88     constexpr char kFragSrcBody[] = R"(
89         in mediump vec4 v_color;
90         layout(blend_support_colorburn) out;
91         layout(location = 0) out mediump vec4 o_color;
92         void main()
93         {
94             o_color = v_color;
95         }
96     )";
97     fragSrc.append(kFragSrcBody);
98 
99     ANGLE_GL_PROGRAM(program, vertSrc.c_str(), fragSrc.c_str());
100     glUseProgram(program);
101 
102     std::array<GLfloat, 16> attribPosData = {1, 1,  0.5, 1, -1, 1,  0.5, 1,
103                                              1, -1, 0.5, 1, -1, -1, 0.5, 1};
104 
105     GLint attribPosLoc = glGetAttribLocation(1, "a_position");
106     ASSERT(attribPosLoc >= 0);
107     glEnableVertexAttribArray(attribPosLoc);
108     glVertexAttribPointer(attribPosLoc, 4, GL_FLOAT, GL_FALSE, 0, attribPosData.data());
109 
110     std::array<GLfloat, 16> attribColorData1 = {1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1,
111                                                 1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1};
112     GLint attribColorLoc                     = glGetAttribLocation(1, "a_color");
113     ASSERT(attribColorLoc >= 0);
114     glEnableVertexAttribArray(attribColorLoc);
115     glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData1.data());
116 
117     glBlendEquation(GL_COLORBURN);
118 
119     const uint16_t indices[] = {0, 1, 2, 2, 1, 3};
120     glClearColor(0.5, 0.5, 0.5, 1.0);
121     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
122 
123     // Disable the blend. The next glDrawElements() should not blend the a_color with clear color
124     glDisable(GL_BLEND);
125     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]);
126     EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(255, 51, 128, 255), kPixelColorThreshhold);
127 }
128 
129 // Test that when blending is disabled, advanced blend is not applied.
130 // Regression test for a bug in the emulation path in the Vulkan backend.
TEST_P(AdvancedBlendTest,AdvancedBlendNotAppliedWhenBlendIsDisabledKHR)131 TEST_P(AdvancedBlendTest, AdvancedBlendNotAppliedWhenBlendIsDisabledKHR)
132 {
133     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
134     testAdvancedBlendNotAppliedWhenBlendIsDisabled(APIExtensionVersion::KHR);
135 }
136 
137 // Test that when blending is disabled, advanced blend is not applied (using ES 3.2).
TEST_P(AdvancedBlendTestES32,AdvancedBlendNotAppliedWhenBlendIsDisabled)138 TEST_P(AdvancedBlendTestES32, AdvancedBlendNotAppliedWhenBlendIsDisabled)
139 {
140     testAdvancedBlendNotAppliedWhenBlendIsDisabled(APIExtensionVersion::Core);
141 }
142 
testAdvancedBlendDisabledAndThenEnabled(APIExtensionVersion usedExtension)143 void AdvancedBlendTest::testAdvancedBlendDisabledAndThenEnabled(APIExtensionVersion usedExtension)
144 {
145     ASSERT(usedExtension == APIExtensionVersion::Core || usedExtension == APIExtensionVersion::KHR);
146 
147     constexpr char kGLSLVersion31[] = R"(#version 310 es
148 )";
149     constexpr char kGLSLVersion32[] = R"(#version 320 es
150 )";
151     constexpr char kBlendKHR[]      = R"(#extension GL_KHR_blend_equation_advanced : require
152 )";
153 
154     std::string vertSrc;
155     std::string fragSrc;
156 
157     if (usedExtension == APIExtensionVersion::KHR)
158     {
159         vertSrc.append(kGLSLVersion31);
160         fragSrc.append(kGLSLVersion31);
161         fragSrc.append(kBlendKHR);
162     }
163     else
164     {
165         vertSrc.append(kGLSLVersion32);
166         fragSrc.append(kGLSLVersion32);
167     }
168 
169     constexpr char kVertSrcBody[] = R"(
170         in highp vec4 a_position;
171         in mediump vec4 a_color;
172         out mediump vec4 v_color;
173         void main()
174         {
175             gl_Position = a_position;
176             v_color = a_color;
177         }
178     )";
179     vertSrc.append(kVertSrcBody);
180 
181     constexpr char kFragSrcBody[] = R"(
182         in mediump vec4 v_color;
183         layout(blend_support_colorburn) out;
184         layout(location = 0) out mediump vec4 o_color;
185         void main()
186         {
187             o_color = v_color;
188         }
189     )";
190     fragSrc.append(kFragSrcBody);
191 
192     ANGLE_GL_PROGRAM(program, vertSrc.c_str(), fragSrc.c_str());
193     glUseProgram(program);
194 
195     std::array<GLfloat, 16> attribPosData = {1, 1,  0.5, 1, -1, 1,  0.5, 1,
196                                              1, -1, 0.5, 1, -1, -1, 0.5, 1};
197 
198     GLint attribPosLoc = glGetAttribLocation(1, "a_position");
199     ASSERT(attribPosLoc >= 0);
200     glEnableVertexAttribArray(attribPosLoc);
201     glVertexAttribPointer(attribPosLoc, 4, GL_FLOAT, GL_FALSE, 0, attribPosData.data());
202 
203     std::array<GLfloat, 16> attribColorData1 = {1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1,
204                                                 1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1};
205     GLint attribColorLoc                     = glGetAttribLocation(1, "a_color");
206     ASSERT(attribColorLoc >= 0);
207     glEnableVertexAttribArray(attribColorLoc);
208     glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData1.data());
209 
210     glBlendEquation(GL_COLORBURN);
211 
212     const uint16_t indices[] = {0, 1, 2, 2, 1, 3};
213     glClearColor(0.5, 0.5, 0.5, 1.0);
214     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
215 
216     // Disable the blend. The next glDrawElements() should not blend the a_color with clear color
217     glDisable(GL_BLEND);
218     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]);
219 
220     // Enable the blend. The next glDrawElements() should blend a_color
221     // with the the existing framebuffer output with GL_COLORBURN blend mode
222     glEnable(GL_BLEND);
223     // Test the blend with coherent blend disabled. This make the test cover both devices that
224     // support / do not support GL_KHR_blend_equation_advanced_coherent
225     if (IsGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent"))
226     {
227         glDisable(GL_BLEND_ADVANCED_COHERENT_KHR);
228     }
229     callBlendBarrier(usedExtension);
230     std::array<GLfloat, 16> attribColorData2 = {0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1,
231                                                 0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1};
232     glEnableVertexAttribArray(attribColorLoc);
233     glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData2.data());
234     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]);
235 
236     EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(255, 0, 0, 255), kPixelColorThreshhold);
237 }
238 
239 // Test that when blending is disabled, advanced blend is not applied, but is applied after
240 // it is enabled.
241 // Regression test for a bug in the emulation path in the Vulkan backend.
TEST_P(AdvancedBlendTest,AdvancedBlendDisabledAndThenEnabledKHR)242 TEST_P(AdvancedBlendTest, AdvancedBlendDisabledAndThenEnabledKHR)
243 {
244     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
245     testAdvancedBlendDisabledAndThenEnabled(APIExtensionVersion::KHR);
246 }
247 
248 // Test that when blending is disabled, advanced blend is not applied, but is applied after
249 // it is enabled (using ES 3.2).
TEST_P(AdvancedBlendTestES32,AdvancedBlendDisabledAndThenEnabled)250 TEST_P(AdvancedBlendTestES32, AdvancedBlendDisabledAndThenEnabled)
251 {
252     testAdvancedBlendDisabledAndThenEnabled(APIExtensionVersion::Core);
253 }
254 
testAdvancedBlendEnabledAndThenDisabled(APIExtensionVersion usedExtension)255 void AdvancedBlendTest::testAdvancedBlendEnabledAndThenDisabled(APIExtensionVersion usedExtension)
256 {
257     ASSERT(usedExtension == APIExtensionVersion::Core || usedExtension == APIExtensionVersion::KHR);
258 
259     constexpr char kGLSLVersion31[] = R"(#version 310 es
260 )";
261     constexpr char kGLSLVersion32[] = R"(#version 320 es
262 )";
263     constexpr char kBlendKHR[]      = R"(#extension GL_KHR_blend_equation_advanced : require
264 )";
265 
266     std::string vertSrc;
267     std::string fragSrc;
268 
269     if (usedExtension == APIExtensionVersion::KHR)
270     {
271         vertSrc.append(kGLSLVersion31);
272         fragSrc.append(kGLSLVersion31);
273         fragSrc.append(kBlendKHR);
274     }
275     else
276     {
277         vertSrc.append(kGLSLVersion32);
278         fragSrc.append(kGLSLVersion32);
279     }
280 
281     constexpr char kVertSrcBody[] = R"(
282         in highp vec4 a_position;
283         in mediump vec4 a_color;
284         out mediump vec4 v_color;
285         void main()
286         {
287             gl_Position = a_position;
288             v_color = a_color;
289         }
290     )";
291     vertSrc.append(kVertSrcBody);
292 
293     constexpr char kFragSrcBody[] = R"(
294         in mediump vec4 v_color;
295         layout(blend_support_colorburn) out;
296         layout(location = 0) out mediump vec4 o_color;
297         void main()
298         {
299             o_color = v_color;
300         }
301     )";
302     fragSrc.append(kFragSrcBody);
303 
304     ANGLE_GL_PROGRAM(program, vertSrc.c_str(), fragSrc.c_str());
305     glUseProgram(program);
306 
307     std::array<GLfloat, 16> attribPosData = {1, 1,  0.5, 1, -1, 1,  0.5, 1,
308                                              1, -1, 0.5, 1, -1, -1, 0.5, 1};
309 
310     GLint attribPosLoc = glGetAttribLocation(1, "a_position");
311     ASSERT(attribPosLoc >= 0);
312     glEnableVertexAttribArray(attribPosLoc);
313     glVertexAttribPointer(attribPosLoc, 4, GL_FLOAT, GL_FALSE, 0, attribPosData.data());
314 
315     std::array<GLfloat, 16> attribColorData1 = {1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1,
316                                                 1, 0.2, 0.5, 1, 1, 0.2, 0.5, 1};
317     GLint attribColorLoc                     = glGetAttribLocation(1, "a_color");
318     ASSERT(attribColorLoc >= 0);
319     glEnableVertexAttribArray(attribColorLoc);
320     glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData1.data());
321 
322     glBlendEquation(GL_COLORBURN);
323 
324     const uint16_t indices[] = {0, 1, 2, 2, 1, 3};
325     glClearColor(0.5, 0.5, 0.5, 1.0);
326     glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
327 
328     // Enable the blend. The next glDrawElements() should blend the a_color with clear color
329     // using the GL_COLORBURN blend mode
330     glEnable(GL_BLEND);
331     // Test the blend with coherent blend disabled. This make the test cover both devices that
332     // support / do not support GL_KHR_blend_equation_advanced_coherent
333     if (IsGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent"))
334     {
335         glDisable(GL_BLEND_ADVANCED_COHERENT_KHR);
336     }
337     callBlendBarrier(usedExtension);
338     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]);
339 
340     // Disable the blend. The next glDrawElements() should not blend the a_color with
341     // the existing framebuffer output with GL_COLORBURN blend mode
342     glDisable(GL_BLEND);
343     std::array<GLfloat, 16> attribColorData2 = {0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1,
344                                                 0.5, 0.5, 0, 1, 0.5, 0.5, 0, 1};
345     glEnableVertexAttribArray(attribColorLoc);
346     glVertexAttribPointer(attribColorLoc, 4, GL_FLOAT, GL_FALSE, 0, attribColorData2.data());
347     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, &indices[0]);
348 
349     EXPECT_PIXEL_COLOR_NEAR(64, 64, GLColor(128, 128, 0, 255), kPixelColorThreshhold);
350 }
351 
352 // Test that when blending is enabled, advanced blend is applied, but is not applied after
353 // it is disabled.
354 // Regression test for a bug in the emulation path in the Vulkan backend.
TEST_P(AdvancedBlendTest,AdvancedBlendEnabledAndThenDisabledKHR)355 TEST_P(AdvancedBlendTest, AdvancedBlendEnabledAndThenDisabledKHR)
356 {
357     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced"));
358     testAdvancedBlendEnabledAndThenDisabled(APIExtensionVersion::KHR);
359 }
360 
361 // Test that when blending is enabled, advanced blend is applied, but is not applied after
362 // it is disabled (using ES 3.2).
TEST_P(AdvancedBlendTestES32,AdvancedBlendEnabledAndThenDisabled)363 TEST_P(AdvancedBlendTestES32, AdvancedBlendEnabledAndThenDisabled)
364 {
365     testAdvancedBlendEnabledAndThenDisabled(APIExtensionVersion::Core);
366 }
367 
368 // Test querying advanced blend equation coherent on supported devices (enabled by default).
TEST_P(AdvancedBlendTest,AdvancedBlendCoherentQuery)369 TEST_P(AdvancedBlendTest, AdvancedBlendCoherentQuery)
370 {
371     ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent"));
372 
373     GLint status = -1;
374     glGetIntegerv(GL_BLEND_ADVANCED_COHERENT_KHR, &status);
375     EXPECT_GL_NO_ERROR();
376     EXPECT_EQ(status, 1);
377 
378     glDisable(GL_BLEND_ADVANCED_COHERENT_KHR);
379     glGetIntegerv(GL_BLEND_ADVANCED_COHERENT_KHR, &status);
380     EXPECT_GL_NO_ERROR();
381     EXPECT_EQ(status, 0);
382 
383     glEnable(GL_BLEND_ADVANCED_COHERENT_KHR);
384     glGetIntegerv(GL_BLEND_ADVANCED_COHERENT_KHR, &status);
385     EXPECT_GL_NO_ERROR();
386     EXPECT_EQ(status, 1);
387 }
388 
389 // Test that querying advanced blend equation coherent results in an error as if this enum does not
390 // exist.
TEST_P(AdvancedBlendTest,AdvancedBlendCoherentQueryFailsIfNotSupported)391 TEST_P(AdvancedBlendTest, AdvancedBlendCoherentQueryFailsIfNotSupported)
392 {
393     ANGLE_SKIP_TEST_IF(IsGLExtensionEnabled("GL_KHR_blend_equation_advanced_coherent"));
394 
395     GLint status = -1;
396     glGetIntegerv(GL_BLEND_ADVANCED_COHERENT_KHR, &status);
397     EXPECT_GL_ERROR(GL_INVALID_ENUM);
398 }
399 
400 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AdvancedBlendTest);
401 ANGLE_INSTANTIATE_TEST_ES31(AdvancedBlendTest);
402 
403 GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(AdvancedBlendTestES32);
404 ANGLE_INSTANTIATE_TEST_ES32(AdvancedBlendTestES32);
405