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 "es31cSampleShadingTests.hpp"
25e5c31af7Sopenharmony_ci#include "deRandom.hpp"
26e5c31af7Sopenharmony_ci#include "deStringUtil.hpp"
27e5c31af7Sopenharmony_ci#include "gluContextInfo.hpp"
28e5c31af7Sopenharmony_ci#include "gluDrawUtil.hpp"
29e5c31af7Sopenharmony_ci#include "gluPixelTransfer.hpp"
30e5c31af7Sopenharmony_ci#include "gluShaderProgram.hpp"
31e5c31af7Sopenharmony_ci#include "glw.h"
32e5c31af7Sopenharmony_ci#include "glwFunctions.hpp"
33e5c31af7Sopenharmony_ci#include "tcuCommandLine.hpp"
34e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
35e5c31af7Sopenharmony_ci#include "tcuSurface.hpp"
36e5c31af7Sopenharmony_ci#include "tcuTestLog.hpp"
37e5c31af7Sopenharmony_ci
38e5c31af7Sopenharmony_cinamespace tcu
39e5c31af7Sopenharmony_ci{
40e5c31af7Sopenharmony_cistatic bool operator<(tcu::Vec4 const& k1, tcu::Vec4 const& k2)
41e5c31af7Sopenharmony_ci{
42e5c31af7Sopenharmony_ci	if (k1.y() < k2.y())
43e5c31af7Sopenharmony_ci	{
44e5c31af7Sopenharmony_ci		return true;
45e5c31af7Sopenharmony_ci	}
46e5c31af7Sopenharmony_ci	else if (k1.y() == k2.y())
47e5c31af7Sopenharmony_ci	{
48e5c31af7Sopenharmony_ci		return k1.x() < k2.x();
49e5c31af7Sopenharmony_ci	}
50e5c31af7Sopenharmony_ci	else
51e5c31af7Sopenharmony_ci	{
52e5c31af7Sopenharmony_ci		return false;
53e5c31af7Sopenharmony_ci	}
54e5c31af7Sopenharmony_ci}
55e5c31af7Sopenharmony_ci}
56e5c31af7Sopenharmony_ci
57e5c31af7Sopenharmony_cinamespace glcts
58e5c31af7Sopenharmony_ci{
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_ciusing tcu::TestLog;
61e5c31af7Sopenharmony_ciusing std::string;
62e5c31af7Sopenharmony_ciusing std::vector;
63e5c31af7Sopenharmony_ciusing glcts::Context;
64e5c31af7Sopenharmony_ci
65e5c31af7Sopenharmony_cistatic std::string specializeVersion(std::string const& source, glu::GLSLVersion version, std::string const& sampler,
66e5c31af7Sopenharmony_ci									 std::string const& outType)
67e5c31af7Sopenharmony_ci{
68e5c31af7Sopenharmony_ci	DE_ASSERT(version == glu::GLSL_VERSION_310_ES || version >= glu::GLSL_VERSION_400);
69e5c31af7Sopenharmony_ci	std::map<std::string, std::string> args;
70e5c31af7Sopenharmony_ci	args["VERSION_DECL"] = glu::getGLSLVersionDeclaration(version);
71e5c31af7Sopenharmony_ci	args["SAMPLER"]		 = sampler;
72e5c31af7Sopenharmony_ci	args["OUT_TYPE"]	 = outType;
73e5c31af7Sopenharmony_ci	return tcu::StringTemplate(source.c_str()).specialize(args);
74e5c31af7Sopenharmony_ci}
75e5c31af7Sopenharmony_ci
76e5c31af7Sopenharmony_ciclass SampleShadingApiCaseGroup : public TestCaseGroup
77e5c31af7Sopenharmony_ci{
78e5c31af7Sopenharmony_cipublic:
79e5c31af7Sopenharmony_ci	SampleShadingApiCaseGroup(Context& context, glu::GLSLVersion glslVersion)
80e5c31af7Sopenharmony_ci		: TestCaseGroup(context, "api", "Basic API verification"), m_glslVersion(glslVersion)
81e5c31af7Sopenharmony_ci	{
82e5c31af7Sopenharmony_ci	}
83e5c31af7Sopenharmony_ci
84e5c31af7Sopenharmony_ci	void init(void)
85e5c31af7Sopenharmony_ci	{
86e5c31af7Sopenharmony_ci		addChild(new SampleShadingApiCase(m_context, m_glslVersion));
87e5c31af7Sopenharmony_ci	}
88e5c31af7Sopenharmony_ci
89e5c31af7Sopenharmony_ciprivate:
90e5c31af7Sopenharmony_ci	class SampleShadingApiCase : public deqp::TestCase
91e5c31af7Sopenharmony_ci	{
92e5c31af7Sopenharmony_ci	public:
93e5c31af7Sopenharmony_ci		SampleShadingApiCase(Context& context, glu::GLSLVersion glslVersion);
94e5c31af7Sopenharmony_ci		~SampleShadingApiCase();
95e5c31af7Sopenharmony_ci
96e5c31af7Sopenharmony_ci		IterateResult iterate();
97e5c31af7Sopenharmony_ci
98e5c31af7Sopenharmony_ci	protected:
99e5c31af7Sopenharmony_ci		glu::GLSLVersion			m_glslVersion;
100e5c31af7Sopenharmony_ci		glw::glMinSampleShadingFunc m_pGLMinSampleShading;
101e5c31af7Sopenharmony_ci	};
102e5c31af7Sopenharmony_ci
103e5c31af7Sopenharmony_ci	glu::GLSLVersion m_glslVersion;
104e5c31af7Sopenharmony_ci};
105e5c31af7Sopenharmony_ci
106e5c31af7Sopenharmony_ciSampleShadingApiCaseGroup::SampleShadingApiCase::SampleShadingApiCase(Context& context, glu::GLSLVersion glslVersion)
107e5c31af7Sopenharmony_ci	: TestCase(context, "verify", ""), m_glslVersion(glslVersion), m_pGLMinSampleShading(0)
108e5c31af7Sopenharmony_ci{
109e5c31af7Sopenharmony_ci	DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_400);
110e5c31af7Sopenharmony_ci}
111e5c31af7Sopenharmony_ci
112e5c31af7Sopenharmony_ciSampleShadingApiCaseGroup::SampleShadingApiCase::~SampleShadingApiCase()
113e5c31af7Sopenharmony_ci{
114e5c31af7Sopenharmony_ci}
115e5c31af7Sopenharmony_ci
116e5c31af7Sopenharmony_ciSampleShadingApiCaseGroup::SampleShadingApiCase::IterateResult SampleShadingApiCaseGroup::SampleShadingApiCase::
117e5c31af7Sopenharmony_ci	iterate()
118e5c31af7Sopenharmony_ci{
119e5c31af7Sopenharmony_ci	const glw::Functions& gl   = m_context.getRenderContext().getFunctions();
120e5c31af7Sopenharmony_ci	bool				  isOk = true;
121e5c31af7Sopenharmony_ci
122e5c31af7Sopenharmony_ci	if (m_glslVersion == glu::GLSL_VERSION_310_ES &&
123e5c31af7Sopenharmony_ci		!m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading"))
124e5c31af7Sopenharmony_ci	{
125e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_OES_sample_shading");
126e5c31af7Sopenharmony_ci		return STOP;
127e5c31af7Sopenharmony_ci	}
128e5c31af7Sopenharmony_ci
129e5c31af7Sopenharmony_ci	m_pGLMinSampleShading = gl.minSampleShading;
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_ci	struct Test
132e5c31af7Sopenharmony_ci	{
133e5c31af7Sopenharmony_ci		GLfloat input;
134e5c31af7Sopenharmony_ci		GLfloat result;
135e5c31af7Sopenharmony_ci	} tests[] = {
136e5c31af7Sopenharmony_ci		{ 0.0f, 0.0f }, { 0.5f, 0.5f }, { -1.0f, 0.0f }, { 2.0f, 1.0f },
137e5c31af7Sopenharmony_ci	};
138e5c31af7Sopenharmony_ci	for (int i = 0; i < DE_LENGTH_OF_ARRAY(tests); ++i)
139e5c31af7Sopenharmony_ci	{
140e5c31af7Sopenharmony_ci		m_pGLMinSampleShading(tests[i].input);
141e5c31af7Sopenharmony_ci		GLfloat result = -1.0f;
142e5c31af7Sopenharmony_ci		gl.getFloatv(GL_MIN_SAMPLE_SHADING_VALUE_OES, &result);
143e5c31af7Sopenharmony_ci		if (result != tests[i].result)
144e5c31af7Sopenharmony_ci		{
145e5c31af7Sopenharmony_ci			isOk = false;
146e5c31af7Sopenharmony_ci		}
147e5c31af7Sopenharmony_ci	}
148e5c31af7Sopenharmony_ci
149e5c31af7Sopenharmony_ci	gl.enable(GL_SAMPLE_SHADING_OES);
150e5c31af7Sopenharmony_ci	if (!gl.isEnabled(GL_SAMPLE_SHADING_OES))
151e5c31af7Sopenharmony_ci	{
152e5c31af7Sopenharmony_ci		isOk = false;
153e5c31af7Sopenharmony_ci	}
154e5c31af7Sopenharmony_ci	gl.disable(GL_SAMPLE_SHADING_OES);
155e5c31af7Sopenharmony_ci	if (gl.isEnabled(GL_SAMPLE_SHADING_OES))
156e5c31af7Sopenharmony_ci	{
157e5c31af7Sopenharmony_ci		isOk = false;
158e5c31af7Sopenharmony_ci	}
159e5c31af7Sopenharmony_ci
160e5c31af7Sopenharmony_ci	m_pGLMinSampleShading(0.0f);
161e5c31af7Sopenharmony_ci
162e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
163e5c31af7Sopenharmony_ci	return STOP;
164e5c31af7Sopenharmony_ci}
165e5c31af7Sopenharmony_ci
166e5c31af7Sopenharmony_ciclass SampleShadingRenderCase : public TestCase
167e5c31af7Sopenharmony_ci{
168e5c31af7Sopenharmony_cipublic:
169e5c31af7Sopenharmony_ci	SampleShadingRenderCase(Context& context, const char* name, const char* description, glu::GLSLVersion glslVersion,
170e5c31af7Sopenharmony_ci							GLenum internalFormat, tcu::TextureFormat const& texFormat, const char* m_sampler,
171e5c31af7Sopenharmony_ci							const char* m_outType, GLfloat min, GLfloat max, const char* m_extension,
172e5c31af7Sopenharmony_ci							GLfloat sampleShading);
173e5c31af7Sopenharmony_ci	~SampleShadingRenderCase();
174e5c31af7Sopenharmony_ci
175e5c31af7Sopenharmony_ci	IterateResult iterate();
176e5c31af7Sopenharmony_ci
177e5c31af7Sopenharmony_ciprotected:
178e5c31af7Sopenharmony_ci	glu::GLSLVersion			m_glslVersion;
179e5c31af7Sopenharmony_ci	glw::glMinSampleShadingFunc m_pGLMinSampleShading;
180e5c31af7Sopenharmony_ci	GLenum						m_internalFormat;
181e5c31af7Sopenharmony_ci	tcu::TextureFormat			m_texFormat;
182e5c31af7Sopenharmony_ci	std::string					m_sampler;
183e5c31af7Sopenharmony_ci	std::string					m_outType;
184e5c31af7Sopenharmony_ci	GLfloat						m_min;
185e5c31af7Sopenharmony_ci	GLfloat						m_max;
186e5c31af7Sopenharmony_ci	std::string					m_extension;
187e5c31af7Sopenharmony_ci	GLfloat						m_sampleShading;
188e5c31af7Sopenharmony_ci
189e5c31af7Sopenharmony_ci	enum
190e5c31af7Sopenharmony_ci	{
191e5c31af7Sopenharmony_ci		WIDTH		= 16,
192e5c31af7Sopenharmony_ci		HEIGHT		= 16,
193e5c31af7Sopenharmony_ci		MAX_SAMPLES = 4,
194e5c31af7Sopenharmony_ci	};
195e5c31af7Sopenharmony_ci
196e5c31af7Sopenharmony_ci	int countUniquePixels(tcu::ConstPixelBufferAccess const& pixels);
197e5c31af7Sopenharmony_ci	int countUniquePixels(const std::vector<tcu::Vec4>& pixels);
198e5c31af7Sopenharmony_ci};
199e5c31af7Sopenharmony_ci
200e5c31af7Sopenharmony_ciSampleShadingRenderCase::SampleShadingRenderCase(Context& context, const char* name, const char* description,
201e5c31af7Sopenharmony_ci												 glu::GLSLVersion glslVersion, GLenum internalFormat,
202e5c31af7Sopenharmony_ci												 tcu::TextureFormat const& texFormat, const char* sampler,
203e5c31af7Sopenharmony_ci												 const char* outType, GLfloat min, GLfloat max, const char* extension,
204e5c31af7Sopenharmony_ci												 GLfloat sampleShading)
205e5c31af7Sopenharmony_ci	: TestCase(context, name, description)
206e5c31af7Sopenharmony_ci	, m_glslVersion(glslVersion)
207e5c31af7Sopenharmony_ci	, m_pGLMinSampleShading(0)
208e5c31af7Sopenharmony_ci	, m_internalFormat(internalFormat)
209e5c31af7Sopenharmony_ci	, m_texFormat(texFormat)
210e5c31af7Sopenharmony_ci	, m_sampler(sampler)
211e5c31af7Sopenharmony_ci	, m_outType(outType)
212e5c31af7Sopenharmony_ci	, m_min(min)
213e5c31af7Sopenharmony_ci	, m_max(max)
214e5c31af7Sopenharmony_ci	, m_extension(extension)
215e5c31af7Sopenharmony_ci	, m_sampleShading(sampleShading)
216e5c31af7Sopenharmony_ci{
217e5c31af7Sopenharmony_ci	DE_ASSERT(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion >= glu::GLSL_VERSION_400);
218e5c31af7Sopenharmony_ci}
219e5c31af7Sopenharmony_ci
220e5c31af7Sopenharmony_ciSampleShadingRenderCase::~SampleShadingRenderCase()
221e5c31af7Sopenharmony_ci{
222e5c31af7Sopenharmony_ci}
223e5c31af7Sopenharmony_ci
224e5c31af7Sopenharmony_ciSampleShadingRenderCase::IterateResult SampleShadingRenderCase::iterate()
225e5c31af7Sopenharmony_ci{
226e5c31af7Sopenharmony_ci	TestLog&			  log  = m_testCtx.getLog();
227e5c31af7Sopenharmony_ci	const glw::Functions& gl   = m_context.getRenderContext().getFunctions();
228e5c31af7Sopenharmony_ci	bool				  isOk = true;
229e5c31af7Sopenharmony_ci
230e5c31af7Sopenharmony_ci	if (m_glslVersion == glu::GLSL_VERSION_310_ES &&
231e5c31af7Sopenharmony_ci		!m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading"))
232e5c31af7Sopenharmony_ci	{
233e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "GL_OES_sample_shading");
234e5c31af7Sopenharmony_ci		return STOP;
235e5c31af7Sopenharmony_ci	}
236e5c31af7Sopenharmony_ci	if (!m_extension.empty() && !m_context.getContextInfo().isExtensionSupported(m_extension.c_str()))
237e5c31af7Sopenharmony_ci	{
238e5c31af7Sopenharmony_ci		m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, m_extension.c_str());
239e5c31af7Sopenharmony_ci		return STOP;
240e5c31af7Sopenharmony_ci	}
241e5c31af7Sopenharmony_ci
242e5c31af7Sopenharmony_ci	m_pGLMinSampleShading = gl.minSampleShading;
243e5c31af7Sopenharmony_ci
244e5c31af7Sopenharmony_ci	GLint maxSamples = 0;
245e5c31af7Sopenharmony_ci	if (((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::RGBA)) ||
246e5c31af7Sopenharmony_ci		((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::RG)) ||
247e5c31af7Sopenharmony_ci		((m_texFormat.type == tcu::TextureFormat::FLOAT) && (m_texFormat.order == tcu::TextureFormat::R)) ||
248e5c31af7Sopenharmony_ci		((m_texFormat.type == tcu::TextureFormat::HALF_FLOAT) && (m_texFormat.order == tcu::TextureFormat::RGBA)))
249e5c31af7Sopenharmony_ci	{
250e5c31af7Sopenharmony_ci		gl.getInternalformativ(GL_TEXTURE_2D_MULTISAMPLE, m_internalFormat, GL_SAMPLES, 1, &maxSamples);
251e5c31af7Sopenharmony_ci		if (maxSamples == 0)
252e5c31af7Sopenharmony_ci		{
253e5c31af7Sopenharmony_ci			m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Multisample is not supported on this format");
254e5c31af7Sopenharmony_ci			return STOP;
255e5c31af7Sopenharmony_ci		}
256e5c31af7Sopenharmony_ci	}
257e5c31af7Sopenharmony_ci	else if (m_texFormat.type == tcu::TextureFormat::SIGNED_INT8 ||
258e5c31af7Sopenharmony_ci			 m_texFormat.type == tcu::TextureFormat::UNSIGNED_INT8)
259e5c31af7Sopenharmony_ci	{
260e5c31af7Sopenharmony_ci		gl.getIntegerv(GL_MAX_INTEGER_SAMPLES, &maxSamples);
261e5c31af7Sopenharmony_ci	}
262e5c31af7Sopenharmony_ci	else
263e5c31af7Sopenharmony_ci	{
264e5c31af7Sopenharmony_ci		gl.getIntegerv(GL_MAX_SAMPLES, &maxSamples);
265e5c31af7Sopenharmony_ci	}
266e5c31af7Sopenharmony_ci	GLint samples = de::min<GLint>(maxSamples, MAX_SAMPLES);
267e5c31af7Sopenharmony_ci
268e5c31af7Sopenharmony_ci	GLuint tex;
269e5c31af7Sopenharmony_ci	gl.genTextures(1, &tex);
270e5c31af7Sopenharmony_ci	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, tex);
271e5c31af7Sopenharmony_ci	gl.texStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, samples, m_internalFormat, WIDTH, HEIGHT, GL_FALSE);
272e5c31af7Sopenharmony_ci
273e5c31af7Sopenharmony_ci	GLuint fboMs;
274e5c31af7Sopenharmony_ci	gl.genFramebuffers(1, &fboMs);
275e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, fboMs);
276e5c31af7Sopenharmony_ci	gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, tex, 0);
277e5c31af7Sopenharmony_ci	gl.viewport(0, 0, WIDTH, HEIGHT);
278e5c31af7Sopenharmony_ci
279e5c31af7Sopenharmony_ci	m_pGLMinSampleShading(m_sampleShading);
280e5c31af7Sopenharmony_ci	gl.enable(GL_SAMPLE_SHADING_OES);
281e5c31af7Sopenharmony_ci
282e5c31af7Sopenharmony_ci	static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };
283e5c31af7Sopenharmony_ci
284e5c31af7Sopenharmony_ci	{
285e5c31af7Sopenharmony_ci		static char const* vss = "${VERSION_DECL}\n"
286e5c31af7Sopenharmony_ci								 "in highp vec2 a_position;\n"
287e5c31af7Sopenharmony_ci								 "in highp vec4 a_color;\n"
288e5c31af7Sopenharmony_ci								 "out highp vec4 v_color;\n"
289e5c31af7Sopenharmony_ci								 "void main (void)\n"
290e5c31af7Sopenharmony_ci								 "{\n"
291e5c31af7Sopenharmony_ci								 "   gl_Position = vec4(a_position, 0.0, 1.0);\n"
292e5c31af7Sopenharmony_ci								 "   v_color = a_color;\n"
293e5c31af7Sopenharmony_ci								 "}\n";
294e5c31af7Sopenharmony_ci
295e5c31af7Sopenharmony_ci		static char const* fss = "${VERSION_DECL}\n"
296e5c31af7Sopenharmony_ci								 "in highp vec4 v_color;\n"
297e5c31af7Sopenharmony_ci								 "layout(location = 0) out highp ${OUT_TYPE} o_color;\n"
298e5c31af7Sopenharmony_ci								 "void main (void)\n"
299e5c31af7Sopenharmony_ci								 "{\n"
300e5c31af7Sopenharmony_ci								 "   o_color = ${OUT_TYPE}(v_color.x, v_color.y, 0.0, 0.0);\n"
301e5c31af7Sopenharmony_ci								 "}\n";
302e5c31af7Sopenharmony_ci
303e5c31af7Sopenharmony_ci		glu::ShaderProgram program(
304e5c31af7Sopenharmony_ci			m_context.getRenderContext(),
305e5c31af7Sopenharmony_ci			glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion, m_sampler, m_outType).c_str(),
306e5c31af7Sopenharmony_ci									specializeVersion(fss, m_glslVersion, m_sampler, m_outType).c_str()));
307e5c31af7Sopenharmony_ci		log << program;
308e5c31af7Sopenharmony_ci		if (!program.isOk())
309e5c31af7Sopenharmony_ci		{
310e5c31af7Sopenharmony_ci			TCU_FAIL("Compile failed");
311e5c31af7Sopenharmony_ci		}
312e5c31af7Sopenharmony_ci
313e5c31af7Sopenharmony_ci		const float position[] = {
314e5c31af7Sopenharmony_ci			-1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
315e5c31af7Sopenharmony_ci		};
316e5c31af7Sopenharmony_ci		const float color[] = {
317e5c31af7Sopenharmony_ci			m_min, m_min, 0.0f, 1.0f, m_min, m_max, 0.0f, 1.0f, m_max, m_min, 0.0f, 1.0f, m_max, m_max, 0.0f, 1.0f,
318e5c31af7Sopenharmony_ci		};
319e5c31af7Sopenharmony_ci
320e5c31af7Sopenharmony_ci		gl.useProgram(program.getProgram());
321e5c31af7Sopenharmony_ci
322e5c31af7Sopenharmony_ci		glu::VertexArrayBinding vertexArrays[] = {
323e5c31af7Sopenharmony_ci			glu::va::Float("a_position", 2, 4, 0, &position[0]), glu::va::Float("a_color", 4, 4, 0, &color[0]),
324e5c31af7Sopenharmony_ci		};
325e5c31af7Sopenharmony_ci		glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
326e5c31af7Sopenharmony_ci				  &vertexArrays[0], glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
327e5c31af7Sopenharmony_ci
328e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw quad");
329e5c31af7Sopenharmony_ci	}
330e5c31af7Sopenharmony_ci	m_pGLMinSampleShading(0.0f);
331e5c31af7Sopenharmony_ci	gl.disable(GL_SAMPLE_SHADING_OES);
332e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
333e5c31af7Sopenharmony_ci	gl.deleteFramebuffers(1, &fboMs);
334e5c31af7Sopenharmony_ci
335e5c31af7Sopenharmony_ci	GLsizei width = WIDTH * samples;
336e5c31af7Sopenharmony_ci
337e5c31af7Sopenharmony_ci	GLuint rbo;
338e5c31af7Sopenharmony_ci	gl.genRenderbuffers(1, &rbo);
339e5c31af7Sopenharmony_ci	gl.bindRenderbuffer(GL_RENDERBUFFER, rbo);
340e5c31af7Sopenharmony_ci	gl.renderbufferStorage(GL_RENDERBUFFER, m_internalFormat, width, HEIGHT);
341e5c31af7Sopenharmony_ci
342e5c31af7Sopenharmony_ci	GLuint fbo;
343e5c31af7Sopenharmony_ci	gl.genFramebuffers(1, &fbo);
344e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
345e5c31af7Sopenharmony_ci	gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo);
346e5c31af7Sopenharmony_ci	gl.viewport(0, 0, width, HEIGHT);
347e5c31af7Sopenharmony_ci
348e5c31af7Sopenharmony_ci	{
349e5c31af7Sopenharmony_ci		static char const* vss = "${VERSION_DECL}\n"
350e5c31af7Sopenharmony_ci								 "in highp vec2 a_position;\n"
351e5c31af7Sopenharmony_ci								 "void main(void)\n"
352e5c31af7Sopenharmony_ci								 "{\n"
353e5c31af7Sopenharmony_ci								 "   gl_Position = vec4(a_position, 0.0, 1.0);\n"
354e5c31af7Sopenharmony_ci								 "}\n";
355e5c31af7Sopenharmony_ci
356e5c31af7Sopenharmony_ci		static char const* fss = "${VERSION_DECL}\n"
357e5c31af7Sopenharmony_ci								 "uniform highp ${SAMPLER} u_tex;\n"
358e5c31af7Sopenharmony_ci								 "uniform int u_samples;\n"
359e5c31af7Sopenharmony_ci								 "layout(location = 0) out highp ${OUT_TYPE} o_color;\n"
360e5c31af7Sopenharmony_ci								 "void main(void)\n"
361e5c31af7Sopenharmony_ci								 "{\n"
362e5c31af7Sopenharmony_ci								 "   ivec2 coord = ivec2(int(gl_FragCoord.x) / u_samples, gl_FragCoord.y);\n"
363e5c31af7Sopenharmony_ci								 "   int sampleId = int(gl_FragCoord.x) % u_samples;\n"
364e5c31af7Sopenharmony_ci								 "   o_color = texelFetch(u_tex, coord, sampleId);\n"
365e5c31af7Sopenharmony_ci								 "}\n";
366e5c31af7Sopenharmony_ci
367e5c31af7Sopenharmony_ci		glu::ShaderProgram program(
368e5c31af7Sopenharmony_ci			m_context.getRenderContext(),
369e5c31af7Sopenharmony_ci			glu::makeVtxFragSources(specializeVersion(vss, m_glslVersion, m_sampler, m_outType).c_str(),
370e5c31af7Sopenharmony_ci									specializeVersion(fss, m_glslVersion, m_sampler, m_outType).c_str()));
371e5c31af7Sopenharmony_ci		log << program;
372e5c31af7Sopenharmony_ci		if (!program.isOk())
373e5c31af7Sopenharmony_ci		{
374e5c31af7Sopenharmony_ci			TCU_FAIL("Compile failed");
375e5c31af7Sopenharmony_ci		}
376e5c31af7Sopenharmony_ci
377e5c31af7Sopenharmony_ci		float const position[] = {
378e5c31af7Sopenharmony_ci			-1.0f, -1.0f, -1.0f, +1.0f, +1.0f, -1.0f, +1.0f, +1.0f,
379e5c31af7Sopenharmony_ci		};
380e5c31af7Sopenharmony_ci
381e5c31af7Sopenharmony_ci		gl.useProgram(program.getProgram());
382e5c31af7Sopenharmony_ci		gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_samples"), samples);
383e5c31af7Sopenharmony_ci		gl.uniform1i(gl.getUniformLocation(program.getProgram(), "u_tex"), 0);
384e5c31af7Sopenharmony_ci
385e5c31af7Sopenharmony_ci		glu::VertexArrayBinding vertexArrays[] = {
386e5c31af7Sopenharmony_ci			glu::va::Float("a_position", 2, 4, 0, &position[0]),
387e5c31af7Sopenharmony_ci		};
388e5c31af7Sopenharmony_ci		glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
389e5c31af7Sopenharmony_ci				  &vertexArrays[0], glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), &quadIndices[0]));
390e5c31af7Sopenharmony_ci
391e5c31af7Sopenharmony_ci		GLU_EXPECT_NO_ERROR(gl.getError(), "Draw quad");
392e5c31af7Sopenharmony_ci	}
393e5c31af7Sopenharmony_ci
394e5c31af7Sopenharmony_ci	tcu::TextureLevel	  results(m_texFormat, width, HEIGHT);
395e5c31af7Sopenharmony_ci	tcu::PixelBufferAccess pixels = results.getAccess();
396e5c31af7Sopenharmony_ci	std::vector<tcu::Vec4> result(pixels.getHeight() * pixels.getWidth());
397e5c31af7Sopenharmony_ci	int					   uniquePixels;
398e5c31af7Sopenharmony_ci
399e5c31af7Sopenharmony_ci	if (pixels.getFormat().type == tcu::TextureFormat::SIGNED_INT8)
400e5c31af7Sopenharmony_ci	{
401e5c31af7Sopenharmony_ci		std::vector<GLint> data(pixels.getHeight() * pixels.getWidth() * 4);
402e5c31af7Sopenharmony_ci		gl.readPixels(0, 0, pixels.getWidth(), pixels.getHeight(), GL_RGBA_INTEGER, GL_INT, &data[0]);
403e5c31af7Sopenharmony_ci		for (unsigned int i = 0; i < data.size(); i += 4)
404e5c31af7Sopenharmony_ci		{
405e5c31af7Sopenharmony_ci			result[i / 4] =
406e5c31af7Sopenharmony_ci				tcu::Vec4((GLfloat)data[i], (GLfloat)data[i + 1], (GLfloat)data[i + 2], (GLfloat)data[i + 3]);
407e5c31af7Sopenharmony_ci		}
408e5c31af7Sopenharmony_ci		uniquePixels = countUniquePixels(result);
409e5c31af7Sopenharmony_ci	}
410e5c31af7Sopenharmony_ci	else if (pixels.getFormat().type == tcu::TextureFormat::UNSIGNED_INT8)
411e5c31af7Sopenharmony_ci	{
412e5c31af7Sopenharmony_ci		std::vector<GLuint> data(pixels.getHeight() * pixels.getWidth() * 4);
413e5c31af7Sopenharmony_ci		gl.readPixels(0, 0, pixels.getWidth(), pixels.getHeight(), GL_RGBA_INTEGER, GL_UNSIGNED_INT, &data[0]);
414e5c31af7Sopenharmony_ci		for (unsigned int i = 0; i < data.size(); i += 4)
415e5c31af7Sopenharmony_ci		{
416e5c31af7Sopenharmony_ci			result[i / 4] =
417e5c31af7Sopenharmony_ci				tcu::Vec4((GLfloat)data[i], (GLfloat)data[i + 1], (GLfloat)data[i + 2], (GLfloat)data[i + 3]);
418e5c31af7Sopenharmony_ci		}
419e5c31af7Sopenharmony_ci		uniquePixels = countUniquePixels(result);
420e5c31af7Sopenharmony_ci	}
421e5c31af7Sopenharmony_ci	else
422e5c31af7Sopenharmony_ci	{
423e5c31af7Sopenharmony_ci		glu::readPixels(m_context.getRenderContext(), 0, 0, pixels);
424e5c31af7Sopenharmony_ci		uniquePixels = countUniquePixels(pixels);
425e5c31af7Sopenharmony_ci	}
426e5c31af7Sopenharmony_ci	int expectedUnique = WIDTH * HEIGHT * (de::clamp(int(float(samples) * m_sampleShading), 1, samples));
427e5c31af7Sopenharmony_ci	if (uniquePixels < expectedUnique)
428e5c31af7Sopenharmony_ci	{
429e5c31af7Sopenharmony_ci		isOk = false;
430e5c31af7Sopenharmony_ci	}
431e5c31af7Sopenharmony_ci
432e5c31af7Sopenharmony_ci	gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
433e5c31af7Sopenharmony_ci	gl.deleteFramebuffers(1, &fbo);
434e5c31af7Sopenharmony_ci
435e5c31af7Sopenharmony_ci	gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
436e5c31af7Sopenharmony_ci	gl.deleteRenderbuffers(1, &rbo);
437e5c31af7Sopenharmony_ci
438e5c31af7Sopenharmony_ci	gl.bindTexture(GL_TEXTURE_2D_MULTISAMPLE, 0);
439e5c31af7Sopenharmony_ci	gl.deleteTextures(1, &tex);
440e5c31af7Sopenharmony_ci
441e5c31af7Sopenharmony_ci	m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, isOk ? "Pass" : "Fail");
442e5c31af7Sopenharmony_ci	return STOP;
443e5c31af7Sopenharmony_ci}
444e5c31af7Sopenharmony_ci
445e5c31af7Sopenharmony_ciint SampleShadingRenderCase::countUniquePixels(tcu::ConstPixelBufferAccess const& pixels)
446e5c31af7Sopenharmony_ci{
447e5c31af7Sopenharmony_ci	std::set<tcu::Vec4> uniquePixels;
448e5c31af7Sopenharmony_ci
449e5c31af7Sopenharmony_ci	for (int y = 0; y < pixels.getHeight(); ++y)
450e5c31af7Sopenharmony_ci	{
451e5c31af7Sopenharmony_ci		for (int x = 0; x < pixels.getWidth(); ++x)
452e5c31af7Sopenharmony_ci		{
453e5c31af7Sopenharmony_ci			uniquePixels.insert(pixels.getPixel(x, y));
454e5c31af7Sopenharmony_ci		}
455e5c31af7Sopenharmony_ci	}
456e5c31af7Sopenharmony_ci
457e5c31af7Sopenharmony_ci	return (int)uniquePixels.size();
458e5c31af7Sopenharmony_ci}
459e5c31af7Sopenharmony_ci
460e5c31af7Sopenharmony_ciint SampleShadingRenderCase::countUniquePixels(const std::vector<tcu::Vec4>& pixels)
461e5c31af7Sopenharmony_ci{
462e5c31af7Sopenharmony_ci	std::set<tcu::Vec4> uniquePixels;
463e5c31af7Sopenharmony_ci
464e5c31af7Sopenharmony_ci	for (unsigned int i = 0; i < pixels.size(); ++i)
465e5c31af7Sopenharmony_ci	{
466e5c31af7Sopenharmony_ci		uniquePixels.insert(pixels[i]);
467e5c31af7Sopenharmony_ci	}
468e5c31af7Sopenharmony_ci
469e5c31af7Sopenharmony_ci	return (int)uniquePixels.size();
470e5c31af7Sopenharmony_ci}
471e5c31af7Sopenharmony_ci
472e5c31af7Sopenharmony_ciclass SampleShadingRenderFormatTests : public glcts::TestCaseGroup
473e5c31af7Sopenharmony_ci{
474e5c31af7Sopenharmony_cipublic:
475e5c31af7Sopenharmony_ci	SampleShadingRenderFormatTests(glcts::Context& context, glu::GLSLVersion glslVersion, GLenum internalFormat,
476e5c31af7Sopenharmony_ci								   const char* format, tcu::TextureFormat const& texFormat, const char* sampler,
477e5c31af7Sopenharmony_ci								   const char* outType, GLfloat min, GLfloat max, const char* extension = "");
478e5c31af7Sopenharmony_ci	~SampleShadingRenderFormatTests(void);
479e5c31af7Sopenharmony_ci
480e5c31af7Sopenharmony_ci	void init(void);
481e5c31af7Sopenharmony_ci
482e5c31af7Sopenharmony_ciprivate:
483e5c31af7Sopenharmony_ci	SampleShadingRenderFormatTests(const SampleShadingTests& other);
484e5c31af7Sopenharmony_ci	SampleShadingRenderFormatTests& operator=(const SampleShadingTests& other);
485e5c31af7Sopenharmony_ci
486e5c31af7Sopenharmony_ci	glu::GLSLVersion   m_glslVersion;
487e5c31af7Sopenharmony_ci	GLenum			   m_internalFormat;
488e5c31af7Sopenharmony_ci	tcu::TextureFormat m_texFormat;
489e5c31af7Sopenharmony_ci	std::string		   m_sampler;
490e5c31af7Sopenharmony_ci	std::string		   m_outType;
491e5c31af7Sopenharmony_ci	GLfloat			   m_min;
492e5c31af7Sopenharmony_ci	GLfloat			   m_max;
493e5c31af7Sopenharmony_ci	std::string		   m_extension;
494e5c31af7Sopenharmony_ci};
495e5c31af7Sopenharmony_ci
496e5c31af7Sopenharmony_ciSampleShadingRenderFormatTests::SampleShadingRenderFormatTests(Context& context, glu::GLSLVersion glslVersion,
497e5c31af7Sopenharmony_ci															   GLenum internalFormat, const char* format,
498e5c31af7Sopenharmony_ci															   tcu::TextureFormat const& texFormat, const char* sampler,
499e5c31af7Sopenharmony_ci															   const char* outType, GLfloat min, GLfloat max,
500e5c31af7Sopenharmony_ci															   const char* extension)
501e5c31af7Sopenharmony_ci	: TestCaseGroup(context, format, "")
502e5c31af7Sopenharmony_ci	, m_glslVersion(glslVersion)
503e5c31af7Sopenharmony_ci	, m_internalFormat(internalFormat)
504e5c31af7Sopenharmony_ci	, m_texFormat(texFormat)
505e5c31af7Sopenharmony_ci	, m_sampler(sampler)
506e5c31af7Sopenharmony_ci	, m_outType(outType)
507e5c31af7Sopenharmony_ci	, m_min(min)
508e5c31af7Sopenharmony_ci	, m_max(max)
509e5c31af7Sopenharmony_ci	, m_extension(extension)
510e5c31af7Sopenharmony_ci{
511e5c31af7Sopenharmony_ci}
512e5c31af7Sopenharmony_ci
513e5c31af7Sopenharmony_ciSampleShadingRenderFormatTests::~SampleShadingRenderFormatTests(void)
514e5c31af7Sopenharmony_ci{
515e5c31af7Sopenharmony_ci}
516e5c31af7Sopenharmony_ci
517e5c31af7Sopenharmony_civoid SampleShadingRenderFormatTests::init(void)
518e5c31af7Sopenharmony_ci{
519e5c31af7Sopenharmony_ci	// sample_shading.render.full
520e5c31af7Sopenharmony_ci	addChild(new SampleShadingRenderCase(m_context, "full", "Sample shader functionality", m_glslVersion,
521e5c31af7Sopenharmony_ci										 m_internalFormat, m_texFormat, m_sampler.c_str(), m_outType.c_str(), m_min,
522e5c31af7Sopenharmony_ci										 m_max, m_extension.c_str(), 1.0));
523e5c31af7Sopenharmony_ci	// sample_shading.render.half
524e5c31af7Sopenharmony_ci	addChild(new SampleShadingRenderCase(m_context, "half", "Sample shader functionality", m_glslVersion,
525e5c31af7Sopenharmony_ci										 m_internalFormat, m_texFormat, m_sampler.c_str(), m_outType.c_str(), m_min,
526e5c31af7Sopenharmony_ci										 m_max, m_extension.c_str(), 0.5));
527e5c31af7Sopenharmony_ci	// sample_shading.render.none
528e5c31af7Sopenharmony_ci	addChild(new SampleShadingRenderCase(m_context, "none", "Sample shader functionality", m_glslVersion,
529e5c31af7Sopenharmony_ci										 m_internalFormat, m_texFormat, m_sampler.c_str(), m_outType.c_str(), m_min,
530e5c31af7Sopenharmony_ci										 m_max, m_extension.c_str(), 0.0));
531e5c31af7Sopenharmony_ci}
532e5c31af7Sopenharmony_ci
533e5c31af7Sopenharmony_ciclass SampleShadingRenderTests : public glcts::TestCaseGroup
534e5c31af7Sopenharmony_ci{
535e5c31af7Sopenharmony_cipublic:
536e5c31af7Sopenharmony_ci	SampleShadingRenderTests(glcts::Context& context, glu::GLSLVersion glslVersion);
537e5c31af7Sopenharmony_ci	~SampleShadingRenderTests(void);
538e5c31af7Sopenharmony_ci
539e5c31af7Sopenharmony_ci	void init(void);
540e5c31af7Sopenharmony_ci
541e5c31af7Sopenharmony_ciprivate:
542e5c31af7Sopenharmony_ci	SampleShadingRenderTests(const SampleShadingTests& other);
543e5c31af7Sopenharmony_ci	SampleShadingRenderTests& operator=(const SampleShadingTests& other);
544e5c31af7Sopenharmony_ci
545e5c31af7Sopenharmony_ci	glu::GLSLVersion m_glslVersion;
546e5c31af7Sopenharmony_ci};
547e5c31af7Sopenharmony_ci
548e5c31af7Sopenharmony_ciSampleShadingRenderTests::SampleShadingRenderTests(Context& context, glu::GLSLVersion glslVersion)
549e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "render", "Sample Shading render tests"), m_glslVersion(glslVersion)
550e5c31af7Sopenharmony_ci{
551e5c31af7Sopenharmony_ci}
552e5c31af7Sopenharmony_ci
553e5c31af7Sopenharmony_ciSampleShadingRenderTests::~SampleShadingRenderTests(void)
554e5c31af7Sopenharmony_ci{
555e5c31af7Sopenharmony_ci}
556e5c31af7Sopenharmony_ci
557e5c31af7Sopenharmony_civoid SampleShadingRenderTests::init(void)
558e5c31af7Sopenharmony_ci{
559e5c31af7Sopenharmony_ci	// sample_shading.render.rgba8
560e5c31af7Sopenharmony_ci	addChild(new SampleShadingRenderFormatTests(
561e5c31af7Sopenharmony_ci		m_context, m_glslVersion, GL_RGBA8, "rgba8",
562e5c31af7Sopenharmony_ci		tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8), "sampler2DMS", "vec4", 0.0, 1.0));
563e5c31af7Sopenharmony_ci	// sample_shading.render.rgba8i
564e5c31af7Sopenharmony_ci	addChild(new SampleShadingRenderFormatTests(
565e5c31af7Sopenharmony_ci		m_context, m_glslVersion, GL_RGBA8I, "rgba8i",
566e5c31af7Sopenharmony_ci		tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT8), "isampler2DMS", "ivec4", -128.0,
567e5c31af7Sopenharmony_ci		127.0));
568e5c31af7Sopenharmony_ci	// sample_shading.render.rgba8ui
569e5c31af7Sopenharmony_ci	addChild(new SampleShadingRenderFormatTests(
570e5c31af7Sopenharmony_ci		m_context, m_glslVersion, GL_RGBA8UI, "rgba8ui",
571e5c31af7Sopenharmony_ci		tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT8), "usampler2DMS", "uvec4", 0.0,
572e5c31af7Sopenharmony_ci		255.0));
573e5c31af7Sopenharmony_ci	// sample_shading.render.rgba32f
574e5c31af7Sopenharmony_ci	const char* extension =
575e5c31af7Sopenharmony_ci		(glu::isContextTypeES(m_context.getRenderContext().getType())) ? "GL_EXT_color_buffer_float" : "";
576e5c31af7Sopenharmony_ci	addChild(new SampleShadingRenderFormatTests(m_context, m_glslVersion, GL_RGBA32F, "rgba32f",
577e5c31af7Sopenharmony_ci												tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT),
578e5c31af7Sopenharmony_ci												"sampler2DMS", "vec4", 0.0, 1.0, extension));
579e5c31af7Sopenharmony_ci}
580e5c31af7Sopenharmony_ci
581e5c31af7Sopenharmony_ciSampleShadingTests::SampleShadingTests(Context& context, glu::GLSLVersion glslVersion)
582e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "sample_shading", "Sample Shading tests"), m_glslVersion(glslVersion)
583e5c31af7Sopenharmony_ci{
584e5c31af7Sopenharmony_ci}
585e5c31af7Sopenharmony_ci
586e5c31af7Sopenharmony_ciSampleShadingTests::~SampleShadingTests(void)
587e5c31af7Sopenharmony_ci{
588e5c31af7Sopenharmony_ci}
589e5c31af7Sopenharmony_ci
590e5c31af7Sopenharmony_civoid SampleShadingTests::init(void)
591e5c31af7Sopenharmony_ci{
592e5c31af7Sopenharmony_ci	// sample_shading.api
593e5c31af7Sopenharmony_ci	addChild(new SampleShadingApiCaseGroup(m_context, m_glslVersion));
594e5c31af7Sopenharmony_ci	// sample_shading.render
595e5c31af7Sopenharmony_ci	addChild(new SampleShadingRenderTests(m_context, m_glslVersion));
596e5c31af7Sopenharmony_ci}
597e5c31af7Sopenharmony_ci
598e5c31af7Sopenharmony_ci} // glcts
599