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

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

Powered by Google App Engine
This is Rietveld 408576698