1/*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 *      http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Shader struct tests.
22 *//*--------------------------------------------------------------------*/
23
24#include "es2fShaderFunctionTests.hpp"
25#include "glsShaderRenderCase.hpp"
26#include "gluTexture.hpp"
27#include "tcuStringTemplate.hpp"
28#include "tcuTextureUtil.hpp"
29
30using namespace deqp::gls;
31
32namespace deqp
33{
34namespace gles2
35{
36namespace Functional
37{
38
39typedef void (*SetupUniformsFunc) (const glw::Functions& gl, deUint32 programID, const tcu::Vec4& constCoords);
40
41class ShaderFunctionCase : public ShaderRenderCase
42{
43public:
44							ShaderFunctionCase		(Context& context, const char* name, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, const char* vertShaderSource, const char* fragShaderSource);
45							~ShaderFunctionCase		(void);
46
47	void					init					(void);
48	void					deinit					(void);
49
50	virtual void			setupUniforms			(int programID, const tcu::Vec4& constCoords);
51
52private:
53							ShaderFunctionCase		(const ShaderFunctionCase&);
54	ShaderFunctionCase&		operator=				(const ShaderFunctionCase&);
55
56	const SetupUniformsFunc	m_setupUniforms;
57
58	glu::Texture2D*			m_brickTexture;
59};
60
61ShaderFunctionCase::ShaderFunctionCase (Context& context, const char* name, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniformsFunc, const char* vertShaderSource, const char* fragShaderSource)
62	: ShaderRenderCase	(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, description, isVertexCase, evalFunc)
63	, m_setupUniforms	(setupUniformsFunc)
64	, m_brickTexture	(DE_NULL)
65{
66	m_vertShaderSource	= vertShaderSource;
67	m_fragShaderSource	= fragShaderSource;
68}
69
70ShaderFunctionCase::~ShaderFunctionCase (void)
71{
72	delete m_brickTexture;
73}
74
75void ShaderFunctionCase::init (void)
76{
77	gls::ShaderRenderCase::init();
78}
79
80void ShaderFunctionCase::deinit (void)
81{
82	gls::ShaderRenderCase::deinit();
83	delete m_brickTexture;
84	m_brickTexture = DE_NULL;
85}
86
87void ShaderFunctionCase::setupUniforms (int programID, const tcu::Vec4& constCoords)
88{
89	ShaderRenderCase::setupUniforms(programID, constCoords);
90	if (m_setupUniforms)
91		m_setupUniforms(m_renderCtx.getFunctions(), programID, constCoords);
92}
93
94static ShaderFunctionCase* createStructCase (Context& context, const char* name, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, SetupUniformsFunc setupUniforms, const LineStream& shaderSrc, const std::map<std::string, std::string>* additionalParams)
95{
96	static const char* defaultVertSrc =
97		"attribute highp vec4 a_position;\n"
98		"attribute highp vec4 a_coords;\n"
99		"varying mediump vec4 v_coords;\n\n"
100		"void main (void)\n"
101		"{\n"
102		"	v_coords = a_coords;\n"
103		"	gl_Position = a_position;\n"
104		"}\n";
105	static const char* defaultFragSrc =
106		"varying mediump vec4 v_color;\n\n"
107		"void main (void)\n"
108		"{\n"
109		"	gl_FragColor = v_color;\n"
110		"}\n";
111
112	// Fill in specialization parameters.
113	std::map<std::string, std::string> spParams;
114	if (isVertexCase)
115	{
116		spParams["DECLARATIONS"] =
117			"attribute highp vec4 a_position;\n"
118			"attribute highp vec4 a_coords;\n"
119			"varying mediump vec4 v_color;";
120		spParams["COORDS"]		= "a_coords";
121		spParams["DST"]			= "v_color";
122		spParams["ASSIGN_POS"]	= "gl_Position = a_position;";
123	}
124	else
125	{
126		spParams["DECLARATIONS"]	=
127			"precision highp float;\n"
128			"varying mediump vec4 v_coords;";
129		spParams["COORDS"]			= "v_coords";
130		spParams["DST"]				= "gl_FragColor";
131		spParams["ASSIGN_POS"]		= "";
132	}
133	if (additionalParams)
134		spParams.insert(additionalParams->begin(), additionalParams->end());
135
136	if (isVertexCase)
137		return new ShaderFunctionCase(context, name, description, isVertexCase, evalFunc, setupUniforms, tcu::StringTemplate(shaderSrc.str()).specialize(spParams).c_str(), defaultFragSrc);
138	else
139		return new ShaderFunctionCase(context, name, description, isVertexCase, evalFunc, setupUniforms, defaultVertSrc, tcu::StringTemplate(shaderSrc.str()).specialize(spParams).c_str());
140}
141
142ShaderFunctionTests::ShaderFunctionTests (Context& context)
143	: TestCaseGroup(context, "function", "Function Tests")
144{
145}
146
147ShaderFunctionTests::~ShaderFunctionTests (void)
148{
149}
150
151void ShaderFunctionTests::init (void)
152{
153	#define FUNCTION_CASE_PARAMETERIZED(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY, PARAMS)										\
154		do {																																	\
155			struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY };  /* NOLINT(EVAL_FUNC_BODY) */						\
156			addChild(createStructCase(m_context, #NAME "_vertex", DESCRIPTION, true, &Eval_##NAME::eval, DE_NULL, SHADER_SRC, PARAMS));	\
157			addChild(createStructCase(m_context, #NAME "_fragment", DESCRIPTION, false, &Eval_##NAME::eval, DE_NULL, SHADER_SRC, PARAMS));\
158		} while (deGetFalse())
159
160	#define FUNCTION_CASE(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY)	\
161		FUNCTION_CASE_PARAMETERIZED(NAME, DESCRIPTION, SHADER_SRC, EVAL_FUNC_BODY, DE_NULL)
162
163	FUNCTION_CASE(local_variable_aliasing, "Function out parameter aliases local variable",
164		LineStream()
165		<< "${DECLARATIONS}"
166		<< ""
167		<< "bool out_params_are_distinct(float x, out float y)"
168		<< "{"
169		<< "    y = 2.;"
170		<< "    return x == 1. && y == 2.;"
171		<< "}"
172		<< ""
173		<< "void main (void)"
174		<< "{"
175		<< "    float x = 1.;"
176		<< "    ${DST} = out_params_are_distinct(x, x) ? vec4(0.,1.,0.,1.) : vec4(1.,0.,0.,1.);"
177		<< "	${ASSIGN_POS}"
178		<< "}",
179		{ c.color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f); });
180
181	FUNCTION_CASE(global_variable_aliasing, "Function out parameter aliases global variable",
182		LineStream()
183		<< "${DECLARATIONS}"
184		<< ""
185		<< ""
186		<< "float x = 1.;"
187		<< "bool out_params_are_distinct_from_global(out float y) {"
188		<< "    y = 2.;"
189		<< "    return x == 1. && y == 2.;"
190		<< "}"
191		<< ""
192		<< "void main (void)"
193		<< "{"
194		<< "    ${DST} = out_params_are_distinct_from_global(x) ? vec4(0.,1.,0.,1.) : vec4(1.,0.,0.,1.);"
195		<< "	${ASSIGN_POS}"
196		<< "}",
197		{ c.color.xyz() = tcu::Vec3(0.0f, 1.0f, 0.0f); });
198}
199
200} // Functional
201} // gles2
202} // deqp
203