Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(340)

Side by Side Diff: gpu/command_buffer/tests/gl_ext_blend_func_extended_unittest.cc

Issue 1309743005: command_buffer: Implement EXT_blend_func_extended (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@new-05-path-fragment-input-gen
Patch Set: Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <GLES2/gl2.h>
6 #include <GLES2/gl2ext.h>
7 #include <GLES2/gl2extchromium.h>
8 #include <GLES3/gl3.h>
9
10 #include "base/command_line.h"
11 #include "gpu/command_buffer/tests/gl_manager.h"
12 #include "gpu/command_buffer/tests/gl_test_utils.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 #include "ui/gl/gl_switches.h"
16
17 #define SHADER(Src) #Src
18 #define BFE_SHADER(Src) "#extension GL_EXT_blend_func_extended : require\n" #Src
19
20 namespace {
21 // Partial implementation of weight function for GLES 2 blend equation that
22 // is dual-source aware.
23 template <int factor, int index>
24 float Weight(float dst[4], float src[4], float src1[4]) {
Zhenyao Mo 2015/08/31 21:12:31 What's the point of passing in dst? It's never use
Kimmo Kinnunen 2015/09/24 13:16:28 Just for clarity. The weight function of GL blend
25 if (factor == GL_SRC_COLOR)
26 return src[index];
27 if (factor == GL_SRC_ALPHA)
28 return src[3];
29 if (factor == GL_SRC1_COLOR_EXT)
30 return src1[index];
31 if (factor == GL_SRC1_ALPHA_EXT)
32 return src1[3];
33 if (factor == GL_ONE_MINUS_SRC1_COLOR_EXT)
34 return 1.0f - src1[index];
35 if (factor == GL_ONE_MINUS_SRC1_ALPHA_EXT)
36 return 1.0f - src1[3];
37 return 0.0f;
38 }
39
40 // Implementation of GLES 2 blend equation that is dual-source aware.
41 template <int RGBs, int RGBd, int As, int Ad>
42 void BlendEquationFuncAdd(float dst[4],
43 float src[4],
44 float src1[4],
45 uint8 result[4]) {
46 float r[4];
47 r[0] = src[0] * Weight<RGBs, 0>(dst, src, src1) +
48 dst[0] * Weight<RGBd, 0>(dst, src, src1);
49 r[1] = src[1] * Weight<RGBs, 1>(dst, src, src1) +
50 dst[1] * Weight<RGBd, 1>(dst, src, src1);
51 r[2] = src[2] * Weight<RGBs, 2>(dst, src, src1) +
52 dst[2] * Weight<RGBd, 2>(dst, src, src1);
53 r[3] = src[3] * Weight<As, 3>(dst, src, src1) +
54 dst[3] * Weight<Ad, 3>(dst, src, src1);
55 for (int i = 0; i < 4; ++i) {
56 result[i] = static_cast<uint8>(
57 std::floor(std::max(0.0f, std::min(1.0f, r[i])) * 255.0f));
58 }
59 }
60 }
61
62 namespace gpu {
63
64 class EXTBlendFuncExtendedTest : public testing::Test {
65 public:
66 protected:
67 void SetUp() override { gl_.Initialize(GLManager::Options()); }
68
69 void TearDown() override { gl_.Destroy(); }
70 bool IsApplicable() const {
71 return GLTestHelper::HasExtension("GL_EXT_blend_func_extended");
72 }
73 GLManager gl_;
74 };
75
76 TEST_F(EXTBlendFuncExtendedTest, TestMaxDualSourceDrawBuffers) {
77 if (!IsApplicable()) {
78 return;
79 }
80
81 GLint maxDualSourceDrawBuffers = 0;
82 glGetIntegerv(GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT, &maxDualSourceDrawBuffers);
83 EXPECT_GT(maxDualSourceDrawBuffers, 0);
84 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
85 }
86
87 class EXTBlendFuncExtendedDrawTest : public testing::Test {
88 public:
89 static const GLsizei kWidth = 100;
90 static const GLsizei kHeight = 100;
91 EXTBlendFuncExtendedDrawTest() : program_(0) {}
92
93 protected:
94 void SetUp() override {
95 GLManager::Options options;
96 options.size = gfx::Size(kWidth, kHeight);
97 gl_.Initialize(options);
98 }
99
100 bool IsApplicable() const {
101 return GLTestHelper::HasExtension("GL_EXT_blend_func_extended");
102 }
103
104 virtual const char* GetVertexShader() {
105 static const char* kVertexShader = SHADER(
106 attribute vec4 position; void main() { gl_Position = position; });
107 return kVertexShader;
108 }
109
110 void CreateProgramWithFragmentShader(const char* fragment_shader_str) {
111 GLuint vertex_shader =
112 GLTestHelper::LoadShader(GL_VERTEX_SHADER, GetVertexShader());
113 GLuint fragment_shader =
114 GLTestHelper::LoadShader(GL_FRAGMENT_SHADER, fragment_shader_str);
115 ASSERT_NE(0u, vertex_shader);
116 ASSERT_NE(0u, fragment_shader);
117 program_ = glCreateProgram();
118 ASSERT_NE(0u, program_);
119 glAttachShader(program_, vertex_shader);
120 glAttachShader(program_, fragment_shader);
121 glDeleteShader(vertex_shader);
122 glDeleteShader(fragment_shader);
123 }
124
125 void LinkProgram() {
126 glLinkProgram(program_);
127 GLint linked = 0;
128 glGetProgramiv(program_, GL_LINK_STATUS, &linked);
129 if (linked == 0) {
130 char buffer[1024];
131 GLsizei length = 0;
132 glGetProgramInfoLog(program_, sizeof(buffer), &length, buffer);
133 std::string log(buffer, length);
134 EXPECT_EQ(1, linked) << "Error linking program: " << log;
135 glDeleteProgram(program_);
136 program_ = 0;
137 }
138 glUseProgram(program_);
139 position_loc_ = glGetAttribLocation(program_, "position");
140 src_loc_ = glGetUniformLocation(program_, "src");
141 src1_loc_ = glGetUniformLocation(program_, "src1");
142 }
143
144 void TearDown() override {
145 if (program_ != 0) {
146 glDeleteProgram(program_);
147 }
148 gl_.Destroy();
149 }
150
151 void DrawAndVerify() {
152 float kDst[4] = {0.5f, 0.5f, 0.5f, 0.5f};
153 float kSrc[4] = {1.0f, 1.0f, 1.0f, 1.0f};
154 float kSrc1[4] = {0.3f, 0.6f, 0.9f, 0.7f};
155
156 glUniform4f(src_loc_, kSrc[0], kSrc[1], kSrc[2], kSrc[3]);
157 glUniform4f(src1_loc_, kSrc1[0], kSrc1[1], kSrc1[2], kSrc1[3]);
158
159 GLTestHelper::SetupUnitQuad(position_loc_);
160
161 glEnable(GL_BLEND);
162 glBlendEquation(GL_FUNC_ADD);
163 glBlendFuncSeparate(GL_SRC1_COLOR_EXT, GL_SRC_ALPHA,
164 GL_ONE_MINUS_SRC1_COLOR_EXT,
165 GL_ONE_MINUS_SRC1_ALPHA_EXT);
166 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
167
168 // Draw one triangle (bottom left half).
169 glViewport(0, 0, kWidth, kHeight);
170 glClearColor(kDst[0], kDst[1], kDst[2], kDst[3]);
171 glClear(GL_COLOR_BUFFER_BIT);
172 glDrawArrays(GL_TRIANGLES, 0, 6);
173 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
174
175 // Verify.
176 uint8 color[4];
177 BlendEquationFuncAdd<GL_SRC1_COLOR_EXT, GL_SRC_ALPHA,
178 GL_ONE_MINUS_SRC1_COLOR_EXT,
179 GL_ONE_MINUS_SRC1_ALPHA_EXT>(kDst, kSrc, kSrc1, color);
180
181 EXPECT_TRUE(GLTestHelper::CheckPixels(kWidth / 4, (3 * kHeight) / 4, 1, 1,
182 1, color));
183 EXPECT_TRUE(GLTestHelper::CheckPixels(kWidth - 1, 0, 1, 1, 1, color));
184 }
185
186 protected:
187 GLuint program_;
188 GLuint position_loc_;
189 GLuint src_loc_;
190 GLuint src1_loc_;
191 GLManager gl_;
192 };
193
194 TEST_F(EXTBlendFuncExtendedDrawTest, ESSL1FragColor) {
195 if (!IsApplicable()) {
196 return;
197 }
198 // clang-format off
199 static const char* kFragColorShader =
200 BFE_SHADER(
201 precision mediump float;
202 uniform vec4 src;
203 uniform vec4 src1;
204 void main() {
205 gl_FragColor = src;
206 gl_SecondaryFragColorEXT = src1;
207 });
208 // clang-format on
209 CreateProgramWithFragmentShader(kFragColorShader);
210 LinkProgram();
211 DrawAndVerify();
212 }
213
214 TEST_F(EXTBlendFuncExtendedDrawTest, ESSL1FragData) {
215 if (!IsApplicable()) {
216 return;
217 }
218 // clang-format off
219 static const char* kFragDataShader =
220 BFE_SHADER(
221 precision mediump float;
222 uniform vec4 src;
223 uniform vec4 src1;
224 void main() {
225 gl_FragData[0] = src;
226 gl_SecondaryFragDataEXT[0] = src1;
227 });
228 // clang-format on
229 CreateProgramWithFragmentShader(kFragDataShader);
230 LinkProgram();
231 DrawAndVerify();
232 }
233
234 class EXTBlendFuncExtendedES3DrawTest : public EXTBlendFuncExtendedDrawTest {
235 protected:
236 void SetUp() override {
237 GLManager::Options options;
238 options.context_type = gles2::CONTEXT_TYPE_OPENGLES3;
239 options.size = gfx::Size(kWidth, kHeight);
240 base::CommandLine command_line(*base::CommandLine::ForCurrentProcess());
241 command_line.AppendSwitch(switches::kEnableUnsafeES3APIs);
242 gl_.InitializeWithCommandLine(options, &command_line);
243 }
244 bool IsApplicable() const {
245 return gl_.IsInitialized() && EXTBlendFuncExtendedDrawTest::IsApplicable();
246 }
247 const char* GetVertexShader() override {
248 // clang-format off
249 static const char* kVertexShader =
250 "#version 300 es\n"
251 SHADER(
252 in vec4 position;
253 void main() {
254 gl_Position = position;
255 });
256 // clang-format on
257 return kVertexShader;
258 }
259 };
260
261 TEST_F(EXTBlendFuncExtendedES3DrawTest, ESSL3Var) {
262 if (!IsApplicable()) {
263 return;
264 }
265 // clang-format off
266 static const char* kFragColorShader =
267 "#version 300 es\n"
268 BFE_SHADER(
269 precision mediump float;
270 uniform vec4 src;
271 uniform vec4 src1;
272 out vec4 FragColor;
273 out vec4 SecondaryFragColor;
274 void main() {
275 FragColor = src;
276 SecondaryFragColor = src1;
277 });
278 // clang-format on
279 CreateProgramWithFragmentShader(kFragColorShader);
280 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragColor");
281 LinkProgram();
282 DrawAndVerify();
283 }
284
285 TEST_F(EXTBlendFuncExtendedES3DrawTest, ESSL3Array) {
286 if (!IsApplicable()) {
287 return;
288 }
289 // clang-format off
290 static const char* kFragDataShader =
291 "#version 300 es\n"
292 BFE_SHADER(
293 precision mediump float;
294 uniform vec4 src;
295 uniform vec4 src1;
296 out vec4 FragData[1];
297 out vec4 SecondaryFragData[1];
298 void main() {
299 FragData[0] = src;
300 SecondaryFragData[0] = src1;
301 });
302 // clang-format on
303 CreateProgramWithFragmentShader(kFragDataShader);
304 glBindFragDataLocationEXT(program_, 0, "FragData");
305 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragData");
306 LinkProgram();
307 DrawAndVerify();
308 }
309
310 TEST_F(EXTBlendFuncExtendedES3DrawTest, ES3Getters) {
311 if (!IsApplicable()) {
312 return;
313 }
314 // clang-format off
315 static const char* kFragColorShader =
316 "#version 300 es\n"
317 BFE_SHADER(
318 precision mediump float;
319 uniform vec4 src;
320 uniform vec4 src1;
321 out vec4 FragColor;
322 out vec4 SecondaryFragColor;
323 void main() {
324 FragColor = src;
325 SecondaryFragColor = src1;
326 });
327 // clang-format on
328 CreateProgramWithFragmentShader(kFragColorShader);
329 glBindFragDataLocationEXT(program_, 0, "FragColor");
330 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragColor");
331
332 // Getters return GL error before linking.
333 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
334 GLint location = glGetFragDataLocation(program_, "FragColor");
335 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
336 GLint index = glGetFragDataIndexEXT(program_, "FragColor");
337 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
338 location = glGetFragDataLocation(program_, "SecondaryFragColor");
339 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
340 index = glGetFragDataIndexEXT(program_, "SecondaryFragColor");
341 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
342 LinkProgram();
343
344 // Getters return location and index after linking.
345 for (int i = 0; i < 2; ++i) {
Zhenyao Mo 2015/08/31 21:12:31 Why run it twice?
Kimmo Kinnunen 2015/09/24 13:16:28 To confirm the setters do not affect the getters u
346 location = glGetFragDataLocation(program_, "FragColor");
347 EXPECT_EQ(0, location);
348 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
349 index = glGetFragDataIndexEXT(program_, "FragColor");
350 EXPECT_EQ(0, index);
351 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
352 location = glGetFragDataLocation(program_, "SecondaryFragColor");
353 EXPECT_EQ(0, location);
354 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
355 index = glGetFragDataIndexEXT(program_, "SecondaryFragColor");
356 EXPECT_EQ(1, index);
357 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
358
359 // The calls should not affect the getters until re-linking.
360 glBindFragDataLocationEXT(program_, 0, "SecondaryFragColor");
361 glBindFragDataLocationIndexedEXT(program_, 0, 1, "FragColor");
362 }
363
364 LinkProgram();
365
366 location = glGetFragDataLocation(program_, "FragColor");
367 EXPECT_EQ(0, location);
368 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
369 index = glGetFragDataIndexEXT(program_, "FragColor");
370 EXPECT_EQ(1, index);
371 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
372 location = glGetFragDataLocation(program_, "SecondaryFragColor");
373 EXPECT_EQ(0, location);
374 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
375 index = glGetFragDataIndexEXT(program_, "SecondaryFragColor");
376 EXPECT_EQ(0, index);
377 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
378
379 // Unknown colors return location -1, index -1.
380 location = glGetFragDataLocation(program_, "UnknownColor");
381 EXPECT_EQ(-1, location);
382 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
383 index = glGetFragDataIndexEXT(program_, "UnknownColor");
384 EXPECT_EQ(-1, index);
385
386 // Reset the settings and verify that the driver gets them correct.
387 glBindFragDataLocationEXT(program_, 0, "FragColor");
388 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragColor");
389 LinkProgram();
390 DrawAndVerify();
391 }
392
393 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698