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