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