1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2014-2016 The Khronos Group Inc.
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
22 */ /*-------------------------------------------------------------------*/
23
24 #include "glcBlendEquationAdvancedTests.hpp"
25 // de
26 #include "deRandom.hpp"
27 #include "deString.h"
28 // tcu
29 #include "tcuRGBA.hpp"
30 #include "tcuRenderTarget.hpp"
31 #include "tcuStringTemplate.hpp"
32 #include "tcuSurface.hpp"
33 #include "tcuTestLog.hpp"
34 #include "tcuVectorType.hpp"
35 #include "tcuVectorUtil.hpp"
36 // glu
37 #include "gluContextInfo.hpp"
38 #include "gluDrawUtil.hpp"
39 #include "gluPixelTransfer.hpp"
40 #include "gluShaderProgram.hpp"
41 // glw
42 #include "glwEnums.hpp"
43 #include "glwFunctions.hpp"
44 // de
45 #include "deMath.h"
46 // stl
47 #include <algorithm>
48 #include <map>
49 #include <memory>
50 #include <sstream>
51 #include <string>
52 #include <vector>
53
54 namespace glcts
55 {
56 using tcu::TestLog;
57
58 static const float s_pos[] = { -1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f };
59 static const deUint16 s_indices[] = { 0, 1, 2, 2, 1, 3 };
60
61 // Lists all modes introduced by the extension.
62 static const glw::GLenum s_modes[] = { GL_MULTIPLY_KHR, GL_SCREEN_KHR, GL_OVERLAY_KHR, GL_DARKEN_KHR,
63 GL_LIGHTEN_KHR, GL_COLORDODGE_KHR, GL_COLORBURN_KHR, GL_HARDLIGHT_KHR,
64 GL_SOFTLIGHT_KHR, GL_DIFFERENCE_KHR, GL_EXCLUSION_KHR, GL_HSL_HUE_KHR,
65 GL_HSL_SATURATION_KHR, GL_HSL_COLOR_KHR, GL_HSL_LUMINOSITY_KHR };
66
GetModeStr(glw::GLenum mode)67 static const char* GetModeStr(glw::GLenum mode)
68 {
69 switch (mode)
70 {
71 case GL_MULTIPLY_KHR:
72 return "GL_MULTIPLY_KHR";
73 case GL_SCREEN_KHR:
74 return "GL_SCREEN_KHR";
75 case GL_OVERLAY_KHR:
76 return "GL_OVERLAY_KHR";
77 case GL_DARKEN_KHR:
78 return "GL_DARKEN_KHR";
79 case GL_LIGHTEN_KHR:
80 return "GL_LIGHTEN_KHR";
81 case GL_COLORDODGE_KHR:
82 return "GL_COLORDODGE_KHR";
83 case GL_COLORBURN_KHR:
84 return "GL_COLORBURN_KHR";
85 case GL_HARDLIGHT_KHR:
86 return "GL_HARDLIGHT_KHR";
87 case GL_SOFTLIGHT_KHR:
88 return "GL_SOFTLIGHT_KHR";
89 case GL_DIFFERENCE_KHR:
90 return "GL_DIFFERENCE_KHR";
91 case GL_EXCLUSION_KHR:
92 return "GL_EXCLUSION_KHR";
93 case GL_HSL_HUE_KHR:
94 return "GL_HSL_HUE_KHR";
95 case GL_HSL_SATURATION_KHR:
96 return "GL_HSL_SATURATION_KHR";
97 case GL_HSL_COLOR_KHR:
98 return "GL_HSL_COLOR_KHR";
99 case GL_HSL_LUMINOSITY_KHR:
100 return "GL_HSL_LUMINOSITY_KHR";
101 default:
102 DE_ASSERT(DE_FALSE && "Blend mode not from GL_KHR_blend_equation_advanced.");
103 return "Blend mode not from GL_KHR_blend_equation_advanced.";
104 }
105 }
106
GetLayoutQualifierStr(glw::GLenum mode)107 static const char* GetLayoutQualifierStr(glw::GLenum mode)
108 {
109 switch (mode)
110 {
111 case GL_MULTIPLY_KHR:
112 return "blend_support_multiply";
113 case GL_SCREEN_KHR:
114 return "blend_support_screen";
115 case GL_OVERLAY_KHR:
116 return "blend_support_overlay";
117 case GL_DARKEN_KHR:
118 return "blend_support_darken";
119 case GL_LIGHTEN_KHR:
120 return "blend_support_lighten";
121 case GL_COLORDODGE_KHR:
122 return "blend_support_colordodge";
123 case GL_COLORBURN_KHR:
124 return "blend_support_colorburn";
125 case GL_HARDLIGHT_KHR:
126 return "blend_support_hardlight";
127 case GL_SOFTLIGHT_KHR:
128 return "blend_support_softlight";
129 case GL_DIFFERENCE_KHR:
130 return "blend_support_difference";
131 case GL_EXCLUSION_KHR:
132 return "blend_support_exclusion";
133 case GL_HSL_HUE_KHR:
134 return "blend_support_hsl_hue";
135 case GL_HSL_SATURATION_KHR:
136 return "blend_support_hsl_saturation";
137 case GL_HSL_COLOR_KHR:
138 return "blend_support_hsl_color";
139 case GL_HSL_LUMINOSITY_KHR:
140 return "blend_support_hsl_luminosity";
141 default:
142 DE_ASSERT(DE_FALSE && "Blend mode not from GL_KHR_blend_equation_advanced.");
143 return "Blend mode not from GL_KHR_blend_equation_advanced.";
144 }
145 }
146
IsExtensionSupported(deqp::Context & context,const char * extension)147 static bool IsExtensionSupported(deqp::Context& context, const char* extension)
148 {
149 const std::vector<std::string>& v = context.getContextInfo().getExtensions();
150 return std::find(v.begin(), v.end(), extension) != v.end();
151 }
152
GetP0(const tcu::Vec4 & src,const tcu::Vec4 & dst)153 static float GetP0(const tcu::Vec4& src, const tcu::Vec4& dst)
154 {
155 return src[3] * dst[3];
156 }
GetP1(const tcu::Vec4 & src,const tcu::Vec4 & dst)157 static float GetP1(const tcu::Vec4& src, const tcu::Vec4& dst)
158 {
159 return src[3] * (1.f - dst[3]);
160 }
GetP2(const tcu::Vec4 & src,const tcu::Vec4 & dst)161 static float GetP2(const tcu::Vec4& src, const tcu::Vec4& dst)
162 {
163 return dst[3] * (1.f - src[3]);
164 }
165
Blend(const tcu::Vec4 & rgb,const tcu::Vec4 & src,const tcu::Vec4 & dst)166 static tcu::Vec4 Blend(const tcu::Vec4& rgb, const tcu::Vec4& src, const tcu::Vec4& dst)
167 {
168 float p[3] = { GetP0(src, dst), GetP1(src, dst), GetP2(src, dst) };
169 float alpha = p[0] + p[1] + p[2];
170 tcu::Vec4 rgbOut = (p[0] * rgb) + (p[1] * src) + (p[2] * dst);
171 return tcu::Vec4(rgbOut[0], rgbOut[1], rgbOut[2], alpha);
172 }
173
BlendMultiply(const tcu::Vec4 & src,const tcu::Vec4 & dst)174 static tcu::Vec4 BlendMultiply(const tcu::Vec4& src, const tcu::Vec4& dst)
175 {
176 tcu::Vec4 rgb = src * dst;
177
178 return Blend(rgb, src, dst);
179 }
180
BlendScreen(const tcu::Vec4 & src,const tcu::Vec4 & dst)181 static tcu::Vec4 BlendScreen(const tcu::Vec4& src, const tcu::Vec4& dst)
182 {
183 tcu::Vec4 rgb = src + dst - src * dst;
184
185 return Blend(rgb, src, dst);
186 }
187
Overlay(float s,float d)188 static float Overlay(float s, float d)
189 {
190 if (d <= 0.5f)
191 return 2.f * s * d;
192 else
193 return 1.f - 2.f * (1.f - s) * (1.f - d);
194 }
195
BlendOverlay(const tcu::Vec4 & src,const tcu::Vec4 & dst)196 static tcu::Vec4 BlendOverlay(const tcu::Vec4& src, const tcu::Vec4& dst)
197 {
198 tcu::Vec4 rgb(Overlay(src[0], dst[0]), Overlay(src[1], dst[1]), Overlay(src[2], dst[2]), 0.f);
199
200 return Blend(rgb, src, dst);
201 }
202
BlendDarken(const tcu::Vec4 & src,const tcu::Vec4 & dst)203 static tcu::Vec4 BlendDarken(const tcu::Vec4& src, const tcu::Vec4& dst)
204 {
205 tcu::Vec4 rgb(de::min(src[0], dst[0]), de::min(src[1], dst[1]), de::min(src[2], dst[2]), 0.f);
206
207 return Blend(rgb, src, dst);
208 }
209
BlendLighten(const tcu::Vec4 & src,const tcu::Vec4 & dst)210 static tcu::Vec4 BlendLighten(const tcu::Vec4& src, const tcu::Vec4& dst)
211 {
212 tcu::Vec4 rgb(de::max(src[0], dst[0]), de::max(src[1], dst[1]), de::max(src[2], dst[2]), 0.f);
213
214 return Blend(rgb, src, dst);
215 }
216
ColorDodge(float s,float d)217 static float ColorDodge(float s, float d)
218 {
219 if (d <= 0.f)
220 return 0.f;
221 else if (d > 0.f && s < 1.f)
222 return de::min(1.f, d / (1.f - s));
223 else
224 return 1.f;
225 }
226
BlendColorDodge(const tcu::Vec4 & src,const tcu::Vec4 & dst)227 static tcu::Vec4 BlendColorDodge(const tcu::Vec4& src, const tcu::Vec4& dst)
228 {
229 tcu::Vec4 rgb(ColorDodge(src[0], dst[0]), ColorDodge(src[1], dst[1]), ColorDodge(src[2], dst[2]), 0.f);
230
231 return Blend(rgb, src, dst);
232 }
233
ColorBurn(float s,float d)234 static float ColorBurn(float s, float d)
235 {
236 if (d >= 1.f)
237 return 1.f;
238 else if (d < 1.f && s > 0.f)
239 return 1.f - de::min(1.f, (1.f - d) / s);
240 else
241 {
242 DE_ASSERT(d < 1.f && s <= 0.f);
243 return 0.f;
244 }
245 }
246
BlendColorBurn(const tcu::Vec4 & src,const tcu::Vec4 & dst)247 static tcu::Vec4 BlendColorBurn(const tcu::Vec4& src, const tcu::Vec4& dst)
248 {
249 tcu::Vec4 rgb(ColorBurn(src[0], dst[0]), ColorBurn(src[1], dst[1]), ColorBurn(src[2], dst[2]), 0.f);
250
251 return Blend(rgb, src, dst);
252 }
253
HardLight(float s,float d)254 static float HardLight(float s, float d)
255 {
256 if (s <= 0.5f)
257 return 2.f * s * d;
258 else
259 return 1.f - 2.f * (1.f - s) * (1.f - d);
260 }
261
BlendHardLight(const tcu::Vec4 & src,const tcu::Vec4 & dst)262 static tcu::Vec4 BlendHardLight(const tcu::Vec4& src, const tcu::Vec4& dst)
263 {
264 tcu::Vec4 rgb(HardLight(src[0], dst[0]), HardLight(src[1], dst[1]), HardLight(src[2], dst[2]), 0.f);
265
266 return Blend(rgb, src, dst);
267 }
268
SoftLight(float s,float d)269 static float SoftLight(float s, float d)
270 {
271 if (s <= 0.5f)
272 return d - (1.f - 2.f * s) * d * (1.f - d);
273 else if (d <= 0.25f)
274 {
275 DE_ASSERT(s > 0.5f && d <= 0.25f);
276 return d + (2.f * s - 1.f) * d * ((16.f * d - 12.f) * d + 3.f);
277 }
278 else
279 {
280 DE_ASSERT(s > 0.5f && d > 0.25f);
281 return d + (2.f * s - 1.f) * (deFloatSqrt(d) - d);
282 }
283 }
284
BlendSoftLight(const tcu::Vec4 & src,const tcu::Vec4 & dst)285 static tcu::Vec4 BlendSoftLight(const tcu::Vec4& src, const tcu::Vec4& dst)
286 {
287 tcu::Vec4 rgb(SoftLight(src[0], dst[0]), SoftLight(src[1], dst[1]), SoftLight(src[2], dst[2]), 0.f);
288
289 return Blend(rgb, src, dst);
290 }
291
BlendDifference(const tcu::Vec4 & src,const tcu::Vec4 & dst)292 static tcu::Vec4 BlendDifference(const tcu::Vec4& src, const tcu::Vec4& dst)
293 {
294 tcu::Vec4 rgb(deFloatAbs(src[0] - dst[0]), deFloatAbs(src[1] - dst[1]), deFloatAbs(src[2] - dst[2]), 0.f);
295
296 return Blend(rgb, src, dst);
297 }
298
Exclusion(float s,float d)299 static float Exclusion(float s, float d)
300 {
301 return s + d - 2.f * s * d;
302 }
303
BlendExclusion(const tcu::Vec4 & src,const tcu::Vec4 & dst)304 static tcu::Vec4 BlendExclusion(const tcu::Vec4& src, const tcu::Vec4& dst)
305 {
306 tcu::Vec4 rgb(Exclusion(src[0], dst[0]), Exclusion(src[1], dst[1]), Exclusion(src[2], dst[2]), 0.f);
307 return Blend(rgb, src, dst);
308 }
309
Luminance(const tcu::Vec4 & rgba)310 static float Luminance(const tcu::Vec4& rgba)
311 {
312 // Coefficients from the KHR_GL_blend_equation_advanced test spec.
313 return 0.30f * rgba[0] + 0.59f * rgba[1] + 0.11f * rgba[2];
314 }
315
316 // Minimum of R, G and B components.
MinRGB(const tcu::Vec4 & rgba)317 static float MinRGB(const tcu::Vec4& rgba)
318 {
319 return deFloatMin(deFloatMin(rgba[0], rgba[1]), rgba[2]);
320 }
321
322 // Maximum of R, G and B components.
MaxRGB(const tcu::Vec4 & rgba)323 static float MaxRGB(const tcu::Vec4& rgba)
324 {
325 return deFloatMax(deFloatMax(rgba[0], rgba[1]), rgba[2]);
326 }
327
Saturation(const tcu::Vec4 & rgba)328 static float Saturation(const tcu::Vec4& rgba)
329 {
330 return MaxRGB(rgba) - MinRGB(rgba);
331 }
332
333 // Take the base RGB color <cbase> and override its luminosity
334 // with that of the RGB color <clum>.
SetLum(const tcu::Vec4 & cbase,const tcu::Vec4 & clum)335 static tcu::Vec4 SetLum(const tcu::Vec4& cbase, const tcu::Vec4& clum)
336 {
337 float lbase = Luminance(cbase);
338 float llum = Luminance(clum);
339 float ldiff = llum - lbase;
340 tcu::Vec4 color = cbase + tcu::Vec4(ldiff);
341 tcu::Vec4 vllum = tcu::Vec4(llum);
342 if (MinRGB(color) < 0.0f)
343 {
344 return vllum + ((color - vllum) * llum) / (llum - MinRGB(color));
345 }
346 else if (MaxRGB(color) > 1.0f)
347 {
348 return vllum + ((color - vllum) * (1.f - llum)) / (MaxRGB(color) - llum);
349 }
350 else
351 {
352 return color;
353 }
354 }
355
356 // Take the base RGB color <cbase> and override its saturation with
357 // that of the RGB color <csat>. The override the luminosity of the
358 // result with that of the RGB color <clum>.
SetLumSat(const tcu::Vec4 & cbase,const tcu::Vec4 & csat,const tcu::Vec4 & clum)359 static tcu::Vec4 SetLumSat(const tcu::Vec4& cbase, const tcu::Vec4& csat, const tcu::Vec4& clum)
360 {
361 float minbase = MinRGB(cbase);
362 float sbase = Saturation(cbase);
363 float ssat = Saturation(csat);
364 tcu::Vec4 color;
365 if (sbase > 0)
366 {
367 // From the extension spec:
368 // Equivalent (modulo rounding errors) to setting the
369 // smallest (R,G,B) component to 0, the largest to <ssat>,
370 // and interpolating the "middle" component based on its
371 // original value relative to the smallest/largest.
372 color = (cbase - tcu::Vec4(minbase)) * ssat / sbase;
373 }
374 else
375 {
376 color = tcu::Vec4(0.0f);
377 }
378 return SetLum(color, clum);
379 }
380
BlendHSLHue(const tcu::Vec4 & src,const tcu::Vec4 & dst)381 static tcu::Vec4 BlendHSLHue(const tcu::Vec4& src, const tcu::Vec4& dst)
382 {
383 tcu::Vec4 rgb = SetLumSat(src, dst, dst);
384 return Blend(rgb, src, dst);
385 }
386
BlendHSLSaturation(const tcu::Vec4 & src,const tcu::Vec4 & dst)387 static tcu::Vec4 BlendHSLSaturation(const tcu::Vec4& src, const tcu::Vec4& dst)
388 {
389 tcu::Vec4 rgb = SetLumSat(dst, src, dst);
390 return Blend(rgb, src, dst);
391 }
392
BlendHSLColor(const tcu::Vec4 & src,const tcu::Vec4 & dst)393 static tcu::Vec4 BlendHSLColor(const tcu::Vec4& src, const tcu::Vec4& dst)
394 {
395 tcu::Vec4 rgb = SetLum(src, dst);
396 return Blend(rgb, src, dst);
397 }
398
BlendHSLuminosity(const tcu::Vec4 & src,const tcu::Vec4 & dst)399 static tcu::Vec4 BlendHSLuminosity(const tcu::Vec4& src, const tcu::Vec4& dst)
400 {
401 tcu::Vec4 rgb = SetLum(dst, src);
402 return Blend(rgb, src, dst);
403 }
404
405 typedef tcu::Vec4 (*BlendFunc)(const tcu::Vec4& src, const tcu::Vec4& dst);
406
GetBlendFunc(glw::GLenum mode)407 static BlendFunc GetBlendFunc(glw::GLenum mode)
408 {
409 switch (mode)
410 {
411 case GL_MULTIPLY_KHR:
412 return BlendMultiply;
413 case GL_SCREEN_KHR:
414 return BlendScreen;
415 case GL_OVERLAY_KHR:
416 return BlendOverlay;
417 case GL_DARKEN_KHR:
418 return BlendDarken;
419 case GL_LIGHTEN_KHR:
420 return BlendLighten;
421 case GL_COLORDODGE_KHR:
422 return BlendColorDodge;
423 case GL_COLORBURN_KHR:
424 return BlendColorBurn;
425 case GL_HARDLIGHT_KHR:
426 return BlendHardLight;
427 case GL_SOFTLIGHT_KHR:
428 return BlendSoftLight;
429 case GL_DIFFERENCE_KHR:
430 return BlendDifference;
431 case GL_EXCLUSION_KHR:
432 return BlendExclusion;
433 case GL_HSL_HUE_KHR:
434 return BlendHSLHue;
435 case GL_HSL_SATURATION_KHR:
436 return BlendHSLSaturation;
437 case GL_HSL_COLOR_KHR:
438 return BlendHSLColor;
439 case GL_HSL_LUMINOSITY_KHR:
440 return BlendHSLuminosity;
441 default:
442 DE_ASSERT(DE_FALSE && "Blend mode not from GL_KHR_blend_equation_advanced.");
443 return NULL;
444 }
445 }
446
ToNormal(const tcu::Vec4 & v)447 static tcu::Vec4 ToNormal(const tcu::Vec4& v)
448 {
449 float a = v[3];
450 if (a == 0)
451 return tcu::Vec4(0.f, 0.f, 0.f, 0.f);
452 return tcu::Vec4(v[0] / a, v[1] / a, v[2] / a, a);
453 }
454
455 // Blend premultiplied src and dst with given blend mode.
Blend(glw::GLenum mode,const tcu::Vec4 & src,const tcu::Vec4 & dst)456 static tcu::Vec4 Blend(glw::GLenum mode, const tcu::Vec4& src, const tcu::Vec4& dst)
457 {
458 BlendFunc blend = GetBlendFunc(mode);
459 tcu::Vec4 srcNorm = ToNormal(src);
460 tcu::Vec4 dstNorm = ToNormal(dst);
461
462 return blend(srcNorm, dstNorm);
463 }
464
GetDef2DVtxSrc(glu::GLSLVersion glslVersion)465 static std::string GetDef2DVtxSrc(glu::GLSLVersion glslVersion)
466 {
467 std::stringstream str;
468
469 DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_430);
470
471 str << glu::getGLSLVersionDeclaration(glslVersion) << "\n"
472 << "in highp vec2 aPos;\n"
473 "void main() {\n"
474 " gl_Position = vec4(aPos, 0.0, 1.0);\n"
475 "}\n";
476 return str.str();
477 }
478
GetSolidShader(const char * layoutQualifier,const char * glslVersion,const char * extensionDirective="#extension GL_KHR_blend_equation_advanced : require")479 static std::string GetSolidShader(
480 const char* layoutQualifier, const char* glslVersion,
481 const char* extensionDirective = "#extension GL_KHR_blend_equation_advanced : require")
482 {
483 static const char* frgSrcTemplate = "${VERSION_DIRECTIVE}\n"
484 "${EXTENSION_DIRECTIVE}\n"
485 "\n"
486 "precision highp float;\n"
487 "\n"
488 "${LAYOUT_QUALIFIER}\n"
489 "layout (location = 0) out vec4 oCol;\n"
490 "\n"
491 "uniform vec4 uSrcCol;\n"
492 "\n"
493 "void main (void) {\n"
494 " oCol = uSrcCol;\n"
495 "}\n";
496
497 std::map<std::string, std::string> args;
498 args["VERSION_DIRECTIVE"] = glslVersion;
499 args["EXTENSION_DIRECTIVE"] = extensionDirective;
500 if (layoutQualifier)
501 args["LAYOUT_QUALIFIER"] = std::string("layout (") + layoutQualifier + std::string(") out;");
502 else
503 args["LAYOUT_QUALIFIER"] = ""; // none
504
505 return tcu::StringTemplate(frgSrcTemplate).specialize(args);
506 }
507
508 /*
509 * Framebuffer helper.
510 * Creates and binds FBO and either one or two renderbuffer color attachments (fmt0, fmt1) with
511 * given size (width, height).
512 *
513 * Note: Does not restore previous 1) fbo binding, 2) scissor or 3) viewport upon exit.
514 */
515 class FBOSentry
516 {
517 public:
518 FBOSentry(const glw::Functions& gl, int width, int height, glw::GLenum fmt0);
519 FBOSentry(const glw::Functions& gl, int width, int height, glw::GLenum fmt0, glw::GLenum fmt1);
520 ~FBOSentry();
521
522 private:
523 void init(int width, int height, glw::GLenum fmt0, glw::GLenum fmt1);
524 const glw::Functions& m_gl;
525 glw::GLuint m_fbo;
526 glw::GLuint m_rbo[2];
527 };
528
FBOSentry(const glw::Functions & gl,int width,int height,glw::GLenum fmt0)529 FBOSentry::FBOSentry(const glw::Functions& gl, int width, int height, glw::GLenum fmt0) : m_gl(gl)
530 {
531 init(width, height, fmt0, GL_NONE);
532 }
533
FBOSentry(const glw::Functions & gl,int width,int height,glw::GLenum fmt0,glw::GLenum fmt1)534 FBOSentry::FBOSentry(const glw::Functions& gl, int width, int height, glw::GLenum fmt0, glw::GLenum fmt1) : m_gl(gl)
535 {
536 init(width, height, fmt0, fmt1);
537 }
538
~FBOSentry()539 FBOSentry::~FBOSentry()
540 {
541 m_gl.deleteFramebuffers(1, &m_fbo);
542 m_gl.deleteRenderbuffers(2, m_rbo);
543 }
544
init(int width,int height,glw::GLenum fmt0,glw::GLenum fmt1)545 void FBOSentry::init(int width, int height, glw::GLenum fmt0, glw::GLenum fmt1)
546 {
547 m_gl.genFramebuffers(1, &m_fbo);
548 m_gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
549
550 m_gl.genRenderbuffers(2, m_rbo);
551 m_gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo[0]);
552 m_gl.renderbufferStorage(GL_RENDERBUFFER, fmt0, width, height);
553 m_gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo[0]);
554
555 if (fmt1 != GL_NONE)
556 {
557 m_gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo[1]);
558 m_gl.renderbufferStorage(GL_RENDERBUFFER, fmt1, width, height);
559 m_gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1, GL_RENDERBUFFER, m_rbo[1]);
560 }
561
562 glw::GLenum status = m_gl.checkFramebufferStatus(GL_FRAMEBUFFER);
563 if (m_gl.getError() != GL_NO_ERROR || status != GL_FRAMEBUFFER_COMPLETE)
564 {
565 TCU_FAIL("Framebuffer failed");
566 }
567
568 m_gl.viewport(0, 0, width, height);
569 m_gl.scissor(0, 0, width, height);
570 }
571
572 class CoherentBlendTestCaseGroup : public deqp::TestCaseGroup
573 {
574 public:
CoherentBlendTestCaseGroup(deqp::Context & context,glu::GLSLVersion glslVersion)575 CoherentBlendTestCaseGroup(deqp::Context& context, glu::GLSLVersion glslVersion)
576 : TestCaseGroup(context, "test_coherency", ""), m_glslVersion(glslVersion)
577 {
578 }
579
init(void)580 void init(void)
581 {
582 addChild(
583 new CoherentBlendTest(m_context, "mixedSequence", m_glslVersion, 4, DE_LENGTH_OF_ARRAY(s_mixed), s_mixed));
584 addChild(new CoherentBlendTest(m_context, "multiplySequence", m_glslVersion, 1, DE_LENGTH_OF_ARRAY(s_multiply),
585 s_multiply));
586 }
587
588 private:
589 struct BlendStep;
590
591 class CoherentBlendTest : public deqp::TestCase
592 {
593 public:
CoherentBlendTest(deqp::Context & context,const char * name,glu::GLSLVersion glslVersion,int repeatCount,int numSteps,const BlendStep * steps)594 CoherentBlendTest(deqp::Context& context, const char* name, glu::GLSLVersion glslVersion, int repeatCount,
595 int numSteps, const BlendStep* steps)
596 : TestCase(context, name, "")
597 , m_glslVersion(glslVersion)
598 , m_repeatCount(repeatCount)
599 , m_numSteps(numSteps)
600 , m_steps(steps)
601 {
602 DE_ASSERT(repeatCount > 0 && numSteps > 0 && steps);
603 }
604
605 IterateResult iterate(void);
606
607 private:
608 glu::GLSLVersion m_glslVersion;
609 int m_repeatCount;
610 int m_numSteps;
611 const BlendStep* m_steps;
612 };
613
614 struct BlendStep
615 {
616 glw::GLenum mode;
617 glw::GLfloat src[4]; // rgba
618 };
619
620 // Blend sequences.
621 static const BlendStep s_mixed[11];
622 static const BlendStep s_multiply[7];
623
624 glu::GLSLVersion m_glslVersion;
625 };
626
627 const CoherentBlendTestCaseGroup::BlendStep CoherentBlendTestCaseGroup::s_mixed[] = {
628 { GL_LIGHTEN_KHR, { 0.250f, 0.375f, 1.000f, 1.000f } }, // => (0.250, 0.375, 1.000, 1.000) (from src)
629 { GL_OVERLAY_KHR, { 1.000f, 1.000f, 1.000f, 1.000f } }, // => ~(0.500, 0.750, 1.000, 1.000)
630 { GL_HARDLIGHT_KHR, { 0.750f, 0.750f, 0.250f, 1.000f } }, // => ~(0.750, 1.000, 0.500, 1.000)
631 { GL_DARKEN_KHR, { 0.250f, 0.250f, 0.250f, 1.000f } }, // => (0.250, 0.250, 0.250, 1.000) (from src)
632 { GL_COLORDODGE_KHR, { 0.750f, 0.875f, 1.000f, 1.000f } }, // => ~(1.000, 1.000, 1.000, 1.000)
633 { GL_MULTIPLY_KHR, { 0.500f, 0.500f, 0.500f, 1.000f } }, // => ~(0.500, 0.500, 0.500, 1.000)
634 { GL_SCREEN_KHR, { 0.500f, 0.500f, 0.500f, 1.000f } }, // => ~(0.750, 0.750, 0.750, 1.000)
635 { GL_DARKEN_KHR, { 0.250f, 0.500f, 0.500f, 1.000f } }, // => (0.250, 0.500, 0.500, 1.000) (from src)
636 { GL_DIFFERENCE_KHR, { 0.000f, 0.875f, 0.125f, 1.000f } }, // => ~(0.250, 0.375, 0.375, 1.000)
637 { GL_EXCLUSION_KHR, { 1.000f, 0.500f, 0.750f, 1.000f } }, // => ~(0.750, 0.500, 0.563, 1.000)
638 { GL_DARKEN_KHR, { 0.125f, 0.125f, 0.125f, 1.000f } }, // => (0.125, 0.125, 0.125, 1.000) (from src)
639 // Last row is unique and "accurate" since it comes from the source.
640 // That means so that it can be easily tested for correctness.
641 };
642
643 const CoherentBlendTestCaseGroup::BlendStep CoherentBlendTestCaseGroup::s_multiply[] = {
644 { GL_LIGHTEN_KHR, { 1.000f, 1.000f, 1.000f, 1.000f } }, { GL_MULTIPLY_KHR, { 0.500f, 0.500f, 0.500f, 1.000f } },
645 { GL_MULTIPLY_KHR, { 0.500f, 0.500f, 0.500f, 1.000f } }, { GL_MULTIPLY_KHR, { 0.500f, 0.500f, 0.500f, 1.000f } },
646 { GL_MULTIPLY_KHR, { 0.500f, 0.500f, 0.500f, 1.000f } }, { GL_MULTIPLY_KHR, { 0.500f, 0.500f, 0.500f, 1.000f } },
647 { GL_MULTIPLY_KHR, { 0.500f, 0.500f, 0.500f, 1.000f } }, // ~4 in 8bits
648 };
649
iterate(void)650 CoherentBlendTestCaseGroup::CoherentBlendTest::IterateResult CoherentBlendTestCaseGroup::CoherentBlendTest::iterate(
651 void)
652 {
653 static const int dim = 1024;
654 const tcu::RenderTarget& rt = m_context.getRenderContext().getRenderTarget();
655 const tcu::PixelFormat& pf = rt.getPixelFormat();
656 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
657 TestLog& log = m_testCtx.getLog();
658
659 // Check that extension is supported.
660 if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
661 {
662 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
663 return STOP;
664 }
665
666 bool needBarrier = !IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced_coherent");
667
668 tcu::Vec4 dstCol(0.f, 0.f, 0.f, 0.f);
669
670 FBOSentry fbo(gl, dim, dim, GL_RGBA8);
671
672 // Setup progra
673 std::string frgSrc = GetSolidShader("blend_support_all_equations", glu::getGLSLVersionDeclaration(m_glslVersion));
674 glu::ShaderProgram p(m_context.getRenderContext(),
675 glu::makeVtxFragSources(GetDef2DVtxSrc(m_glslVersion).c_str(), frgSrc.c_str()));
676 if (!p.isOk())
677 {
678 log << p;
679 TCU_FAIL("Compile failed");
680 }
681 gl.useProgram(p.getProgram());
682 GLU_EXPECT_NO_ERROR(gl.getError(), "Program failed");
683
684 glu::VertexArrayBinding posBinding = glu::va::Float("aPos", 2, 4, 0, &s_pos[0]);
685
686 // Enable blending.
687 gl.disable(GL_DITHER);
688 gl.enable(GL_BLEND);
689
690 // Clear.
691 gl.clearColor(dstCol[0], dstCol[1], dstCol[2], dstCol[3]);
692 gl.clear(GL_COLOR_BUFFER_BIT);
693
694 // Blend barrier.
695 if (needBarrier)
696 gl.blendBarrier();
697
698 // Repeat block.
699 for (int i = 0; i < m_repeatCount; i++)
700 // Loop blending steps.
701 for (int j = 0; j < m_numSteps; j++)
702 {
703 const BlendStep& s = m_steps[j];
704 tcu::Vec4 srcCol(s.src[0], s.src[1], s.src[2], s.src[3]);
705 tcu::Vec4 refCol = Blend(s.mode, srcCol, dstCol);
706 dstCol = refCol;
707
708 // Set blend equation.
709 gl.blendEquation(s.mode);
710 GLU_EXPECT_NO_ERROR(gl.getError(), "BlendEquation failed");
711
712 // Set source color.
713 gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uSrcCol"), srcCol[0], srcCol[1], srcCol[2], srcCol[3]);
714 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniforms failed");
715
716 // Draw.
717 glu::draw(m_context.getRenderContext(), p.getProgram(), 1, &posBinding,
718 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0]));
719 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
720
721 // Blend barrier.
722 if (needBarrier)
723 gl.blendBarrier();
724 }
725
726 // Read the results.
727 glw::GLubyte* result = new glw::GLubyte[4 * dim * dim];
728 gl.readPixels(0, 0, dim, dim, GL_RGBA, GL_UNSIGNED_BYTE, result);
729 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed");
730
731 // Check that first pixel is ok.
732 tcu::RGBA res = tcu::RGBA::fromBytes(result);
733 tcu::RGBA ref = pf.convertColor(tcu::RGBA(dstCol));
734 tcu::RGBA threshold = pf.getColorThreshold() + pf.getColorThreshold();
735 bool firstOk = tcu::compareThreshold(ref, res, threshold);
736
737 // Check that all pixels are the same as the first one.
738 bool allSame = true;
739 for (int i = 0; i < dim * (dim - 1); i++)
740 allSame = allSame && (0 == memcmp(result, result + (i * 4), 4));
741
742 bool pass = firstOk && allSame;
743 if (!pass)
744 {
745 log << TestLog::Message << "Exceeds: " << threshold << " diff:" << tcu::computeAbsDiff(ref, res)
746 << " res:" << res << " ref:" << tcu::RGBA(dstCol) << TestLog::EndMessage;
747 }
748
749 delete[] result;
750
751 m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail (results differ)");
752 return STOP;
753 }
754
755 class BlendTestCaseGroup : public deqp::TestCaseGroup
756 {
757 public:
758 enum QualifierType
759 {
760 MATCHING_QUALIFIER, // Use single qualifier that matches used blending mode.
761 ALL_QUALIFIER // Use "all_equations" qualifier.
762 };
763
BlendTestCaseGroup(deqp::Context & context,glu::GLSLVersion glslVersion,QualifierType qualifierType)764 BlendTestCaseGroup(deqp::Context& context, glu::GLSLVersion glslVersion, QualifierType qualifierType)
765 : TestCaseGroup(context, (qualifierType == ALL_QUALIFIER) ? "blend_all" : "blend_specific",
766 "Test all added blends.")
767 , m_glslVersion(glslVersion)
768 , m_useAllQualifier(qualifierType == ALL_QUALIFIER)
769 {
770 DE_ASSERT(qualifierType == MATCHING_QUALIFIER || qualifierType == ALL_QUALIFIER);
771 }
772
init(void)773 void init(void)
774 {
775 // Pump individual modes.
776 for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_modes); i++)
777 {
778 addChild(new BlendTest(m_context, m_glslVersion, s_modes[i], m_useAllQualifier,
779 DE_LENGTH_OF_ARRAY(s_common) / 8, s_common, DE_LENGTH_OF_ARRAY(s_rgb10a2) / 8, s_rgb10a2));
780 }
781 }
782
783 private:
784 glu::GLSLVersion m_glslVersion;
785 bool m_useAllQualifier;
786
787 class BlendTest : public deqp::TestCase
788 {
789 public:
BlendTest(deqp::Context & context,glu::GLSLVersion glslVersion,glw::GLenum mode,bool useAllQualifier,int numColors,const glw::GLfloat * colors,int numSpecificColors,const glw::GLfloat * specificColors)790 BlendTest(deqp::Context& context, glu::GLSLVersion glslVersion, glw::GLenum mode, bool useAllQualifier,
791 int numColors, const glw::GLfloat* colors, int numSpecificColors, const glw::GLfloat* specificColors)
792 : TestCase(context, (std::string(GetModeStr(mode)) + (useAllQualifier ? "_all_qualifier" : "")).c_str(),
793 "Test new blend modes for correctness.")
794 , m_glslVersion(glslVersion)
795 , m_mode(mode)
796 , m_useAllQualifier(useAllQualifier)
797 , m_numColors(numColors)
798 , m_colors(colors)
799 , m_numSpecificColors(numSpecificColors)
800 , m_specificColors(specificColors)
801 , m_useRGB10A2Data(GL_FALSE)
802 {
803 }
804
805 IterateResult iterate(void);
806
807 private:
808 void getTestColors(int index, tcu::Vec4& src, tcu::Vec4& dst) const;
809 void getCoordinates(int index, int& x, int& y) const;
810
811 glu::GLSLVersion m_glslVersion;
812 glw::GLenum m_mode;
813 bool m_useAllQualifier;
814 int m_numColors;
815 const glw::GLfloat* m_colors;
816 int m_numSpecificColors;
817 const glw::GLfloat* m_specificColors;
818 bool m_useRGB10A2Data;
819 };
820
821 static const glw::GLfloat s_common[46 * 8];
822 static const glw::GLfloat s_rgb10a2[42 * 8];
823 };
824
825 // Alpha values for pre-multiplied colors.
826 static const float A1 = 0.750f; // Between 1 and 0.5
827 static const float A2 = 0.375f; // Between 0.5 and 0.25
828 static const float A3 = 0.125f; // Between 0.25 and 0.0
829
830 const glw::GLfloat BlendTestCaseGroup::s_common[] = {
831 // Test that pre-multiplied is converted correctly.
832 // Should not test invalid premultiplied colours (1, 1, 1, 0).
833 1.000f, 0.750f, 0.500f, 1.00f, 0.000f, 0.000f, 0.000f, 0.00f, 0.250f, 0.125f, 0.000f, 1.00f, 0.000f, 0.000f, 0.000f,
834 0.00f,
835
836 // Test clamping.
837 1.000f, 0.750f, 0.500f, 1.00f, -0.125f, -0.125f, -0.125f, 1.00f, 0.250f, 0.125f, 0.000f, 1.00f, -0.125f, -0.125f,
838 -0.125f, 1.00f, 1.000f, 0.750f, 0.500f, 1.00f, 1.125f, 1.125f, 1.125f, 1.00f, 0.250f, 0.125f, 0.000f, 1.00f, 1.125f,
839 1.125f, 1.125f, 1.00f,
840
841 // Cobinations that test other branches of blend equations.
842 1.000f, 0.750f, 0.500f, 1.00f, 1.000f, 1.000f, 1.000f, 1.00f, 0.250f, 0.125f, 0.000f, 1.00f, 1.000f, 1.000f, 1.000f,
843 1.00f, 1.000f, 0.750f, 0.500f, 1.00f, 0.500f, 0.500f, 0.500f, 1.00f, 0.250f, 0.125f, 0.000f, 1.00f, 0.500f, 0.500f,
844 0.500f, 1.00f, 1.000f, 0.750f, 0.500f, 1.00f, 0.250f, 0.250f, 0.250f, 1.00f, 0.250f, 0.125f, 0.000f, 1.00f, 0.250f,
845 0.250f, 0.250f, 1.00f, 1.000f, 0.750f, 0.500f, 1.00f, 0.125f, 0.125f, 0.125f, 1.00f, 0.250f, 0.125f, 0.000f, 1.00f,
846 0.125f, 0.125f, 0.125f, 1.00f, 1.000f, 0.750f, 0.500f, 1.00f, 0.000f, 0.000f, 0.000f, 1.00f, 0.250f, 0.125f, 0.000f,
847 1.00f, 0.000f, 0.000f, 0.000f, 1.00f,
848
849 // Above block with few different pre-multiplied alpha values.
850 A1 * 1.000f, A1 * 0.750f, A1 * 0.500f, A1 * 1.00f, A1 * 1.000f, A1 * 1.000f, A1 * 1.000f, A1 * 1.00f, A1 * 0.250f,
851 A1 * 0.125f, A1 * 0.000f, A1 * 1.00f, A1 * 1.000f, A1 * 1.000f, A1 * 1.000f, A1 * 1.00f, A1 * 1.000f, A1 * 0.750f,
852 A1 * 0.500f, A1 * 1.00f, A1 * 0.500f, A1 * 0.500f, A1 * 0.500f, A1 * 1.00f, A1 * 0.250f, A1 * 0.125f, A1 * 0.000f,
853 A1 * 1.00f, A1 * 0.500f, A1 * 0.500f, A1 * 0.500f, A1 * 1.00f, A1 * 1.000f, A1 * 0.750f, A1 * 0.500f, A1 * 1.00f,
854 A1 * 0.250f, A1 * 0.250f, A1 * 0.250f, A1 * 1.00f, A1 * 0.250f, A1 * 0.125f, A1 * 0.000f, A1 * 1.00f, A1 * 0.250f,
855 A1 * 0.250f, A1 * 0.250f, A1 * 1.00f, A1 * 1.000f, A1 * 0.750f, A1 * 0.500f, A1 * 1.00f, A1 * 0.125f, A1 * 0.125f,
856 A1 * 0.125f, A1 * 1.00f, A1 * 0.250f, A1 * 0.125f, A1 * 0.000f, A1 * 1.00f, A1 * 0.125f, A1 * 0.125f, A1 * 0.125f,
857 A1 * 1.00f, A1 * 1.000f, A1 * 0.750f, A1 * 0.500f, A1 * 1.00f, A1 * 0.000f, A1 * 0.000f, A1 * 0.000f, A1 * 1.00f,
858 A1 * 0.250f, A1 * 0.125f, A1 * 0.000f, A1 * 1.00f, A1 * 0.000f, A1 * 0.000f, A1 * 0.000f, A1 * 1.00f,
859
860 A2 * 1.000f, A2 * 0.750f, A2 * 0.500f, A2 * 1.00f, A2 * 1.000f, A2 * 1.000f, A2 * 1.000f, A2 * 1.00f, A2 * 0.250f,
861 A2 * 0.125f, A2 * 0.000f, A2 * 1.00f, A2 * 1.000f, A2 * 1.000f, A2 * 1.000f, A2 * 1.00f, A2 * 1.000f, A2 * 0.750f,
862 A2 * 0.500f, A2 * 1.00f, A2 * 0.500f, A2 * 0.500f, A2 * 0.500f, A2 * 1.00f, A2 * 0.250f, A2 * 0.125f, A2 * 0.000f,
863 A2 * 1.00f, A2 * 0.500f, A2 * 0.500f, A2 * 0.500f, A2 * 1.00f, A2 * 1.000f, A2 * 0.750f, A2 * 0.500f, A2 * 1.00f,
864 A2 * 0.250f, A2 * 0.250f, A2 * 0.250f, A2 * 1.00f, A2 * 0.250f, A2 * 0.125f, A2 * 0.000f, A2 * 1.00f, A2 * 0.250f,
865 A2 * 0.250f, A2 * 0.250f, A2 * 1.00f, A2 * 1.000f, A2 * 0.750f, A2 * 0.500f, A2 * 1.00f, A2 * 0.125f, A2 * 0.125f,
866 A2 * 0.125f, A2 * 1.00f, A2 * 0.250f, A2 * 0.125f, A2 * 0.000f, A2 * 1.00f, A2 * 0.125f, A2 * 0.125f, A2 * 0.125f,
867 A2 * 1.00f, A2 * 1.000f, A2 * 0.750f, A2 * 0.500f, A2 * 1.00f, A2 * 0.000f, A2 * 0.000f, A2 * 0.000f, A2 * 1.00f,
868 A2 * 0.250f, A2 * 0.125f, A2 * 0.000f, A2 * 1.00f, A2 * 0.000f, A2 * 0.000f, A2 * 0.000f, A2 * 1.00f,
869
870 A3 * 1.000f, A3 * 0.750f, A3 * 0.500f, A3 * 1.00f, A3 * 1.000f, A3 * 1.000f, A3 * 1.000f, A3 * 1.00f, A3 * 0.250f,
871 A3 * 0.125f, A3 * 0.000f, A3 * 1.00f, A3 * 1.000f, A3 * 1.000f, A3 * 1.000f, A3 * 1.00f, A3 * 1.000f, A3 * 0.750f,
872 A3 * 0.500f, A3 * 1.00f, A3 * 0.500f, A3 * 0.500f, A3 * 0.500f, A3 * 1.00f, A3 * 0.250f, A3 * 0.125f, A3 * 0.000f,
873 A3 * 1.00f, A3 * 0.500f, A3 * 0.500f, A3 * 0.500f, A3 * 1.00f, A3 * 1.000f, A3 * 0.750f, A3 * 0.500f, A3 * 1.00f,
874 A3 * 0.250f, A3 * 0.250f, A3 * 0.250f, A3 * 1.00f, A3 * 0.250f, A3 * 0.125f, A3 * 0.000f, A3 * 1.00f, A3 * 0.250f,
875 A3 * 0.250f, A3 * 0.250f, A3 * 1.00f, A3 * 1.000f, A3 * 0.750f, A3 * 0.500f, A3 * 1.00f, A3 * 0.125f, A3 * 0.125f,
876 A3 * 0.125f, A3 * 1.00f, A3 * 0.250f, A3 * 0.125f, A3 * 0.000f, A3 * 1.00f, A3 * 0.125f, A3 * 0.125f, A3 * 0.125f,
877 A3 * 1.00f, A3 * 1.000f, A3 * 0.750f, A3 * 0.500f, A3 * 1.00f, A3 * 0.000f, A3 * 0.000f, A3 * 0.000f, A3 * 1.00f,
878 A3 * 0.250f, A3 * 0.125f, A3 * 0.000f, A3 * 1.00f, A3 * 0.000f, A3 * 0.000f, A3 * 0.000f, A3 * 1.00f,
879 };
880
881 // Some data in the s_common array are invalid for BlendHSLHue and BlendHSLSaturation function when the render target
882 // format is GL_RGB10A2. These data will lead to undefine behavior(divide 0). Remove those data and create a new array
883 // to test this format and the blend functions.
884 const glw::GLfloat BlendTestCaseGroup::s_rgb10a2[] = {
885 // Test that pre-multiplied is converted correctly.
886 // Should not test invalid premultiplied colours (1, 1, 1, 0).
887 1.000f, 0.750f, 0.500f, 1.00f, 0.000f, 0.000f, 0.000f, 0.00f, 0.250f, 0.125f, 0.000f, 1.00f, 0.000f, 0.000f, 0.000f,
888 0.00f,
889
890 // Test clamping.
891 1.000f, 0.750f, 0.500f, 1.00f, -0.125f, -0.125f, -0.125f, 1.00f, 0.250f, 0.125f, 0.000f, 1.00f, -0.125f, -0.125f,
892 -0.125f, 1.00f, 1.000f, 0.750f, 0.500f, 1.00f, 1.125f, 1.125f, 1.125f, 1.00f, 0.250f, 0.125f, 0.000f, 1.00f, 1.125f,
893 1.125f, 1.125f, 1.00f,
894
895 // Cobinations that test other branches of blend equations.
896 1.000f, 0.750f, 0.500f, 1.00f, 1.000f, 1.000f, 1.000f, 1.00f, 0.250f, 0.125f, 0.000f, 1.00f, 1.000f, 1.000f, 1.000f,
897 1.00f, 1.000f, 0.750f, 0.500f, 1.00f, 0.500f, 0.500f, 0.500f, 1.00f, 0.250f, 0.125f, 0.000f, 1.00f, 0.500f, 0.500f,
898 0.500f, 1.00f, 1.000f, 0.750f, 0.500f, 1.00f, 0.250f, 0.250f, 0.250f, 1.00f, 0.250f, 0.125f, 0.000f, 1.00f, 0.250f,
899 0.250f, 0.250f, 1.00f, 1.000f, 0.750f, 0.500f, 1.00f, 0.125f, 0.125f, 0.125f, 1.00f, 0.250f, 0.125f, 0.000f, 1.00f,
900 0.125f, 0.125f, 0.125f, 1.00f, 1.000f, 0.750f, 0.500f, 1.00f, 0.000f, 0.000f, 0.000f, 1.00f, 0.250f, 0.125f, 0.000f,
901 1.00f, 0.000f, 0.000f, 0.000f, 1.00f,
902
903 // Above block with few different pre-multiplied alpha values.
904 A1 * 1.000f, A1 * 0.750f, A1 * 0.500f, A1 * 1.00f, A1 * 0.500f, A1 * 0.500f, A1 * 0.500f, A1 * 1.00f, A1 * 0.250f,
905 A1 * 0.125f, A1 * 0.000f, A1 * 1.00f, A1 * 0.500f, A1 * 0.500f, A1 * 0.500f, A1 * 1.00f, A1 * 1.000f, A1 * 0.750f,
906 A1 * 0.500f, A1 * 1.00f, A1 * 0.250f, A1 * 0.250f, A1 * 0.250f, A1 * 1.00f, A1 * 0.250f, A1 * 0.125f, A1 * 0.000f,
907 A1 * 1.00f, A1 * 0.250f, A1 * 0.250f, A1 * 0.250f, A1 * 1.00f, A1 * 1.000f, A1 * 0.750f, A1 * 0.500f, A1 * 1.00f,
908 A1 * 0.125f, A1 * 0.125f, A1 * 0.125f, A1 * 1.00f, A1 * 0.250f, A1 * 0.125f, A1 * 0.000f, A1 * 1.00f, A1 * 0.125f,
909 A1 * 0.125f, A1 * 0.125f, A1 * 1.00f, A1 * 1.000f, A1 * 0.750f, A1 * 0.500f, A1 * 1.00f, A1 * 0.000f, A1 * 0.000f,
910 A1 * 0.000f, A1 * 1.00f, A1 * 0.250f, A1 * 0.125f, A1 * 0.000f, A1 * 1.00f, A1 * 0.000f, A1 * 0.000f, A1 * 0.000f,
911 A1 * 1.00f,
912
913 A2 * 1.000f, A2 * 0.750f, A2 * 0.500f, A2 * 1.00f, A2 * 0.500f, A2 * 0.500f, A2 * 0.500f, A2 * 1.00f, A2 * 0.250f,
914 A2 * 0.125f, A2 * 0.000f, A2 * 1.00f, A2 * 0.500f, A2 * 0.500f, A2 * 0.500f, A2 * 1.00f, A2 * 1.000f, A2 * 0.750f,
915 A2 * 0.500f, A2 * 1.00f, A2 * 0.250f, A2 * 0.250f, A2 * 0.250f, A2 * 1.00f, A2 * 0.250f, A2 * 0.125f, A2 * 0.000f,
916 A2 * 1.00f, A2 * 0.250f, A2 * 0.250f, A2 * 0.250f, A2 * 1.00f, A2 * 1.000f, A2 * 0.750f, A2 * 0.500f, A2 * 1.00f,
917 A2 * 0.125f, A2 * 0.125f, A2 * 0.125f, A2 * 1.00f, A2 * 0.250f, A2 * 0.125f, A2 * 0.000f, A2 * 1.00f, A2 * 0.125f,
918 A2 * 0.125f, A2 * 0.125f, A2 * 1.00f, A2 * 1.000f, A2 * 0.750f, A2 * 0.500f, A2 * 1.00f, A2 * 0.000f, A2 * 0.000f,
919 A2 * 0.000f, A2 * 1.00f, A2 * 0.250f, A2 * 0.125f, A2 * 0.000f, A2 * 1.00f, A2 * 0.000f, A2 * 0.000f, A2 * 0.000f,
920 A2 * 1.00f,
921
922 A3 * 1.000f, A3 * 0.750f, A3 * 0.500f, A3 * 1.00f, A3 * 1.000f, A3 * 1.000f, A3 * 1.000f, A3 * 1.00f, A3 * 0.250f,
923 A3 * 0.125f, A3 * 0.000f, A3 * 1.00f, A3 * 1.000f, A3 * 1.000f, A3 * 1.000f, A3 * 1.00f, A3 * 1.000f, A3 * 0.750f,
924 A3 * 0.500f, A3 * 1.00f, A3 * 0.500f, A3 * 0.500f, A3 * 0.500f, A3 * 1.00f, A3 * 0.250f, A3 * 0.125f, A3 * 0.000f,
925 A3 * 1.00f, A3 * 0.500f, A3 * 0.500f, A3 * 0.500f, A3 * 1.00f, A3 * 1.000f, A3 * 0.750f, A3 * 0.500f, A3 * 1.00f,
926 A3 * 0.250f, A3 * 0.250f, A3 * 0.250f, A3 * 1.00f, A3 * 0.250f, A3 * 0.125f, A3 * 0.000f, A3 * 1.00f, A3 * 0.250f,
927 A3 * 0.250f, A3 * 0.250f, A3 * 1.00f, A3 * 1.000f, A3 * 0.750f, A3 * 0.500f, A3 * 1.00f, A3 * 0.125f, A3 * 0.125f,
928 A3 * 0.125f, A3 * 1.00f, A3 * 0.250f, A3 * 0.125f, A3 * 0.000f, A3 * 1.00f, A3 * 0.125f, A3 * 0.125f, A3 * 0.125f,
929 A3 * 1.00f, A3 * 1.000f, A3 * 0.750f, A3 * 0.500f, A3 * 1.00f, A3 * 0.000f, A3 * 0.000f, A3 * 0.000f, A3 * 1.00f,
930 A3 * 0.250f, A3 * 0.125f, A3 * 0.000f, A3 * 1.00f, A3 * 0.000f, A3 * 0.000f, A3 * 0.000f, A3 * 1.00f,
931 };
932
MaskChannels(const tcu::PixelFormat & pf,const tcu::Vec4 & v)933 static tcu::Vec4 MaskChannels(const tcu::PixelFormat& pf, const tcu::Vec4& v)
934 {
935 return tcu::Vec4(pf.redBits > 0 ? v[0] : 0.f, pf.greenBits > 0 ? v[1] : 0.f, pf.blueBits > 0 ? v[2] : 0.f,
936 pf.alphaBits > 0 ? v[3] : 1.f);
937 }
938
939 //
940 // Quantize the input colour by the colour bit depth for each channel.
941 //
QuantizeChannels(const tcu::PixelFormat & pf,const tcu::Vec4 & v)942 static tcu::Vec4 QuantizeChannels(const tcu::PixelFormat& pf, const tcu::Vec4& v)
943 {
944 float maxChanel[4] = { static_cast<float>(1 << pf.redBits) - 1.0f, static_cast<float>(1 << pf.greenBits) - 1.0f,
945 static_cast<float>(1 << pf.blueBits) - 1.0f, static_cast<float>(1 << pf.alphaBits) - 1.0f };
946
947 return tcu::Vec4(static_cast<float>((unsigned int)(v[0] * maxChanel[0])) / maxChanel[0],
948 static_cast<float>((unsigned int)(v[1] * maxChanel[1])) / maxChanel[1],
949 static_cast<float>((unsigned int)(v[2] * maxChanel[2])) / maxChanel[2],
950 pf.alphaBits ? static_cast<float>((unsigned int)(v[3] * maxChanel[3])) / maxChanel[3] : 1.0f);
951 }
952
getTestColors(int index,tcu::Vec4 & src,tcu::Vec4 & dst) const953 void BlendTestCaseGroup::BlendTest::getTestColors(int index, tcu::Vec4& src, tcu::Vec4& dst) const
954 {
955 DE_ASSERT(0 <= index && index < (m_useRGB10A2Data ? m_numSpecificColors : m_numColors));
956
957 const tcu::RenderTarget& rt = m_context.getRenderContext().getRenderTarget();
958 const tcu::PixelFormat& pf = rt.getPixelFormat();
959 const glw::GLfloat* s = (m_useRGB10A2Data ? m_specificColors : m_colors) + 8 * index;
960
961 src = MaskChannels(pf, tcu::Vec4(s[0], s[1], s[2], s[3]));
962 dst = MaskChannels(pf, tcu::Vec4(s[4], s[5], s[6], s[7]));
963 src = tcu::clamp(src, tcu::Vec4(0.f), tcu::Vec4(1.f));
964 dst = tcu::clamp(dst, tcu::Vec4(0.f), tcu::Vec4(1.f));
965
966 // Quantize the destination channels
967 // this matches what implementation does on render target write
968 dst = QuantizeChannels(pf, dst);
969 }
970
getCoordinates(int index,int & x,int & y) const971 void BlendTestCaseGroup::BlendTest::getCoordinates(int index, int& x, int& y) const
972 {
973 const tcu::RenderTarget& rt = m_context.getRenderContext().getRenderTarget();
974 y = index / rt.getWidth();
975 x = index % rt.getWidth();
976 }
977
iterate(void)978 BlendTestCaseGroup::BlendTest::IterateResult BlendTestCaseGroup::BlendTest::iterate(void)
979 {
980 const tcu::RenderTarget& rt = m_context.getRenderContext().getRenderTarget();
981 const tcu::PixelFormat& pf = rt.getPixelFormat();
982 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
983 TestLog& log = m_testCtx.getLog();
984
985 // Check that extension is supported.
986 if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
987 {
988 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
989 return STOP;
990 }
991
992 if ((GetBlendFunc(m_mode) == BlendHSLHue || GetBlendFunc(m_mode) == BlendHSLSaturation)
993 && (pf.redBits == 10 && pf.greenBits == 10 && pf.blueBits == 10 && pf.alphaBits == 2))
994 {
995 m_useRGB10A2Data = GL_TRUE;
996 }
997
998 // Setup program.
999 std::string frgSrc =
1000 GetSolidShader(m_useAllQualifier ? "blend_support_all_equations" : GetLayoutQualifierStr(m_mode),
1001 glu::getGLSLVersionDeclaration(m_glslVersion));
1002 glu::ShaderProgram p(m_context.getRenderContext(),
1003 glu::makeVtxFragSources(GetDef2DVtxSrc(m_glslVersion).c_str(), frgSrc.c_str()));
1004 if (!p.isOk())
1005 {
1006 log << p;
1007 TCU_FAIL("Compile failed");
1008 }
1009 gl.useProgram(p.getProgram());
1010 GLU_EXPECT_NO_ERROR(gl.getError(), "Program failed");
1011
1012 glu::VertexArrayBinding posBinding = glu::va::Float("aPos", 2, 4, 0, &s_pos[0]);
1013
1014 // Enable blending and set blend equation.
1015 gl.disable(GL_DITHER);
1016 gl.enable(GL_SCISSOR_TEST);
1017 gl.enable(GL_BLEND);
1018 gl.blendEquation(m_mode);
1019 GLU_EXPECT_NO_ERROR(gl.getError(), "BlendEquation failed");
1020
1021 bool needBarrier = !IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced_coherent");
1022
1023 // Render loop.
1024 for (int colorIndex = 0; colorIndex < (m_useRGB10A2Data ? m_numSpecificColors : m_numColors); colorIndex++)
1025 {
1026 tcu::Vec4 srcCol, dstCol;
1027 getTestColors(colorIndex, srcCol, dstCol);
1028
1029 // Get pixel to blend.
1030 int x, y;
1031 getCoordinates(colorIndex, x, y);
1032 gl.scissor(x, y, 1, 1);
1033
1034 // Clear to destination color.
1035 gl.clearColor(dstCol[0], dstCol[1], dstCol[2], dstCol[3]);
1036 gl.clear(GL_COLOR_BUFFER_BIT);
1037 if (needBarrier)
1038 gl.blendBarrier();
1039
1040 // Set source color.
1041 gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uSrcCol"), srcCol[0], srcCol[1], srcCol[2], srcCol[3]);
1042 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniforms failed");
1043
1044 // Draw.
1045 glu::draw(m_context.getRenderContext(), p.getProgram(), 1, &posBinding,
1046 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0]));
1047 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
1048 if (needBarrier)
1049 gl.blendBarrier();
1050 }
1051
1052 // Read the results.
1053 const int w = rt.getWidth();
1054 const int h = rt.getHeight();
1055 glw::GLubyte* resultBytes = new glw::GLubyte[4 * w * h];
1056 gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
1057 gl.readPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, resultBytes);
1058 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed");
1059
1060 bool pass = true;
1061 for (int colorIndex = 0; colorIndex < (m_useRGB10A2Data ? m_numSpecificColors : m_numColors); colorIndex++)
1062 {
1063 tcu::Vec4 srcCol, dstCol;
1064 getTestColors(colorIndex, srcCol, dstCol);
1065
1066 // Get result and calculate reference.
1067 int x, y;
1068 getCoordinates(colorIndex, x, y);
1069
1070 tcu::Vec4 refCol = Blend(m_mode, srcCol, dstCol);
1071 tcu::RGBA ref = pf.convertColor(tcu::RGBA(refCol));
1072 tcu::RGBA res = tcu::RGBA::fromBytes(resultBytes + 4 * (x + w * y));
1073 tcu::RGBA tmp = pf.getColorThreshold();
1074 tcu::RGBA threshold = tcu::RGBA(std::min(2 + 2 * tmp.getRed(), 255), std::min(2 + 2 * tmp.getGreen(), 255),
1075 std::min(2 + 2 * tmp.getBlue(), 255), std::min(2 + 2 * tmp.getAlpha(), 255));
1076 bool pixelOk = tcu::compareThreshold(ref, res, threshold);
1077 pass = pass && pixelOk;
1078 if (!pixelOk)
1079 {
1080 log << TestLog::Message << "(" << x << "," << y << ") "
1081 << "(" << colorIndex << ") "
1082 << "Exceeds: " << threshold << " diff:" << tcu::computeAbsDiff(ref, res) << " res:" << res
1083 << " ref:" << ref << " dst:" << tcu::RGBA(dstCol) << " src:" << tcu::RGBA(srcCol)
1084 << TestLog::EndMessage;
1085 }
1086 }
1087
1088 m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail (results differ)");
1089 delete[] resultBytes;
1090 return STOP;
1091 }
1092
1093 /*
1094 * From 'Other' part of the spec:
1095 * "Test different behaviors for GLSL #extension
1096 * GL_XXX_blend_equation_advanced"
1097 *
1098 * - require : Covered by "Blend" tests.
1099 * - enable : Use layout modifier from GL_KHR_blend_equation_advanced and
1100 * expect compile to succeed. (warn if not supported)
1101 * - warn : Use layout modifier from GL_KHR_blend_equation_advanced and
1102 * expect compile to succeed. (work, but issue warning)
1103 * - disable : Use layout modifier from GL_KHR_blend_equation_advanced and
1104 * expect compile to fail with error.
1105 *
1106 */
1107 class ExtensionDirectiveTestCaseGroup : public deqp::TestCaseGroup
1108 {
1109 public:
ExtensionDirectiveTestCaseGroup(deqp::Context & context,glu::GLSLVersion glslVersion)1110 ExtensionDirectiveTestCaseGroup(deqp::Context& context, glu::GLSLVersion glslVersion)
1111 : TestCaseGroup(context, "extension_directive", "Test #extension directive."), m_glslVersion(glslVersion)
1112 {
1113 }
1114
init(void)1115 void init(void)
1116 {
1117 addChild(new ExtensionDirectiveTestCase(m_context, m_glslVersion, "disable"));
1118 addChild(new ExtensionDirectiveTestCase(m_context, m_glslVersion, "enable"));
1119 addChild(new ExtensionDirectiveTestCase(m_context, m_glslVersion, "warn"));
1120 }
1121
1122 private:
1123 class ExtensionDirectiveTestCase : public deqp::TestCase
1124 {
1125 public:
ExtensionDirectiveTestCase(deqp::Context & context,glu::GLSLVersion glslVersion,const char * behaviour)1126 ExtensionDirectiveTestCase(deqp::Context& context, glu::GLSLVersion glslVersion, const char* behaviour)
1127 : TestCase(context, (std::string("extension_directive_") + behaviour).c_str(), "Test #extension directive.")
1128 , m_glslVersion(glslVersion)
1129 , m_behaviourStr(behaviour)
1130 {
1131 // Initialize expected compiler behaviour.
1132 std::string b(behaviour);
1133 if (b == "disable")
1134 {
1135 m_requireInfoLog = true;
1136 m_requireCompile = false;
1137 }
1138 else if (b == "enable")
1139 {
1140 m_requireInfoLog = false;
1141 m_requireCompile = true;
1142 }
1143 else
1144 {
1145 DE_ASSERT(b == "warn");
1146 m_requireInfoLog = false;
1147 m_requireCompile = true;
1148 }
1149 }
1150
iterate(void)1151 IterateResult iterate(void)
1152 {
1153 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1154 TestLog& log = m_testCtx.getLog();
1155 const int dim = 4;
1156
1157 // Check that extension is supported.
1158 if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
1159 {
1160 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
1161 return STOP;
1162 }
1163
1164 FBOSentry fbo(gl, dim, dim, GL_RGBA8);
1165
1166 tcu::Vec4 dstCol(1.f, 1.f, 1.f, 1.f);
1167 tcu::Vec4 srcCol(0.f, 0.f, 0.f, 1.f);
1168
1169 // Clear to destination color.
1170 gl.clearColor(dstCol.x(), dstCol.y(), dstCol.z(), dstCol.w());
1171 gl.clear(GL_COLOR_BUFFER_BIT);
1172
1173 // Setup program.
1174 std::string directive = "#extension GL_KHR_blend_equation_advanced : " + m_behaviourStr;
1175 std::string frgSrc = GetSolidShader("blend_support_multiply", glu::getGLSLVersionDeclaration(m_glslVersion),
1176 directive.c_str());
1177 glu::ShaderProgram p(m_context.getRenderContext(),
1178 glu::makeVtxFragSources(GetDef2DVtxSrc(m_glslVersion).c_str(), frgSrc.c_str()));
1179 // If check that there is some info log if it is expected.
1180 const bool infoLogOk =
1181 m_requireInfoLog ? p.getShaderInfo(glu::SHADERTYPE_FRAGMENT).infoLog.size() > 0 : true;
1182 if (!p.isOk())
1183 {
1184 if (m_requireCompile)
1185 {
1186 log << p;
1187 TCU_FAIL("Compile failed");
1188 }
1189 else
1190 {
1191 // If shader was expected to fail, so assume info log has something.
1192 bool pass = infoLogOk;
1193 m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1194 pass ? "Pass" : "Fail. Expected info log.");
1195 }
1196 return STOP;
1197 }
1198 gl.useProgram(p.getProgram());
1199 GLU_EXPECT_NO_ERROR(gl.getError(), "Program failed");
1200
1201 // Program ok, check whether info log was as expected.
1202 if (!infoLogOk)
1203 {
1204 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail. No warnings were generated.");
1205 return STOP;
1206 }
1207
1208 // Enable blending and set blend equation.
1209 gl.disable(GL_DITHER);
1210 gl.enable(GL_BLEND);
1211 gl.blendEquation(GL_MULTIPLY_KHR);
1212 GLU_EXPECT_NO_ERROR(gl.getError(), "BlendEquation failed");
1213
1214 // Setup source color.
1215 gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uSrcCol"), srcCol.x(), srcCol.y(), srcCol.z(),
1216 srcCol.w());
1217 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform failed");
1218
1219 glu::VertexArrayBinding posBinding = glu::va::Float("aPos", 2, 4, 0, &s_pos[0]);
1220 GLU_EXPECT_NO_ERROR(gl.getError(), "Attributes failed");
1221
1222 glu::draw(m_context.getRenderContext(), p.getProgram(), 1, &posBinding,
1223 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0]));
1224 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
1225
1226 // Check the result to see that extension was actually enabled.
1227 glw::GLubyte result[4] = { 1, 2, 3, 4 };
1228 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, result);
1229 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed");
1230 bool pass = tcu::RGBA::fromBytes(result) == tcu::RGBA(0, 0, 0, 0xFF);
1231 m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail");
1232
1233 return STOP;
1234 }
1235
1236 private:
1237 glu::GLSLVersion m_glslVersion;
1238 std::string m_behaviourStr;
1239 bool m_requireInfoLog;
1240 bool m_requireCompile;
1241 };
1242
1243 glu::GLSLVersion m_glslVersion;
1244 };
1245
1246 /*
1247 * From 'Other' part of the spec:
1248 * "If XXX_blend_equation_advanced_coherent is supported, test
1249 * Each blending mode needs to be tested without specifying the proper
1250 * blend_support_[mode] or blend_support_all layout qualifier in the
1251 * fragment shader. Expect INVALID_OPERATION GL error after calling
1252 * DrawElements/Arrays."
1253 */
1254 class MissingQualifierTestGroup : public deqp::TestCaseGroup
1255 {
1256 public:
1257 enum MissingType
1258 {
1259 MISMATCH, // wrong qualifier in the shader.
1260 MISSING, // no qualifier at all.
1261 };
1262
MissingQualifierTestGroup(deqp::Context & context,glu::GLSLVersion glslVersion,MissingType missingType)1263 MissingQualifierTestGroup(deqp::Context& context, glu::GLSLVersion glslVersion, MissingType missingType)
1264 : TestCaseGroup(context, missingType == MISMATCH ? "mismatching_qualifier" : "missing_qualifier", "")
1265 , m_glslVersion(glslVersion)
1266 , m_missingType(missingType)
1267 {
1268 }
1269
init(void)1270 void init(void)
1271 {
1272 // Pump individual modes.
1273 for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_modes); i++)
1274 {
1275 const char* qualifier = m_missingType == MISSING ?
1276 DE_NULL :
1277 GetLayoutQualifierStr(s_modes[(i + 1) % DE_LENGTH_OF_ARRAY(s_modes)]);
1278 addChild(new MissingCase(m_context, m_glslVersion, s_modes[i], qualifier));
1279 }
1280 }
1281
1282 private:
1283 class MissingCase : public deqp::TestCase
1284 {
1285 public:
MissingCase(deqp::Context & context,glu::GLSLVersion glslVersion,glw::GLenum mode,const char * layoutQualifier)1286 MissingCase(deqp::Context& context, glu::GLSLVersion glslVersion, glw::GLenum mode, const char* layoutQualifier)
1287 : TestCase(context, GetModeStr(mode), "")
1288 , m_glslVersion(glslVersion)
1289 , m_mode(mode)
1290 , m_layoutQualifier(layoutQualifier)
1291 {
1292 }
1293
1294 IterateResult iterate(void);
1295
1296 private:
1297 glu::GLSLVersion m_glslVersion;
1298 glw::GLenum m_mode;
1299 const char* m_layoutQualifier; // NULL => no qualifier at all.
1300 };
1301
1302 glu::GLSLVersion m_glslVersion;
1303 MissingType m_missingType;
1304 };
1305
iterate(void)1306 MissingQualifierTestGroup::MissingCase::IterateResult MissingQualifierTestGroup::MissingCase::iterate(void)
1307 {
1308 const int dim = 4;
1309 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1310 TestLog& log = m_testCtx.getLog();
1311
1312 // Check that extension is supported.
1313 if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
1314 {
1315 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
1316 return STOP;
1317 }
1318
1319 FBOSentry fbo(gl, dim, dim, GL_RGBA8);
1320
1321 tcu::Vec4 dstCol(1.f, 1.f, 1.f, 1.f);
1322 tcu::Vec4 srcCol(0.f, 0.f, 0.f, 1.f);
1323
1324 // Clear to destination color.
1325 gl.clearColor(dstCol.x(), dstCol.y(), dstCol.z(), dstCol.w());
1326 gl.clear(GL_COLOR_BUFFER_BIT);
1327
1328 // Setup program.
1329 glu::ShaderProgram p(m_context.getRenderContext(),
1330 glu::makeVtxFragSources(
1331 GetDef2DVtxSrc(m_glslVersion).c_str(),
1332 GetSolidShader(m_layoutQualifier, glu::getGLSLVersionDeclaration(m_glslVersion)).c_str()));
1333 if (!p.isOk())
1334 {
1335 log << p;
1336 TCU_FAIL("Compile failed");
1337 }
1338
1339 gl.useProgram(p.getProgram());
1340 GLU_EXPECT_NO_ERROR(gl.getError(), "Program failed");
1341
1342 // Enable blending and set blend equation.
1343 gl.disable(GL_DITHER);
1344 gl.enable(GL_BLEND);
1345 gl.blendEquation(m_mode);
1346 GLU_EXPECT_NO_ERROR(gl.getError(), "BlendEquation failed");
1347
1348 // Setup source color.
1349 gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uSrcCol"), srcCol.x(), srcCol.y(), srcCol.z(), srcCol.w());
1350 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform failed");
1351
1352 glu::VertexArrayBinding posBinding = glu::va::Float("aPos", 2, 4, 0, &s_pos[0]);
1353 GLU_EXPECT_NO_ERROR(gl.getError(), "Attributes failed");
1354
1355 glu::draw(m_context.getRenderContext(), p.getProgram(), 1, &posBinding,
1356 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0]));
1357
1358 glw::GLenum error = gl.getError();
1359 bool pass = (error == GL_INVALID_OPERATION);
1360
1361 m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail");
1362
1363 return STOP;
1364 }
1365
1366 /*
1367 * From 'Other' part of the spec:
1368 * "If XXX_blend_equation_advanced_coherent is supported, test
1369 * BLEND_ADVANCED_COHERENT_XXX setting:
1370 * - The setting should work with Enable, Disable and IsEnable without producing errors
1371 * - Default value should be TRUE"
1372 *
1373 * 1. Test that coherent is enabled by default.
1374 * 2. Disable and check the state.
1375 * 3. Enable and check the state and test that rendering does not produce errors.
1376 */
1377
1378 class CoherentEnableCaseGroup : public deqp::TestCaseGroup
1379 {
1380 public:
CoherentEnableCaseGroup(deqp::Context & context)1381 CoherentEnableCaseGroup(deqp::Context& context) : TestCaseGroup(context, "coherent", "")
1382 {
1383 }
1384
init(void)1385 void init(void)
1386 {
1387 addChild(new CoherentEnableCase(m_context));
1388 }
1389
1390 private:
1391 class CoherentEnableCase : public deqp::TestCase
1392 {
1393 public:
CoherentEnableCase(deqp::Context & context)1394 CoherentEnableCase(deqp::Context& context) : TestCase(context, "enableDisable", "")
1395 {
1396 }
1397 IterateResult iterate(void);
1398 };
1399 };
1400
iterate(void)1401 CoherentEnableCaseGroup::CoherentEnableCase::IterateResult CoherentEnableCaseGroup::CoherentEnableCase::iterate(void)
1402 {
1403 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1404
1405 // Check that extension is supported.
1406 if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
1407 {
1408 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
1409 return STOP;
1410 }
1411 if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced_coherent"))
1412 {
1413 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced_coherent");
1414 return STOP;
1415 }
1416
1417 std::vector<bool> res;
1418 // Enabled by default.
1419 res.push_back(gl.isEnabled(GL_BLEND_ADVANCED_COHERENT_KHR) == GL_TRUE);
1420 res.push_back(gl.getError() == GL_NO_ERROR);
1421
1422 // Check disabling.
1423 gl.disable(GL_BLEND_ADVANCED_COHERENT_KHR);
1424 res.push_back(gl.getError() == GL_NO_ERROR);
1425 res.push_back(gl.isEnabled(GL_BLEND_ADVANCED_COHERENT_KHR) == GL_FALSE);
1426 res.push_back(gl.getError() == GL_NO_ERROR);
1427
1428 // Check enabling.
1429 gl.enable(GL_BLEND_ADVANCED_COHERENT_KHR);
1430 res.push_back(gl.getError() == GL_NO_ERROR);
1431 res.push_back(gl.isEnabled(GL_BLEND_ADVANCED_COHERENT_KHR) == GL_TRUE);
1432 res.push_back(gl.getError() == GL_NO_ERROR);
1433
1434 // Pass if no failures found.
1435 bool pass = std::find(res.begin(), res.end(), false) == res.end();
1436
1437 m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail");
1438
1439 return STOP;
1440 }
1441 /*
1442 * From 'Other' part of the spec:
1443 * "Test that rendering into more than one color buffers at once produces
1444 * INVALID_OPERATION error when calling drawArrays/drawElements"
1445 */
1446 class MRTCaseGroup : public deqp::TestCaseGroup
1447 {
1448 public:
MRTCaseGroup(deqp::Context & context,glu::GLSLVersion glslVersion)1449 MRTCaseGroup(deqp::Context& context, glu::GLSLVersion glslVersion)
1450 : TestCaseGroup(context, "MRT", "GL_KHR_blend_equation_advanced"), m_glslVersion(glslVersion)
1451 {
1452 }
1453
init(void)1454 void init(void)
1455 {
1456 addChild(new MRTCase(m_context, m_glslVersion, MRTCase::ARRAY));
1457 addChild(new MRTCase(m_context, m_glslVersion, MRTCase::SEPARATE));
1458 }
1459
1460 private:
1461 class MRTCase : public deqp::TestCase
1462 {
1463 public:
1464 enum DeclarationType
1465 {
1466 ARRAY,
1467 SEPARATE
1468 };
1469
MRTCase(deqp::Context & context,glu::GLSLVersion glslVersion,DeclarationType declType)1470 MRTCase(deqp::Context& context, glu::GLSLVersion glslVersion, DeclarationType declType)
1471 : TestCase(context, (declType == ARRAY ? "MRT_array" : "MRT_separate"), "GL_KHR_blend_equation_advanced")
1472 , m_glslVersion(glslVersion)
1473 , m_declarationType(declType)
1474 {
1475 DE_ASSERT(m_declarationType == ARRAY || m_declarationType == SEPARATE);
1476 }
1477
1478 IterateResult iterate(void);
1479
1480 private:
1481 glu::GLSLVersion m_glslVersion;
1482 DeclarationType m_declarationType;
1483 };
1484
1485 glu::GLSLVersion m_glslVersion;
1486 };
1487
iterate(void)1488 MRTCaseGroup::MRTCase::IterateResult MRTCaseGroup::MRTCase::iterate(void)
1489 {
1490 TestLog& log = m_testCtx.getLog();
1491 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1492
1493 if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
1494 {
1495 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
1496 return STOP;
1497 }
1498
1499 static const char* frgSrcTemplateArray = "${VERSION_DIRECTIVE}\n"
1500 "#extension GL_KHR_blend_equation_advanced : require\n"
1501 "\n"
1502 "precision highp float;\n"
1503 "layout (blend_support_multiply) out;\n"
1504 "layout (location = 0) out vec4 oCol[2];\n"
1505 "\n"
1506 "uniform vec4 uMultCol;\n"
1507 "\n"
1508 "void main (void) {\n"
1509 " oCol[0] = uMultCol;\n"
1510 " oCol[1] = uMultCol;\n"
1511 "}\n";
1512
1513 static const char* frgSrcTemplateSeparate = "${VERSION_DIRECTIVE}\n"
1514 "#extension GL_KHR_blend_equation_advanced : require\n"
1515 "\n"
1516 "precision highp float;\n"
1517 "layout (blend_support_multiply) out;\n"
1518 "layout (location = 0) out vec4 oCol0;\n"
1519 "layout (location = 1) out vec4 oCol1;\n"
1520 "\n"
1521 "uniform vec4 uMultCol;\n"
1522 "\n"
1523 "void main (void) {\n"
1524 " oCol0 = uMultCol;\n"
1525 " oCol1 = uMultCol;\n"
1526 "}\n";
1527
1528 static const char* frgSrcTemplate = m_declarationType == ARRAY ? frgSrcTemplateArray : frgSrcTemplateSeparate;
1529
1530 std::map<std::string, std::string> args;
1531 args["VERSION_DIRECTIVE"] = glu::getGLSLVersionDeclaration(m_glslVersion);
1532 std::string frgSrc = tcu::StringTemplate(frgSrcTemplate).specialize(args);
1533
1534 FBOSentry fbo(gl, 4, 4, GL_RGBA8, GL_RGBA8);
1535
1536 static const glw::GLenum bufs[2] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
1537 gl.drawBuffers(2, bufs);
1538
1539 // Clear buffers to white.
1540 gl.clearColor(1.f, 1.f, 1.f, 1.f);
1541 gl.clear(GL_COLOR_BUFFER_BIT);
1542
1543 // Setup program.
1544 glu::ShaderProgram p(m_context.getRenderContext(),
1545 glu::makeVtxFragSources(GetDef2DVtxSrc(m_glslVersion).c_str(), frgSrc.c_str()));
1546 if (!p.isOk())
1547 {
1548 log << p;
1549 TCU_FAIL("Compile failed");
1550 }
1551
1552 gl.useProgram(p.getProgram());
1553 GLU_EXPECT_NO_ERROR(gl.getError(), "Program failed");
1554
1555 // Enable blending and set blend equation.
1556 gl.disable(GL_DITHER);
1557 gl.enable(GL_BLEND);
1558 gl.blendEquation(GL_DARKEN_KHR);
1559 GLU_EXPECT_NO_ERROR(gl.getError(), "BlendEquation failed");
1560
1561 // Multiply with zero.
1562 gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uMultCol"), 0.f, 0.f, 0.f, 1.00f);
1563 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniforms failed");
1564
1565 // Set vertex buffer
1566 glw::GLuint vbo;
1567 gl.genBuffers(1, &vbo);
1568 gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
1569 gl.bufferData(GL_ARRAY_BUFFER, sizeof(s_pos), s_pos, GL_STATIC_DRAW);
1570
1571 // Set vertices.
1572 glw::GLuint vao;
1573 gl.genVertexArrays(1, &vao);
1574 gl.bindVertexArray(vao);
1575 glw::GLint loc = gl.getAttribLocation(p.getProgram(), "aPos");
1576 gl.enableVertexAttribArray(loc);
1577 gl.vertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 8, DE_NULL);
1578 GLU_EXPECT_NO_ERROR(gl.getError(), "Attributes failed");
1579
1580 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
1581 bool errorOk = (gl.getError() == GL_INVALID_OPERATION);
1582
1583 gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, s_indices);
1584 errorOk = errorOk && (gl.getError() == GL_INVALID_OPERATION);
1585
1586 if (!errorOk)
1587 log << TestLog::Message << "DrawArrays/DrawElements didn't produce error." << TestLog::EndMessage;
1588
1589 // Expect unaltered destination pixels.
1590 bool contentsOk = true;
1591 for (int i = 0; i < 2; i++)
1592 {
1593 glw::GLubyte result[4] = { 1, 2, 3, 4 };
1594 gl.readBuffer(bufs[0]);
1595 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, result);
1596 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed");
1597 if (tcu::RGBA::fromBytes(result) != tcu::RGBA::white())
1598 {
1599 contentsOk = false;
1600 log << TestLog::Message << "Buffer " << i << " "
1601 << "contents changed: " << tcu::RGBA::fromBytes(result) << " expected:" << tcu::RGBA::white()
1602 << TestLog::EndMessage;
1603 }
1604 }
1605
1606 gl.deleteVertexArrays(1, &vao);
1607 gl.deleteBuffers(1, &vbo);
1608
1609 bool pass = errorOk && contentsOk;
1610 m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail");
1611 return STOP;
1612 }
1613
1614 /*
1615 * From "Other" part of the spec:
1616 * "Test that the new blending modes cannot be used with
1617 * BlendEquationSeparate(i). Expect INVALID_ENUM GL error"
1618 *
1619 * Tests that BlendEquationSeparate does not accept extension's blending modes
1620 * either in rgb or alpha parameter.
1621 */
1622 class BlendEquationSeparateCase : public deqp::TestCaseGroup
1623 {
1624 public:
BlendEquationSeparateCase(deqp::Context & context)1625 BlendEquationSeparateCase(deqp::Context& context)
1626 : TestCaseGroup(context, "BlendEquationSeparate",
1627 "Test that advanced blend modes are correctly rejected from glBlendEquationSeparate.")
1628 {
1629 }
1630
init(void)1631 void init(void)
1632 {
1633 // Pump individual modes.
1634 for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_modes); i++)
1635 addChild(new ModeCase(m_context, s_modes[i]));
1636 }
1637
1638 private:
1639 class ModeCase : public deqp::TestCase
1640 {
1641 public:
ModeCase(deqp::Context & context,glw::GLenum mode)1642 ModeCase(deqp::Context& context, glw::GLenum mode)
1643 : TestCase(context, GetModeStr(mode), "Test one mode"), m_mode(mode)
1644 {
1645 }
1646
iterate(void)1647 IterateResult iterate(void)
1648 {
1649 // Check that extension is supported.
1650 if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
1651 {
1652 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
1653 return STOP;
1654 }
1655
1656 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1657
1658 // Set separate blend equations.
1659 // Expect error and that default value (FUNC_ADD) is not changed.
1660
1661 // RGB.
1662 gl.blendEquationSeparate(m_mode, GL_FUNC_ADD);
1663 bool rgbOk = gl.getError() == GL_INVALID_ENUM;
1664 glw::GLint rgbEq = GL_NONE;
1665 gl.getIntegerv(GL_BLEND_EQUATION_RGB, &rgbEq);
1666 rgbOk = rgbOk && (rgbEq == GL_FUNC_ADD);
1667
1668 // Alpha.
1669 gl.blendEquationSeparate(GL_FUNC_ADD, m_mode);
1670 bool alphaOk = gl.getError() == GL_INVALID_ENUM;
1671 glw::GLint alphaEq = GL_NONE;
1672 gl.getIntegerv(GL_BLEND_EQUATION_ALPHA, &alphaEq);
1673 alphaOk = alphaOk && (alphaEq == GL_FUNC_ADD);
1674
1675 bool pass = rgbOk && alphaOk;
1676 m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail");
1677 return STOP;
1678 }
1679
1680 private:
1681 glw::GLenum m_mode;
1682 };
1683 };
1684
1685 /*
1686 * From "Other" part of the spec:
1687 * "Check that GLSL GL_KHR_blend_equation_advanced #define exists and is 1"
1688 *
1689 * Test that regardless of extension directive the definition exists and has value 1.
1690 */
1691
1692 class PreprocessorCaseGroup : public deqp::TestCaseGroup
1693 {
1694 public:
PreprocessorCaseGroup(deqp::Context & context,glu::GLSLVersion glslVersion)1695 PreprocessorCaseGroup(deqp::Context& context, glu::GLSLVersion glslVersion)
1696 : TestCaseGroup(context, "preprocessor", "GL_KHR_blend_equation_advanced"), m_glslVersion(glslVersion)
1697 {
1698 }
1699
init(void)1700 void init(void)
1701 {
1702 addChild(new PreprocessorCase(m_context, m_glslVersion, DE_NULL));
1703 addChild(new PreprocessorCase(m_context, m_glslVersion, "require"));
1704 addChild(new PreprocessorCase(m_context, m_glslVersion, "enable"));
1705 addChild(new PreprocessorCase(m_context, m_glslVersion, "warn"));
1706 addChild(new PreprocessorCase(m_context, m_glslVersion, "disable"));
1707 }
1708
1709 private:
1710 class PreprocessorCase : public deqp::TestCase
1711 {
1712 public:
PreprocessorCase(deqp::Context & context,glu::GLSLVersion glslVersion,const char * behaviour)1713 PreprocessorCase(deqp::Context& context, glu::GLSLVersion glslVersion, const char* behaviour)
1714 : TestCase(context, behaviour ? behaviour : "none", "GL_KHR_blend_equation_advanced")
1715 , m_glslVersion(glslVersion)
1716 , m_behaviour(behaviour)
1717 {
1718 }
1719
1720 IterateResult iterate(void);
1721
1722 private:
1723 glu::GLSLVersion m_glslVersion;
1724 const char* m_behaviour;
1725 };
1726
1727 glu::GLSLVersion m_glslVersion;
1728 };
1729
iterate(void)1730 PreprocessorCaseGroup::PreprocessorCase::IterateResult PreprocessorCaseGroup::PreprocessorCase::iterate(void)
1731 {
1732 TestLog& log = m_testCtx.getLog();
1733 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1734 const int dim = 4;
1735
1736 if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
1737 {
1738 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
1739 return STOP;
1740 }
1741
1742 FBOSentry fbo(gl, dim, dim, GL_RGBA8);
1743 gl.clearColor(0.125f, 0.125f, 0.125f, 1.f);
1744 gl.clear(GL_COLOR_BUFFER_BIT);
1745
1746 // Test that GL_KHR_blend_equation_advanced is defined and it has value 1.
1747 // Renders green pixels if above is true, red pixels otherwise.
1748 static const char* frgSrcTemplate = "${VERSION_DIRECTIVE}\n"
1749 "${EXTENSION_DIRECTIVE}\n"
1750 "precision highp float;\n"
1751 "\n"
1752 "uniform vec4 uDefined;\n"
1753 "uniform vec4 uNonDefined;\n"
1754 "\n"
1755 "uniform int uValue;\n"
1756 "\n"
1757 "layout(location = 0) out vec4 oCol;\n"
1758 "\n"
1759 "void main (void) {\n"
1760 " vec4 col = uNonDefined;\n"
1761 "#if defined(GL_KHR_blend_equation_advanced)\n"
1762 " int val = GL_KHR_blend_equation_advanced;\n"
1763 " if (uValue == val) {\n"
1764 " col = uDefined;\n"
1765 " }\n"
1766 "#endif\n"
1767 " oCol = col;\n"
1768 "}\n";
1769
1770 std::map<std::string, std::string> args;
1771 args["VERSION_DIRECTIVE"] = glu::getGLSLVersionDeclaration(m_glslVersion);
1772 if (m_behaviour)
1773 args["EXTENSION_DIRECTIVE"] = std::string("#extension GL_KHR_blend_equation_advanced : ") + m_behaviour;
1774 else
1775 args["EXTENSION_DIRECTIVE"] = "";
1776 std::string frgSrc = tcu::StringTemplate(frgSrcTemplate).specialize(args);
1777
1778 glu::ShaderProgram p(m_context.getRenderContext(),
1779 glu::makeVtxFragSources(GetDef2DVtxSrc(m_glslVersion).c_str(), frgSrc.c_str()));
1780 if (!p.isOk())
1781 {
1782 log << p;
1783 TCU_FAIL("Compile failed");
1784 }
1785 gl.useProgram(p.getProgram());
1786 GLU_EXPECT_NO_ERROR(gl.getError(), "Program failed");
1787
1788 gl.uniform1i(gl.getUniformLocation(p.getProgram(), "uValue"), 1);
1789 gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uDefined"), 0.f, 1.f, 0.f, 1.f);
1790 gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uNonDefined"), 1.f, 0.f, 1.f, 1.f);
1791 GLU_EXPECT_NO_ERROR(gl.getError(), "Uniforms failed");
1792
1793 glu::VertexArrayBinding posBinding = glu::va::Float("aPos", 2, 4, 0, &s_pos[0]);
1794 glu::draw(m_context.getRenderContext(), p.getProgram(), 1, &posBinding,
1795 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0]));
1796 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
1797
1798 // Check the results.
1799 tcu::Surface resultSurface(dim, dim);
1800 glu::readPixels(m_context.getRenderContext(), 0, 0, resultSurface.getAccess());
1801 GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed");
1802 bool pass = tcu::RGBA::green() == resultSurface.getPixel(0, 0);
1803
1804 m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail");
1805
1806 return STOP;
1807 }
1808
BlendEquationAdvancedTests(deqp::Context & context,glu::GLSLVersion glslVersion)1809 BlendEquationAdvancedTests::BlendEquationAdvancedTests(deqp::Context& context, glu::GLSLVersion glslVersion)
1810 : TestCaseGroup(context, "blend_equation_advanced", "KHR_blend_equation_advanced tests"), m_glslVersion(glslVersion)
1811 {
1812 }
1813
~BlendEquationAdvancedTests(void)1814 BlendEquationAdvancedTests::~BlendEquationAdvancedTests(void)
1815 {
1816 }
1817
init(void)1818 void BlendEquationAdvancedTests::init(void)
1819 {
1820 // Test that enable/disable and getting status works.
1821 addChild(new CoherentEnableCaseGroup(m_context));
1822
1823 // Test that preprocessor macro GL_KHR_blend_equation_advanced
1824 // is always defined and its value is 1.
1825 addChild(new PreprocessorCaseGroup(m_context, m_glslVersion));
1826
1827 // Test that BlendEquationSeparate rejects advanced blend modes.
1828 addChild(new BlendEquationSeparateCase(m_context));
1829
1830 // Test that advanced blend equations cannot be used with multiple render targets.
1831 addChild(new MRTCaseGroup(m_context, m_glslVersion));
1832
1833 // Test that using new blend modes produce errors if appropriate qualifier
1834 // is not in the shader (test without any blend qualifier and with mismatching qualifier).
1835 addChild(new MissingQualifierTestGroup(m_context, m_glslVersion, MissingQualifierTestGroup::MISMATCH));
1836 addChild(new MissingQualifierTestGroup(m_context, m_glslVersion, MissingQualifierTestGroup::MISSING));
1837
1838 // Test #extension directive behaviour.
1839 // Case "require" is tested indirectly by blending tests.
1840 addChild(new ExtensionDirectiveTestCaseGroup(m_context, m_glslVersion));
1841
1842 // Test that each blend mode produces correct results.
1843 addChild(new BlendTestCaseGroup(m_context, m_glslVersion, BlendTestCaseGroup::ALL_QUALIFIER));
1844 addChild(new BlendTestCaseGroup(m_context, m_glslVersion, BlendTestCaseGroup::MATCHING_QUALIFIER));
1845
1846 // Test that coherent blending or barrier works.
1847 addChild(new CoherentBlendTestCaseGroup(m_context, m_glslVersion));
1848 }
1849
1850 } // glcts
1851