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 if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_blend_minmax"))
43 {
44 std::cout << "Test skipped because ES3 or GL_EXT_blend_minmax is not available." << std::endl;
45 return;
46 }
47
48 // TODO(geofflang): figure out why this fails
49 if (IsIntel() && GetParam() == ES2_OPENGL())
50 {
51 std::cout << "Test skipped on OpenGL Intel due to flakyness." << std::endl;
52 return;
53 }
54
55 SetUpFramebuffer(colorFormat);
56
57 int minValue = 0;
58 int maxValue = 1;
59 if (type == GL_FLOAT)
60 {
61 minValue = -1024;
62 maxValue = 1024;
63 }
64
65 const size_t colorCount = 128;
66 Color colors[colorCount];
67 for (size_t i = 0; i < colorCount; i++)
68 {
69 for (size_t j = 0; j < 4; j++)
70 {
71 colors[i].values[j] =
72 static_cast<float>(minValue + (rand() % (maxValue - minValue)));
73 }
74 }
75
76 float prevColor[4];
77 for (size_t i = 0; i < colorCount; i++)
78 {
79 const Color &color = colors[i];
80 glUseProgram(mProgram);
81 glUniform4f(mColorLocation, color.values[0], color.values[1], color.values[2], color.values[3]);
82
83 bool blendMin = (rand() % 2 == 0);
84 glBlendEquation(blendMin ? GL_MIN : GL_MAX);
85
86 drawQuad(mProgram, "aPosition", 0.5f);
87
88 float pixel[4];
89 if (type == GL_UNSIGNED_BYTE)
90 {
91 GLubyte ubytePixel[4];
92 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, ubytePixel);
93 for (size_t componentIdx = 0; componentIdx < ArraySize(pixel); componentIdx++)
94 {
95 pixel[componentIdx] = ubytePixel[componentIdx] / 255.0f;
96 }
97 }
98 else if (type == GL_FLOAT)
99 {
100 glReadPixels(0, 0, 1, 1, GL_RGBA, GL_FLOAT, pixel);
101 }
102 else
103 {
104 FAIL() << "Unexpected pixel type";
105 }
106
107 if (i > 0)
108 {
109 const float errorRange = 1.0f / 255.0f;
110 for (size_t componentIdx = 0; componentIdx < ArraySize(pixel); componentIdx++)
111 {
112 EXPECT_NEAR(
113 getExpected(blendMin, color.values[componentIdx], prevColor[componentIdx]),
114 pixel[componentIdx], errorRange);
115 }
116 }
117
118 memcpy(prevColor, pixel, sizeof(pixel));
119 }
120 }
121
SetUp()122 virtual void SetUp()
123 {
124 ANGLETest::SetUp();
125
126 const std::string testVertexShaderSource = SHADER_SOURCE
127 (
128 attribute highp vec4 aPosition;
129
130 void main(void)
131 {
132 gl_Position = aPosition;
133 }
134 );
135
136 const std::string testFragmentShaderSource = SHADER_SOURCE
137 (
138 uniform highp vec4 color;
139 void main(void)
140 {
141 gl_FragColor = color;
142 }
143 );
144
145 mProgram = CompileProgram(testVertexShaderSource, testFragmentShaderSource);
146 if (mProgram == 0)
147 {
148 FAIL() << "shader compilation failed.";
149 }
150
151 mColorLocation = glGetUniformLocation(mProgram, "color");
152
153 glUseProgram(mProgram);
154
155 glClearColor(0, 0, 0, 0);
156 glClearDepthf(0.0);
157 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
158
159 glEnable(GL_BLEND);
160 glDisable(GL_DEPTH_TEST);
161 }
162
SetUpFramebuffer(GLenum colorFormat)163 void SetUpFramebuffer(GLenum colorFormat)
164 {
165 glGenFramebuffers(1, &mFramebuffer);
166 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebuffer);
167 glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebuffer);
168
169 glGenRenderbuffers(1, &mColorRenderbuffer);
170 glBindRenderbuffer(GL_RENDERBUFFER, mColorRenderbuffer);
171 glRenderbufferStorage(GL_RENDERBUFFER, colorFormat, getWindowWidth(), getWindowHeight());
172 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mColorRenderbuffer);
173
174 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
175 glClear(GL_COLOR_BUFFER_BIT);
176
177 ASSERT_GL_NO_ERROR();
178 }
179
TearDown()180 virtual void TearDown()
181 {
182 glDeleteProgram(mProgram);
183 glDeleteFramebuffers(1, &mFramebuffer);
184 glDeleteRenderbuffers(1, &mColorRenderbuffer);
185
186 ANGLETest::TearDown();
187 }
188
189 GLuint mProgram;
190 GLint mColorLocation;
191
192 GLuint mFramebuffer;
193 GLuint mColorRenderbuffer;
194 };
195
TEST_P(BlendMinMaxTest,RGBA8)196 TEST_P(BlendMinMaxTest, RGBA8)
197 {
198 runTest(GL_RGBA8, GL_UNSIGNED_BYTE);
199 }
200
TEST_P(BlendMinMaxTest,RGBA32F)201 TEST_P(BlendMinMaxTest, RGBA32F)
202 {
203 if (getClientMajorVersion() < 3 || !extensionEnabled("GL_EXT_color_buffer_float"))
204 {
205 std::cout << "Test skipped because ES3 and GL_EXT_color_buffer_float are not available."
206 << std::endl;
207 return;
208 }
209
210 // TODO(jmadill): Figure out why this is broken on Intel
211 if (IsIntel() && (GetParam() == ES2_D3D11() || GetParam() == ES2_D3D9()))
212 {
213 std::cout << "Test skipped on Intel OpenGL." << std::endl;
214 return;
215 }
216
217 // TODO (bug 1284): Investigate RGBA32f D3D SDK Layers messages on D3D11_FL9_3
218 if (IsD3D11_FL93())
219 {
220 std::cout << "Test skipped on Feature Level 9_3." << std::endl;
221 return;
222 }
223
224 runTest(GL_RGBA32F, GL_FLOAT);
225 }
226
TEST_P(BlendMinMaxTest,RGBA16F)227 TEST_P(BlendMinMaxTest, RGBA16F)
228 {
229 if (getClientMajorVersion() < 3 && !extensionEnabled("GL_EXT_color_buffer_half_float"))
230 {
231 std::cout << "Test skipped because ES3 or GL_EXT_color_buffer_half_float is not available."
232 << std::endl;
233 return;
234 }
235
236 // TODO(jmadill): figure out why this fails
237 if (IsIntel() && (GetParam() == ES2_D3D11() || GetParam() == ES2_D3D9()))
238 {
239 std::cout << "Test skipped on Intel due to failures." << std::endl;
240 return;
241 }
242
243 runTest(GL_RGBA16F, GL_FLOAT);
244 }
245
246 // Use this to select which configurations (e.g. which renderer, which GLES major version) these tests should be run against.
247 ANGLE_INSTANTIATE_TEST(BlendMinMaxTest,
248 ES2_D3D9(),
249 ES2_D3D11(),
250 ES3_D3D11(),
251 ES2_D3D11_FL9_3(),
252 ES2_OPENGL(),
253 ES3_OPENGL(),
254 ES2_OPENGLES(),
255 ES3_OPENGLES());
256