1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * OpenGL Conformance Test Suite
3e5c31af7Sopenharmony_ci * -----------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright (c) 2014-2016 The Khronos Group Inc.
6e5c31af7Sopenharmony_ci *
7e5c31af7Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
8e5c31af7Sopenharmony_ci * you may not use this file except in compliance with the License.
9e5c31af7Sopenharmony_ci * You may obtain a copy of the License at
10e5c31af7Sopenharmony_ci *
11e5c31af7Sopenharmony_ci *      http://www.apache.org/licenses/LICENSE-2.0
12e5c31af7Sopenharmony_ci *
13e5c31af7Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
14e5c31af7Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
15e5c31af7Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16e5c31af7Sopenharmony_ci * See the License for the specific language governing permissions and
17e5c31af7Sopenharmony_ci * limitations under the License.
18e5c31af7Sopenharmony_ci *
19e5c31af7Sopenharmony_ci */ /*!
20e5c31af7Sopenharmony_ci * \file
21e5c31af7Sopenharmony_ci * \brief
22e5c31af7Sopenharmony_ci */ /*-------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "deMath.h"
25e5c31af7Sopenharmony_ci#include "deRandom.hpp"
26e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
27e5c31af7Sopenharmony_ci#include "gl4cES31CompatibilityTests.hpp"
28e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp"
29e5c31af7Sopenharmony_ci#include "gluDrawUtil.hpp"
30e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp"
31e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp"
32e5c31af7Sopenharmony_ci#include "glw.h"
33e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
34e5c31af7Sopenharmony_ci#include "tcuCommandLine.hpp"
35e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
36e5c31af7Sopenharmony_ci#include "tcuSurface.hpp"
37e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
38e5c31af7Sopenharmony_ci
39e5c31af7Sopenharmony_cinamespace tcu
40e5c31af7Sopenharmony_ci{
41e5c31af7Sopenharmony_cistatic bool operator<(tcu::Vec4 const& k1, tcu::Vec4 const& k2)
42e5c31af7Sopenharmony_ci{
43e5c31af7Sopenharmony_ci	if (k1.y() < k2.y())
44e5c31af7Sopenharmony_ci	{
45e5c31af7Sopenharmony_ci		return true;
46e5c31af7Sopenharmony_ci	}
47e5c31af7Sopenharmony_ci	else if (k1.y() == k2.y())
48e5c31af7Sopenharmony_ci	{
49e5c31af7Sopenharmony_ci		return k1.x() < k2.x();
50e5c31af7Sopenharmony_ci	}
51e5c31af7Sopenharmony_ci	else
52e5c31af7Sopenharmony_ci	{
53e5c31af7Sopenharmony_ci		return false;
54e5c31af7Sopenharmony_ci	}
55e5c31af7Sopenharmony_ci}
56e5c31af7Sopenharmony_ci}
57e5c31af7Sopenharmony_ci
58e5c31af7Sopenharmony_cinamespace gl4cts
59e5c31af7Sopenharmony_ci{
60e5c31af7Sopenharmony_cinamespace es31compatibility
61e5c31af7Sopenharmony_ci{
62e5c31af7Sopenharmony_ci
63e5c31af7Sopenharmony_ciusing tcu::TestLog;
64e5c31af7Sopenharmony_ciusing std::string;
65e5c31af7Sopenharmony_ciusing std::vector;
66e5c31af7Sopenharmony_ciusing deqp::Context;
67e5c31af7Sopenharmony_ci
68e5c31af7Sopenharmony_cistatic std::string specializeVersion(std::string const& source, glu::GLSLVersion version,
69e5c31af7Sopenharmony_ci									 std::string const& sampler = "", std::string const& outType = "")
70e5c31af7Sopenharmony_ci{
71e5c31af7Sopenharmony_ci	DE_ASSERT(version == glu::GLSL_VERSION_310_ES || version >= glu::GLSL_VERSION_400);
72e5c31af7Sopenharmony_ci	std::map<std::string, std::string> args;
73e5c31af7Sopenharmony_ci	args["VERSION_DECL"] = glu::getGLSLVersionDeclaration(version);
74e5c31af7Sopenharmony_ci	args["SAMPLER"]		 = sampler;
75e5c31af7Sopenharmony_ci	args["OUT_TYPE"]	 = outType;
76e5c31af7Sopenharmony_ci	if (version == glu::GLSL_VERSION_310_ES)
77e5c31af7Sopenharmony_ci	{
78e5c31af7Sopenharmony_ci		args["OES_SV_RQ"] = "#extension GL_OES_sample_variables : require\n";
79e5c31af7Sopenharmony_ci		args["OES_SV_EN"] = "#extension GL_OES_sample_variables : enable\n";
80e5c31af7Sopenharmony_ci	}
81e5c31af7Sopenharmony_ci	else
82e5c31af7Sopenharmony_ci	{
83e5c31af7Sopenharmony_ci		args["OES_SV_RQ"] = "";
84e5c31af7Sopenharmony_ci		args["OES_SV_EN"] = "";
85e5c31af7Sopenharmony_ci	}
86e5c31af7Sopenharmony_ci	return tcu::StringTemplate(source.c_str()).specialize(args);
87e5c31af7Sopenharmony_ci}
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_ciclass SampleShadingExtensionCase : public deqp::TestCase
90e5c31af7Sopenharmony_ci{
91e5c31af7Sopenharmony_cipublic:
92e5c31af7Sopenharmony_ci	SampleShadingExtensionCase(Context& context, const char* name, const char* description,
93e5c31af7Sopenharmony_ci							   glu::GLSLVersion glslVersion);
94e5c31af7Sopenharmony_ci	~SampleShadingExtensionCase();
95e5c31af7Sopenharmony_ci
96e5c31af7Sopenharmony_ci	IterateResult iterate();
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_ciprotected:
99e5c31af7Sopenharmony_ci	glu::GLSLVersion m_glslVersion;
100e5c31af7Sopenharmony_ci};
101e5c31af7Sopenharmony_ci
102e5c31af7Sopenharmony_ciSampleShadingExtensionCase::SampleShadingExtensionCase(Context& context, const char* name, const char* description,
103e5c31af7Sopenharmony_ci													   glu::GLSLVersion glslVersion)
104e5c31af7Sopenharmony_ci	: TestCase(context, name, description), m_glslVersion(glslVersion)
105e5c31af7Sopenharmony_ci{
106e5c31af7Sopenharmony_ci	DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES);
107e5c31af7Sopenharmony_ci}
108e5c31af7Sopenharmony_ci
109e5c31af7Sopenharmony_ciSampleShadingExtensionCase::~SampleShadingExtensionCase()
110e5c31af7Sopenharmony_ci{
111e5c31af7Sopenharmony_ci}
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_ciSampleShadingExtensionCase::IterateResult SampleShadingExtensionCase::iterate()
114e5c31af7Sopenharmony_ci{
115e5c31af7Sopenharmony_ci	TestLog& log = m_testCtx.getLog();
116e5c31af7Sopenharmony_ci
117e5c31af7Sopenharmony_ci	/* OpenGL support query. */
118e5c31af7Sopenharmony_ci	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
119e5c31af7Sopenharmony_ci	bool is_arb_es31_compatibility = m_context.getContextInfo().isExtensionSupported("GL_ARB_ES3_1_compatibility");
120e5c31af7Sopenharmony_ci
121e5c31af7Sopenharmony_ci	if (!(is_at_least_gl_45 || is_arb_es31_compatibility))
122e5c31af7Sopenharmony_ci	{
123e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_ARB_ES3_1_compatibility");
124e5c31af7Sopenharmony_ci		return STOP;
125e5c31af7Sopenharmony_ci	}
126e5c31af7Sopenharmony_ci
127e5c31af7Sopenharmony_ci	static char const* vss = "${VERSION_DECL}\n"
128e5c31af7Sopenharmony_ci							 "in highp vec4 a_position;\n"
129e5c31af7Sopenharmony_ci							 "void main()\n"
130e5c31af7Sopenharmony_ci							 "{\n"
131e5c31af7Sopenharmony_ci							 "    gl_Position = a_position;\n"
132e5c31af7Sopenharmony_ci							 "}\n";
133e5c31af7Sopenharmony_ci
134e5c31af7Sopenharmony_ci	{
135e5c31af7Sopenharmony_ci		static char const* fss = "${VERSION_DECL}\n"
136e5c31af7Sopenharmony_ci								 "${OES_SV_RQ}"
137e5c31af7Sopenharmony_ci								 "out highp vec4 o_color;\n"
138e5c31af7Sopenharmony_ci								 "void main()\n"
139e5c31af7Sopenharmony_ci								 "{\n"
140e5c31af7Sopenharmony_ci								 "    for (int i = 0; i < (gl_MaxSamples + 31) / 32; ++i) {\n"
141e5c31af7Sopenharmony_ci								 "        gl_SampleMask[i] = gl_SampleMaskIn[i];\n"
142e5c31af7Sopenharmony_ci								 "    }\n"
143e5c31af7Sopenharmony_ci								 "    o_color = vec4(gl_SampleID, gl_SamplePosition.x, gl_SamplePosition.y, 1);\n"
144e5c31af7Sopenharmony_ci								 "}\n";
145e5c31af7Sopenharmony_ci
146e5c31af7Sopenharmony_ci		glu::ShaderProgram programRequire(m_context.getRenderContext(),
147e5c31af7Sopenharmony_ci										  glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion).c_str(),
148e5c31af7Sopenharmony_ci																  specializeVersion(fss, m_glslVersion).c_str()));
149e5c31af7Sopenharmony_ci		log << programRequire;
150e5c31af7Sopenharmony_ci		if (!programRequire.isOk())
151e5c31af7Sopenharmony_ci		{
152e5c31af7Sopenharmony_ci			TCU_FAIL("Compile failed");
153e5c31af7Sopenharmony_ci		}
154e5c31af7Sopenharmony_ci	}
155e5c31af7Sopenharmony_ci
156e5c31af7Sopenharmony_ci	{
157e5c31af7Sopenharmony_ci		static char const* fss = "${VERSION_DECL}\n"
158e5c31af7Sopenharmony_ci								 "${OES_SV_EN}"
159e5c31af7Sopenharmony_ci								 "out highp vec4 o_color;\n"
160e5c31af7Sopenharmony_ci								 "void main()\n"
161e5c31af7Sopenharmony_ci								 "{\n"
162e5c31af7Sopenharmony_ci								 "#if !GL_OES_sample_variables\n"
163e5c31af7Sopenharmony_ci								 "    this is broken\n"
164e5c31af7Sopenharmony_ci								 "#endif\n"
165e5c31af7Sopenharmony_ci								 "    for (int i = 0; i < (gl_MaxSamples + 31) / 32; ++i) {\n"
166e5c31af7Sopenharmony_ci								 "        gl_SampleMask[i] = gl_SampleMaskIn[i];\n"
167e5c31af7Sopenharmony_ci								 "    }\n"
168e5c31af7Sopenharmony_ci								 "    o_color = vec4(gl_SampleID, gl_SamplePosition.x, gl_SamplePosition.y, 1);\n"
169e5c31af7Sopenharmony_ci								 "}\n";
170e5c31af7Sopenharmony_ci
171e5c31af7Sopenharmony_ci		glu::ShaderProgram programEnable(m_context.getRenderContext(),
172e5c31af7Sopenharmony_ci										 glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion).c_str(),
173e5c31af7Sopenharmony_ci																 specializeVersion(fss, m_glslVersion).c_str()));
174e5c31af7Sopenharmony_ci		log << programEnable;
175e5c31af7Sopenharmony_ci		if (!programEnable.isOk())
176e5c31af7Sopenharmony_ci		{
177e5c31af7Sopenharmony_ci			TCU_FAIL("Compile failed");
178e5c31af7Sopenharmony_ci		}
179e5c31af7Sopenharmony_ci	}
180e5c31af7Sopenharmony_ci
181e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
182e5c31af7Sopenharmony_ci	return STOP;
183e5c31af7Sopenharmony_ci}
184e5c31af7Sopenharmony_ci
185e5c31af7Sopenharmony_ciclass SampleShadingMaskCase : public deqp::TestCase
186e5c31af7Sopenharmony_ci{
187e5c31af7Sopenharmony_cipublic:
188e5c31af7Sopenharmony_ci	SampleShadingMaskCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion,
189e5c31af7Sopenharmony_ci						  GLenum internalFormat, tcu::TextureFormat const& texFormat, const char* sampler,
190e5c31af7Sopenharmony_ci						  const char* outType, GLint samples, GLint sampleMask);
191e5c31af7Sopenharmony_ci	~SampleShadingMaskCase();
192e5c31af7Sopenharmony_ci
193e5c31af7Sopenharmony_ci	IterateResult iterate();
194e5c31af7Sopenharmony_ci
195e5c31af7Sopenharmony_ciprotected:
196e5c31af7Sopenharmony_ci	glu::GLSLVersion   m_glslVersion;
197e5c31af7Sopenharmony_ci	GLenum			   m_internalFormat;
198e5c31af7Sopenharmony_ci	tcu::TextureFormat m_texFormat;
199e5c31af7Sopenharmony_ci	std::string		   m_sampler;
200e5c31af7Sopenharmony_ci	std::string		   m_outType;
201e5c31af7Sopenharmony_ci	GLint			   m_samples;
202e5c31af7Sopenharmony_ci	GLint			   m_sampleMask;
203e5c31af7Sopenharmony_ci
204e5c31af7Sopenharmony_ci	enum
205e5c31af7Sopenharmony_ci	{
206e5c31af7Sopenharmony_ci		WIDTH		= 16,
207e5c31af7Sopenharmony_ci		HEIGHT		= 16,
208e5c31af7Sopenharmony_ci		MAX_SAMPLES = 4,
209e5c31af7Sopenharmony_ci	};
210e5c31af7Sopenharmony_ci};
211e5c31af7Sopenharmony_ci
212e5c31af7Sopenharmony_ciSampleShadingMaskCase::SampleShadingMaskCase(Context& context, const char* name, const char* description,
213e5c31af7Sopenharmony_ci											 glu::GLSLVersion glslVersion, GLenum internalFormat,
214e5c31af7Sopenharmony_ci											 tcu::TextureFormat const& texFormat, const char* sampler,
215e5c31af7Sopenharmony_ci											 const char* outType, GLint samples, GLint sampleMask)
216e5c31af7Sopenharmony_ci	: TestCase(context, name, description)
217e5c31af7Sopenharmony_ci	, m_glslVersion(glslVersion)
218e5c31af7Sopenharmony_ci	, m_internalFormat(internalFormat)
219e5c31af7Sopenharmony_ci	, m_texFormat(texFormat)
220e5c31af7Sopenharmony_ci	, m_sampler(sampler)
221e5c31af7Sopenharmony_ci	, m_outType(outType)
222e5c31af7Sopenharmony_ci	, m_samples(samples)
223e5c31af7Sopenharmony_ci	, m_sampleMask(sampleMask)
224e5c31af7Sopenharmony_ci{
225e5c31af7Sopenharmony_ci	DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_400);
226e5c31af7Sopenharmony_ci}
227e5c31af7Sopenharmony_ci
228e5c31af7Sopenharmony_ciSampleShadingMaskCase::~SampleShadingMaskCase()
229e5c31af7Sopenharmony_ci{
230e5c31af7Sopenharmony_ci}
231e5c31af7Sopenharmony_ci
232e5c31af7Sopenharmony_ciSampleShadingMaskCase::IterateResult SampleShadingMaskCase::iterate()
233e5c31af7Sopenharmony_ci{
234e5c31af7Sopenharmony_ci	TestLog&			  log  = m_testCtx.getLog();
235e5c31af7Sopenharmony_ci	const glw::Functions& gl   = m_context.getRenderContext().getFunctions();
236e5c31af7Sopenharmony_ci	bool				  isOk = true;
237e5c31af7Sopenharmony_ci
238e5c31af7Sopenharmony_ci	/* OpenGL support query. */
239e5c31af7Sopenharmony_ci	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
240e5c31af7Sopenharmony_ci	bool is_arb_es31_compatibility = m_context.getContextInfo().isExtensionSupported("GL_ARB_ES3_1_compatibility");
241e5c31af7Sopenharmony_ci
242e5c31af7Sopenharmony_ci	if (!(is_at_least_gl_45 || is_arb_es31_compatibility))
243e5c31af7Sopenharmony_ci	{
244e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_ARB_ES3_1_compatibility");
245e5c31af7Sopenharmony_ci		return STOP;
246e5c31af7Sopenharmony_ci	}
247e5c31af7Sopenharmony_ci
248e5c31af7Sopenharmony_ci	GLint maxSamples;
249e5c31af7Sopenharmony_ci	if (((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::RGBA)) ||
250e5c31af7Sopenharmony_ci		((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::RG)) ||
251e5c31af7Sopenharmony_ci		((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::R)) ||
252e5c31af7Sopenharmony_ci		((m_texFormat.type == tcu::TextureFormat::HALF_FLOAT) && (m_texFormat.order == tcu::TextureFormat::RGBA)))
253e5c31af7Sopenharmony_ci	{
254e5c31af7Sopenharmony_ci		gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, m_internalFormat, GL_SAMPLES, 1, &maxSamples);
255e5c31af7Sopenharmony_ci		if (m_samples > maxSamples)
256e5c31af7Sopenharmony_ci		{
257e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED,
258e5c31af7Sopenharmony_ci									"Test sample count greater than samples that the format supports");
259e5c31af7Sopenharmony_ci			return STOP;
260e5c31af7Sopenharmony_ci		}
261e5c31af7Sopenharmony_ci	}
262e5c31af7Sopenharmony_ci	else if (m_texFormat.type == tcu::TextureFormat::SIGNED_INT8 ||
263e5c31af7Sopenharmony_ci			 m_texFormat.type == tcu::TextureFormat::UNSIGNED_INT8)
264e5c31af7Sopenharmony_ci	{
265e5c31af7Sopenharmony_ci		gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &maxSamples);
266e5c31af7Sopenharmony_ci		if (m_samples > maxSamples)
267e5c31af7Sopenharmony_ci		{
268e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test sample count greater than MAX_INTEGER_SAMPLES");
269e5c31af7Sopenharmony_ci			return STOP;
270e5c31af7Sopenharmony_ci		}
271e5c31af7Sopenharmony_ci	}
272e5c31af7Sopenharmony_ci	else
273e5c31af7Sopenharmony_ci	{
274e5c31af7Sopenharmony_ci		gl.getIntegerv(GL_MAX_SAMPLES, &maxSamples);
275e5c31af7Sopenharmony_ci		if (m_samples > maxSamples)
276e5c31af7Sopenharmony_ci		{
277e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test sample count greater than MAX_SAMPLES");
278e5c31af7Sopenharmony_ci			return STOP;
279e5c31af7Sopenharmony_ci		}
280e5c31af7Sopenharmony_ci	}
281e5c31af7Sopenharmony_ci
282e5c31af7Sopenharmony_ci	// Create a multisample texture, or a regular texture if samples is zero.
283e5c31af7Sopenharmony_ci	GLuint tex;
284e5c31af7Sopenharmony_ci	gl.genTextures(1, &tex);
285e5c31af7Sopenharmony_ci	GLenum target;
286e5c31af7Sopenharmony_ci	if (m_samples)
287e5c31af7Sopenharmony_ci	{
288e5c31af7Sopenharmony_ci		target = GL_TEXTURE_2D_MULTISAMPLE;
289e5c31af7Sopenharmony_ci		gl.bindTexture(target, tex);
290e5c31af7Sopenharmony_ci		gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, m_internalFormat, WIDTH, HEIGHT, GL_FALSE);
291e5c31af7Sopenharmony_ci	}
292e5c31af7Sopenharmony_ci	else
293e5c31af7Sopenharmony_ci	{
294e5c31af7Sopenharmony_ci		target = GL_TEXTURE_2D;
295e5c31af7Sopenharmony_ci		gl.bindTexture(target, tex);
296e5c31af7Sopenharmony_ci		gl.texStorage2D(GL_TEXTURE_2D, 1, m_internalFormat, WIDTH, HEIGHT);
297e5c31af7Sopenharmony_ci		if (m_texFormat.type == tcu::TextureFormat::SIGNED_INT8 ||
298e5c31af7Sopenharmony_ci			m_texFormat.type == tcu::TextureFormat::UNSIGNED_INT8 || m_texFormat.type == tcu::TextureFormat::FLOAT)
299e5c31af7Sopenharmony_ci		{
300e5c31af7Sopenharmony_ci			gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
301e5c31af7Sopenharmony_ci			gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
302e5c31af7Sopenharmony_ci		}
303e5c31af7Sopenharmony_ci	}
304e5c31af7Sopenharmony_ci
305e5c31af7Sopenharmony_ci	// Create a framebuffer with the texture attached and clear to "green".
306e5c31af7Sopenharmony_ci	GLuint fboMs;
307e5c31af7Sopenharmony_ci	gl.genFramebuffers(1, &fboMs);
308e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, fboMs);
309e5c31af7Sopenharmony_ci	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, tex, 0);
310e5c31af7Sopenharmony_ci	gl.viewport(0, 0, WIDTH, HEIGHT);
311e5c31af7Sopenharmony_ci	if (m_texFormat.type == tcu::TextureFormat::SIGNED_INT8)
312e5c31af7Sopenharmony_ci	{
313e5c31af7Sopenharmony_ci		GLint color[4] = { 0, 1, 0, 1 };
314e5c31af7Sopenharmony_ci		gl.clearBufferiv(GL_COLOR, 0, color);
315e5c31af7Sopenharmony_ci	}
316e5c31af7Sopenharmony_ci	else if (m_texFormat.type == tcu::TextureFormat::UNSIGNED_INT8)
317e5c31af7Sopenharmony_ci	{
318e5c31af7Sopenharmony_ci		GLuint color[4] = { 0, 1, 0, 1 };
319e5c31af7Sopenharmony_ci		gl.clearBufferuiv(GL_COLOR, 0, color);
320e5c31af7Sopenharmony_ci	}
321e5c31af7Sopenharmony_ci	else
322e5c31af7Sopenharmony_ci	{
323e5c31af7Sopenharmony_ci		GLfloat color[4] = { 0.0f, 1.0f, 0.0f, 1.0f };
324e5c31af7Sopenharmony_ci		gl.clearBufferfv(GL_COLOR, 0, color);
325e5c31af7Sopenharmony_ci	}
326e5c31af7Sopenharmony_ci
327e5c31af7Sopenharmony_ci	static deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 };
328e5c31af7Sopenharmony_ci
329e5c31af7Sopenharmony_ci	{
330e5c31af7Sopenharmony_ci		// Draw a quad setting all samples to "red". We only expect "red"
331e5c31af7Sopenharmony_ci		// to be written if the sample mask bit for that sample is 1.
332e5c31af7Sopenharmony_ci
333e5c31af7Sopenharmony_ci		static char const* vss = "${VERSION_DECL}\n"
334e5c31af7Sopenharmony_ci								 "in highp vec2 a_position;\n"
335e5c31af7Sopenharmony_ci								 "void main()\n"
336e5c31af7Sopenharmony_ci								 "{\n"
337e5c31af7Sopenharmony_ci								 "   gl_Position = vec4(a_position, 0.0, 1.0);\n"
338e5c31af7Sopenharmony_ci								 "}\n";
339e5c31af7Sopenharmony_ci
340e5c31af7Sopenharmony_ci		static char const* fss = "${VERSION_DECL}\n"
341e5c31af7Sopenharmony_ci								 "${OES_SV_RQ}"
342e5c31af7Sopenharmony_ci								 "layout(location = 0) out highp ${OUT_TYPE} o_color;\n"
343e5c31af7Sopenharmony_ci								 "uniform int u_sampleMask;\n"
344e5c31af7Sopenharmony_ci								 "void main()\n"
345e5c31af7Sopenharmony_ci								 "{\n"
346e5c31af7Sopenharmony_ci								 "    for (int i = 0; i < (gl_NumSamples + 31) / 32; ++i) {\n"
347e5c31af7Sopenharmony_ci								 "        gl_SampleMask[i] = u_sampleMask & gl_SampleMaskIn[i];\n"
348e5c31af7Sopenharmony_ci								 "    }\n"
349e5c31af7Sopenharmony_ci								 "    o_color = ${OUT_TYPE}(1, 0, 0, 1);\n"
350e5c31af7Sopenharmony_ci								 "}\n";
351e5c31af7Sopenharmony_ci
352e5c31af7Sopenharmony_ci		glu::ShaderProgram program(
353e5c31af7Sopenharmony_ci			m_context.getRenderContext(),
354e5c31af7Sopenharmony_ci			glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion, m_sampler, m_outType).c_str(),
355e5c31af7Sopenharmony_ci									specializeVersion(fss, m_glslVersion, m_sampler, m_outType).c_str()));
356e5c31af7Sopenharmony_ci		log << program;
357e5c31af7Sopenharmony_ci		if (!program.isOk())
358e5c31af7Sopenharmony_ci		{
359e5c31af7Sopenharmony_ci			TCU_FAIL("Compile failed");
360e5c31af7Sopenharmony_ci		}
361e5c31af7Sopenharmony_ci
362e5c31af7Sopenharmony_ci		static float const position[] = {
363e5c31af7Sopenharmony_ci			-1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
364e5c31af7Sopenharmony_ci		};
365e5c31af7Sopenharmony_ci
366e5c31af7Sopenharmony_ci		gl.useProgram(program.getProgram());
367e5c31af7Sopenharmony_ci		gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_sampleMask"), m_sampleMask);
368e5c31af7Sopenharmony_ci
369e5c31af7Sopenharmony_ci		glu::VertexArrayBinding vertexArrays[] = {
370e5c31af7Sopenharmony_ci			glu::va::Float("a_position", 2, 4, 0, &position[0]),
371e5c31af7Sopenharmony_ci		};
372e5c31af7Sopenharmony_ci		glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
373e5c31af7Sopenharmony_ci				  &vertexArrays[0], glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
374e5c31af7Sopenharmony_ci
375e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw quad");
376e5c31af7Sopenharmony_ci	}
377e5c31af7Sopenharmony_ci
378e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
379e5c31af7Sopenharmony_ci	gl.deleteFramebuffers(1, &fboMs);
380e5c31af7Sopenharmony_ci
381e5c31af7Sopenharmony_ci	GLsizei width = WIDTH * ((m_samples) ? m_samples : 1);
382e5c31af7Sopenharmony_ci
383e5c31af7Sopenharmony_ci	GLuint rbo;
384e5c31af7Sopenharmony_ci	gl.genRenderbuffers(1, &rbo);
385e5c31af7Sopenharmony_ci	gl.bindRenderbuffer(GL_RENDERBUFFER, rbo);
386e5c31af7Sopenharmony_ci	gl.renderbufferStorage(GL_RENDERBUFFER, m_internalFormat, width, HEIGHT);
387e5c31af7Sopenharmony_ci
388e5c31af7Sopenharmony_ci	GLuint fbo;
389e5c31af7Sopenharmony_ci	gl.genFramebuffers(1, &fbo);
390e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
391e5c31af7Sopenharmony_ci	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
392e5c31af7Sopenharmony_ci	gl.viewport(0, 0, width, HEIGHT);
393e5c31af7Sopenharmony_ci
394e5c31af7Sopenharmony_ci	{
395e5c31af7Sopenharmony_ci		// Resolve the multi-sample texture into a render-buffer sized such that
396e5c31af7Sopenharmony_ci		// the width can hold all samples of a pixel.
397e5c31af7Sopenharmony_ci		static char const* vss = "${VERSION_DECL}\n"
398e5c31af7Sopenharmony_ci								 "in highp vec2 a_position;\n"
399e5c31af7Sopenharmony_ci								 "void main(void)\n"
400e5c31af7Sopenharmony_ci								 "{\n"
401e5c31af7Sopenharmony_ci								 "   gl_Position = vec4(a_position, 0.0, 1.0);\n"
402e5c31af7Sopenharmony_ci								 "}\n";
403e5c31af7Sopenharmony_ci
404e5c31af7Sopenharmony_ci		static char const* fss = "${VERSION_DECL}\n"
405e5c31af7Sopenharmony_ci								 "uniform highp ${SAMPLER} u_tex;\n"
406e5c31af7Sopenharmony_ci								 "uniform highp ${SAMPLER}MS u_texMS;\n"
407e5c31af7Sopenharmony_ci								 "uniform int u_samples;\n"
408e5c31af7Sopenharmony_ci								 "layout(location = 0) out highp ${OUT_TYPE} o_color;\n"
409e5c31af7Sopenharmony_ci								 "void main(void)\n"
410e5c31af7Sopenharmony_ci								 "{\n"
411e5c31af7Sopenharmony_ci								 "    if (u_samples > 0) {\n"
412e5c31af7Sopenharmony_ci								 "        ivec2 coord = ivec2(int(gl_FragCoord.x) / u_samples, gl_FragCoord.y);\n"
413e5c31af7Sopenharmony_ci								 "        int sampleId = int(gl_FragCoord.x) % u_samples;\n"
414e5c31af7Sopenharmony_ci								 "        o_color = texelFetch(u_texMS, coord, sampleId);\n"
415e5c31af7Sopenharmony_ci								 "    } else {\n"
416e5c31af7Sopenharmony_ci								 "        ivec2 coord = ivec2(gl_FragCoord.x, gl_FragCoord.y);\n"
417e5c31af7Sopenharmony_ci								 "       o_color = texelFetch(u_tex, coord, 0);\n"
418e5c31af7Sopenharmony_ci								 "    }\n"
419e5c31af7Sopenharmony_ci								 "}\n";
420e5c31af7Sopenharmony_ci
421e5c31af7Sopenharmony_ci		glu::ShaderProgram program(
422e5c31af7Sopenharmony_ci			m_context.getRenderContext(),
423e5c31af7Sopenharmony_ci			glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion, m_sampler, m_outType).c_str(),
424e5c31af7Sopenharmony_ci									specializeVersion(fss, m_glslVersion, m_sampler, m_outType).c_str()));
425e5c31af7Sopenharmony_ci		log << program;
426e5c31af7Sopenharmony_ci		if (!program.isOk())
427e5c31af7Sopenharmony_ci		{
428e5c31af7Sopenharmony_ci			TCU_FAIL("Compile failed");
429e5c31af7Sopenharmony_ci		}
430e5c31af7Sopenharmony_ci
431e5c31af7Sopenharmony_ci		static float const position[] = {
432e5c31af7Sopenharmony_ci			-1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
433e5c31af7Sopenharmony_ci		};
434e5c31af7Sopenharmony_ci
435e5c31af7Sopenharmony_ci		gl.useProgram(program.getProgram());
436e5c31af7Sopenharmony_ci		gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_samples"), m_samples);
437e5c31af7Sopenharmony_ci		if (m_samples > 0)
438e5c31af7Sopenharmony_ci		{
439e5c31af7Sopenharmony_ci			// only MS sampler needed, TU 1 is not used
440e5c31af7Sopenharmony_ci			gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_tex"), 1);
441e5c31af7Sopenharmony_ci			gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_texMS"), 0);
442e5c31af7Sopenharmony_ci		}
443e5c31af7Sopenharmony_ci		else
444e5c31af7Sopenharmony_ci		{
445e5c31af7Sopenharmony_ci			// only non-MS sampler needed, TU 1 is not used
446e5c31af7Sopenharmony_ci			gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_tex"), 0);
447e5c31af7Sopenharmony_ci			gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_texMS"), 1);
448e5c31af7Sopenharmony_ci		}
449e5c31af7Sopenharmony_ci
450e5c31af7Sopenharmony_ci		glu::VertexArrayBinding vertexArrays[] = {
451e5c31af7Sopenharmony_ci			glu::va::Float("a_position", 2, 4, 0, &position[0]),
452e5c31af7Sopenharmony_ci		};
453e5c31af7Sopenharmony_ci		glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
454e5c31af7Sopenharmony_ci				  &vertexArrays[0], glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
455e5c31af7Sopenharmony_ci
456e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw quad");
457e5c31af7Sopenharmony_ci	}
458e5c31af7Sopenharmony_ci
459e5c31af7Sopenharmony_ci	tcu::TextureLevel	  textureLevel(m_texFormat, width, HEIGHT);
460e5c31af7Sopenharmony_ci	tcu::PixelBufferAccess pixels = textureLevel.getAccess();
461e5c31af7Sopenharmony_ci	std::vector<tcu::Vec4> result(pixels.getHeight() * pixels.getWidth());
462e5c31af7Sopenharmony_ci
463e5c31af7Sopenharmony_ci	if (pixels.getFormat().type == tcu::TextureFormat::SIGNED_INT8)
464e5c31af7Sopenharmony_ci	{
465e5c31af7Sopenharmony_ci		std::vector<GLint> data(pixels.getHeight() * pixels.getWidth() * 4);
466e5c31af7Sopenharmony_ci		gl.readPixels(0, 0, pixels.getWidth(), pixels.getHeight(), GL_RGBA_INTEGER, GL_INT, &data[0]);
467e5c31af7Sopenharmony_ci		for (unsigned int i = 0; i < data.size(); i += 4)
468e5c31af7Sopenharmony_ci		{
469e5c31af7Sopenharmony_ci			result[i / 4] =
470e5c31af7Sopenharmony_ci				tcu::Vec4((GLfloat)data[i], (GLfloat)data[i + 1], (GLfloat)data[i + 2], (GLfloat)data[i + 3]);
471e5c31af7Sopenharmony_ci		}
472e5c31af7Sopenharmony_ci	}
473e5c31af7Sopenharmony_ci	else if (pixels.getFormat().type == tcu::TextureFormat::UNSIGNED_INT8)
474e5c31af7Sopenharmony_ci	{
475e5c31af7Sopenharmony_ci		std::vector<GLuint> data(pixels.getHeight() * pixels.getWidth() * 4);
476e5c31af7Sopenharmony_ci		gl.readPixels(0, 0, pixels.getWidth(), pixels.getHeight(), GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data[0]);
477e5c31af7Sopenharmony_ci		for (unsigned int i = 0; i < data.size(); i += 4)
478e5c31af7Sopenharmony_ci		{
479e5c31af7Sopenharmony_ci			result[i / 4] =
480e5c31af7Sopenharmony_ci				tcu::Vec4((GLfloat)data[i], (GLfloat)data[i + 1], (GLfloat)data[i + 2], (GLfloat)data[i + 3]);
481e5c31af7Sopenharmony_ci		}
482e5c31af7Sopenharmony_ci	}
483e5c31af7Sopenharmony_ci	else
484e5c31af7Sopenharmony_ci	{
485e5c31af7Sopenharmony_ci		glu::readPixels(m_context.getRenderContext(), 0, 0, pixels);
486e5c31af7Sopenharmony_ci	}
487e5c31af7Sopenharmony_ci
488e5c31af7Sopenharmony_ci	for (int y = 0; y < HEIGHT; ++y)
489e5c31af7Sopenharmony_ci	{
490e5c31af7Sopenharmony_ci		for (int x = 0; x < WIDTH; ++x)
491e5c31af7Sopenharmony_ci		{
492e5c31af7Sopenharmony_ci			GLint samples = (m_samples) ? m_samples : 1;
493e5c31af7Sopenharmony_ci			for (int sample = 0; sample < samples; ++sample)
494e5c31af7Sopenharmony_ci			{
495e5c31af7Sopenharmony_ci				tcu::Vec4 pixel;
496e5c31af7Sopenharmony_ci				if (pixels.getFormat().type == tcu::TextureFormat::SIGNED_INT8 ||
497e5c31af7Sopenharmony_ci					pixels.getFormat().type == tcu::TextureFormat::UNSIGNED_INT8)
498e5c31af7Sopenharmony_ci				{
499e5c31af7Sopenharmony_ci					pixel = result[y * WIDTH + x * samples + sample];
500e5c31af7Sopenharmony_ci				}
501e5c31af7Sopenharmony_ci				else
502e5c31af7Sopenharmony_ci				{
503e5c31af7Sopenharmony_ci					pixel = pixels.getPixel(x * samples + sample, y);
504e5c31af7Sopenharmony_ci				}
505e5c31af7Sopenharmony_ci
506e5c31af7Sopenharmony_ci				// Make sure only those samples where the sample mask bit is
507e5c31af7Sopenharmony_ci				// non-zero have the "red" pixel values.
508e5c31af7Sopenharmony_ci				if (!m_samples || (m_sampleMask & (1 << sample)))
509e5c31af7Sopenharmony_ci				{
510e5c31af7Sopenharmony_ci					if (pixel != tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f))
511e5c31af7Sopenharmony_ci					{
512e5c31af7Sopenharmony_ci						isOk = false;
513e5c31af7Sopenharmony_ci					}
514e5c31af7Sopenharmony_ci				}
515e5c31af7Sopenharmony_ci				else
516e5c31af7Sopenharmony_ci				{
517e5c31af7Sopenharmony_ci					if (pixel != tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f))
518e5c31af7Sopenharmony_ci					{
519e5c31af7Sopenharmony_ci						isOk = false;
520e5c31af7Sopenharmony_ci					}
521e5c31af7Sopenharmony_ci				}
522e5c31af7Sopenharmony_ci			}
523e5c31af7Sopenharmony_ci		}
524e5c31af7Sopenharmony_ci	}
525e5c31af7Sopenharmony_ci
526e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
527e5c31af7Sopenharmony_ci	gl.deleteFramebuffers(1, &fbo);
528e5c31af7Sopenharmony_ci
529e5c31af7Sopenharmony_ci	gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
530e5c31af7Sopenharmony_ci	gl.deleteRenderbuffers(1, &rbo);
531e5c31af7Sopenharmony_ci
532e5c31af7Sopenharmony_ci	gl.bindTexture(target, 0);
533e5c31af7Sopenharmony_ci	gl.deleteTextures(1, &tex);
534e5c31af7Sopenharmony_ci
535e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
536e5c31af7Sopenharmony_ci	return STOP;
537e5c31af7Sopenharmony_ci}
538e5c31af7Sopenharmony_ci
539e5c31af7Sopenharmony_ciclass SampleShadingPositionCase : public deqp::TestCase
540e5c31af7Sopenharmony_ci{
541e5c31af7Sopenharmony_cipublic:
542e5c31af7Sopenharmony_ci	SampleShadingPositionCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion,
543e5c31af7Sopenharmony_ci							  GLint samples, GLboolean fixedSampleLocations);
544e5c31af7Sopenharmony_ci	~SampleShadingPositionCase();
545e5c31af7Sopenharmony_ci
546e5c31af7Sopenharmony_ci	IterateResult iterate();
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ciprotected:
549e5c31af7Sopenharmony_ci	glu::GLSLVersion m_glslVersion;
550e5c31af7Sopenharmony_ci	GLint			 m_samples;
551e5c31af7Sopenharmony_ci	GLboolean		 m_fixedSampleLocations;
552e5c31af7Sopenharmony_ci
553e5c31af7Sopenharmony_ci	enum
554e5c31af7Sopenharmony_ci	{
555e5c31af7Sopenharmony_ci		WIDTH		= 8,
556e5c31af7Sopenharmony_ci		HEIGHT		= 8,
557e5c31af7Sopenharmony_ci		MAX_SAMPLES = 8,
558e5c31af7Sopenharmony_ci	};
559e5c31af7Sopenharmony_ci};
560e5c31af7Sopenharmony_ci
561e5c31af7Sopenharmony_ciSampleShadingPositionCase::SampleShadingPositionCase(Context& context, const char* name, const char* description,
562e5c31af7Sopenharmony_ci													 glu::GLSLVersion glslVersion, GLint samples,
563e5c31af7Sopenharmony_ci													 GLboolean fixedSampleLocations)
564e5c31af7Sopenharmony_ci	: TestCase(context, name, description)
565e5c31af7Sopenharmony_ci	, m_glslVersion(glslVersion)
566e5c31af7Sopenharmony_ci	, m_samples(samples)
567e5c31af7Sopenharmony_ci	, m_fixedSampleLocations(fixedSampleLocations)
568e5c31af7Sopenharmony_ci{
569e5c31af7Sopenharmony_ci	DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_400);
570e5c31af7Sopenharmony_ci}
571e5c31af7Sopenharmony_ci
572e5c31af7Sopenharmony_ciSampleShadingPositionCase::~SampleShadingPositionCase()
573e5c31af7Sopenharmony_ci{
574e5c31af7Sopenharmony_ci}
575e5c31af7Sopenharmony_ci
576e5c31af7Sopenharmony_ciSampleShadingPositionCase::IterateResult SampleShadingPositionCase::iterate()
577e5c31af7Sopenharmony_ci{
578e5c31af7Sopenharmony_ci	TestLog&			  log  = m_testCtx.getLog();
579e5c31af7Sopenharmony_ci	const glw::Functions& gl   = m_context.getRenderContext().getFunctions();
580e5c31af7Sopenharmony_ci	bool				  isOk = true;
581e5c31af7Sopenharmony_ci
582e5c31af7Sopenharmony_ci	/* OpenGL support query. */
583e5c31af7Sopenharmony_ci	bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
584e5c31af7Sopenharmony_ci	bool is_arb_es31_compatibility = m_context.getContextInfo().isExtensionSupported("GL_ARB_ES3_1_compatibility");
585e5c31af7Sopenharmony_ci
586e5c31af7Sopenharmony_ci	if (!(is_at_least_gl_45 || is_arb_es31_compatibility))
587e5c31af7Sopenharmony_ci	{
588e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_ARB_ES3_1_compatibility");
589e5c31af7Sopenharmony_ci		return STOP;
590e5c31af7Sopenharmony_ci	}
591e5c31af7Sopenharmony_ci
592e5c31af7Sopenharmony_ci	GLint maxSamples;
593e5c31af7Sopenharmony_ci	gl.getIntegerv(GL_MAX_SAMPLES, &maxSamples);
594e5c31af7Sopenharmony_ci	if (m_samples > maxSamples)
595e5c31af7Sopenharmony_ci	{
596e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Test sample count great than MAX_SAMPLES");
597e5c31af7Sopenharmony_ci		return STOP;
598e5c31af7Sopenharmony_ci	}
599e5c31af7Sopenharmony_ci
600e5c31af7Sopenharmony_ci	// Create a multisample texture, or a regular texture if samples is zero.
601e5c31af7Sopenharmony_ci	GLuint tex;
602e5c31af7Sopenharmony_ci	gl.genTextures(1, &tex);
603e5c31af7Sopenharmony_ci	GLenum target;
604e5c31af7Sopenharmony_ci	if (m_samples)
605e5c31af7Sopenharmony_ci	{
606e5c31af7Sopenharmony_ci		target = GL_TEXTURE_2D_MULTISAMPLE;
607e5c31af7Sopenharmony_ci		gl.bindTexture(target, tex);
608e5c31af7Sopenharmony_ci		gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, m_samples, GL_RGBA8, WIDTH, HEIGHT,
609e5c31af7Sopenharmony_ci								   m_fixedSampleLocations);
610e5c31af7Sopenharmony_ci	}
611e5c31af7Sopenharmony_ci	else
612e5c31af7Sopenharmony_ci	{
613e5c31af7Sopenharmony_ci		target = GL_TEXTURE_2D;
614e5c31af7Sopenharmony_ci		gl.bindTexture(target, tex);
615e5c31af7Sopenharmony_ci		gl.texStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, WIDTH, HEIGHT);
616e5c31af7Sopenharmony_ci	}
617e5c31af7Sopenharmony_ci
618e5c31af7Sopenharmony_ci	// Attach the texture to the framebuffer to render to it.
619e5c31af7Sopenharmony_ci	GLuint fboMs;
620e5c31af7Sopenharmony_ci	gl.genFramebuffers(1, &fboMs);
621e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, fboMs);
622e5c31af7Sopenharmony_ci	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, target, tex, 0);
623e5c31af7Sopenharmony_ci	gl.viewport(0, 0, WIDTH, HEIGHT);
624e5c31af7Sopenharmony_ci
625e5c31af7Sopenharmony_ci	// Save all the sample positions for this multisample framebuffer.
626e5c31af7Sopenharmony_ci	std::vector<tcu::Vec4> samplePositions;
627e5c31af7Sopenharmony_ci	if (m_samples)
628e5c31af7Sopenharmony_ci	{
629e5c31af7Sopenharmony_ci		samplePositions.resize(m_samples);
630e5c31af7Sopenharmony_ci		for (int sample = 0; sample < m_samples; ++sample)
631e5c31af7Sopenharmony_ci		{
632e5c31af7Sopenharmony_ci			GLfloat position[2];
633e5c31af7Sopenharmony_ci			gl.getMultisamplefv(GL_SAMPLE_POSITION, sample, position);
634e5c31af7Sopenharmony_ci			samplePositions[sample] = tcu::Vec4(position[0], position[1], 0.0f, 1.0f);
635e5c31af7Sopenharmony_ci		}
636e5c31af7Sopenharmony_ci	}
637e5c31af7Sopenharmony_ci
638e5c31af7Sopenharmony_ci	static deUint16 const quadIndices[] = { 0, 1, 2, 2, 1, 3 };
639e5c31af7Sopenharmony_ci
640e5c31af7Sopenharmony_ci	{
641e5c31af7Sopenharmony_ci		// Render all the sample positions to each pixel sample.
642e5c31af7Sopenharmony_ci
643e5c31af7Sopenharmony_ci		static char const* vss = "${VERSION_DECL}\n"
644e5c31af7Sopenharmony_ci								 "in highp vec2 a_position;\n"
645e5c31af7Sopenharmony_ci								 "void main()\n"
646e5c31af7Sopenharmony_ci								 "{\n"
647e5c31af7Sopenharmony_ci								 "   gl_Position = vec4(a_position, 0.0, 1.0);\n"
648e5c31af7Sopenharmony_ci								 "}\n";
649e5c31af7Sopenharmony_ci
650e5c31af7Sopenharmony_ci		static char const* fss = "${VERSION_DECL}\n"
651e5c31af7Sopenharmony_ci								 "${OES_SV_RQ}"
652e5c31af7Sopenharmony_ci								 "layout(location = 0) out highp vec4 o_color;\n"
653e5c31af7Sopenharmony_ci								 "void main()\n"
654e5c31af7Sopenharmony_ci								 "{\n"
655e5c31af7Sopenharmony_ci								 "    o_color = vec4(gl_SamplePosition, 0, 1);\n"
656e5c31af7Sopenharmony_ci								 "}\n";
657e5c31af7Sopenharmony_ci
658e5c31af7Sopenharmony_ci		glu::ShaderProgram program(m_context.getRenderContext(),
659e5c31af7Sopenharmony_ci								   glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion).c_str(),
660e5c31af7Sopenharmony_ci														   specializeVersion(fss, m_glslVersion).c_str()));
661e5c31af7Sopenharmony_ci		log << program;
662e5c31af7Sopenharmony_ci
663e5c31af7Sopenharmony_ci		if (!program.isOk())
664e5c31af7Sopenharmony_ci		{
665e5c31af7Sopenharmony_ci			TCU_FAIL("Compile failed");
666e5c31af7Sopenharmony_ci		}
667e5c31af7Sopenharmony_ci
668e5c31af7Sopenharmony_ci		const float position[] = {
669e5c31af7Sopenharmony_ci			-1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
670e5c31af7Sopenharmony_ci		};
671e5c31af7Sopenharmony_ci
672e5c31af7Sopenharmony_ci		gl.useProgram(program.getProgram());
673e5c31af7Sopenharmony_ci
674e5c31af7Sopenharmony_ci		glu::VertexArrayBinding vertexArrays[] = {
675e5c31af7Sopenharmony_ci			glu::va::Float("a_position", 2, 4, 0, &position[0]),
676e5c31af7Sopenharmony_ci		};
677e5c31af7Sopenharmony_ci		glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
678e5c31af7Sopenharmony_ci				  &vertexArrays[0], glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
679e5c31af7Sopenharmony_ci
680e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw quad");
681e5c31af7Sopenharmony_ci	}
682e5c31af7Sopenharmony_ci
683e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
684e5c31af7Sopenharmony_ci	gl.deleteFramebuffers(1, &fboMs);
685e5c31af7Sopenharmony_ci
686e5c31af7Sopenharmony_ci	// Create a regular non-multisample render buffer to resolve to multisample texture into.
687e5c31af7Sopenharmony_ci	// The width is increased to save all samples of the pixel.
688e5c31af7Sopenharmony_ci
689e5c31af7Sopenharmony_ci	GLsizei width = WIDTH * ((m_samples) ? m_samples : 1);
690e5c31af7Sopenharmony_ci
691e5c31af7Sopenharmony_ci	GLuint rbo;
692e5c31af7Sopenharmony_ci	gl.genRenderbuffers(1, &rbo);
693e5c31af7Sopenharmony_ci	gl.bindRenderbuffer(GL_RENDERBUFFER, rbo);
694e5c31af7Sopenharmony_ci	gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, width, HEIGHT);
695e5c31af7Sopenharmony_ci
696e5c31af7Sopenharmony_ci	GLuint fbo;
697e5c31af7Sopenharmony_ci	gl.genFramebuffers(1, &fbo);
698e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
699e5c31af7Sopenharmony_ci	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
700e5c31af7Sopenharmony_ci	gl.viewport(0, 0, width, HEIGHT);
701e5c31af7Sopenharmony_ci
702e5c31af7Sopenharmony_ci	{
703e5c31af7Sopenharmony_ci		// Resolve the multisample texture to the renderbuffer.
704e5c31af7Sopenharmony_ci
705e5c31af7Sopenharmony_ci		static char const* vss = "${VERSION_DECL}\n"
706e5c31af7Sopenharmony_ci								 "in highp vec2 a_position;\n"
707e5c31af7Sopenharmony_ci								 "void main(void)\n"
708e5c31af7Sopenharmony_ci								 "{\n"
709e5c31af7Sopenharmony_ci								 "   gl_Position = vec4(a_position, 0.0, 1.0);\n"
710e5c31af7Sopenharmony_ci								 "}\n";
711e5c31af7Sopenharmony_ci
712e5c31af7Sopenharmony_ci		static char const* fss = "${VERSION_DECL}\n"
713e5c31af7Sopenharmony_ci								 "uniform highp sampler2D u_tex;\n"
714e5c31af7Sopenharmony_ci								 "uniform highp sampler2DMS u_texMS;\n"
715e5c31af7Sopenharmony_ci								 "uniform int u_samples;\n"
716e5c31af7Sopenharmony_ci								 "layout(location = 0) out highp vec4 o_color;\n"
717e5c31af7Sopenharmony_ci								 "void main(void)\n"
718e5c31af7Sopenharmony_ci								 "{\n"
719e5c31af7Sopenharmony_ci								 "    if (u_samples > 0) {\n"
720e5c31af7Sopenharmony_ci								 "        ivec2 coord = ivec2(int(gl_FragCoord.x) / u_samples, gl_FragCoord.y);\n"
721e5c31af7Sopenharmony_ci								 "        int sampleId = int(gl_FragCoord.x) % u_samples;\n"
722e5c31af7Sopenharmony_ci								 "        o_color = texelFetch(u_texMS, coord, sampleId);\n"
723e5c31af7Sopenharmony_ci								 "    } else {\n"
724e5c31af7Sopenharmony_ci								 "        ivec2 coord = ivec2(gl_FragCoord.x, gl_FragCoord.y);\n"
725e5c31af7Sopenharmony_ci								 "        o_color = texelFetch(u_tex, coord, 0);\n"
726e5c31af7Sopenharmony_ci								 "    }\n"
727e5c31af7Sopenharmony_ci								 "}\n";
728e5c31af7Sopenharmony_ci
729e5c31af7Sopenharmony_ci		glu::ShaderProgram program(m_context.getRenderContext(),
730e5c31af7Sopenharmony_ci								   glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion).c_str(),
731e5c31af7Sopenharmony_ci														   specializeVersion(fss, m_glslVersion).c_str()));
732e5c31af7Sopenharmony_ci		log << program;
733e5c31af7Sopenharmony_ci		if (!program.isOk())
734e5c31af7Sopenharmony_ci		{
735e5c31af7Sopenharmony_ci			TCU_FAIL("Compile failed");
736e5c31af7Sopenharmony_ci		}
737e5c31af7Sopenharmony_ci
738e5c31af7Sopenharmony_ci		static float const position[] = {
739e5c31af7Sopenharmony_ci			-1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
740e5c31af7Sopenharmony_ci		};
741e5c31af7Sopenharmony_ci
742e5c31af7Sopenharmony_ci		gl.useProgram(program.getProgram());
743e5c31af7Sopenharmony_ci		gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_samples"), m_samples);
744e5c31af7Sopenharmony_ci		if (m_samples > 0)
745e5c31af7Sopenharmony_ci		{
746e5c31af7Sopenharmony_ci			// only MS sampler needed, TU 1 is not used
747e5c31af7Sopenharmony_ci			gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_tex"), 1);
748e5c31af7Sopenharmony_ci			gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_texMS"), 0);
749e5c31af7Sopenharmony_ci		}
750e5c31af7Sopenharmony_ci		else
751e5c31af7Sopenharmony_ci		{
752e5c31af7Sopenharmony_ci			// only non-MS sampler needed, TU 1 is not used
753e5c31af7Sopenharmony_ci			gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_tex"), 0);
754e5c31af7Sopenharmony_ci			gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_texMS"), 1);
755e5c31af7Sopenharmony_ci		}
756e5c31af7Sopenharmony_ci
757e5c31af7Sopenharmony_ci		glu::VertexArrayBinding vertexArrays[] = {
758e5c31af7Sopenharmony_ci			glu::va::Float("a_position", 2, 4, 0, &position[0]),
759e5c31af7Sopenharmony_ci		};
760e5c31af7Sopenharmony_ci		glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
761e5c31af7Sopenharmony_ci				  &vertexArrays[0], glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
762e5c31af7Sopenharmony_ci
763e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw quad");
764e5c31af7Sopenharmony_ci	}
765e5c31af7Sopenharmony_ci
766e5c31af7Sopenharmony_ci	// Read the renderbuffer pixels and verify we get back what we're expecting.
767e5c31af7Sopenharmony_ci	tcu::TextureLevel results(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), width,
768e5c31af7Sopenharmony_ci							  HEIGHT);
769e5c31af7Sopenharmony_ci	tcu::PixelBufferAccess pixels = results.getAccess();
770e5c31af7Sopenharmony_ci	glu::readPixels(m_context.getRenderContext(), 0, 0, pixels);
771e5c31af7Sopenharmony_ci	if (m_samples)
772e5c31af7Sopenharmony_ci	{
773e5c31af7Sopenharmony_ci		// If m_fixedSampleLocations are used make sure the first pixel's samples
774e5c31af7Sopenharmony_ci		// all match the SAMPLE_POSITION state saved earlier.
775e5c31af7Sopenharmony_ci		std::set<tcu::Vec4> fixedSampleLocations;
776e5c31af7Sopenharmony_ci		if (m_fixedSampleLocations)
777e5c31af7Sopenharmony_ci		{
778e5c31af7Sopenharmony_ci			for (int sample = 0; sample < m_samples; ++sample)
779e5c31af7Sopenharmony_ci			{
780e5c31af7Sopenharmony_ci				tcu::Vec4 pixel = pixels.getPixel(sample, 0);
781e5c31af7Sopenharmony_ci				fixedSampleLocations.insert(pixel);
782e5c31af7Sopenharmony_ci				if (deFloatAbs(pixel.x() - samplePositions[sample].x()) > 0.01 ||
783e5c31af7Sopenharmony_ci					deFloatAbs(pixel.y() - samplePositions[sample].y()) > 0.01)
784e5c31af7Sopenharmony_ci				{
785e5c31af7Sopenharmony_ci
786e5c31af7Sopenharmony_ci					isOk = false;
787e5c31af7Sopenharmony_ci				}
788e5c31af7Sopenharmony_ci			}
789e5c31af7Sopenharmony_ci		}
790e5c31af7Sopenharmony_ci
791e5c31af7Sopenharmony_ci		// Verify all samples of every pixel to make sure each position is unique.
792e5c31af7Sopenharmony_ci		for (int y = 0; y < HEIGHT; ++y)
793e5c31af7Sopenharmony_ci		{
794e5c31af7Sopenharmony_ci			for (int x = 0; x < WIDTH; ++x)
795e5c31af7Sopenharmony_ci			{
796e5c31af7Sopenharmony_ci				std::set<tcu::Vec4> uniquePixels;
797e5c31af7Sopenharmony_ci				for (int sample = 0; sample < m_samples; ++sample)
798e5c31af7Sopenharmony_ci				{
799e5c31af7Sopenharmony_ci					uniquePixels.insert(pixels.getPixel(x * m_samples + sample, y));
800e5c31af7Sopenharmony_ci				}
801e5c31af7Sopenharmony_ci				if ((GLint)uniquePixels.size() != m_samples)
802e5c31af7Sopenharmony_ci				{
803e5c31af7Sopenharmony_ci					isOk = false;
804e5c31af7Sopenharmony_ci				}
805e5c31af7Sopenharmony_ci				// For the m_fixedSampleLocations case make sure each position
806e5c31af7Sopenharmony_ci				// matches the sample positions of pixel(0, 0) saved earlier.
807e5c31af7Sopenharmony_ci				if (m_fixedSampleLocations)
808e5c31af7Sopenharmony_ci				{
809e5c31af7Sopenharmony_ci					if (fixedSampleLocations != uniquePixels)
810e5c31af7Sopenharmony_ci					{
811e5c31af7Sopenharmony_ci						isOk = false;
812e5c31af7Sopenharmony_ci					}
813e5c31af7Sopenharmony_ci				}
814e5c31af7Sopenharmony_ci			}
815e5c31af7Sopenharmony_ci		}
816e5c31af7Sopenharmony_ci	}
817e5c31af7Sopenharmony_ci	else
818e5c31af7Sopenharmony_ci	{
819e5c31af7Sopenharmony_ci		// For the non-multisample case make sure all the positions are (0.5,0.5).
820e5c31af7Sopenharmony_ci		for (int y = 0; y < pixels.getHeight(); ++y)
821e5c31af7Sopenharmony_ci		{
822e5c31af7Sopenharmony_ci			for (int x = 0; x < pixels.getWidth(); ++x)
823e5c31af7Sopenharmony_ci			{
824e5c31af7Sopenharmony_ci				tcu::Vec4 pixel = pixels.getPixel(x, y);
825e5c31af7Sopenharmony_ci				if (deFloatAbs(pixel.x() - 0.5f) > 0.01 || deFloatAbs(pixel.y() - 0.5f) > 0.01 || pixel.z() != 0.0f ||
826e5c31af7Sopenharmony_ci					pixel.w() != 1.0f)
827e5c31af7Sopenharmony_ci				{
828e5c31af7Sopenharmony_ci					isOk = false;
829e5c31af7Sopenharmony_ci				}
830e5c31af7Sopenharmony_ci			}
831e5c31af7Sopenharmony_ci		}
832e5c31af7Sopenharmony_ci	}
833e5c31af7Sopenharmony_ci
834e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
835e5c31af7Sopenharmony_ci	gl.deleteFramebuffers(1, &fbo);
836e5c31af7Sopenharmony_ci
837e5c31af7Sopenharmony_ci	gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
838e5c31af7Sopenharmony_ci	gl.deleteRenderbuffers(1, &rbo);
839e5c31af7Sopenharmony_ci
840e5c31af7Sopenharmony_ci	gl.bindTexture(target, 0);
841e5c31af7Sopenharmony_ci	gl.deleteTextures(1, &tex);
842e5c31af7Sopenharmony_ci
843e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
844e5c31af7Sopenharmony_ci	return STOP;
845e5c31af7Sopenharmony_ci}
846e5c31af7Sopenharmony_ci
847e5c31af7Sopenharmony_ciSampleVariablesTests::SampleVariablesTests(Context& context, glu::GLSLVersion glslVersion)
848e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "sample_variables", "Sample Variables tests"), m_glslVersion(glslVersion)
849e5c31af7Sopenharmony_ci{
850e5c31af7Sopenharmony_ci}
851e5c31af7Sopenharmony_ci
852e5c31af7Sopenharmony_ciSampleVariablesTests::~SampleVariablesTests()
853e5c31af7Sopenharmony_ci{
854e5c31af7Sopenharmony_ci}
855e5c31af7Sopenharmony_ci
856e5c31af7Sopenharmony_civoid SampleVariablesTests::init()
857e5c31af7Sopenharmony_ci{
858e5c31af7Sopenharmony_ci	de::Random rnd(m_context.getTestContext().getCommandLine().getBaseSeed());
859e5c31af7Sopenharmony_ci
860e5c31af7Sopenharmony_ci	struct Sample
861e5c31af7Sopenharmony_ci	{
862e5c31af7Sopenharmony_ci		char const* name;
863e5c31af7Sopenharmony_ci		GLint		samples;
864e5c31af7Sopenharmony_ci	} samples[] = {
865e5c31af7Sopenharmony_ci		{ "samples_0", 0 }, { "samples_1", 1 }, { "samples_2", 2 }, { "samples_4", 4 }, { "samples_8", 8 },
866e5c31af7Sopenharmony_ci	};
867e5c31af7Sopenharmony_ci
868e5c31af7Sopenharmony_ci	// sample_variables.extension
869e5c31af7Sopenharmony_ci	if (m_glslVersion == glu::GLSL_VERSION_310_ES)
870e5c31af7Sopenharmony_ci	{
871e5c31af7Sopenharmony_ci		addChild(new SampleShadingExtensionCase(m_context, "extension", "#extension verification", m_glslVersion));
872e5c31af7Sopenharmony_ci	}
873e5c31af7Sopenharmony_ci
874e5c31af7Sopenharmony_ci	// sample_variables.mask
875e5c31af7Sopenharmony_ci	tcu::TestCaseGroup* maskGroup = new tcu::TestCaseGroup(m_testCtx, "mask", "gl_SampleMask tests");
876e5c31af7Sopenharmony_ci	addChild(maskGroup);
877e5c31af7Sopenharmony_ci	struct Format
878e5c31af7Sopenharmony_ci	{
879e5c31af7Sopenharmony_ci		char const*		   name;
880e5c31af7Sopenharmony_ci		GLenum			   internalFormat;
881e5c31af7Sopenharmony_ci		tcu::TextureFormat textureFormat;
882e5c31af7Sopenharmony_ci		char const*		   sampler;
883e5c31af7Sopenharmony_ci		char const*		   outType;
884e5c31af7Sopenharmony_ci	} formats[] = {
885e5c31af7Sopenharmony_ci		{ "rgba8", GL_RGBA8, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), "sampler2D",
886e5c31af7Sopenharmony_ci		  "vec4" },
887e5c31af7Sopenharmony_ci		{ "rgba8i", GL_RGBA8I, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8),
888e5c31af7Sopenharmony_ci		  "isampler2D", "ivec4" },
889e5c31af7Sopenharmony_ci		{ "rgba8ui", GL_RGBA8UI, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8),
890e5c31af7Sopenharmony_ci		  "usampler2D", "uvec4" },
891e5c31af7Sopenharmony_ci		{ "rgba32f", GL_RGBA32F, tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT), "sampler2D",
892e5c31af7Sopenharmony_ci		  "vec4" },
893e5c31af7Sopenharmony_ci	};
894e5c31af7Sopenharmony_ci	for (int format = 0; format < DE_LENGTH_OF_ARRAY(formats); ++format)
895e5c31af7Sopenharmony_ci	{
896e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* maskFormatGroup = new tcu::TestCaseGroup(m_testCtx, formats[format].name, "");
897e5c31af7Sopenharmony_ci		maskGroup->addChild(maskFormatGroup);
898e5c31af7Sopenharmony_ci
899e5c31af7Sopenharmony_ci		for (int sample = 0; sample < DE_LENGTH_OF_ARRAY(samples); ++sample)
900e5c31af7Sopenharmony_ci		{
901e5c31af7Sopenharmony_ci			tcu::TestCaseGroup* maskFormatSampleGroup = new tcu::TestCaseGroup(m_testCtx, samples[sample].name, "");
902e5c31af7Sopenharmony_ci			maskFormatGroup->addChild(maskFormatSampleGroup);
903e5c31af7Sopenharmony_ci
904e5c31af7Sopenharmony_ci			maskFormatSampleGroup->addChild(
905e5c31af7Sopenharmony_ci				new SampleShadingMaskCase(m_context, "mask_zero", "", m_glslVersion, formats[format].internalFormat,
906e5c31af7Sopenharmony_ci										  formats[format].textureFormat, formats[format].sampler,
907e5c31af7Sopenharmony_ci										  formats[format].outType, samples[sample].samples, 0));
908e5c31af7Sopenharmony_ci
909e5c31af7Sopenharmony_ci			for (int mask = 0; mask < SAMPLE_MASKS; ++mask)
910e5c31af7Sopenharmony_ci			{
911e5c31af7Sopenharmony_ci				std::stringstream ss;
912e5c31af7Sopenharmony_ci				ss << "mask_" << mask;
913e5c31af7Sopenharmony_ci				maskFormatSampleGroup->addChild(new SampleShadingMaskCase(
914e5c31af7Sopenharmony_ci					m_context, ss.str().c_str(), "", m_glslVersion, formats[format].internalFormat,
915e5c31af7Sopenharmony_ci					formats[format].textureFormat, formats[format].sampler, formats[format].outType,
916e5c31af7Sopenharmony_ci					samples[sample].samples, rnd.getUint32()));
917e5c31af7Sopenharmony_ci			}
918e5c31af7Sopenharmony_ci		}
919e5c31af7Sopenharmony_ci	}
920e5c31af7Sopenharmony_ci
921e5c31af7Sopenharmony_ci	// sample_variables.position
922e5c31af7Sopenharmony_ci	tcu::TestCaseGroup* positionGroup = new tcu::TestCaseGroup(m_testCtx, "position", "gl_SamplePosition tests");
923e5c31af7Sopenharmony_ci	addChild(positionGroup);
924e5c31af7Sopenharmony_ci	struct Fixed
925e5c31af7Sopenharmony_ci	{
926e5c31af7Sopenharmony_ci		char const* name;
927e5c31af7Sopenharmony_ci		GLboolean   fixedSampleLocations;
928e5c31af7Sopenharmony_ci	} fixed[] = {
929e5c31af7Sopenharmony_ci		{ "non-fixed", GL_FALSE }, { "fixed", GL_TRUE },
930e5c31af7Sopenharmony_ci	};
931e5c31af7Sopenharmony_ci	for (int j = 0; j < DE_LENGTH_OF_ARRAY(fixed); ++j)
932e5c31af7Sopenharmony_ci	{
933e5c31af7Sopenharmony_ci		tcu::TestCaseGroup* positionFixedGroup = new tcu::TestCaseGroup(m_testCtx, fixed[j].name, "");
934e5c31af7Sopenharmony_ci		positionGroup->addChild(positionFixedGroup);
935e5c31af7Sopenharmony_ci		for (int sample = 0; sample < DE_LENGTH_OF_ARRAY(samples); ++sample)
936e5c31af7Sopenharmony_ci		{
937e5c31af7Sopenharmony_ci			positionFixedGroup->addChild(new SampleShadingPositionCase(m_context, samples[sample].name, "",
938e5c31af7Sopenharmony_ci																	   m_glslVersion, samples[sample].samples,
939e5c31af7Sopenharmony_ci																	   fixed[j].fixedSampleLocations));
940e5c31af7Sopenharmony_ci		}
941e5c31af7Sopenharmony_ci	}
942e5c31af7Sopenharmony_ci}
943e5c31af7Sopenharmony_ci
944e5c31af7Sopenharmony_ci} // es31compatibility
945e5c31af7Sopenharmony_ci} // gl4cts
946