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