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

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]) {
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 static const char* kFragColorShader =
199 BFE_SHADER(precision mediump float; uniform vec4 src; uniform vec4 src1;
200 void main() {
201 gl_FragColor = src;
202 gl_SecondaryFragColorEXT = src1;
203 });
204
205 CreateProgramWithFragmentShader(kFragColorShader);
206 LinkProgram();
207 DrawAndVerify();
208 }
209
210 TEST_F(EXTBlendFuncExtendedDrawTest, ESSL1FragData) {
211 if (!IsApplicable()) {
212 return;
213 }
214 static const char* kFragDataShader =
215 BFE_SHADER(precision mediump float; uniform vec4 src; uniform vec4 src1;
216 void main() {
217 gl_FragData[0] = src;
218 gl_SecondaryFragDataEXT[0] = src1;
219 });
220 CreateProgramWithFragmentShader(kFragDataShader);
221 LinkProgram();
222 DrawAndVerify();
223 }
224
225 class EXTBlendFuncExtendedES3DrawTest : public EXTBlendFuncExtendedDrawTest {
226 protected:
227 void SetUp() override {
228 GLManager::Options options;
229 options.context_type = GLManager::CONTEXT_TYPE_OPENGLES3;
230 options.size = gfx::Size(kWidth, kHeight);
231 base::CommandLine command_line(*base::CommandLine::ForCurrentProcess());
232 command_line.AppendSwitch(switches::kEnableUnsafeES3APIs);
233 gl_.InitializeWithCommandLine(options, &command_line);
234 }
235 bool IsApplicable() const {
236 return gl_.IsInitialized() && EXTBlendFuncExtendedDrawTest::IsApplicable();
237 }
238 const char* GetVertexShader() override {
239 static const char* kVertexShader = "#version 300 es\n" SHADER(
240 in vec4 position; void main() { gl_Position = position; });
241 return kVertexShader;
242 }
243 };
244
245 TEST_F(EXTBlendFuncExtendedES3DrawTest, ESSL3Var) {
246 if (!IsApplicable()) {
247 return;
248 }
249 static const char* kFragColorShader = "#version 300 es\n" BFE_SHADER(
250 precision mediump float; uniform vec4 src; uniform vec4 src1;
251 out vec4 FragColor; out vec4 SecondaryFragColor; void main() {
252 FragColor = src;
253 SecondaryFragColor = src1;
254 });
255
256 CreateProgramWithFragmentShader(kFragColorShader);
257 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragColor");
258 LinkProgram();
259 DrawAndVerify();
260 }
261
262 TEST_F(EXTBlendFuncExtendedES3DrawTest, ESSL3Array) {
263 if (!IsApplicable()) {
264 return;
265 }
266
267 static const char* kFragDataShader = "#version 300 es\n" BFE_SHADER(
268 precision mediump float; uniform vec4 src; uniform vec4 src1;
269 out vec4 FragData[1]; out vec4 SecondaryFragData[1]; void main() {
270 FragData[0] = src;
271 SecondaryFragData[0] = src1;
272 });
273
274 CreateProgramWithFragmentShader(kFragDataShader);
275 glBindFragDataLocationEXT(program_, 0, "FragData");
276 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragData");
277 LinkProgram();
278 DrawAndVerify();
279 }
280
281 TEST_F(EXTBlendFuncExtendedES3DrawTest, ES3Getters) {
282 if (!IsApplicable()) {
283 return;
284 }
285
286 static const char* kFragColorShader = "#version 300 es\n" BFE_SHADER(
287 precision mediump float; uniform vec4 src; uniform vec4 src1;
288 out vec4 FragColor; out vec4 SecondaryFragColor; void main() {
289 FragColor = src;
290 SecondaryFragColor = src1;
291 });
292
293 CreateProgramWithFragmentShader(kFragColorShader);
294 glBindFragDataLocationEXT(program_, 0, "FragColor");
295 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragColor");
296
297 // Getters return GL error before linking.
298 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
299 GLint location = glGetFragDataLocation(program_, "FragColor");
300 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
301 GLint index = glGetFragDataIndexEXT(program_, "FragColor");
302 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
303 location = glGetFragDataLocation(program_, "SecondaryFragColor");
304 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
305 index = glGetFragDataIndexEXT(program_, "SecondaryFragColor");
306 EXPECT_EQ(static_cast<GLenum>(GL_INVALID_OPERATION), glGetError());
307 LinkProgram();
308
309 // Getters return location and index after linking.
310 for (int i = 0; i < 2; ++i) {
311 location = glGetFragDataLocation(program_, "FragColor");
312 EXPECT_EQ(0, location);
313 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
314 index = glGetFragDataIndexEXT(program_, "FragColor");
315 EXPECT_EQ(0, index);
316 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
317 location = glGetFragDataLocation(program_, "SecondaryFragColor");
318 EXPECT_EQ(0, location);
319 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
320 index = glGetFragDataIndexEXT(program_, "SecondaryFragColor");
321 EXPECT_EQ(1, index);
322 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
323
324 // The calls should not affect the getters until re-linking.
325 glBindFragDataLocationEXT(program_, 0, "SecondaryFragColor");
326 glBindFragDataLocationIndexedEXT(program_, 0, 1, "FragColor");
327 }
328
329 LinkProgram();
330
331 location = glGetFragDataLocation(program_, "FragColor");
332 EXPECT_EQ(0, location);
333 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
334 index = glGetFragDataIndexEXT(program_, "FragColor");
335 EXPECT_EQ(1, index);
336 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
337 location = glGetFragDataLocation(program_, "SecondaryFragColor");
338 EXPECT_EQ(0, location);
339 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
340 index = glGetFragDataIndexEXT(program_, "SecondaryFragColor");
341 EXPECT_EQ(0, index);
342 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
343
344 // Unknown colors return location -1, index -1.
345 location = glGetFragDataLocation(program_, "UnknownColor");
346 EXPECT_EQ(-1, location);
347 EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
348 index = glGetFragDataIndexEXT(program_, "UnknownColor");
349 EXPECT_EQ(-1, index);
350
351 // Reset the settings and verify that the driver gets them correct.
352 glBindFragDataLocationEXT(program_, 0, "FragColor");
353 glBindFragDataLocationIndexedEXT(program_, 0, 1, "SecondaryFragColor");
354 LinkProgram();
355 DrawAndVerify();
356 }
Mark Kilgard 2015/08/28 19:53:25 very nice testing
357
358 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698