1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Advanced blending (GL_KHR_blend_equation_advanced) tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es31fAdvancedBlendTests.hpp"
25 #include "gluStrUtil.hpp"
26 #include "glsFragmentOpUtil.hpp"
27 #include "gluPixelTransfer.hpp"
28 #include "gluObjectWrapper.hpp"
29 #include "gluContextInfo.hpp"
30 #include "gluShaderProgram.hpp"
31 #include "tcuPixelFormat.hpp"
32 #include "tcuTexture.hpp"
33 #include "tcuTextureUtil.hpp"
34 #include "tcuImageCompare.hpp"
35 #include "tcuRenderTarget.hpp"
36 #include "tcuTestLog.hpp"
37 #include "tcuStringTemplate.hpp"
38 #include "deRandom.hpp"
39 #include "rrFragmentOperations.hpp"
40 #include "sglrReferenceUtils.hpp"
41 #include "glwEnums.hpp"
42 #include "glwFunctions.hpp"
43
44 #include <string>
45 #include <vector>
46
47 namespace deqp
48 {
49
50 using gls::FragmentOpUtil::IntegerQuad;
51 using gls::FragmentOpUtil::ReferenceQuadRenderer;
52 using tcu::TextureLevel;
53 using tcu::Vec2;
54 using tcu::Vec4;
55 using tcu::UVec4;
56 using tcu::TestLog;
57 using tcu::TextureFormat;
58 using std::string;
59 using std::vector;
60 using std::map;
61
62 namespace gles31
63 {
64 namespace Functional
65 {
66
67 namespace
68 {
69
70 enum
71 {
72 MAX_VIEWPORT_WIDTH = 128,
73 MAX_VIEWPORT_HEIGHT = 128
74 };
75
76 enum RenderTargetType
77 {
78 RENDERTARGETTYPE_DEFAULT = 0, //!< Default framebuffer
79 RENDERTARGETTYPE_SRGB_FBO,
80 RENDERTARGETTYPE_MSAA_FBO,
81
82 RENDERTARGETTYPE_LAST
83 };
84
85 class AdvancedBlendCase : public TestCase
86 {
87 public:
88 AdvancedBlendCase (Context& context, const char* name, const char* desc, deUint32 mode, int overdrawCount, bool coherent, RenderTargetType rtType);
89
90 ~AdvancedBlendCase (void);
91
92 void init (void);
93 void deinit (void);
94
95 IterateResult iterate (void);
96
97 private:
98 AdvancedBlendCase (const AdvancedBlendCase&);
99 AdvancedBlendCase& operator= (const AdvancedBlendCase&);
100
101 const deUint32 m_blendMode;
102 const int m_overdrawCount;
103 const bool m_coherentBlending;
104 const RenderTargetType m_rtType;
105 const int m_numIters;
106
107 deUint32 m_colorRbo;
108 deUint32 m_fbo;
109
110 deUint32 m_resolveColorRbo;
111 deUint32 m_resolveFbo;
112
113 glu::ShaderProgram* m_program;
114
115 ReferenceQuadRenderer* m_referenceRenderer;
116 TextureLevel* m_refColorBuffer;
117
118 const int m_renderWidth;
119 const int m_renderHeight;
120 const int m_viewportWidth;
121 const int m_viewportHeight;
122
123 int m_iterNdx;
124 };
125
AdvancedBlendCase(Context & context,const char * name,const char * desc,deUint32 mode,int overdrawCount,bool coherent,RenderTargetType rtType)126 AdvancedBlendCase::AdvancedBlendCase (Context& context,
127 const char* name,
128 const char* desc,
129 deUint32 mode,
130 int overdrawCount,
131 bool coherent,
132 RenderTargetType rtType)
133 : TestCase (context, name, desc)
134 , m_blendMode (mode)
135 , m_overdrawCount (overdrawCount)
136 , m_coherentBlending (coherent)
137 , m_rtType (rtType)
138 , m_numIters (5)
139 , m_colorRbo (0)
140 , m_fbo (0)
141 , m_resolveColorRbo (0)
142 , m_resolveFbo (0)
143 , m_program (DE_NULL)
144 , m_referenceRenderer (DE_NULL)
145 , m_refColorBuffer (DE_NULL)
146 , m_renderWidth (rtType != RENDERTARGETTYPE_DEFAULT ? 2*MAX_VIEWPORT_WIDTH : m_context.getRenderTarget().getWidth())
147 , m_renderHeight (rtType != RENDERTARGETTYPE_DEFAULT ? 2*MAX_VIEWPORT_HEIGHT : m_context.getRenderTarget().getHeight())
148 , m_viewportWidth (de::min<int>(m_renderWidth, MAX_VIEWPORT_WIDTH))
149 , m_viewportHeight (de::min<int>(m_renderHeight, MAX_VIEWPORT_HEIGHT))
150 , m_iterNdx (0)
151 {
152 }
153
getBlendLayoutQualifier(rr::BlendEquationAdvanced equation)154 const char* getBlendLayoutQualifier (rr::BlendEquationAdvanced equation)
155 {
156 static const char* s_qualifiers[] =
157 {
158 "blend_support_multiply",
159 "blend_support_screen",
160 "blend_support_overlay",
161 "blend_support_darken",
162 "blend_support_lighten",
163 "blend_support_colordodge",
164 "blend_support_colorburn",
165 "blend_support_hardlight",
166 "blend_support_softlight",
167 "blend_support_difference",
168 "blend_support_exclusion",
169 "blend_support_hsl_hue",
170 "blend_support_hsl_saturation",
171 "blend_support_hsl_color",
172 "blend_support_hsl_luminosity",
173 };
174 DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_qualifiers) == rr::BLENDEQUATION_ADVANCED_LAST);
175 DE_ASSERT(de::inBounds<int>(equation, 0, rr::BLENDEQUATION_ADVANCED_LAST));
176 return s_qualifiers[equation];
177 }
178
getBlendProgramSrc(rr::BlendEquationAdvanced equation)179 glu::ProgramSources getBlendProgramSrc (rr::BlendEquationAdvanced equation)
180 {
181 static const char* s_vertSrc = "#version 310 es\n"
182 "in highp vec4 a_position;\n"
183 "in mediump vec4 a_color;\n"
184 "out mediump vec4 v_color;\n"
185 "void main()\n"
186 "{\n"
187 " gl_Position = a_position;\n"
188 " v_color = a_color;\n"
189 "}\n";
190 static const char* s_fragSrc = "#version 310 es\n"
191 "#extension GL_KHR_blend_equation_advanced : require\n"
192 "in mediump vec4 v_color;\n"
193 "layout(${SUPPORT_QUALIFIER}) out;\n"
194 "layout(location = 0) out mediump vec4 o_color;\n"
195 "void main()\n"
196 "{\n"
197 " o_color = v_color;\n"
198 "}\n";
199
200 map<string, string> args;
201
202 args["SUPPORT_QUALIFIER"] = getBlendLayoutQualifier(equation);
203
204 return glu::ProgramSources()
205 << glu::VertexSource(s_vertSrc)
206 << glu::FragmentSource(tcu::StringTemplate(s_fragSrc).specialize(args));
207 }
208
init(void)209 void AdvancedBlendCase::init (void)
210 {
211 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
212 const bool useFbo = m_rtType != RENDERTARGETTYPE_DEFAULT;
213 const bool useSRGB = m_rtType == RENDERTARGETTYPE_SRGB_FBO;
214
215 if (!m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced"))
216 throw tcu::NotSupportedError("GL_KHR_blend_equation_advanced is not supported", DE_NULL, __FILE__, __LINE__);
217
218 if (m_coherentBlending && !m_context.getContextInfo().isExtensionSupported("GL_KHR_blend_equation_advanced_coherent"))
219 throw tcu::NotSupportedError("GL_KHR_blend_equation_advanced_coherent is not supported", DE_NULL, __FILE__, __LINE__);
220
221 TCU_CHECK(gl.blendBarrierKHR);
222
223 DE_ASSERT(!m_program);
224 DE_ASSERT(!m_referenceRenderer);
225 DE_ASSERT(!m_refColorBuffer);
226
227 m_program = new glu::ShaderProgram(m_context.getRenderContext(), getBlendProgramSrc(sglr::rr_util::mapGLBlendEquationAdvanced(m_blendMode)));
228 m_testCtx.getLog() << *m_program;
229
230 if (!m_program->isOk())
231 {
232 delete m_program;
233 m_program = DE_NULL;
234 TCU_FAIL("Compile failed");
235 }
236
237 m_referenceRenderer = new ReferenceQuadRenderer;
238 m_refColorBuffer = new TextureLevel(TextureFormat(useSRGB ? TextureFormat::sRGBA : TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_viewportWidth, m_viewportHeight);
239
240 if (useFbo)
241 {
242 const deUint32 format = useSRGB ? GL_SRGB8_ALPHA8 : GL_RGBA8;
243 const int numSamples = m_rtType == RENDERTARGETTYPE_MSAA_FBO ? 4 : 0;
244
245 m_testCtx.getLog() << TestLog::Message << "Using FBO of size (" << m_renderWidth << ", " << m_renderHeight << ") with format "
246 << glu::getPixelFormatStr(format) << " and " << numSamples << " samples"
247 << TestLog::EndMessage;
248
249 gl.genRenderbuffers(1, &m_colorRbo);
250 gl.bindRenderbuffer(GL_RENDERBUFFER, m_colorRbo);
251 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, numSamples, format, m_renderWidth, m_renderHeight);
252 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create color RBO");
253
254 gl.genFramebuffers(1, &m_fbo);
255 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
256 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorRbo);
257 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create FBO");
258
259 TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
260
261 if (numSamples > 0)
262 {
263 // Create resolve FBO
264 gl.genRenderbuffers(1, &m_resolveColorRbo);
265 gl.bindRenderbuffer(GL_RENDERBUFFER, m_resolveColorRbo);
266 gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 0, format, m_renderWidth, m_renderHeight);
267 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create resolve color RBO");
268
269 gl.genFramebuffers(1, &m_resolveFbo);
270 gl.bindFramebuffer(GL_FRAMEBUFFER, m_resolveFbo);
271 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_resolveColorRbo);
272 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create FBO");
273
274 TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
275
276 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
277 }
278 }
279 else
280 DE_ASSERT(m_rtType == RENDERTARGETTYPE_DEFAULT);
281
282 m_iterNdx = 0;
283 }
284
~AdvancedBlendCase(void)285 AdvancedBlendCase::~AdvancedBlendCase (void)
286 {
287 AdvancedBlendCase::deinit();
288 }
289
deinit(void)290 void AdvancedBlendCase::deinit (void)
291 {
292 delete m_program;
293 delete m_referenceRenderer;
294 delete m_refColorBuffer;
295
296 m_program = DE_NULL;
297 m_referenceRenderer = DE_NULL;
298 m_refColorBuffer = DE_NULL;
299
300 if (m_colorRbo || m_fbo)
301 {
302 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
303
304 gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
305 gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
306
307 if (m_colorRbo != 0)
308 {
309 gl.deleteRenderbuffers(1, &m_colorRbo);
310 m_colorRbo = 0;
311 }
312
313 if (m_fbo != 0)
314 {
315 gl.deleteFramebuffers(1, &m_fbo);
316 m_fbo = 0;
317 }
318
319 if (m_resolveColorRbo)
320 {
321 gl.deleteRenderbuffers(1, &m_resolveColorRbo);
322 m_resolveColorRbo = 0;
323 }
324
325 if (m_resolveFbo)
326 {
327 gl.deleteRenderbuffers(1, &m_resolveFbo);
328 m_resolveFbo = 0;
329 }
330 }
331 }
332
randomColor(de::Random * rnd)333 static tcu::Vec4 randomColor (de::Random* rnd)
334 {
335 const float rgbValues[] = { 0.0f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f };
336 const float alphaValues[] = { 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f };
337
338 // \note Spec assumes premultiplied inputs.
339 const float a = rnd->choose<float>(DE_ARRAY_BEGIN(alphaValues), DE_ARRAY_END(alphaValues));
340 const float r = a * rnd->choose<float>(DE_ARRAY_BEGIN(rgbValues), DE_ARRAY_END(rgbValues));
341 const float g = a * rnd->choose<float>(DE_ARRAY_BEGIN(rgbValues), DE_ARRAY_END(rgbValues));
342 const float b = a * rnd->choose<float>(DE_ARRAY_BEGIN(rgbValues), DE_ARRAY_END(rgbValues));
343 return tcu::Vec4(r, g, b, a);
344 }
345
getLinearAccess(const tcu::ConstPixelBufferAccess & access)346 static tcu::ConstPixelBufferAccess getLinearAccess (const tcu::ConstPixelBufferAccess& access)
347 {
348 if (access.getFormat().order == TextureFormat::sRGBA)
349 return tcu::ConstPixelBufferAccess(TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8),
350 access.getWidth(), access.getHeight(), access.getDepth(),
351 access.getRowPitch(), access.getSlicePitch(), access.getDataPtr());
352 else
353 return access;
354 }
355
iterate(void)356 AdvancedBlendCase::IterateResult AdvancedBlendCase::iterate (void)
357 {
358 const glu::RenderContext& renderCtx = m_context.getRenderContext();
359 const glw::Functions& gl = renderCtx.getFunctions();
360 de::Random rnd (deStringHash(getName()) ^ deInt32Hash(m_iterNdx));
361 const int viewportX = rnd.getInt(0, m_renderWidth - m_viewportWidth);
362 const int viewportY = rnd.getInt(0, m_renderHeight - m_viewportHeight);
363 const bool useFbo = m_rtType != RENDERTARGETTYPE_DEFAULT;
364 const bool requiresResolve = m_rtType == RENDERTARGETTYPE_MSAA_FBO;
365 const int numQuads = m_overdrawCount+1;
366 TextureLevel renderedImg (TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8), m_viewportWidth, m_viewportHeight);
367 vector<Vec4> colors (numQuads*4);
368
369 for (vector<Vec4>::iterator col = colors.begin(); col != colors.end(); ++col)
370 *col = randomColor(&rnd);
371
372 // Render with GL.
373 {
374 const deUint32 program = m_program->getProgram();
375 const int posLoc = gl.getAttribLocation(program, "a_position");
376 const int colorLoc = gl.getAttribLocation(program, "a_color");
377 const glu::Buffer indexBuffer (renderCtx);
378 const glu::Buffer positionBuffer (renderCtx);
379 const glu::Buffer colorBuffer (renderCtx);
380 vector<Vec2> positions (numQuads*4);
381 vector<deUint16> indices (numQuads*6);
382 const deUint16 singleQuadIndices[] = { 0, 2, 1, 1, 2, 3 };
383 const Vec2 singleQuadPos[] =
384 {
385 Vec2(-1.0f, -1.0f),
386 Vec2(-1.0f, +1.0f),
387 Vec2(+1.0f, -1.0f),
388 Vec2(+1.0f, +1.0f),
389 };
390
391 TCU_CHECK(posLoc >= 0 && colorLoc >= 0);
392
393 for (int quadNdx = 0; quadNdx < numQuads; quadNdx++)
394 {
395 std::copy(DE_ARRAY_BEGIN(singleQuadPos), DE_ARRAY_END(singleQuadPos), &positions[quadNdx*4]);
396 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(singleQuadIndices); ndx++)
397 indices[quadNdx*6 + ndx] = (deUint16)(quadNdx*4 + singleQuadIndices[ndx]);
398 }
399
400 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, *indexBuffer);
401 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (glw::GLsizeiptr)(indices.size()*sizeof(indices[0])), &indices[0], GL_STATIC_DRAW);
402
403 gl.bindBuffer(GL_ARRAY_BUFFER, *positionBuffer);
404 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(positions.size()*sizeof(positions[0])), &positions[0], GL_STATIC_DRAW);
405 gl.enableVertexAttribArray(posLoc);
406 gl.vertexAttribPointer(posLoc, 2, GL_FLOAT, GL_FALSE, 0, DE_NULL);
407
408 gl.bindBuffer(GL_ARRAY_BUFFER, *colorBuffer);
409 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(colors.size()*sizeof(colors[0])), &colors[0], GL_STATIC_DRAW);
410 gl.enableVertexAttribArray(colorLoc);
411 gl.vertexAttribPointer(colorLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
412 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to create buffers");
413
414 gl.useProgram(program);
415 gl.viewport(viewportX, viewportY, m_viewportWidth, m_viewportHeight);
416 gl.blendEquation(m_blendMode);
417 if (m_coherentBlending)
418 gl.enable(GL_BLEND_ADVANCED_COHERENT_KHR);
419
420 GLU_EXPECT_NO_ERROR(gl.getError(), "Failed to set render state");
421
422 gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
423
424 gl.disable(GL_BLEND);
425 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, DE_NULL);
426 gl.enable(GL_BLEND);
427
428 if (!m_coherentBlending)
429 gl.blendBarrierKHR();
430
431 if (m_coherentBlending)
432 {
433 gl.drawElements(GL_TRIANGLES, 6*(numQuads-1), GL_UNSIGNED_SHORT, (const void*)(deUintptr)(6*sizeof(deUint16)));
434 }
435 else
436 {
437 for (int quadNdx = 1; quadNdx < numQuads; quadNdx++)
438 {
439 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void*)(deUintptr)(quadNdx*6*sizeof(deUint16)));
440 gl.blendBarrierKHR();
441 }
442 }
443
444 gl.flush();
445 GLU_EXPECT_NO_ERROR(gl.getError(), "Render failed");
446 }
447
448 // Render reference.
449 {
450 rr::FragmentOperationState referenceState;
451 const tcu::PixelBufferAccess colorAccess = gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess());
452 const tcu::PixelBufferAccess nullAccess (TextureFormat(), 0, 0, 0, DE_NULL);
453 IntegerQuad quad;
454
455 if (!useFbo && m_context.getRenderTarget().getPixelFormat().alphaBits == 0)
456 {
457 // Emulate lack of alpha by clearing to 1 and masking out alpha writes
458 tcu::clear(*m_refColorBuffer, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
459 referenceState.colorMask = tcu::BVec4(true, true, true, false);
460 }
461
462 referenceState.blendEquationAdvaced = sglr::rr_util::mapGLBlendEquationAdvanced(m_blendMode);
463
464 quad.posA = tcu::IVec2(0, 0);
465 quad.posB = tcu::IVec2(m_viewportWidth-1, m_viewportHeight-1);
466
467 for (int quadNdx = 0; quadNdx < numQuads; quadNdx++)
468 {
469 referenceState.blendMode = quadNdx == 0 ? rr::BLENDMODE_NONE : rr::BLENDMODE_ADVANCED;
470 std::copy(&colors[4*quadNdx], &colors[4*quadNdx] + 4, &quad.color[0]);
471 m_referenceRenderer->render(colorAccess, nullAccess /* no depth */, nullAccess /* no stencil */, quad, referenceState);
472 }
473 }
474
475 if (requiresResolve)
476 {
477 gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, m_resolveFbo);
478 gl.blitFramebuffer(0, 0, m_renderWidth, m_renderHeight, 0, 0, m_renderWidth, m_renderHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
479 GLU_EXPECT_NO_ERROR(gl.getError(), "Resolve blit failed");
480
481 gl.bindFramebuffer(GL_READ_FRAMEBUFFER, m_resolveFbo);
482 }
483
484 glu::readPixels(renderCtx, viewportX, viewportY, renderedImg.getAccess());
485 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels()");
486
487 if (requiresResolve)
488 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
489
490 {
491 const bool isHSLMode = m_blendMode == GL_HSL_HUE_KHR ||
492 m_blendMode == GL_HSL_SATURATION_KHR ||
493 m_blendMode == GL_HSL_COLOR_KHR ||
494 m_blendMode == GL_HSL_LUMINOSITY_KHR;
495 bool comparePass = false;
496
497 if (isHSLMode)
498 {
499 // Compensate for more demanding HSL code by using fuzzy comparison.
500 const float threshold = 0.002f;
501 comparePass = tcu::fuzzyCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result",
502 getLinearAccess(m_refColorBuffer->getAccess()),
503 renderedImg.getAccess(),
504 threshold, tcu::COMPARE_LOG_RESULT);
505 }
506 else
507 {
508 const UVec4 compareThreshold = (useFbo ? tcu::PixelFormat(8, 8, 8, 8) : m_context.getRenderTarget().getPixelFormat()).getColorThreshold().toIVec().asUint()
509 * UVec4(5) / UVec4(2) + UVec4(3 * m_overdrawCount);
510
511 comparePass = tcu::bilinearCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result",
512 getLinearAccess(m_refColorBuffer->getAccess()),
513 renderedImg.getAccess(),
514 tcu::RGBA(compareThreshold[0], compareThreshold[1], compareThreshold[2], compareThreshold[3]),
515 tcu::COMPARE_LOG_RESULT);
516 }
517
518 if (!comparePass)
519 {
520 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
521 return STOP;
522 }
523 }
524
525 m_iterNdx += 1;
526
527 if (m_iterNdx < m_numIters)
528 return CONTINUE;
529 else
530 {
531 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
532 return STOP;
533 }
534 }
535
536 } // anonymous
537
AdvancedBlendTests(Context & context)538 AdvancedBlendTests::AdvancedBlendTests (Context& context)
539 : TestCaseGroup(context, "blend_equation_advanced", "GL_KHR_blend_equation_advanced Tests")
540 {
541 }
542
~AdvancedBlendTests(void)543 AdvancedBlendTests::~AdvancedBlendTests (void)
544 {
545 }
546
init(void)547 void AdvancedBlendTests::init (void)
548 {
549 static const struct
550 {
551 deUint32 mode;
552 const char* name;
553 } s_blendModes[] =
554 {
555 { GL_MULTIPLY_KHR, "multiply" },
556 { GL_SCREEN_KHR, "screen" },
557 { GL_OVERLAY_KHR, "overlay" },
558 { GL_DARKEN_KHR, "darken" },
559 { GL_LIGHTEN_KHR, "lighten" },
560 { GL_COLORDODGE_KHR, "colordodge" },
561 { GL_COLORBURN_KHR, "colorburn" },
562 { GL_HARDLIGHT_KHR, "hardlight" },
563 { GL_SOFTLIGHT_KHR, "softlight" },
564 { GL_DIFFERENCE_KHR, "difference" },
565 { GL_EXCLUSION_KHR, "exclusion" },
566 { GL_HSL_HUE_KHR, "hsl_hue" },
567 { GL_HSL_SATURATION_KHR, "hsl_saturation" },
568 { GL_HSL_COLOR_KHR, "hsl_color" },
569 { GL_HSL_LUMINOSITY_KHR, "hsl_luminosity" }
570 };
571
572 tcu::TestCaseGroup* const basicGroup = new tcu::TestCaseGroup(m_testCtx, "basic", "Single quad only");
573 tcu::TestCaseGroup* const srgbGroup = new tcu::TestCaseGroup(m_testCtx, "srgb", "Advanced blending with sRGB FBO");
574 tcu::TestCaseGroup* const msaaGroup = new tcu::TestCaseGroup(m_testCtx, "msaa", "Advanced blending with MSAA FBO");
575 tcu::TestCaseGroup* const barrierGroup = new tcu::TestCaseGroup(m_testCtx, "barrier", "Multiple overlapping quads with blend barriers");
576 tcu::TestCaseGroup* const coherentGroup = new tcu::TestCaseGroup(m_testCtx, "coherent", "Overlapping quads with coherent blending");
577 tcu::TestCaseGroup* const coherentMsaaGroup = new tcu::TestCaseGroup(m_testCtx, "coherent_msaa", "Overlapping quads with coherent blending with MSAA FBO");
578
579 addChild(basicGroup);
580 addChild(srgbGroup);
581 addChild(msaaGroup);
582 addChild(barrierGroup);
583 addChild(coherentGroup);
584 addChild(coherentMsaaGroup);
585
586 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(s_blendModes); modeNdx++)
587 {
588 const char* const name = s_blendModes[modeNdx].name;
589 const char* const desc = "";
590 const deUint32 mode = s_blendModes[modeNdx].mode;
591
592 basicGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 1, false, RENDERTARGETTYPE_DEFAULT));
593 srgbGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 1, false, RENDERTARGETTYPE_SRGB_FBO));
594 msaaGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 1, false, RENDERTARGETTYPE_MSAA_FBO));
595 barrierGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 4, false, RENDERTARGETTYPE_DEFAULT));
596 coherentGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 4, true, RENDERTARGETTYPE_DEFAULT));
597 coherentMsaaGroup->addChild (new AdvancedBlendCase(m_context, name, desc, mode, 4, true, RENDERTARGETTYPE_MSAA_FBO));
598 }
599 }
600
601 } // Functional
602 } // gles31
603 } // deqp
604