1e5c31af7Sopenharmony_ci/*-------------------------------------------------------------------------
2e5c31af7Sopenharmony_ci * drawElements Quality Program OpenGL ES 2.0 Module
3e5c31af7Sopenharmony_ci * -------------------------------------------------
4e5c31af7Sopenharmony_ci *
5e5c31af7Sopenharmony_ci * Copyright 2014 The Android Open Source Project
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 Algorithm implementation tests.
22e5c31af7Sopenharmony_ci *//*--------------------------------------------------------------------*/
23e5c31af7Sopenharmony_ci
24e5c31af7Sopenharmony_ci#include "es2fShaderAlgorithmTests.hpp"
25e5c31af7Sopenharmony_ci#include "glsShaderRenderCase.hpp"
26e5c31af7Sopenharmony_ci#include "gluShaderUtil.hpp"
27e5c31af7Sopenharmony_ci#include "tcuStringTemplate.hpp"
28e5c31af7Sopenharmony_ci
29e5c31af7Sopenharmony_ci#include "deInt32.h"
30e5c31af7Sopenharmony_ci#include "deMemory.h"
31e5c31af7Sopenharmony_ci
32e5c31af7Sopenharmony_ci#include <map>
33e5c31af7Sopenharmony_ci#include <algorithm>
34e5c31af7Sopenharmony_ci
35e5c31af7Sopenharmony_ciusing namespace std;
36e5c31af7Sopenharmony_ciusing namespace tcu;
37e5c31af7Sopenharmony_ciusing namespace glu;
38e5c31af7Sopenharmony_ciusing namespace deqp::gls;
39e5c31af7Sopenharmony_ci
40e5c31af7Sopenharmony_cinamespace deqp
41e5c31af7Sopenharmony_ci{
42e5c31af7Sopenharmony_cinamespace gles2
43e5c31af7Sopenharmony_ci{
44e5c31af7Sopenharmony_cinamespace Functional
45e5c31af7Sopenharmony_ci{
46e5c31af7Sopenharmony_ci
47e5c31af7Sopenharmony_ci// ShaderAlgorithmCase
48e5c31af7Sopenharmony_ci
49e5c31af7Sopenharmony_ciclass ShaderAlgorithmCase : public ShaderRenderCase
50e5c31af7Sopenharmony_ci{
51e5c31af7Sopenharmony_cipublic:
52e5c31af7Sopenharmony_ci								ShaderAlgorithmCase			(Context& context, const char* name, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, const char* vertShaderSource, const char* fragShaderSource);
53e5c31af7Sopenharmony_ci	virtual						~ShaderAlgorithmCase		(void);
54e5c31af7Sopenharmony_ci
55e5c31af7Sopenharmony_ciprivate:
56e5c31af7Sopenharmony_ci								ShaderAlgorithmCase			(const ShaderAlgorithmCase&);	// not allowed!
57e5c31af7Sopenharmony_ci	ShaderAlgorithmCase&		operator=					(const ShaderAlgorithmCase&);	// not allowed!
58e5c31af7Sopenharmony_ci};
59e5c31af7Sopenharmony_ci
60e5c31af7Sopenharmony_ciShaderAlgorithmCase::ShaderAlgorithmCase (Context& context, const char* name, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, const char* vertShaderSource, const char* fragShaderSource)
61e5c31af7Sopenharmony_ci	: ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, description, isVertexCase, evalFunc)
62e5c31af7Sopenharmony_ci{
63e5c31af7Sopenharmony_ci	m_vertShaderSource	= vertShaderSource;
64e5c31af7Sopenharmony_ci	m_fragShaderSource	= fragShaderSource;
65e5c31af7Sopenharmony_ci}
66e5c31af7Sopenharmony_ci
67e5c31af7Sopenharmony_ciShaderAlgorithmCase::~ShaderAlgorithmCase (void)
68e5c31af7Sopenharmony_ci{
69e5c31af7Sopenharmony_ci}
70e5c31af7Sopenharmony_ci
71e5c31af7Sopenharmony_ci// Helpers.
72e5c31af7Sopenharmony_ci
73e5c31af7Sopenharmony_cistatic ShaderAlgorithmCase* createExpressionCase (Context& context, const char* caseName, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, LineStream& shaderBody)
74e5c31af7Sopenharmony_ci{
75e5c31af7Sopenharmony_ci	std::ostringstream vtx;
76e5c31af7Sopenharmony_ci	std::ostringstream frag;
77e5c31af7Sopenharmony_ci	std::ostringstream& op = isVertexCase ? vtx : frag;
78e5c31af7Sopenharmony_ci
79e5c31af7Sopenharmony_ci	vtx << "attribute highp vec4 a_position;\n";
80e5c31af7Sopenharmony_ci	vtx << "attribute highp vec4 a_unitCoords;\n";
81e5c31af7Sopenharmony_ci
82e5c31af7Sopenharmony_ci	if (isVertexCase)
83e5c31af7Sopenharmony_ci	{
84e5c31af7Sopenharmony_ci		vtx << "varying mediump vec3 v_color;\n";
85e5c31af7Sopenharmony_ci		frag << "varying mediump vec3 v_color;\n";
86e5c31af7Sopenharmony_ci	}
87e5c31af7Sopenharmony_ci	else
88e5c31af7Sopenharmony_ci	{
89e5c31af7Sopenharmony_ci		vtx << "varying mediump vec4 v_coords;\n";
90e5c31af7Sopenharmony_ci		frag << "varying mediump vec4 v_coords;\n";
91e5c31af7Sopenharmony_ci	}
92e5c31af7Sopenharmony_ci
93e5c31af7Sopenharmony_ci//	op << "uniform mediump sampler2D ut_brick;\n";
94e5c31af7Sopenharmony_ci
95e5c31af7Sopenharmony_ci	vtx << "\n";
96e5c31af7Sopenharmony_ci	vtx << "void main()\n";
97e5c31af7Sopenharmony_ci	vtx << "{\n";
98e5c31af7Sopenharmony_ci	vtx << "	gl_Position = a_position;\n";
99e5c31af7Sopenharmony_ci
100e5c31af7Sopenharmony_ci	frag << "\n";
101e5c31af7Sopenharmony_ci	frag << "void main()\n";
102e5c31af7Sopenharmony_ci	frag << "{\n";
103e5c31af7Sopenharmony_ci
104e5c31af7Sopenharmony_ci	// Write matrix.
105e5c31af7Sopenharmony_ci	if (isVertexCase)
106e5c31af7Sopenharmony_ci		op << "	${PRECISION} vec4 coords = a_unitCoords;\n";
107e5c31af7Sopenharmony_ci	else
108e5c31af7Sopenharmony_ci		op << "	${PRECISION} vec4 coords = v_coords;\n";
109e5c31af7Sopenharmony_ci
110e5c31af7Sopenharmony_ci	op << "	${PRECISION} vec3 res = vec3(0.0);\n";
111e5c31af7Sopenharmony_ci	op << shaderBody.str();
112e5c31af7Sopenharmony_ci
113e5c31af7Sopenharmony_ci	if (isVertexCase)
114e5c31af7Sopenharmony_ci	{
115e5c31af7Sopenharmony_ci		vtx << "	v_color = res;\n";
116e5c31af7Sopenharmony_ci		frag << "	gl_FragColor = vec4(v_color, 1.0);\n";
117e5c31af7Sopenharmony_ci	}
118e5c31af7Sopenharmony_ci	else
119e5c31af7Sopenharmony_ci	{
120e5c31af7Sopenharmony_ci		vtx << "	v_coords = a_unitCoords;\n";
121e5c31af7Sopenharmony_ci		frag << "	gl_FragColor = vec4(res, 1.0);\n";
122e5c31af7Sopenharmony_ci	}
123e5c31af7Sopenharmony_ci
124e5c31af7Sopenharmony_ci	vtx << "}\n";
125e5c31af7Sopenharmony_ci	frag << "}\n";
126e5c31af7Sopenharmony_ci
127e5c31af7Sopenharmony_ci	// Fill in shader templates.
128e5c31af7Sopenharmony_ci	map<string, string> params;
129e5c31af7Sopenharmony_ci	params.insert(pair<string, string>("PRECISION", "mediump"));
130e5c31af7Sopenharmony_ci
131e5c31af7Sopenharmony_ci	StringTemplate vertTemplate(vtx.str().c_str());
132e5c31af7Sopenharmony_ci	StringTemplate fragTemplate(frag.str().c_str());
133e5c31af7Sopenharmony_ci	string vertexShaderSource = vertTemplate.specialize(params);
134e5c31af7Sopenharmony_ci	string fragmentShaderSource = fragTemplate.specialize(params);
135e5c31af7Sopenharmony_ci
136e5c31af7Sopenharmony_ci	return new ShaderAlgorithmCase(context, caseName, description, isVertexCase, evalFunc, vertexShaderSource.c_str(), fragmentShaderSource.c_str());
137e5c31af7Sopenharmony_ci}
138e5c31af7Sopenharmony_ci
139e5c31af7Sopenharmony_ci// ShaderAlgorithmTests.
140e5c31af7Sopenharmony_ci
141e5c31af7Sopenharmony_ciShaderAlgorithmTests::ShaderAlgorithmTests(Context& context)
142e5c31af7Sopenharmony_ci	: TestCaseGroup(context, "algorithm", "Miscellaneous algorithm implementations using shaders.")
143e5c31af7Sopenharmony_ci{
144e5c31af7Sopenharmony_ci}
145e5c31af7Sopenharmony_ci
146e5c31af7Sopenharmony_ciShaderAlgorithmTests::~ShaderAlgorithmTests (void)
147e5c31af7Sopenharmony_ci{
148e5c31af7Sopenharmony_ci}
149e5c31af7Sopenharmony_ci
150e5c31af7Sopenharmony_civoid ShaderAlgorithmTests::init (void)
151e5c31af7Sopenharmony_ci{
152e5c31af7Sopenharmony_ci//	TestCaseGroup* colorGroup = new TestCaseGroup(m_testCtx, "color", "Miscellaneous color related algorithm tests.");
153e5c31af7Sopenharmony_ci//	addChild(colorGroup);
154e5c31af7Sopenharmony_ci
155e5c31af7Sopenharmony_ci	#define SHADER_OP_CASE(NAME, DESCRIPTION, SHADER_OP, EVAL_FUNC_BODY)														\
156e5c31af7Sopenharmony_ci		do {																													\
157e5c31af7Sopenharmony_ci			struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY };	/* NOLINT(EVAL_FUNC_BODY) */		\
158e5c31af7Sopenharmony_ci			addChild(createExpressionCase(m_context, #NAME "_vertex", DESCRIPTION, true, &Eval_##NAME::eval, SHADER_OP));		\
159e5c31af7Sopenharmony_ci			addChild(createExpressionCase(m_context, #NAME "_fragment", DESCRIPTION, false, &Eval_##NAME::eval, SHADER_OP));	\
160e5c31af7Sopenharmony_ci		} while (deGetFalse())
161e5c31af7Sopenharmony_ci
162e5c31af7Sopenharmony_ci	SHADER_OP_CASE(hsl_to_rgb, "Conversion from HSL color space into RGB.",
163e5c31af7Sopenharmony_ci		LineStream(1)
164e5c31af7Sopenharmony_ci		<< "mediump float H = coords.x, S = coords.y, L = coords.z;"
165e5c31af7Sopenharmony_ci		<< "mediump float v = (L <= 0.5) ? (L * (1.0 + S)) : (L + S - L * S);"
166e5c31af7Sopenharmony_ci		<< "res = vec3(L); // default to gray"
167e5c31af7Sopenharmony_ci		<< "if (v > 0.0)"
168e5c31af7Sopenharmony_ci		<< "{"
169e5c31af7Sopenharmony_ci		<< "	mediump float m = L + L - v;"
170e5c31af7Sopenharmony_ci		<< "	mediump float sv = (v - m) / v;"
171e5c31af7Sopenharmony_ci		<< "	H *= 6.0;"
172e5c31af7Sopenharmony_ci		<< "	mediump int sextant = int(H);"
173e5c31af7Sopenharmony_ci		<< "	mediump float fract = H - float(sextant);"
174e5c31af7Sopenharmony_ci		<< "	mediump float vsf = v * sv * fract;"
175e5c31af7Sopenharmony_ci		<< "	mediump float mid1 = m + vsf;"
176e5c31af7Sopenharmony_ci		<< "	mediump float mid2 = m - vsf;"
177e5c31af7Sopenharmony_ci		<< "	if (sextant == 0)      res = vec3(v, mid1, m);"
178e5c31af7Sopenharmony_ci		<< "	else if (sextant == 1) res = vec3(mid2, v, m);"
179e5c31af7Sopenharmony_ci		<< "	else if (sextant == 2) res = vec3(m, v, mid1);"
180e5c31af7Sopenharmony_ci		<< "	else if (sextant == 3) res = vec3(m, mid2, v);"
181e5c31af7Sopenharmony_ci		<< "	else if (sextant == 4) res = vec3(mid1, m, v);"
182e5c31af7Sopenharmony_ci		<< "	else                   res = vec3(v, m, mid2);"
183e5c31af7Sopenharmony_ci		<< "}",
184e5c31af7Sopenharmony_ci		{
185e5c31af7Sopenharmony_ci			float H = c.unitCoords.x();
186e5c31af7Sopenharmony_ci			float S = c.unitCoords.y();
187e5c31af7Sopenharmony_ci			float L = c.unitCoords.z();
188e5c31af7Sopenharmony_ci			Vec3 rgb = Vec3(L);
189e5c31af7Sopenharmony_ci			float v = (L <= 0.5f) ? (L * (1.0f + S)) : (L + S - L * S);
190e5c31af7Sopenharmony_ci			if (v > 0.0f)
191e5c31af7Sopenharmony_ci			{
192e5c31af7Sopenharmony_ci				float m = L + L - v;
193e5c31af7Sopenharmony_ci				float sv = (v - m) / v;
194e5c31af7Sopenharmony_ci				H *= 6.0f;
195e5c31af7Sopenharmony_ci				int sextant = int(H);
196e5c31af7Sopenharmony_ci				float fract = H - float(sextant);
197e5c31af7Sopenharmony_ci				float vsf = v * sv * fract;
198e5c31af7Sopenharmony_ci				float mid1 = m + vsf;
199e5c31af7Sopenharmony_ci				float mid2 = m - vsf;
200e5c31af7Sopenharmony_ci				if (sextant == 0)		rgb = Vec3(v, mid1, m);
201e5c31af7Sopenharmony_ci				else if (sextant == 1)	rgb = Vec3(mid2, v, m);
202e5c31af7Sopenharmony_ci				else if (sextant == 2)	rgb = Vec3(m, v, mid1);
203e5c31af7Sopenharmony_ci				else if (sextant == 3)	rgb = Vec3(m, mid2, v);
204e5c31af7Sopenharmony_ci				else if (sextant == 4)	rgb = Vec3(mid1, m, v);
205e5c31af7Sopenharmony_ci				else					rgb = Vec3(v, m, mid2);
206e5c31af7Sopenharmony_ci			}
207e5c31af7Sopenharmony_ci			c.color.xyz() = rgb;
208e5c31af7Sopenharmony_ci		});
209e5c31af7Sopenharmony_ci
210e5c31af7Sopenharmony_ci	SHADER_OP_CASE(rgb_to_hsl, "Conversion from RGB color space into HSL.",
211e5c31af7Sopenharmony_ci		LineStream(1)
212e5c31af7Sopenharmony_ci		<< "mediump float r = coords.x, g = coords.y, b = coords.z;"
213e5c31af7Sopenharmony_ci		<< "mediump float minVal = min(min(r, g), b);"
214e5c31af7Sopenharmony_ci		<< "mediump float maxVal = max(max(r, g), b);"
215e5c31af7Sopenharmony_ci		<< "mediump float L = (minVal + maxVal) * 0.5;"
216e5c31af7Sopenharmony_ci		<< "if (minVal == maxVal)"
217e5c31af7Sopenharmony_ci		<< "	res = vec3(0.0, 0.0, L);"
218e5c31af7Sopenharmony_ci		<< "else"
219e5c31af7Sopenharmony_ci		<< "{"
220e5c31af7Sopenharmony_ci		<< "	mediump float H;"
221e5c31af7Sopenharmony_ci		<< "	mediump float S;"
222e5c31af7Sopenharmony_ci		<< "	if (L < 0.5)"
223e5c31af7Sopenharmony_ci		<< "		S = (maxVal - minVal) / (maxVal + minVal);"
224e5c31af7Sopenharmony_ci		<< "	else"
225e5c31af7Sopenharmony_ci		<< "		S = (maxVal - minVal) / (2.0 - maxVal - minVal);"
226e5c31af7Sopenharmony_ci		<< ""
227e5c31af7Sopenharmony_ci		<< "	mediump float ooDiff = 1.0 / (maxVal - minVal);"
228e5c31af7Sopenharmony_ci		<< "	if (r == maxVal)      H = (g - b) * ooDiff;"
229e5c31af7Sopenharmony_ci		<< "	else if (g == maxVal) H = 2.0 + (b - r) * ooDiff;"
230e5c31af7Sopenharmony_ci		<< "	else                  H = 4.0 + (r - g) * ooDiff;"
231e5c31af7Sopenharmony_ci		<< "	H /= 6.0;"
232e5c31af7Sopenharmony_ci		<< ""
233e5c31af7Sopenharmony_ci		<< "	res = vec3(H, S, L);"
234e5c31af7Sopenharmony_ci		<< "}",
235e5c31af7Sopenharmony_ci		{
236e5c31af7Sopenharmony_ci			float r = c.unitCoords.x();
237e5c31af7Sopenharmony_ci			float g = c.unitCoords.y();
238e5c31af7Sopenharmony_ci			float b = c.unitCoords.z();
239e5c31af7Sopenharmony_ci			float minVal = min(min(r, g), b);
240e5c31af7Sopenharmony_ci			float maxVal = max(max(r, g), b);
241e5c31af7Sopenharmony_ci			float L = (minVal + maxVal) * 0.5f;
242e5c31af7Sopenharmony_ci			Vec3 hsl;
243e5c31af7Sopenharmony_ci
244e5c31af7Sopenharmony_ci			if (minVal == maxVal)
245e5c31af7Sopenharmony_ci				hsl = Vec3(0.0f, 0.0f, L);
246e5c31af7Sopenharmony_ci			else
247e5c31af7Sopenharmony_ci			{
248e5c31af7Sopenharmony_ci				float H;
249e5c31af7Sopenharmony_ci				float S;
250e5c31af7Sopenharmony_ci				if (L < 0.5f)
251e5c31af7Sopenharmony_ci					S = (maxVal - minVal) / (maxVal + minVal);
252e5c31af7Sopenharmony_ci				else
253e5c31af7Sopenharmony_ci					S = (maxVal - minVal) / (2.0f - maxVal - minVal);
254e5c31af7Sopenharmony_ci
255e5c31af7Sopenharmony_ci				float ooDiff = 1.0f / (maxVal - minVal);
256e5c31af7Sopenharmony_ci				if (r == maxVal)		H = (g - b) * ooDiff;
257e5c31af7Sopenharmony_ci				else if (g == maxVal)	H = 2.0f + (b - r) * ooDiff;
258e5c31af7Sopenharmony_ci				else					H = 4.0f + (r - g) * ooDiff;
259e5c31af7Sopenharmony_ci				H /= 6.0f;
260e5c31af7Sopenharmony_ci
261e5c31af7Sopenharmony_ci				hsl = Vec3(H, S, L);
262e5c31af7Sopenharmony_ci			}
263e5c31af7Sopenharmony_ci			c.color.xyz() = hsl;
264e5c31af7Sopenharmony_ci		});
265e5c31af7Sopenharmony_ci
266e5c31af7Sopenharmony_ci/*	SHADER_OP_CASE(image_to_grayscale, "Convert image to grayscale.",
267e5c31af7Sopenharmony_ci		LineStream(1)
268e5c31af7Sopenharmony_ci		<< "res = texture2D(ut_brick, coords.xy).rgb;",
269e5c31af7Sopenharmony_ci		{
270e5c31af7Sopenharmony_ci			c.color.xyz() = Vec3(0.5f);
271e5c31af7Sopenharmony_ci		});*/
272e5c31af7Sopenharmony_ci}
273e5c31af7Sopenharmony_ci
274e5c31af7Sopenharmony_ci} // Functional
275e5c31af7Sopenharmony_ci} // gles2
276e5c31af7Sopenharmony_ci} // deqp
277