xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcBlendEquationAdvancedTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 uint16_t 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(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(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(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", "")
577         , m_glslVersion(glslVersion)
578     {
579     }
580 
init(void)581     void init(void)
582     {
583         addChild(
584             new CoherentBlendTest(m_context, "mixedSequence", m_glslVersion, 4, DE_LENGTH_OF_ARRAY(s_mixed), s_mixed));
585         addChild(new CoherentBlendTest(m_context, "multiplySequence", m_glslVersion, 1, DE_LENGTH_OF_ARRAY(s_multiply),
586                                        s_multiply));
587     }
588 
589 private:
590     struct BlendStep;
591 
592     class CoherentBlendTest : public deqp::TestCase
593     {
594     public:
CoherentBlendTest(deqp::Context & context,const char * name,glu::GLSLVersion glslVersion,int repeatCount,int numSteps,const BlendStep * steps)595         CoherentBlendTest(deqp::Context &context, const char *name, glu::GLSLVersion glslVersion, int repeatCount,
596                           int numSteps, const BlendStep *steps)
597             : TestCase(context, name, "")
598             , m_glslVersion(glslVersion)
599             , m_repeatCount(repeatCount)
600             , m_numSteps(numSteps)
601             , m_steps(steps)
602         {
603             DE_ASSERT(repeatCount > 0 && numSteps > 0 && steps);
604         }
605 
606         IterateResult iterate(void);
607 
608     private:
609         glu::GLSLVersion m_glslVersion;
610         int m_repeatCount;
611         int m_numSteps;
612         const BlendStep *m_steps;
613     };
614 
615     struct BlendStep
616     {
617         glw::GLenum mode;
618         glw::GLfloat src[4]; // rgba
619     };
620 
621     // Blend sequences.
622     static const BlendStep s_mixed[11];
623     static const BlendStep s_multiply[7];
624 
625     glu::GLSLVersion m_glslVersion;
626 };
627 
628 const CoherentBlendTestCaseGroup::BlendStep CoherentBlendTestCaseGroup::s_mixed[] = {
629     {GL_LIGHTEN_KHR, {0.250f, 0.375f, 1.000f, 1.000f}},    // =>  (0.250, 0.375, 1.000, 1.000) (from src)
630     {GL_OVERLAY_KHR, {1.000f, 1.000f, 1.000f, 1.000f}},    // => ~(0.500, 0.750, 1.000, 1.000)
631     {GL_HARDLIGHT_KHR, {0.750f, 0.750f, 0.250f, 1.000f}},  // => ~(0.750, 1.000, 0.500, 1.000)
632     {GL_DARKEN_KHR, {0.250f, 0.250f, 0.250f, 1.000f}},     // =>  (0.250, 0.250, 0.250, 1.000) (from src)
633     {GL_COLORDODGE_KHR, {0.750f, 0.875f, 1.000f, 1.000f}}, // => ~(1.000, 1.000, 1.000, 1.000)
634     {GL_MULTIPLY_KHR, {0.500f, 0.500f, 0.500f, 1.000f}},   // => ~(0.500, 0.500, 0.500, 1.000)
635     {GL_SCREEN_KHR, {0.500f, 0.500f, 0.500f, 1.000f}},     // => ~(0.750, 0.750, 0.750, 1.000)
636     {GL_DARKEN_KHR, {0.250f, 0.500f, 0.500f, 1.000f}},     // =>  (0.250, 0.500, 0.500, 1.000) (from src)
637     {GL_DIFFERENCE_KHR, {0.000f, 0.875f, 0.125f, 1.000f}}, // => ~(0.250, 0.375, 0.375, 1.000)
638     {GL_EXCLUSION_KHR, {1.000f, 0.500f, 0.750f, 1.000f}},  // => ~(0.750, 0.500, 0.563, 1.000)
639     {GL_DARKEN_KHR, {0.125f, 0.125f, 0.125f, 1.000f}},     // =>  (0.125, 0.125, 0.125, 1.000) (from src)
640     // Last row is unique and "accurate" since it comes from the source.
641     // That means so that it can be easily tested for correctness.
642 };
643 
644 const CoherentBlendTestCaseGroup::BlendStep CoherentBlendTestCaseGroup::s_multiply[] = {
645     {GL_LIGHTEN_KHR, {1.000f, 1.000f, 1.000f, 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}}, {GL_MULTIPLY_KHR, {0.500f, 0.500f, 0.500f, 1.000f}},
648     {GL_MULTIPLY_KHR, {0.500f, 0.500f, 0.500f, 1.000f}}, // ~4 in 8bits
649 };
650 
iterate(void)651 CoherentBlendTestCaseGroup::CoherentBlendTest::IterateResult CoherentBlendTestCaseGroup::CoherentBlendTest::iterate(
652     void)
653 {
654     static const int dim        = 1024;
655     const tcu::RenderTarget &rt = m_context.getRenderContext().getRenderTarget();
656     const tcu::PixelFormat &pf  = rt.getPixelFormat();
657     const glw::Functions &gl    = m_context.getRenderContext().getFunctions();
658     TestLog &log                = m_testCtx.getLog();
659 
660     // Check that extension is supported.
661     if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
662     {
663         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
664         return STOP;
665     }
666 
667     bool needBarrier = !IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced_coherent");
668 
669     tcu::Vec4 dstCol(0.f, 0.f, 0.f, 0.f);
670 
671     FBOSentry fbo(gl, dim, dim, GL_RGBA8);
672 
673     // Setup progra
674     std::string frgSrc = GetSolidShader("blend_support_all_equations", glu::getGLSLVersionDeclaration(m_glslVersion));
675     glu::ShaderProgram p(m_context.getRenderContext(),
676                          glu::makeVtxFragSources(GetDef2DVtxSrc(m_glslVersion).c_str(), frgSrc.c_str()));
677     if (!p.isOk())
678     {
679         log << p;
680         TCU_FAIL("Compile failed");
681     }
682     gl.useProgram(p.getProgram());
683     GLU_EXPECT_NO_ERROR(gl.getError(), "Program failed");
684 
685     glu::VertexArrayBinding posBinding = glu::va::Float("aPos", 2, 4, 0, &s_pos[0]);
686 
687     // Enable blending.
688     gl.disable(GL_DITHER);
689     gl.enable(GL_BLEND);
690 
691     // Clear.
692     gl.clearColor(dstCol[0], dstCol[1], dstCol[2], dstCol[3]);
693     gl.clear(GL_COLOR_BUFFER_BIT);
694 
695     // Blend barrier.
696     if (needBarrier)
697         gl.blendBarrier();
698 
699     // Repeat block.
700     for (int i = 0; i < m_repeatCount; i++)
701         // Loop blending steps.
702         for (int j = 0; j < m_numSteps; j++)
703         {
704             const BlendStep &s = m_steps[j];
705             tcu::Vec4 srcCol(s.src[0], s.src[1], s.src[2], s.src[3]);
706             tcu::Vec4 refCol = Blend(s.mode, srcCol, dstCol);
707             dstCol           = refCol;
708 
709             // Set blend equation.
710             gl.blendEquation(s.mode);
711             GLU_EXPECT_NO_ERROR(gl.getError(), "BlendEquation failed");
712 
713             // Set source color.
714             gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uSrcCol"), srcCol[0], srcCol[1], srcCol[2], srcCol[3]);
715             GLU_EXPECT_NO_ERROR(gl.getError(), "Uniforms failed");
716 
717             // Draw.
718             glu::draw(m_context.getRenderContext(), p.getProgram(), 1, &posBinding,
719                       glu::pr::Triangles(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0]));
720             GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
721 
722             // Blend barrier.
723             if (needBarrier)
724                 gl.blendBarrier();
725         }
726 
727     // Read the results.
728     glw::GLubyte *result = new glw::GLubyte[4 * dim * dim];
729     gl.readPixels(0, 0, dim, dim, GL_RGBA, GL_UNSIGNED_BYTE, result);
730     GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed");
731 
732     // Check that first pixel is ok.
733     tcu::RGBA res       = tcu::RGBA::fromBytes(result);
734     tcu::RGBA ref       = pf.convertColor(tcu::RGBA(dstCol));
735     tcu::RGBA threshold = pf.getColorThreshold() + pf.getColorThreshold();
736     bool firstOk        = tcu::compareThreshold(ref, res, threshold);
737 
738     // Check that all pixels are the same as the first one.
739     bool allSame = true;
740     for (int i = 0; i < dim * (dim - 1); i++)
741         allSame = allSame && (0 == memcmp(result, result + (i * 4), 4));
742 
743     bool pass = firstOk && allSame;
744     if (!pass)
745     {
746         log << TestLog::Message << "Exceeds: " << threshold << " diff:" << tcu::computeAbsDiff(ref, res)
747             << "  res:" << res << "  ref:" << tcu::RGBA(dstCol) << TestLog::EndMessage;
748     }
749 
750     delete[] result;
751 
752     m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "" : "results differ");
753     return STOP;
754 }
755 
756 class BlendTestCaseGroup : public deqp::TestCaseGroup
757 {
758 public:
759     enum QualifierType
760     {
761         MATCHING_QUALIFIER, // Use single qualifier that matches used blending mode.
762         ALL_QUALIFIER       // Use "all_equations" qualifier.
763     };
764 
BlendTestCaseGroup(deqp::Context & context,glu::GLSLVersion glslVersion,QualifierType qualifierType)765     BlendTestCaseGroup(deqp::Context &context, glu::GLSLVersion glslVersion, QualifierType qualifierType)
766         : TestCaseGroup(context, (qualifierType == ALL_QUALIFIER) ? "blend_all" : "blend_specific",
767                         "Test all added blends.")
768         , m_glslVersion(glslVersion)
769         , m_useAllQualifier(qualifierType == ALL_QUALIFIER)
770     {
771         DE_ASSERT(qualifierType == MATCHING_QUALIFIER || qualifierType == ALL_QUALIFIER);
772     }
773 
init(void)774     void init(void)
775     {
776         // Pump individual modes.
777         for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_modes); i++)
778         {
779             addChild(new BlendTest(m_context, m_glslVersion, s_modes[i], m_useAllQualifier,
780                                    DE_LENGTH_OF_ARRAY(s_common) / 8, s_common, DE_LENGTH_OF_ARRAY(s_rgb10a2) / 8,
781                                    s_rgb10a2));
782         }
783     }
784 
785 private:
786     glu::GLSLVersion m_glslVersion;
787     bool m_useAllQualifier;
788 
789     class BlendTest : public deqp::TestCase
790     {
791     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)792         BlendTest(deqp::Context &context, glu::GLSLVersion glslVersion, glw::GLenum mode, bool useAllQualifier,
793                   int numColors, const glw::GLfloat *colors, int numSpecificColors, const glw::GLfloat *specificColors)
794             : TestCase(context, (std::string(GetModeStr(mode)) + (useAllQualifier ? "_all_qualifier" : "")).c_str(),
795                        "Test new blend modes for correctness.")
796             , m_glslVersion(glslVersion)
797             , m_mode(mode)
798             , m_useAllQualifier(useAllQualifier)
799             , m_numColors(numColors)
800             , m_colors(colors)
801             , m_numSpecificColors(numSpecificColors)
802             , m_specificColors(specificColors)
803             , m_useRGB10A2Data(GL_FALSE)
804         {
805         }
806 
807         IterateResult iterate(void);
808 
809     private:
810         void getTestColors(int index, tcu::Vec4 &src, tcu::Vec4 &dst) const;
811         void getCoordinates(int index, int &x, int &y) const;
812 
813         glu::GLSLVersion m_glslVersion;
814         glw::GLenum m_mode;
815         bool m_useAllQualifier;
816         int m_numColors;
817         const glw::GLfloat *m_colors;
818         int m_numSpecificColors;
819         const glw::GLfloat *m_specificColors;
820         bool m_useRGB10A2Data;
821     };
822 
823     static const glw::GLfloat s_common[46 * 8];
824     static const glw::GLfloat s_rgb10a2[42 * 8];
825 };
826 
827 // Alpha values for pre-multiplied colors.
828 static const float A1 = 0.750f; // Between 1    and 0.5
829 static const float A2 = 0.375f; // Between 0.5  and 0.25
830 static const float A3 = 0.125f; // Between 0.25 and 0.0
831 
832 const glw::GLfloat BlendTestCaseGroup::s_common[] = {
833     // Test that pre-multiplied is converted correctly.
834     // Should not test invalid premultiplied colours (1, 1, 1, 0).
835     1.000f,
836     0.750f,
837     0.500f,
838     1.00f,
839     0.000f,
840     0.000f,
841     0.000f,
842     0.00f,
843     0.250f,
844     0.125f,
845     0.000f,
846     1.00f,
847     0.000f,
848     0.000f,
849     0.000f,
850     0.00f,
851 
852     // Test clamping.
853     1.000f,
854     0.750f,
855     0.500f,
856     1.00f,
857     -0.125f,
858     -0.125f,
859     -0.125f,
860     1.00f,
861     0.250f,
862     0.125f,
863     0.000f,
864     1.00f,
865     -0.125f,
866     -0.125f,
867     -0.125f,
868     1.00f,
869     1.000f,
870     0.750f,
871     0.500f,
872     1.00f,
873     1.125f,
874     1.125f,
875     1.125f,
876     1.00f,
877     0.250f,
878     0.125f,
879     0.000f,
880     1.00f,
881     1.125f,
882     1.125f,
883     1.125f,
884     1.00f,
885 
886     // Cobinations that test other branches of blend equations.
887     1.000f,
888     0.750f,
889     0.500f,
890     1.00f,
891     1.000f,
892     1.000f,
893     1.000f,
894     1.00f,
895     0.250f,
896     0.125f,
897     0.000f,
898     1.00f,
899     1.000f,
900     1.000f,
901     1.000f,
902     1.00f,
903     1.000f,
904     0.750f,
905     0.500f,
906     1.00f,
907     0.500f,
908     0.500f,
909     0.500f,
910     1.00f,
911     0.250f,
912     0.125f,
913     0.000f,
914     1.00f,
915     0.500f,
916     0.500f,
917     0.500f,
918     1.00f,
919     1.000f,
920     0.750f,
921     0.500f,
922     1.00f,
923     0.250f,
924     0.250f,
925     0.250f,
926     1.00f,
927     0.250f,
928     0.125f,
929     0.000f,
930     1.00f,
931     0.250f,
932     0.250f,
933     0.250f,
934     1.00f,
935     1.000f,
936     0.750f,
937     0.500f,
938     1.00f,
939     0.125f,
940     0.125f,
941     0.125f,
942     1.00f,
943     0.250f,
944     0.125f,
945     0.000f,
946     1.00f,
947     0.125f,
948     0.125f,
949     0.125f,
950     1.00f,
951     1.000f,
952     0.750f,
953     0.500f,
954     1.00f,
955     0.000f,
956     0.000f,
957     0.000f,
958     1.00f,
959     0.250f,
960     0.125f,
961     0.000f,
962     1.00f,
963     0.000f,
964     0.000f,
965     0.000f,
966     1.00f,
967 
968     // Above block with few different pre-multiplied alpha values.
969     A1 * 1.000f,
970     A1 * 0.750f,
971     A1 * 0.500f,
972     A1 * 1.00f,
973     A1 * 1.000f,
974     A1 * 1.000f,
975     A1 * 1.000f,
976     A1 * 1.00f,
977     A1 * 0.250f,
978     A1 * 0.125f,
979     A1 * 0.000f,
980     A1 * 1.00f,
981     A1 * 1.000f,
982     A1 * 1.000f,
983     A1 * 1.000f,
984     A1 * 1.00f,
985     A1 * 1.000f,
986     A1 * 0.750f,
987     A1 * 0.500f,
988     A1 * 1.00f,
989     A1 * 0.500f,
990     A1 * 0.500f,
991     A1 * 0.500f,
992     A1 * 1.00f,
993     A1 * 0.250f,
994     A1 * 0.125f,
995     A1 * 0.000f,
996     A1 * 1.00f,
997     A1 * 0.500f,
998     A1 * 0.500f,
999     A1 * 0.500f,
1000     A1 * 1.00f,
1001     A1 * 1.000f,
1002     A1 * 0.750f,
1003     A1 * 0.500f,
1004     A1 * 1.00f,
1005     A1 * 0.250f,
1006     A1 * 0.250f,
1007     A1 * 0.250f,
1008     A1 * 1.00f,
1009     A1 * 0.250f,
1010     A1 * 0.125f,
1011     A1 * 0.000f,
1012     A1 * 1.00f,
1013     A1 * 0.250f,
1014     A1 * 0.250f,
1015     A1 * 0.250f,
1016     A1 * 1.00f,
1017     A1 * 1.000f,
1018     A1 * 0.750f,
1019     A1 * 0.500f,
1020     A1 * 1.00f,
1021     A1 * 0.125f,
1022     A1 * 0.125f,
1023     A1 * 0.125f,
1024     A1 * 1.00f,
1025     A1 * 0.250f,
1026     A1 * 0.125f,
1027     A1 * 0.000f,
1028     A1 * 1.00f,
1029     A1 * 0.125f,
1030     A1 * 0.125f,
1031     A1 * 0.125f,
1032     A1 * 1.00f,
1033     A1 * 1.000f,
1034     A1 * 0.750f,
1035     A1 * 0.500f,
1036     A1 * 1.00f,
1037     A1 * 0.000f,
1038     A1 * 0.000f,
1039     A1 * 0.000f,
1040     A1 * 1.00f,
1041     A1 * 0.250f,
1042     A1 * 0.125f,
1043     A1 * 0.000f,
1044     A1 * 1.00f,
1045     A1 * 0.000f,
1046     A1 * 0.000f,
1047     A1 * 0.000f,
1048     A1 * 1.00f,
1049 
1050     A2 * 1.000f,
1051     A2 * 0.750f,
1052     A2 * 0.500f,
1053     A2 * 1.00f,
1054     A2 * 1.000f,
1055     A2 * 1.000f,
1056     A2 * 1.000f,
1057     A2 * 1.00f,
1058     A2 * 0.250f,
1059     A2 * 0.125f,
1060     A2 * 0.000f,
1061     A2 * 1.00f,
1062     A2 * 1.000f,
1063     A2 * 1.000f,
1064     A2 * 1.000f,
1065     A2 * 1.00f,
1066     A2 * 1.000f,
1067     A2 * 0.750f,
1068     A2 * 0.500f,
1069     A2 * 1.00f,
1070     A2 * 0.500f,
1071     A2 * 0.500f,
1072     A2 * 0.500f,
1073     A2 * 1.00f,
1074     A2 * 0.250f,
1075     A2 * 0.125f,
1076     A2 * 0.000f,
1077     A2 * 1.00f,
1078     A2 * 0.500f,
1079     A2 * 0.500f,
1080     A2 * 0.500f,
1081     A2 * 1.00f,
1082     A2 * 1.000f,
1083     A2 * 0.750f,
1084     A2 * 0.500f,
1085     A2 * 1.00f,
1086     A2 * 0.250f,
1087     A2 * 0.250f,
1088     A2 * 0.250f,
1089     A2 * 1.00f,
1090     A2 * 0.250f,
1091     A2 * 0.125f,
1092     A2 * 0.000f,
1093     A2 * 1.00f,
1094     A2 * 0.250f,
1095     A2 * 0.250f,
1096     A2 * 0.250f,
1097     A2 * 1.00f,
1098     A2 * 1.000f,
1099     A2 * 0.750f,
1100     A2 * 0.500f,
1101     A2 * 1.00f,
1102     A2 * 0.125f,
1103     A2 * 0.125f,
1104     A2 * 0.125f,
1105     A2 * 1.00f,
1106     A2 * 0.250f,
1107     A2 * 0.125f,
1108     A2 * 0.000f,
1109     A2 * 1.00f,
1110     A2 * 0.125f,
1111     A2 * 0.125f,
1112     A2 * 0.125f,
1113     A2 * 1.00f,
1114     A2 * 1.000f,
1115     A2 * 0.750f,
1116     A2 * 0.500f,
1117     A2 * 1.00f,
1118     A2 * 0.000f,
1119     A2 * 0.000f,
1120     A2 * 0.000f,
1121     A2 * 1.00f,
1122     A2 * 0.250f,
1123     A2 * 0.125f,
1124     A2 * 0.000f,
1125     A2 * 1.00f,
1126     A2 * 0.000f,
1127     A2 * 0.000f,
1128     A2 * 0.000f,
1129     A2 * 1.00f,
1130 
1131     A3 * 1.000f,
1132     A3 * 0.750f,
1133     A3 * 0.500f,
1134     A3 * 1.00f,
1135     A3 * 1.000f,
1136     A3 * 1.000f,
1137     A3 * 1.000f,
1138     A3 * 1.00f,
1139     A3 * 0.250f,
1140     A3 * 0.125f,
1141     A3 * 0.000f,
1142     A3 * 1.00f,
1143     A3 * 1.000f,
1144     A3 * 1.000f,
1145     A3 * 1.000f,
1146     A3 * 1.00f,
1147     A3 * 1.000f,
1148     A3 * 0.750f,
1149     A3 * 0.500f,
1150     A3 * 1.00f,
1151     A3 * 0.500f,
1152     A3 * 0.500f,
1153     A3 * 0.500f,
1154     A3 * 1.00f,
1155     A3 * 0.250f,
1156     A3 * 0.125f,
1157     A3 * 0.000f,
1158     A3 * 1.00f,
1159     A3 * 0.500f,
1160     A3 * 0.500f,
1161     A3 * 0.500f,
1162     A3 * 1.00f,
1163     A3 * 1.000f,
1164     A3 * 0.750f,
1165     A3 * 0.500f,
1166     A3 * 1.00f,
1167     A3 * 0.250f,
1168     A3 * 0.250f,
1169     A3 * 0.250f,
1170     A3 * 1.00f,
1171     A3 * 0.250f,
1172     A3 * 0.125f,
1173     A3 * 0.000f,
1174     A3 * 1.00f,
1175     A3 * 0.250f,
1176     A3 * 0.250f,
1177     A3 * 0.250f,
1178     A3 * 1.00f,
1179     A3 * 1.000f,
1180     A3 * 0.750f,
1181     A3 * 0.500f,
1182     A3 * 1.00f,
1183     A3 * 0.125f,
1184     A3 * 0.125f,
1185     A3 * 0.125f,
1186     A3 * 1.00f,
1187     A3 * 0.250f,
1188     A3 * 0.125f,
1189     A3 * 0.000f,
1190     A3 * 1.00f,
1191     A3 * 0.125f,
1192     A3 * 0.125f,
1193     A3 * 0.125f,
1194     A3 * 1.00f,
1195     A3 * 1.000f,
1196     A3 * 0.750f,
1197     A3 * 0.500f,
1198     A3 * 1.00f,
1199     A3 * 0.000f,
1200     A3 * 0.000f,
1201     A3 * 0.000f,
1202     A3 * 1.00f,
1203     A3 * 0.250f,
1204     A3 * 0.125f,
1205     A3 * 0.000f,
1206     A3 * 1.00f,
1207     A3 * 0.000f,
1208     A3 * 0.000f,
1209     A3 * 0.000f,
1210     A3 * 1.00f,
1211 };
1212 
1213 // Some data in the s_common array are invalid for BlendHSLHue and BlendHSLSaturation function when the render target
1214 // format is GL_RGB10A2. These data will lead to undefine behavior(divide 0). Remove those data and create a new array
1215 // to test this format and the blend functions.
1216 const glw::GLfloat BlendTestCaseGroup::s_rgb10a2[] = {
1217     // Test that pre-multiplied is converted correctly.
1218     // Should not test invalid premultiplied colours (1, 1, 1, 0).
1219     1.000f,
1220     0.750f,
1221     0.500f,
1222     1.00f,
1223     0.000f,
1224     0.000f,
1225     0.000f,
1226     0.00f,
1227     0.250f,
1228     0.125f,
1229     0.000f,
1230     1.00f,
1231     0.000f,
1232     0.000f,
1233     0.000f,
1234     0.00f,
1235 
1236     // Test clamping.
1237     1.000f,
1238     0.750f,
1239     0.500f,
1240     1.00f,
1241     -0.125f,
1242     -0.125f,
1243     -0.125f,
1244     1.00f,
1245     0.250f,
1246     0.125f,
1247     0.000f,
1248     1.00f,
1249     -0.125f,
1250     -0.125f,
1251     -0.125f,
1252     1.00f,
1253     1.000f,
1254     0.750f,
1255     0.500f,
1256     1.00f,
1257     1.125f,
1258     1.125f,
1259     1.125f,
1260     1.00f,
1261     0.250f,
1262     0.125f,
1263     0.000f,
1264     1.00f,
1265     1.125f,
1266     1.125f,
1267     1.125f,
1268     1.00f,
1269 
1270     // Cobinations that test other branches of blend equations.
1271     1.000f,
1272     0.750f,
1273     0.500f,
1274     1.00f,
1275     1.000f,
1276     1.000f,
1277     1.000f,
1278     1.00f,
1279     0.250f,
1280     0.125f,
1281     0.000f,
1282     1.00f,
1283     1.000f,
1284     1.000f,
1285     1.000f,
1286     1.00f,
1287     1.000f,
1288     0.750f,
1289     0.500f,
1290     1.00f,
1291     0.500f,
1292     0.500f,
1293     0.500f,
1294     1.00f,
1295     0.250f,
1296     0.125f,
1297     0.000f,
1298     1.00f,
1299     0.500f,
1300     0.500f,
1301     0.500f,
1302     1.00f,
1303     1.000f,
1304     0.750f,
1305     0.500f,
1306     1.00f,
1307     0.250f,
1308     0.250f,
1309     0.250f,
1310     1.00f,
1311     0.250f,
1312     0.125f,
1313     0.000f,
1314     1.00f,
1315     0.250f,
1316     0.250f,
1317     0.250f,
1318     1.00f,
1319     1.000f,
1320     0.750f,
1321     0.500f,
1322     1.00f,
1323     0.125f,
1324     0.125f,
1325     0.125f,
1326     1.00f,
1327     0.250f,
1328     0.125f,
1329     0.000f,
1330     1.00f,
1331     0.125f,
1332     0.125f,
1333     0.125f,
1334     1.00f,
1335     1.000f,
1336     0.750f,
1337     0.500f,
1338     1.00f,
1339     0.000f,
1340     0.000f,
1341     0.000f,
1342     1.00f,
1343     0.250f,
1344     0.125f,
1345     0.000f,
1346     1.00f,
1347     0.000f,
1348     0.000f,
1349     0.000f,
1350     1.00f,
1351 
1352     // Above block with few different pre-multiplied alpha values.
1353     A1 * 1.000f,
1354     A1 * 0.750f,
1355     A1 * 0.500f,
1356     A1 * 1.00f,
1357     A1 * 0.500f,
1358     A1 * 0.500f,
1359     A1 * 0.500f,
1360     A1 * 1.00f,
1361     A1 * 0.250f,
1362     A1 * 0.125f,
1363     A1 * 0.000f,
1364     A1 * 1.00f,
1365     A1 * 0.500f,
1366     A1 * 0.500f,
1367     A1 * 0.500f,
1368     A1 * 1.00f,
1369     A1 * 1.000f,
1370     A1 * 0.750f,
1371     A1 * 0.500f,
1372     A1 * 1.00f,
1373     A1 * 0.250f,
1374     A1 * 0.250f,
1375     A1 * 0.250f,
1376     A1 * 1.00f,
1377     A1 * 0.250f,
1378     A1 * 0.125f,
1379     A1 * 0.000f,
1380     A1 * 1.00f,
1381     A1 * 0.250f,
1382     A1 * 0.250f,
1383     A1 * 0.250f,
1384     A1 * 1.00f,
1385     A1 * 1.000f,
1386     A1 * 0.750f,
1387     A1 * 0.500f,
1388     A1 * 1.00f,
1389     A1 * 0.125f,
1390     A1 * 0.125f,
1391     A1 * 0.125f,
1392     A1 * 1.00f,
1393     A1 * 0.250f,
1394     A1 * 0.125f,
1395     A1 * 0.000f,
1396     A1 * 1.00f,
1397     A1 * 0.125f,
1398     A1 * 0.125f,
1399     A1 * 0.125f,
1400     A1 * 1.00f,
1401     A1 * 1.000f,
1402     A1 * 0.750f,
1403     A1 * 0.500f,
1404     A1 * 1.00f,
1405     A1 * 0.000f,
1406     A1 * 0.000f,
1407     A1 * 0.000f,
1408     A1 * 1.00f,
1409     A1 * 0.250f,
1410     A1 * 0.125f,
1411     A1 * 0.000f,
1412     A1 * 1.00f,
1413     A1 * 0.000f,
1414     A1 * 0.000f,
1415     A1 * 0.000f,
1416     A1 * 1.00f,
1417 
1418     A2 * 1.000f,
1419     A2 * 0.750f,
1420     A2 * 0.500f,
1421     A2 * 1.00f,
1422     A2 * 0.500f,
1423     A2 * 0.500f,
1424     A2 * 0.500f,
1425     A2 * 1.00f,
1426     A2 * 0.250f,
1427     A2 * 0.125f,
1428     A2 * 0.000f,
1429     A2 * 1.00f,
1430     A2 * 0.500f,
1431     A2 * 0.500f,
1432     A2 * 0.500f,
1433     A2 * 1.00f,
1434     A2 * 1.000f,
1435     A2 * 0.750f,
1436     A2 * 0.500f,
1437     A2 * 1.00f,
1438     A2 * 0.250f,
1439     A2 * 0.250f,
1440     A2 * 0.250f,
1441     A2 * 1.00f,
1442     A2 * 0.250f,
1443     A2 * 0.125f,
1444     A2 * 0.000f,
1445     A2 * 1.00f,
1446     A2 * 0.250f,
1447     A2 * 0.250f,
1448     A2 * 0.250f,
1449     A2 * 1.00f,
1450     A2 * 1.000f,
1451     A2 * 0.750f,
1452     A2 * 0.500f,
1453     A2 * 1.00f,
1454     A2 * 0.125f,
1455     A2 * 0.125f,
1456     A2 * 0.125f,
1457     A2 * 1.00f,
1458     A2 * 0.250f,
1459     A2 * 0.125f,
1460     A2 * 0.000f,
1461     A2 * 1.00f,
1462     A2 * 0.125f,
1463     A2 * 0.125f,
1464     A2 * 0.125f,
1465     A2 * 1.00f,
1466     A2 * 1.000f,
1467     A2 * 0.750f,
1468     A2 * 0.500f,
1469     A2 * 1.00f,
1470     A2 * 0.000f,
1471     A2 * 0.000f,
1472     A2 * 0.000f,
1473     A2 * 1.00f,
1474     A2 * 0.250f,
1475     A2 * 0.125f,
1476     A2 * 0.000f,
1477     A2 * 1.00f,
1478     A2 * 0.000f,
1479     A2 * 0.000f,
1480     A2 * 0.000f,
1481     A2 * 1.00f,
1482 
1483     A3 * 1.000f,
1484     A3 * 0.750f,
1485     A3 * 0.500f,
1486     A3 * 1.00f,
1487     A3 * 1.000f,
1488     A3 * 1.000f,
1489     A3 * 1.000f,
1490     A3 * 1.00f,
1491     A3 * 0.250f,
1492     A3 * 0.125f,
1493     A3 * 0.000f,
1494     A3 * 1.00f,
1495     A3 * 1.000f,
1496     A3 * 1.000f,
1497     A3 * 1.000f,
1498     A3 * 1.00f,
1499     A3 * 1.000f,
1500     A3 * 0.750f,
1501     A3 * 0.500f,
1502     A3 * 1.00f,
1503     A3 * 0.500f,
1504     A3 * 0.500f,
1505     A3 * 0.500f,
1506     A3 * 1.00f,
1507     A3 * 0.250f,
1508     A3 * 0.125f,
1509     A3 * 0.000f,
1510     A3 * 1.00f,
1511     A3 * 0.500f,
1512     A3 * 0.500f,
1513     A3 * 0.500f,
1514     A3 * 1.00f,
1515     A3 * 1.000f,
1516     A3 * 0.750f,
1517     A3 * 0.500f,
1518     A3 * 1.00f,
1519     A3 * 0.250f,
1520     A3 * 0.250f,
1521     A3 * 0.250f,
1522     A3 * 1.00f,
1523     A3 * 0.250f,
1524     A3 * 0.125f,
1525     A3 * 0.000f,
1526     A3 * 1.00f,
1527     A3 * 0.250f,
1528     A3 * 0.250f,
1529     A3 * 0.250f,
1530     A3 * 1.00f,
1531     A3 * 1.000f,
1532     A3 * 0.750f,
1533     A3 * 0.500f,
1534     A3 * 1.00f,
1535     A3 * 0.125f,
1536     A3 * 0.125f,
1537     A3 * 0.125f,
1538     A3 * 1.00f,
1539     A3 * 0.250f,
1540     A3 * 0.125f,
1541     A3 * 0.000f,
1542     A3 * 1.00f,
1543     A3 * 0.125f,
1544     A3 * 0.125f,
1545     A3 * 0.125f,
1546     A3 * 1.00f,
1547     A3 * 1.000f,
1548     A3 * 0.750f,
1549     A3 * 0.500f,
1550     A3 * 1.00f,
1551     A3 * 0.000f,
1552     A3 * 0.000f,
1553     A3 * 0.000f,
1554     A3 * 1.00f,
1555     A3 * 0.250f,
1556     A3 * 0.125f,
1557     A3 * 0.000f,
1558     A3 * 1.00f,
1559     A3 * 0.000f,
1560     A3 * 0.000f,
1561     A3 * 0.000f,
1562     A3 * 1.00f,
1563 };
1564 
MaskChannels(const tcu::PixelFormat & pf,const tcu::Vec4 & v)1565 static tcu::Vec4 MaskChannels(const tcu::PixelFormat &pf, const tcu::Vec4 &v)
1566 {
1567     return tcu::Vec4(pf.redBits > 0 ? v[0] : 0.f, pf.greenBits > 0 ? v[1] : 0.f, pf.blueBits > 0 ? v[2] : 0.f,
1568                      pf.alphaBits > 0 ? v[3] : 1.f);
1569 }
1570 
1571 //
1572 // Quantize the input colour by the colour bit depth for each channel.
1573 //
QuantizeChannels(const tcu::PixelFormat & pf,const tcu::Vec4 & v)1574 static tcu::Vec4 QuantizeChannels(const tcu::PixelFormat &pf, const tcu::Vec4 &v)
1575 {
1576     float maxChanel[4] = {static_cast<float>(1 << pf.redBits) - 1.0f, static_cast<float>(1 << pf.greenBits) - 1.0f,
1577                           static_cast<float>(1 << pf.blueBits) - 1.0f, static_cast<float>(1 << pf.alphaBits) - 1.0f};
1578 
1579     return tcu::Vec4(static_cast<float>((unsigned int)(v[0] * maxChanel[0])) / maxChanel[0],
1580                      static_cast<float>((unsigned int)(v[1] * maxChanel[1])) / maxChanel[1],
1581                      static_cast<float>((unsigned int)(v[2] * maxChanel[2])) / maxChanel[2],
1582                      pf.alphaBits ? static_cast<float>((unsigned int)(v[3] * maxChanel[3])) / maxChanel[3] : 1.0f);
1583 }
1584 
getTestColors(int index,tcu::Vec4 & src,tcu::Vec4 & dst) const1585 void BlendTestCaseGroup::BlendTest::getTestColors(int index, tcu::Vec4 &src, tcu::Vec4 &dst) const
1586 {
1587     DE_ASSERT(0 <= index && index < (m_useRGB10A2Data ? m_numSpecificColors : m_numColors));
1588 
1589     const tcu::RenderTarget &rt = m_context.getRenderContext().getRenderTarget();
1590     const tcu::PixelFormat &pf  = rt.getPixelFormat();
1591     const glw::GLfloat *s       = (m_useRGB10A2Data ? m_specificColors : m_colors) + 8 * index;
1592 
1593     src = MaskChannels(pf, tcu::Vec4(s[0], s[1], s[2], s[3]));
1594     dst = MaskChannels(pf, tcu::Vec4(s[4], s[5], s[6], s[7]));
1595     src = tcu::clamp(src, tcu::Vec4(0.f), tcu::Vec4(1.f));
1596     dst = tcu::clamp(dst, tcu::Vec4(0.f), tcu::Vec4(1.f));
1597 
1598     // Quantize the destination channels
1599     // this matches what implementation does on render target write
1600     dst = QuantizeChannels(pf, dst);
1601 }
1602 
getCoordinates(int index,int & x,int & y) const1603 void BlendTestCaseGroup::BlendTest::getCoordinates(int index, int &x, int &y) const
1604 {
1605     const tcu::RenderTarget &rt = m_context.getRenderContext().getRenderTarget();
1606     y                           = index / rt.getWidth();
1607     x                           = index % rt.getWidth();
1608 }
1609 
iterate(void)1610 BlendTestCaseGroup::BlendTest::IterateResult BlendTestCaseGroup::BlendTest::iterate(void)
1611 {
1612     const tcu::RenderTarget &rt = m_context.getRenderContext().getRenderTarget();
1613     const tcu::PixelFormat &pf  = rt.getPixelFormat();
1614     const glw::Functions &gl    = m_context.getRenderContext().getFunctions();
1615     TestLog &log                = m_testCtx.getLog();
1616 
1617     // Check that extension is supported.
1618     if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
1619     {
1620         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
1621         return STOP;
1622     }
1623 
1624     if ((GetBlendFunc(m_mode) == BlendHSLHue || GetBlendFunc(m_mode) == BlendHSLSaturation) &&
1625         (pf.redBits == 10 && pf.greenBits == 10 && pf.blueBits == 10 && pf.alphaBits == 2))
1626     {
1627         m_useRGB10A2Data = GL_TRUE;
1628     }
1629 
1630     // Setup program.
1631     std::string frgSrc =
1632         GetSolidShader(m_useAllQualifier ? "blend_support_all_equations" : GetLayoutQualifierStr(m_mode),
1633                        glu::getGLSLVersionDeclaration(m_glslVersion));
1634     glu::ShaderProgram p(m_context.getRenderContext(),
1635                          glu::makeVtxFragSources(GetDef2DVtxSrc(m_glslVersion).c_str(), frgSrc.c_str()));
1636     if (!p.isOk())
1637     {
1638         log << p;
1639         TCU_FAIL("Compile failed");
1640     }
1641     gl.useProgram(p.getProgram());
1642     GLU_EXPECT_NO_ERROR(gl.getError(), "Program failed");
1643 
1644     glu::VertexArrayBinding posBinding = glu::va::Float("aPos", 2, 4, 0, &s_pos[0]);
1645 
1646     // Enable blending and set blend equation.
1647     gl.disable(GL_DITHER);
1648     gl.enable(GL_SCISSOR_TEST);
1649     gl.enable(GL_BLEND);
1650     gl.blendEquation(m_mode);
1651     GLU_EXPECT_NO_ERROR(gl.getError(), "BlendEquation failed");
1652 
1653     bool needBarrier = !IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced_coherent");
1654 
1655     // Render loop.
1656     for (int colorIndex = 0; colorIndex < (m_useRGB10A2Data ? m_numSpecificColors : m_numColors); colorIndex++)
1657     {
1658         tcu::Vec4 srcCol, dstCol;
1659         getTestColors(colorIndex, srcCol, dstCol);
1660 
1661         // Get pixel to blend.
1662         int x, y;
1663         getCoordinates(colorIndex, x, y);
1664         gl.scissor(x, y, 1, 1);
1665 
1666         // Clear to destination color.
1667         gl.clearColor(dstCol[0], dstCol[1], dstCol[2], dstCol[3]);
1668         gl.clear(GL_COLOR_BUFFER_BIT);
1669         if (needBarrier)
1670             gl.blendBarrier();
1671 
1672         // Set source color.
1673         gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uSrcCol"), srcCol[0], srcCol[1], srcCol[2], srcCol[3]);
1674         GLU_EXPECT_NO_ERROR(gl.getError(), "Uniforms failed");
1675 
1676         // Draw.
1677         glu::draw(m_context.getRenderContext(), p.getProgram(), 1, &posBinding,
1678                   glu::pr::Triangles(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0]));
1679         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
1680         if (needBarrier)
1681             gl.blendBarrier();
1682     }
1683 
1684     // Read the results.
1685     const int w               = rt.getWidth();
1686     const int h               = rt.getHeight();
1687     glw::GLubyte *resultBytes = new glw::GLubyte[4 * w * h];
1688     gl.pixelStorei(GL_PACK_ALIGNMENT, 1);
1689     gl.readPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, resultBytes);
1690     GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed");
1691 
1692     bool pass = true;
1693     for (int colorIndex = 0; colorIndex < (m_useRGB10A2Data ? m_numSpecificColors : m_numColors); colorIndex++)
1694     {
1695         tcu::Vec4 srcCol, dstCol;
1696         getTestColors(colorIndex, srcCol, dstCol);
1697 
1698         // Get result and calculate reference.
1699         int x, y;
1700         getCoordinates(colorIndex, x, y);
1701 
1702         tcu::Vec4 refCol    = Blend(m_mode, srcCol, dstCol);
1703         tcu::RGBA ref       = pf.convertColor(tcu::RGBA(refCol));
1704         tcu::RGBA res       = tcu::RGBA::fromBytes(resultBytes + 4 * (x + w * y));
1705         tcu::RGBA tmp       = pf.getColorThreshold();
1706         tcu::RGBA threshold = tcu::RGBA(std::min(2 + 2 * tmp.getRed(), 255), std::min(2 + 2 * tmp.getGreen(), 255),
1707                                         std::min(2 + 2 * tmp.getBlue(), 255), std::min(2 + 2 * tmp.getAlpha(), 255));
1708         bool pixelOk        = tcu::compareThreshold(ref, res, threshold);
1709         pass                = pass && pixelOk;
1710         if (!pixelOk)
1711         {
1712             log << TestLog::Message << "(" << x << "," << y << ")  "
1713                 << "(" << colorIndex << ") "
1714                 << "Exceeds: " << threshold << " diff:" << tcu::computeAbsDiff(ref, res) << "  res:" << res
1715                 << "  ref:" << ref << "  dst:" << tcu::RGBA(dstCol) << "  src:" << tcu::RGBA(srcCol)
1716                 << TestLog::EndMessage;
1717         }
1718     }
1719 
1720     m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "" : "results differ");
1721     delete[] resultBytes;
1722     return STOP;
1723 }
1724 
1725 /*
1726  * From 'Other' part of the spec:
1727  *    "Test different behaviors for GLSL #extension
1728  *     GL_XXX_blend_equation_advanced"
1729  *
1730  * - require : Covered by "Blend" tests.
1731  * - enable  : Use layout modifier from GL_KHR_blend_equation_advanced and
1732  *             expect compile to succeed. (warn if not supported)
1733  * - warn    : Use layout modifier from GL_KHR_blend_equation_advanced and
1734  *             expect compile to succeed. (work, but issue warning)
1735  * - disable : Use layout modifier from GL_KHR_blend_equation_advanced and
1736  *             expect compile to fail with error.
1737  *
1738  */
1739 class ExtensionDirectiveTestCaseGroup : public deqp::TestCaseGroup
1740 {
1741 public:
ExtensionDirectiveTestCaseGroup(deqp::Context & context,glu::GLSLVersion glslVersion)1742     ExtensionDirectiveTestCaseGroup(deqp::Context &context, glu::GLSLVersion glslVersion)
1743         : TestCaseGroup(context, "extension_directive", "Test #extension directive.")
1744         , m_glslVersion(glslVersion)
1745     {
1746     }
1747 
init(void)1748     void init(void)
1749     {
1750         addChild(new ExtensionDirectiveTestCase(m_context, m_glslVersion, "disable"));
1751         addChild(new ExtensionDirectiveTestCase(m_context, m_glslVersion, "enable"));
1752         addChild(new ExtensionDirectiveTestCase(m_context, m_glslVersion, "warn"));
1753     }
1754 
1755 private:
1756     class ExtensionDirectiveTestCase : public deqp::TestCase
1757     {
1758     public:
ExtensionDirectiveTestCase(deqp::Context & context,glu::GLSLVersion glslVersion,const char * behaviour)1759         ExtensionDirectiveTestCase(deqp::Context &context, glu::GLSLVersion glslVersion, const char *behaviour)
1760             : TestCase(context, (std::string("extension_directive_") + behaviour).c_str(), "Test #extension directive.")
1761             , m_glslVersion(glslVersion)
1762             , m_behaviourStr(behaviour)
1763         {
1764             // Initialize expected compiler behaviour.
1765             std::string b(behaviour);
1766             if (b == "disable")
1767             {
1768                 m_requireInfoLog = true;
1769                 m_requireCompile = false;
1770             }
1771             else if (b == "enable")
1772             {
1773                 m_requireInfoLog = false;
1774                 m_requireCompile = true;
1775             }
1776             else
1777             {
1778                 DE_ASSERT(b == "warn");
1779                 m_requireInfoLog = false;
1780                 m_requireCompile = true;
1781             }
1782         }
1783 
iterate(void)1784         IterateResult iterate(void)
1785         {
1786             const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1787             TestLog &log             = m_testCtx.getLog();
1788             const int dim            = 4;
1789 
1790             // Check that extension is supported.
1791             if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
1792             {
1793                 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
1794                 return STOP;
1795             }
1796 
1797             FBOSentry fbo(gl, dim, dim, GL_RGBA8);
1798 
1799             tcu::Vec4 dstCol(1.f, 1.f, 1.f, 1.f);
1800             tcu::Vec4 srcCol(0.f, 0.f, 0.f, 1.f);
1801 
1802             // Clear to destination color.
1803             gl.clearColor(dstCol.x(), dstCol.y(), dstCol.z(), dstCol.w());
1804             gl.clear(GL_COLOR_BUFFER_BIT);
1805 
1806             // Setup program.
1807             std::string directive = "#extension GL_KHR_blend_equation_advanced : " + m_behaviourStr;
1808             std::string frgSrc = GetSolidShader("blend_support_multiply", glu::getGLSLVersionDeclaration(m_glslVersion),
1809                                                 directive.c_str());
1810             glu::ShaderProgram p(m_context.getRenderContext(),
1811                                  glu::makeVtxFragSources(GetDef2DVtxSrc(m_glslVersion).c_str(), frgSrc.c_str()));
1812             // If check that there is some info log if it is expected.
1813             const bool infoLogOk =
1814                 m_requireInfoLog ? p.getShaderInfo(glu::SHADERTYPE_FRAGMENT).infoLog.size() > 0 : true;
1815             if (!p.isOk())
1816             {
1817                 if (m_requireCompile)
1818                 {
1819                     log << p;
1820                     TCU_FAIL("Compile failed");
1821                 }
1822                 else
1823                 {
1824                     // If shader was expected to fail, so assume info log has something.
1825                     bool pass = infoLogOk;
1826                     m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1827                                             pass ? "Pass" : "Fail. Expected info log.");
1828                 }
1829                 return STOP;
1830             }
1831             gl.useProgram(p.getProgram());
1832             GLU_EXPECT_NO_ERROR(gl.getError(), "Program failed");
1833 
1834             // Program ok, check whether info log was as expected.
1835             if (!infoLogOk)
1836             {
1837                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail. No warnings were generated.");
1838                 return STOP;
1839             }
1840 
1841             // Enable blending and set blend equation.
1842             gl.disable(GL_DITHER);
1843             gl.enable(GL_BLEND);
1844             gl.blendEquation(GL_MULTIPLY_KHR);
1845             GLU_EXPECT_NO_ERROR(gl.getError(), "BlendEquation failed");
1846 
1847             // Setup source color.
1848             gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uSrcCol"), srcCol.x(), srcCol.y(), srcCol.z(),
1849                          srcCol.w());
1850             GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform failed");
1851 
1852             glu::VertexArrayBinding posBinding = glu::va::Float("aPos", 2, 4, 0, &s_pos[0]);
1853             GLU_EXPECT_NO_ERROR(gl.getError(), "Attributes failed");
1854 
1855             glu::draw(m_context.getRenderContext(), p.getProgram(), 1, &posBinding,
1856                       glu::pr::Triangles(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0]));
1857             GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
1858 
1859             // Check the result to see that extension was actually enabled.
1860             glw::GLubyte result[4] = {1, 2, 3, 4};
1861             gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, result);
1862             GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed");
1863             bool pass = tcu::RGBA::fromBytes(result) == tcu::RGBA(0, 0, 0, 0xFF);
1864             m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail");
1865 
1866             return STOP;
1867         }
1868 
1869     private:
1870         glu::GLSLVersion m_glslVersion;
1871         std::string m_behaviourStr;
1872         bool m_requireInfoLog;
1873         bool m_requireCompile;
1874     };
1875 
1876     glu::GLSLVersion m_glslVersion;
1877 };
1878 
1879 /*
1880  * From 'Other' part of the spec:
1881  *    "If XXX_blend_equation_advanced_coherent is supported, test
1882  *     Each blending mode needs to be tested without specifying the proper
1883  *     blend_support_[mode] or blend_support_all layout qualifier in the
1884  *     fragment shader. Expect INVALID_OPERATION GL error after calling
1885  *     DrawElements/Arrays."
1886  */
1887 class MissingQualifierTestGroup : public deqp::TestCaseGroup
1888 {
1889 public:
1890     enum MissingType
1891     {
1892         MISMATCH, // wrong qualifier in the shader.
1893         MISSING,  // no qualifier at all.
1894     };
1895 
MissingQualifierTestGroup(deqp::Context & context,glu::GLSLVersion glslVersion,MissingType missingType)1896     MissingQualifierTestGroup(deqp::Context &context, glu::GLSLVersion glslVersion, MissingType missingType)
1897         : TestCaseGroup(context, missingType == MISMATCH ? "mismatching_qualifier" : "missing_qualifier", "")
1898         , m_glslVersion(glslVersion)
1899         , m_missingType(missingType)
1900     {
1901     }
1902 
init(void)1903     void init(void)
1904     {
1905         // Pump individual modes.
1906         for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_modes); i++)
1907         {
1908             const char *qualifier = m_missingType == MISSING ?
1909                                         DE_NULL :
1910                                         GetLayoutQualifierStr(s_modes[(i + 1) % DE_LENGTH_OF_ARRAY(s_modes)]);
1911             addChild(new MissingCase(m_context, m_glslVersion, s_modes[i], qualifier));
1912         }
1913     }
1914 
1915 private:
1916     class MissingCase : public deqp::TestCase
1917     {
1918     public:
MissingCase(deqp::Context & context,glu::GLSLVersion glslVersion,glw::GLenum mode,const char * layoutQualifier)1919         MissingCase(deqp::Context &context, glu::GLSLVersion glslVersion, glw::GLenum mode, const char *layoutQualifier)
1920             : TestCase(context, GetModeStr(mode), "")
1921             , m_glslVersion(glslVersion)
1922             , m_mode(mode)
1923             , m_layoutQualifier(layoutQualifier)
1924         {
1925         }
1926 
1927         IterateResult iterate(void);
1928 
1929     private:
1930         glu::GLSLVersion m_glslVersion;
1931         glw::GLenum m_mode;
1932         const char *m_layoutQualifier; // NULL => no qualifier at all.
1933     };
1934 
1935     glu::GLSLVersion m_glslVersion;
1936     MissingType m_missingType;
1937 };
1938 
iterate(void)1939 MissingQualifierTestGroup::MissingCase::IterateResult MissingQualifierTestGroup::MissingCase::iterate(void)
1940 {
1941     const int dim            = 4;
1942     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1943     TestLog &log             = m_testCtx.getLog();
1944 
1945     // Check that extension is supported.
1946     if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
1947     {
1948         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
1949         return STOP;
1950     }
1951 
1952     FBOSentry fbo(gl, dim, dim, GL_RGBA8);
1953 
1954     tcu::Vec4 dstCol(1.f, 1.f, 1.f, 1.f);
1955     tcu::Vec4 srcCol(0.f, 0.f, 0.f, 1.f);
1956 
1957     // Clear to destination color.
1958     gl.clearColor(dstCol.x(), dstCol.y(), dstCol.z(), dstCol.w());
1959     gl.clear(GL_COLOR_BUFFER_BIT);
1960 
1961     // Setup program.
1962     glu::ShaderProgram p(m_context.getRenderContext(),
1963                          glu::makeVtxFragSources(
1964                              GetDef2DVtxSrc(m_glslVersion).c_str(),
1965                              GetSolidShader(m_layoutQualifier, glu::getGLSLVersionDeclaration(m_glslVersion)).c_str()));
1966     if (!p.isOk())
1967     {
1968         log << p;
1969         TCU_FAIL("Compile failed");
1970     }
1971 
1972     gl.useProgram(p.getProgram());
1973     GLU_EXPECT_NO_ERROR(gl.getError(), "Program failed");
1974 
1975     // Enable blending and set blend equation.
1976     gl.disable(GL_DITHER);
1977     gl.enable(GL_BLEND);
1978     gl.blendEquation(m_mode);
1979     GLU_EXPECT_NO_ERROR(gl.getError(), "BlendEquation failed");
1980 
1981     // Setup source color.
1982     gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uSrcCol"), srcCol.x(), srcCol.y(), srcCol.z(), srcCol.w());
1983     GLU_EXPECT_NO_ERROR(gl.getError(), "Uniform failed");
1984 
1985     glu::VertexArrayBinding posBinding = glu::va::Float("aPos", 2, 4, 0, &s_pos[0]);
1986     GLU_EXPECT_NO_ERROR(gl.getError(), "Attributes failed");
1987 
1988     glu::draw(m_context.getRenderContext(), p.getProgram(), 1, &posBinding,
1989               glu::pr::Triangles(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0]));
1990 
1991     glw::GLenum error = gl.getError();
1992     bool pass         = (error == GL_INVALID_OPERATION);
1993 
1994     m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail");
1995 
1996     return STOP;
1997 }
1998 
1999 /*
2000  * From 'Other' part of the spec:
2001  *    "If XXX_blend_equation_advanced_coherent is supported, test
2002  *     BLEND_ADVANCED_COHERENT_XXX setting:
2003  *     - The setting should work with Enable, Disable and IsEnable without producing errors
2004  *     - Default value should be TRUE"
2005  *
2006  *  1. Test that coherent is enabled by default.
2007  *  2. Disable and check the state.
2008  *  3. Enable and check the state and test that rendering does not produce errors.
2009  */
2010 
2011 class CoherentEnableCaseGroup : public deqp::TestCaseGroup
2012 {
2013 public:
CoherentEnableCaseGroup(deqp::Context & context)2014     CoherentEnableCaseGroup(deqp::Context &context) : TestCaseGroup(context, "coherent", "")
2015     {
2016     }
2017 
init(void)2018     void init(void)
2019     {
2020         addChild(new CoherentEnableCase(m_context));
2021     }
2022 
2023 private:
2024     class CoherentEnableCase : public deqp::TestCase
2025     {
2026     public:
CoherentEnableCase(deqp::Context & context)2027         CoherentEnableCase(deqp::Context &context) : TestCase(context, "enableDisable", "")
2028         {
2029         }
2030         IterateResult iterate(void);
2031     };
2032 };
2033 
iterate(void)2034 CoherentEnableCaseGroup::CoherentEnableCase::IterateResult CoherentEnableCaseGroup::CoherentEnableCase::iterate(void)
2035 {
2036     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2037 
2038     // Check that extension is supported.
2039     if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
2040     {
2041         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
2042         return STOP;
2043     }
2044     if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced_coherent"))
2045     {
2046         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced_coherent");
2047         return STOP;
2048     }
2049 
2050     std::vector<bool> res;
2051     // Enabled by default.
2052     res.push_back(gl.isEnabled(GL_BLEND_ADVANCED_COHERENT_KHR) == GL_TRUE);
2053     res.push_back(gl.getError() == GL_NO_ERROR);
2054 
2055     // Check disabling.
2056     gl.disable(GL_BLEND_ADVANCED_COHERENT_KHR);
2057     res.push_back(gl.getError() == GL_NO_ERROR);
2058     res.push_back(gl.isEnabled(GL_BLEND_ADVANCED_COHERENT_KHR) == GL_FALSE);
2059     res.push_back(gl.getError() == GL_NO_ERROR);
2060 
2061     // Check enabling.
2062     gl.enable(GL_BLEND_ADVANCED_COHERENT_KHR);
2063     res.push_back(gl.getError() == GL_NO_ERROR);
2064     res.push_back(gl.isEnabled(GL_BLEND_ADVANCED_COHERENT_KHR) == GL_TRUE);
2065     res.push_back(gl.getError() == GL_NO_ERROR);
2066 
2067     // Pass if no failures found.
2068     bool pass = std::find(res.begin(), res.end(), false) == res.end();
2069 
2070     m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail");
2071 
2072     return STOP;
2073 }
2074 /*
2075  * From 'Other' part of the spec:
2076  *    "Test that rendering into more than one color buffers at once produces
2077  *     INVALID_OPERATION error when calling drawArrays/drawElements"
2078  */
2079 class MRTCaseGroup : public deqp::TestCaseGroup
2080 {
2081 public:
MRTCaseGroup(deqp::Context & context,glu::GLSLVersion glslVersion)2082     MRTCaseGroup(deqp::Context &context, glu::GLSLVersion glslVersion)
2083         : TestCaseGroup(context, "MRT", "GL_KHR_blend_equation_advanced")
2084         , m_glslVersion(glslVersion)
2085     {
2086     }
2087 
init(void)2088     void init(void)
2089     {
2090         addChild(new MRTCase(m_context, m_glslVersion, MRTCase::ARRAY));
2091         addChild(new MRTCase(m_context, m_glslVersion, MRTCase::SEPARATE));
2092     }
2093 
2094 private:
2095     class MRTCase : public deqp::TestCase
2096     {
2097     public:
2098         enum DeclarationType
2099         {
2100             ARRAY,
2101             SEPARATE
2102         };
2103 
MRTCase(deqp::Context & context,glu::GLSLVersion glslVersion,DeclarationType declType)2104         MRTCase(deqp::Context &context, glu::GLSLVersion glslVersion, DeclarationType declType)
2105             : TestCase(context, (declType == ARRAY ? "MRT_array" : "MRT_separate"), "GL_KHR_blend_equation_advanced")
2106             , m_glslVersion(glslVersion)
2107             , m_declarationType(declType)
2108         {
2109             DE_ASSERT(m_declarationType == ARRAY || m_declarationType == SEPARATE);
2110         }
2111 
2112         IterateResult iterate(void);
2113 
2114     private:
2115         glu::GLSLVersion m_glslVersion;
2116         DeclarationType m_declarationType;
2117     };
2118 
2119     glu::GLSLVersion m_glslVersion;
2120 };
2121 
iterate(void)2122 MRTCaseGroup::MRTCase::IterateResult MRTCaseGroup::MRTCase::iterate(void)
2123 {
2124     TestLog &log             = m_testCtx.getLog();
2125     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2126 
2127     if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
2128     {
2129         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
2130         return STOP;
2131     }
2132 
2133     static const char *frgSrcTemplateArray = "${VERSION_DIRECTIVE}\n"
2134                                              "#extension GL_KHR_blend_equation_advanced : require\n"
2135                                              "\n"
2136                                              "precision highp float;\n"
2137                                              "layout (blend_support_multiply) out;\n"
2138                                              "layout (location = 0) out vec4 oCol[2];\n"
2139                                              "\n"
2140                                              "uniform vec4 uMultCol;\n"
2141                                              "\n"
2142                                              "void main (void) {\n"
2143                                              "   oCol[0] = uMultCol;\n"
2144                                              "   oCol[1] = uMultCol;\n"
2145                                              "}\n";
2146 
2147     static const char *frgSrcTemplateSeparate = "${VERSION_DIRECTIVE}\n"
2148                                                 "#extension GL_KHR_blend_equation_advanced : require\n"
2149                                                 "\n"
2150                                                 "precision highp float;\n"
2151                                                 "layout (blend_support_multiply) out;\n"
2152                                                 "layout (location = 0) out vec4 oCol0;\n"
2153                                                 "layout (location = 1) out vec4 oCol1;\n"
2154                                                 "\n"
2155                                                 "uniform vec4 uMultCol;\n"
2156                                                 "\n"
2157                                                 "void main (void) {\n"
2158                                                 "   oCol0 = uMultCol;\n"
2159                                                 "   oCol1 = uMultCol;\n"
2160                                                 "}\n";
2161 
2162     static const char *frgSrcTemplate = m_declarationType == ARRAY ? frgSrcTemplateArray : frgSrcTemplateSeparate;
2163 
2164     std::map<std::string, std::string> args;
2165     args["VERSION_DIRECTIVE"] = glu::getGLSLVersionDeclaration(m_glslVersion);
2166     std::string frgSrc        = tcu::StringTemplate(frgSrcTemplate).specialize(args);
2167 
2168     FBOSentry fbo(gl, 4, 4, GL_RGBA8, GL_RGBA8);
2169 
2170     static const glw::GLenum bufs[2] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1};
2171     gl.drawBuffers(2, bufs);
2172 
2173     // Clear buffers to white.
2174     gl.clearColor(1.f, 1.f, 1.f, 1.f);
2175     gl.clear(GL_COLOR_BUFFER_BIT);
2176 
2177     // Setup program.
2178     glu::ShaderProgram p(m_context.getRenderContext(),
2179                          glu::makeVtxFragSources(GetDef2DVtxSrc(m_glslVersion).c_str(), frgSrc.c_str()));
2180     if (!p.isOk())
2181     {
2182         log << p;
2183         TCU_FAIL("Compile failed");
2184     }
2185 
2186     gl.useProgram(p.getProgram());
2187     GLU_EXPECT_NO_ERROR(gl.getError(), "Program failed");
2188 
2189     // Enable blending and set blend equation.
2190     gl.disable(GL_DITHER);
2191     gl.enable(GL_BLEND);
2192     gl.blendEquation(GL_DARKEN_KHR);
2193     GLU_EXPECT_NO_ERROR(gl.getError(), "BlendEquation failed");
2194 
2195     // Multiply with zero.
2196     gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uMultCol"), 0.f, 0.f, 0.f, 1.00f);
2197     GLU_EXPECT_NO_ERROR(gl.getError(), "Uniforms failed");
2198 
2199     // Set vertex buffer
2200     glw::GLuint vbo;
2201     gl.genBuffers(1, &vbo);
2202     gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
2203     gl.bufferData(GL_ARRAY_BUFFER, sizeof(s_pos), s_pos, GL_STATIC_DRAW);
2204 
2205     // Set vertices.
2206     glw::GLuint vao;
2207     gl.genVertexArrays(1, &vao);
2208     gl.bindVertexArray(vao);
2209     glw::GLint loc = gl.getAttribLocation(p.getProgram(), "aPos");
2210     gl.enableVertexAttribArray(loc);
2211     gl.vertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 8, DE_NULL);
2212     GLU_EXPECT_NO_ERROR(gl.getError(), "Attributes failed");
2213 
2214     gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
2215     bool errorOk = (gl.getError() == GL_INVALID_OPERATION);
2216 
2217     gl.drawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, s_indices);
2218     errorOk = errorOk && (gl.getError() == GL_INVALID_OPERATION);
2219 
2220     if (!errorOk)
2221         log << TestLog::Message << "DrawArrays/DrawElements didn't produce error." << TestLog::EndMessage;
2222 
2223     // Expect unaltered destination pixels.
2224     bool contentsOk = true;
2225     for (int i = 0; i < 2; i++)
2226     {
2227         glw::GLubyte result[4] = {1, 2, 3, 4};
2228         gl.readBuffer(bufs[0]);
2229         gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, result);
2230         GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed");
2231         if (tcu::RGBA::fromBytes(result) != tcu::RGBA::white())
2232         {
2233             contentsOk = false;
2234             log << TestLog::Message << "Buffer " << i << " "
2235                 << "contents changed: " << tcu::RGBA::fromBytes(result) << " expected:" << tcu::RGBA::white()
2236                 << TestLog::EndMessage;
2237         }
2238     }
2239 
2240     gl.deleteVertexArrays(1, &vao);
2241     gl.deleteBuffers(1, &vbo);
2242 
2243     bool pass = errorOk && contentsOk;
2244     m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail");
2245     return STOP;
2246 }
2247 
2248 /*
2249  * From "Other" part of the spec:
2250  *    "Test that the new blending modes cannot be used with
2251  *     BlendEquationSeparate(i). Expect INVALID_ENUM GL error"
2252  *
2253  * Tests that BlendEquationSeparate does not accept extension's blending modes
2254  * either in rgb or alpha parameter.
2255  */
2256 class BlendEquationSeparateCase : public deqp::TestCaseGroup
2257 {
2258 public:
BlendEquationSeparateCase(deqp::Context & context)2259     BlendEquationSeparateCase(deqp::Context &context)
2260         : TestCaseGroup(context, "BlendEquationSeparate",
2261                         "Test that advanced blend modes are correctly rejected from glBlendEquationSeparate.")
2262     {
2263     }
2264 
init(void)2265     void init(void)
2266     {
2267         // Pump individual modes.
2268         for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_modes); i++)
2269             addChild(new ModeCase(m_context, s_modes[i]));
2270     }
2271 
2272 private:
2273     class ModeCase : public deqp::TestCase
2274     {
2275     public:
ModeCase(deqp::Context & context,glw::GLenum mode)2276         ModeCase(deqp::Context &context, glw::GLenum mode)
2277             : TestCase(context, GetModeStr(mode), "Test one mode")
2278             , m_mode(mode)
2279         {
2280         }
2281 
iterate(void)2282         IterateResult iterate(void)
2283         {
2284             // Check that extension is supported.
2285             if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
2286             {
2287                 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
2288                 return STOP;
2289             }
2290 
2291             const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2292 
2293             // Set separate blend equations.
2294             // Expect error and that default value (FUNC_ADD) is not changed.
2295 
2296             // RGB.
2297             gl.blendEquationSeparate(m_mode, GL_FUNC_ADD);
2298             bool rgbOk       = gl.getError() == GL_INVALID_ENUM;
2299             glw::GLint rgbEq = GL_NONE;
2300             gl.getIntegerv(GL_BLEND_EQUATION_RGB, &rgbEq);
2301             rgbOk = rgbOk && (rgbEq == GL_FUNC_ADD);
2302 
2303             // Alpha.
2304             gl.blendEquationSeparate(GL_FUNC_ADD, m_mode);
2305             bool alphaOk       = gl.getError() == GL_INVALID_ENUM;
2306             glw::GLint alphaEq = GL_NONE;
2307             gl.getIntegerv(GL_BLEND_EQUATION_ALPHA, &alphaEq);
2308             alphaOk = alphaOk && (alphaEq == GL_FUNC_ADD);
2309 
2310             bool pass = rgbOk && alphaOk;
2311             m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail");
2312             return STOP;
2313         }
2314 
2315     private:
2316         glw::GLenum m_mode;
2317     };
2318 };
2319 
2320 /*
2321  *  From "Other" part of the spec:
2322  *     "Check that GLSL GL_KHR_blend_equation_advanced #define exists and is 1"
2323  *
2324  *  Test that regardless of extension directive the definition exists and has value 1.
2325  */
2326 
2327 class PreprocessorCaseGroup : public deqp::TestCaseGroup
2328 {
2329 public:
PreprocessorCaseGroup(deqp::Context & context,glu::GLSLVersion glslVersion)2330     PreprocessorCaseGroup(deqp::Context &context, glu::GLSLVersion glslVersion)
2331         : TestCaseGroup(context, "preprocessor", "GL_KHR_blend_equation_advanced")
2332         , m_glslVersion(glslVersion)
2333     {
2334     }
2335 
init(void)2336     void init(void)
2337     {
2338         addChild(new PreprocessorCase(m_context, m_glslVersion, DE_NULL));
2339         addChild(new PreprocessorCase(m_context, m_glslVersion, "require"));
2340         addChild(new PreprocessorCase(m_context, m_glslVersion, "enable"));
2341         addChild(new PreprocessorCase(m_context, m_glslVersion, "warn"));
2342         addChild(new PreprocessorCase(m_context, m_glslVersion, "disable"));
2343     }
2344 
2345 private:
2346     class PreprocessorCase : public deqp::TestCase
2347     {
2348     public:
PreprocessorCase(deqp::Context & context,glu::GLSLVersion glslVersion,const char * behaviour)2349         PreprocessorCase(deqp::Context &context, glu::GLSLVersion glslVersion, const char *behaviour)
2350             : TestCase(context, behaviour ? behaviour : "none", "GL_KHR_blend_equation_advanced")
2351             , m_glslVersion(glslVersion)
2352             , m_behaviour(behaviour)
2353         {
2354         }
2355 
2356         IterateResult iterate(void);
2357 
2358     private:
2359         glu::GLSLVersion m_glslVersion;
2360         const char *m_behaviour;
2361     };
2362 
2363     glu::GLSLVersion m_glslVersion;
2364 };
2365 
iterate(void)2366 PreprocessorCaseGroup::PreprocessorCase::IterateResult PreprocessorCaseGroup::PreprocessorCase::iterate(void)
2367 {
2368     TestLog &log             = m_testCtx.getLog();
2369     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2370     const int dim            = 4;
2371 
2372     if (!IsExtensionSupported(m_context, "GL_KHR_blend_equation_advanced"))
2373     {
2374         m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_KHR_blend_equation_advanced");
2375         return STOP;
2376     }
2377 
2378     FBOSentry fbo(gl, dim, dim, GL_RGBA8);
2379     gl.clearColor(0.125f, 0.125f, 0.125f, 1.f);
2380     gl.clear(GL_COLOR_BUFFER_BIT);
2381 
2382     // Test that GL_KHR_blend_equation_advanced is defined and it has value 1.
2383     // Renders green pixels if above is true, red pixels otherwise.
2384     static const char *frgSrcTemplate = "${VERSION_DIRECTIVE}\n"
2385                                         "${EXTENSION_DIRECTIVE}\n"
2386                                         "precision highp float;\n"
2387                                         "\n"
2388                                         "uniform vec4 uDefined;\n"
2389                                         "uniform vec4 uNonDefined;\n"
2390                                         "\n"
2391                                         "uniform int  uValue;\n"
2392                                         "\n"
2393                                         "layout(location = 0) out vec4 oCol;\n"
2394                                         "\n"
2395                                         "void main (void) {\n"
2396                                         "    vec4 col = uNonDefined;\n"
2397                                         "#if defined(GL_KHR_blend_equation_advanced)\n"
2398                                         "    int val = GL_KHR_blend_equation_advanced;\n"
2399                                         "    if (uValue == val) {\n"
2400                                         "        col = uDefined;\n"
2401                                         "    }\n"
2402                                         "#endif\n"
2403                                         "    oCol = col;\n"
2404                                         "}\n";
2405 
2406     std::map<std::string, std::string> args;
2407     args["VERSION_DIRECTIVE"] = glu::getGLSLVersionDeclaration(m_glslVersion);
2408     if (m_behaviour)
2409         args["EXTENSION_DIRECTIVE"] = std::string("#extension GL_KHR_blend_equation_advanced : ") + m_behaviour;
2410     else
2411         args["EXTENSION_DIRECTIVE"] = "";
2412     std::string frgSrc = tcu::StringTemplate(frgSrcTemplate).specialize(args);
2413 
2414     glu::ShaderProgram p(m_context.getRenderContext(),
2415                          glu::makeVtxFragSources(GetDef2DVtxSrc(m_glslVersion).c_str(), frgSrc.c_str()));
2416     if (!p.isOk())
2417     {
2418         log << p;
2419         TCU_FAIL("Compile failed");
2420     }
2421     gl.useProgram(p.getProgram());
2422     GLU_EXPECT_NO_ERROR(gl.getError(), "Program failed");
2423 
2424     gl.uniform1i(gl.getUniformLocation(p.getProgram(), "uValue"), 1);
2425     gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uDefined"), 0.f, 1.f, 0.f, 1.f);
2426     gl.uniform4f(gl.getUniformLocation(p.getProgram(), "uNonDefined"), 1.f, 0.f, 1.f, 1.f);
2427     GLU_EXPECT_NO_ERROR(gl.getError(), "Uniforms failed");
2428 
2429     glu::VertexArrayBinding posBinding = glu::va::Float("aPos", 2, 4, 0, &s_pos[0]);
2430     glu::draw(m_context.getRenderContext(), p.getProgram(), 1, &posBinding,
2431               glu::pr::Triangles(DE_LENGTH_OF_ARRAY(s_indices), &s_indices[0]));
2432     GLU_EXPECT_NO_ERROR(gl.getError(), "Draw failed");
2433 
2434     // Check the results.
2435     tcu::Surface resultSurface(dim, dim);
2436     glu::readPixels(m_context.getRenderContext(), 0, 0, resultSurface.getAccess());
2437     GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels failed");
2438     bool pass = tcu::RGBA::green() == resultSurface.getPixel(0, 0);
2439 
2440     m_testCtx.setTestResult(pass ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, pass ? "Pass" : "Fail");
2441 
2442     return STOP;
2443 }
2444 
BlendEquationAdvancedTests(deqp::Context & context,glu::GLSLVersion glslVersion)2445 BlendEquationAdvancedTests::BlendEquationAdvancedTests(deqp::Context &context, glu::GLSLVersion glslVersion)
2446     : TestCaseGroup(context, "blend_equation_advanced", "KHR_blend_equation_advanced tests")
2447     , m_glslVersion(glslVersion)
2448 {
2449 }
2450 
~BlendEquationAdvancedTests(void)2451 BlendEquationAdvancedTests::~BlendEquationAdvancedTests(void)
2452 {
2453 }
2454 
init(void)2455 void BlendEquationAdvancedTests::init(void)
2456 {
2457     // Test that enable/disable and getting status works.
2458     addChild(new CoherentEnableCaseGroup(m_context));
2459 
2460     // Test that preprocessor macro GL_KHR_blend_equation_advanced
2461     // is always defined and its value is 1.
2462     addChild(new PreprocessorCaseGroup(m_context, m_glslVersion));
2463 
2464     // Test that BlendEquationSeparate rejects advanced blend modes.
2465     addChild(new BlendEquationSeparateCase(m_context));
2466 
2467     // Test that advanced blend equations cannot be used with multiple render targets.
2468     addChild(new MRTCaseGroup(m_context, m_glslVersion));
2469 
2470     // Test that using new blend modes produce errors if appropriate qualifier
2471     // is not in the shader (test without any blend qualifier and with mismatching qualifier).
2472     addChild(new MissingQualifierTestGroup(m_context, m_glslVersion, MissingQualifierTestGroup::MISMATCH));
2473     addChild(new MissingQualifierTestGroup(m_context, m_glslVersion, MissingQualifierTestGroup::MISSING));
2474 
2475     // Test #extension directive behaviour.
2476     // Case "require" is tested indirectly by blending tests.
2477     addChild(new ExtensionDirectiveTestCaseGroup(m_context, m_glslVersion));
2478 
2479     // Test that each blend mode produces correct results.
2480     addChild(new BlendTestCaseGroup(m_context, m_glslVersion, BlendTestCaseGroup::ALL_QUALIFIER));
2481     addChild(new BlendTestCaseGroup(m_context, m_glslVersion, BlendTestCaseGroup::MATCHING_QUALIFIER));
2482 
2483     // Test that coherent blending or barrier works.
2484     addChild(new CoherentBlendTestCaseGroup(m_context, m_glslVersion));
2485 }
2486 
2487 } // namespace glcts
2488