xref: /aosp_15_r20/external/angle/src/tests/gl_tests/BlendMinMaxTest.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1 //
2 // Copyright 2015 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 
9 using namespace angle;
10 
11 class BlendMinMaxTest : public ANGLETest<>
12 {
13   protected:
BlendMinMaxTest()14     BlendMinMaxTest()
15     {
16         setWindowWidth(128);
17         setWindowHeight(128);
18         setConfigRedBits(8);
19         setConfigGreenBits(8);
20         setConfigBlueBits(8);
21         setConfigAlphaBits(8);
22         setConfigDepthBits(24);
23 
24         mProgram           = 0;
25         mColorLocation     = -1;
26         mFramebuffer       = 0;
27         mColorRenderbuffer = 0;
28     }
29 
30     struct Color
31     {
32         float values[4];
33     };
34 
getExpected(bool blendMin,float curColor,float prevColor)35     static float getExpected(bool blendMin, float curColor, float prevColor)
36     {
37         return blendMin ? std::min(curColor, prevColor) : std::max(curColor, prevColor);
38     }
39 
runTest(GLenum colorFormat,GLenum type)40     void runTest(GLenum colorFormat, GLenum type)
41     {
42         ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
43                            !IsGLExtensionEnabled("GL_EXT_blend_minmax"));
44 
45         SetUpFramebuffer(colorFormat);
46 
47         int minValue = 0;
48         int maxValue = 1;
49         if (type == GL_FLOAT)
50         {
51             minValue = -1024;
52             maxValue = 1024;
53         }
54 
55         const size_t colorCount = 128;
56         Color colors[colorCount];
57         for (size_t i = 0; i < colorCount; i++)
58         {
59             for (size_t j = 0; j < 4; j++)
60             {
61                 colors[i].values[j] =
62                     static_cast<float>(minValue + (rand() % (maxValue - minValue)));
63             }
64         }
65 
66         float prevColor[4];
67         for (size_t i = 0; i < colorCount; i++)
68         {
69             const Color &color = colors[i];
70             glUseProgram(mProgram);
71             glUniform4f(mColorLocation, color.values[0], color.values[1], color.values[2],
72                         color.values[3]);
73 
74             bool blendMin = (rand() % 2 == 0);
75             glBlendEquation(blendMin ? GL_MIN : GL_MAX);
76 
77             drawQuad(mProgram, essl1_shaders::PositionAttrib(), 0.5f);
78 
79             float pixel[4];
80             if (type == GL_UNSIGNED_BYTE)
81             {
82                 GLubyte ubytePixel[4];
83                 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, ubytePixel);
84                 for (size_t componentIdx = 0; componentIdx < ArraySize(pixel); componentIdx++)
85                 {
86                     pixel[componentIdx] = ubytePixel[componentIdx] / 255.0f;
87                 }
88             }
89             else if (type == GL_FLOAT)
90             {
91                 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, pixel);
92             }
93             else
94             {
95                 FAIL() << "Unexpected pixel type";
96             }
97 
98             if (i > 0)
99             {
100                 const float errorRange = 1.0f / 255.0f;
101                 for (size_t componentIdx = 0; componentIdx < ArraySize(pixel); componentIdx++)
102                 {
103                     EXPECT_NEAR(
104                         getExpected(blendMin, color.values[componentIdx], prevColor[componentIdx]),
105                         pixel[componentIdx], errorRange)
106                         << " blendMin=" << blendMin << " componentIdx=" << componentIdx << std::endl
107                         << " color.values[0]=" << color.values[0]
108                         << " prevColor[0]=" << prevColor[0] << std::endl
109                         << " color.values[1]=" << color.values[1]
110                         << " prevColor[1]=" << prevColor[1] << std::endl
111                         << " color.values[2]=" << color.values[2]
112                         << " prevColor[2]=" << prevColor[2] << std::endl
113                         << " color.values[3]=" << color.values[3]
114                         << " prevColor[3]=" << prevColor[3];
115                 }
116             }
117 
118             memcpy(prevColor, pixel, sizeof(pixel));
119         }
120     }
121 
testSetUp()122     void testSetUp() override
123     {
124         mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
125         if (mProgram == 0)
126         {
127             FAIL() << "shader compilation failed.";
128         }
129 
130         mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
131 
132         glUseProgram(mProgram);
133 
134         glClearColor(0, 0, 0, 0);
135         glClearDepthf(0.0);
136         glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
137 
138         glEnable(GL_BLEND);
139         glDisable(GL_DEPTH_TEST);
140     }
141 
SetUpFramebuffer(GLenum colorFormat)142     void SetUpFramebuffer(GLenum colorFormat)
143     {
144         glGenFramebuffers(1, &mFramebuffer);
145         glBindFramebuffer(GL_FRAMEBUFFER, mFramebuffer);
146 
147         glGenRenderbuffers(1, &mColorRenderbuffer);
148         glBindRenderbuffer(GL_RENDERBUFFER, mColorRenderbuffer);
149         glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, getWindowWidth(), getWindowHeight());
150         glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
151                                   mColorRenderbuffer);
152 
153         glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
154         glClear(GL_COLOR_BUFFER_BIT);
155 
156         ASSERT_GL_NO_ERROR();
157     }
158 
testTearDown()159     void testTearDown() override
160     {
161         glDeleteProgram(mProgram);
162         glDeleteFramebuffers(1, &mFramebuffer);
163         glDeleteRenderbuffers(1, &mColorRenderbuffer);
164     }
165 
166     GLuint mProgram;
167     GLint mColorLocation;
168 
169     GLuint mFramebuffer;
170     GLuint mColorRenderbuffer;
171 };
172 
TEST_P(BlendMinMaxTest,RGBA8)173 TEST_P(BlendMinMaxTest, RGBA8)
174 {
175     runTest(GL_RGBA8, GL_UNSIGNED_BYTE);
176 }
177 
TEST_P(BlendMinMaxTest,RGBA32F)178 TEST_P(BlendMinMaxTest, RGBA32F)
179 {
180     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 || !IsGLExtensionEnabled("GL_EXT_float_blend") ||
181                        !IsGLExtensionEnabled("GL_EXT_color_buffer_float"));
182 
183     runTest(GL_RGBA32F, GL_FLOAT);
184 }
185 
TEST_P(BlendMinMaxTest,RGBA16F)186 TEST_P(BlendMinMaxTest, RGBA16F)
187 {
188     ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 &&
189                        !IsGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
190 
191     runTest(GL_RGBA16F, GL_FLOAT);
192 }
193 
194 // Use this to select which configurations (e.g. which renderer, which GLES major version) these
195 // tests should be run against.
196 ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(BlendMinMaxTest);
197