• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.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 FBO test utilities.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fFboTestUtil.hpp"
25 #include "sglrContextUtil.hpp"
26 #include "sglrGLContext.hpp"
27 #include "sglrReferenceContext.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "tcuTextureUtil.hpp"
30 #include "deStringUtil.hpp"
31 #include "deMath.h"
32 #include "glwEnums.hpp"
33 #include "glwFunctions.hpp"
34 
35 #include <limits>
36 
37 namespace deqp
38 {
39 namespace gles3
40 {
41 namespace Functional
42 {
43 namespace FboTestUtil
44 {
45 
46 using std::string;
47 using std::vector;
48 using tcu::Vec2;
49 using tcu::Vec3;
50 using tcu::Vec4;
51 using tcu::IVec2;
52 using tcu::IVec3;
53 using tcu::IVec4;
54 
mapDataTypeToGenericVecType(glu::DataType type)55 static rr::GenericVecType mapDataTypeToGenericVecType(glu::DataType type)
56 {
57 	switch (type)
58 	{
59 		case glu::TYPE_FLOAT_VEC4:	return rr::GENERICVECTYPE_FLOAT;
60 		case glu::TYPE_INT_VEC4:	return rr::GENERICVECTYPE_INT32;
61 		case glu::TYPE_UINT_VEC4:	return rr::GENERICVECTYPE_UINT32;
62 		default:
63 			DE_ASSERT(DE_FALSE);
64 			return rr::GENERICVECTYPE_LAST;
65 	}
66 }
67 
68 template <typename T>
castVectorSaturate(const tcu::Vec4 & in)69 static tcu::Vector<T, 4> castVectorSaturate (const tcu::Vec4& in)
70 {
71 	return tcu::Vector<T, 4>(((double)in.x() + 0.5 >= (double)std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : (((double)in.x() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.x()))),
72 	                         ((double)in.y() + 0.5 >= (double)std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : (((double)in.y() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.y()))),
73 							 ((double)in.z() + 0.5 >= (double)std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : (((double)in.z() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.z()))),
74 							 ((double)in.w() + 0.5 >= (double)std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : (((double)in.w() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.w()))));
75 }
76 
FlatColorShader(glu::DataType outputType)77 FlatColorShader::FlatColorShader (glu::DataType outputType)
78 	: ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
79 					<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
80 					<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
81 					<< sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
82 					<< sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4)
83 					<< sglr::pdec::VertexSource(
84 							"#version 300 es\n"
85 							"in highp vec4 a_position;\n"
86 							"void main (void)\n"
87 							"{\n"
88 							"	gl_Position = a_position;\n"
89 							"}\n")
90 					<< sglr::pdec::FragmentSource(
91 							string(
92 								"#version 300 es\n"
93 								"uniform highp vec4 u_color;\n"
94 								"layout(location = 0) out highp ") + glu::getDataTypeName(outputType) + " o_color;\n"
95 								"void main (void)\n"
96 								"{\n"
97 								"	o_color = " + glu::getDataTypeName(outputType) + "(u_color);\n"
98 								"}\n"))
99 	, m_outputType(outputType)
100 {
101 }
102 
setColor(sglr::Context & context,deUint32 program,const tcu::Vec4 & color)103 void FlatColorShader::setColor (sglr::Context& context, deUint32 program, const tcu::Vec4& color)
104 {
105 	deInt32 location = context.getUniformLocation(program, "u_color");
106 
107 	context.useProgram(program);
108 	context.uniform4fv(location, 1, color.getPtr());
109 }
110 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const111 void FlatColorShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
112 {
113 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
114 	{
115 		rr::VertexPacket& packet = *packets[packetNdx];
116 
117 		packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
118 	}
119 }
120 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const121 void FlatColorShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
122 {
123 	const tcu::Vec4		color	(m_uniforms[0].value.f4);
124 	const tcu::IVec4	icolor	= castVectorSaturate<deInt32>(color);
125 	const tcu::UVec4	uicolor	= castVectorSaturate<deUint32>(color);
126 
127 	DE_UNREF(packets);
128 
129 	if (m_outputType == glu::TYPE_FLOAT_VEC4)
130 	{
131 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
132 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
133 			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
134 	}
135 	else if (m_outputType == glu::TYPE_INT_VEC4)
136 	{
137 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
138 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
139 			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
140 	}
141 	else if (m_outputType == glu::TYPE_UINT_VEC4)
142 	{
143 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
144 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
145 			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
146 	}
147 	else
148 		DE_ASSERT(DE_FALSE);
149 }
150 
GradientShader(glu::DataType outputType)151 GradientShader::GradientShader (glu::DataType outputType)
152 	: ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
153 					<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
154 					<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
155 					<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
156 					<< sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
157 					<< sglr::pdec::Uniform("u_gradientMin", glu::TYPE_FLOAT_VEC4)
158 					<< sglr::pdec::Uniform("u_gradientMax", glu::TYPE_FLOAT_VEC4)
159 					<< sglr::pdec::VertexSource(
160 							"#version 300 es\n"
161 							"in highp vec4 a_position;\n"
162 							"in highp vec4 a_coord;\n"
163 							"out highp vec4 v_coord;\n"
164 							"void main (void)\n"
165 							"{\n"
166 							"	gl_Position = a_position;\n"
167 							"	v_coord = a_coord;\n"
168 							"}\n")
169 					<< sglr::pdec::FragmentSource(
170 							string(
171 								"#version 300 es\n"
172 								"in highp vec4 v_coord;\n"
173 								"uniform highp vec4 u_gradientMin;\n"
174 								"uniform highp vec4 u_gradientMax;\n"
175 								"layout(location = 0) out highp ") + glu::getDataTypeName(outputType) + " o_color;\n"
176 								"void main (void)\n"
177 								"{\n"
178 								"	highp float x = v_coord.x;\n"
179 								"	highp float y = v_coord.y;\n"
180 								"	highp float f0 = (x + y) * 0.5;\n"
181 								"	highp float f1 = 0.5 + (x - y) * 0.5;\n"
182 								"	highp vec4 fv = vec4(f0, f1, 1.0f-f0, 1.0f-f1);\n"
183 								"	o_color = " + glu::getDataTypeName(outputType) + "(u_gradientMin + (u_gradientMax-u_gradientMin)*fv);\n"
184 								"}\n"))
185 	, m_outputType(outputType)
186 {
187 }
188 
setGradient(sglr::Context & ctx,deUint32 program,const tcu::Vec4 & gradientMin,const tcu::Vec4 & gradientMax)189 void GradientShader::setGradient (sglr::Context& ctx, deUint32 program, const tcu::Vec4& gradientMin, const tcu::Vec4& gradientMax)
190 {
191 	ctx.useProgram(program);
192 	ctx.uniform4fv(ctx.getUniformLocation(program, "u_gradientMin"), 1, gradientMin.getPtr());
193 	ctx.uniform4fv(ctx.getUniformLocation(program, "u_gradientMax"), 1, gradientMax.getPtr());
194 }
195 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const196 void GradientShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
197 {
198 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
199 	{
200 		rr::VertexPacket& packet = *packets[packetNdx];
201 
202 		packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
203 		packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
204 	}
205 }
206 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const207 void GradientShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
208 {
209 	const tcu::Vec4	gradientMin(m_uniforms[0].value.f4);
210 	const tcu::Vec4	gradientMax(m_uniforms[1].value.f4);
211 
212 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
213 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
214 	{
215 		const tcu::Vec4		coord	= rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
216 		const float			x		= coord.x();
217 		const float			y		= coord.y();
218 		const float			f0		= (x + y) * 0.5f;
219 		const float			f1		= 0.5f + (x - y) * 0.5f;
220 		const tcu::Vec4		fv		= Vec4(f0, f1, 1.0f-f0, 1.0f-f1);
221 
222 		const tcu::Vec4		color	= gradientMin + (gradientMax-gradientMin) * fv;
223 		const tcu::IVec4	icolor	= castVectorSaturate<deInt32>(color);
224 		const tcu::UVec4	uicolor	= castVectorSaturate<deUint32>(color);
225 
226 		if (m_outputType == glu::TYPE_FLOAT_VEC4)			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
227 		else if (m_outputType == glu::TYPE_INT_VEC4)		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
228 		else if (m_outputType == glu::TYPE_UINT_VEC4)		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
229 		else
230 			DE_ASSERT(DE_FALSE);
231 	}
232 }
233 
genTexFragmentShader(const vector<glu::DataType> & samplerTypes,glu::DataType outputType)234 static string genTexFragmentShader (const vector<glu::DataType>& samplerTypes, glu::DataType outputType)
235 {
236 	const char*			precision	= "highp";
237 	std::ostringstream	src;
238 
239 	src << "#version 300 es\n"
240 		<< "layout(location = 0) out highp " << glu::getDataTypeName(outputType) << " o_color0;\n";
241 
242 	src << "in highp vec2 v_coord;\n";
243 
244 	for (int samplerNdx = 0; samplerNdx < (int)samplerTypes.size(); samplerNdx++)
245 	{
246 		src << "uniform " << precision << " " << glu::getDataTypeName(samplerTypes[samplerNdx]) << " u_sampler" << samplerNdx << ";\n";
247 		src << "uniform " << precision << " vec4 u_texScale" << samplerNdx << ";\n";
248 		src << "uniform " << precision << " vec4 u_texBias" << samplerNdx << ";\n";
249 	}
250 
251 	// Output scale & bias
252 	src << "uniform " << precision << " vec4 u_outScale0;\n"
253 		<< "uniform " << precision << " vec4 u_outBias0;\n";
254 
255 	src << "\n"
256 		<< "void main (void)\n"
257 		<< "{\n"
258 		<< "	" << precision << " vec4 out0 = vec4(0.0);\n";
259 
260 	// Texture input fetch and combine.
261 	for (int inNdx = 0; inNdx < (int)samplerTypes.size(); inNdx++)
262 		src << "\tout0 += vec4("
263 			<< "texture(u_sampler" << inNdx << ", v_coord)) * u_texScale" << inNdx << " + u_texBias" << inNdx << ";\n";
264 
265 	// Write output.
266 	src << "	o_color0 = " << glu::getDataTypeName(outputType) << "(out0 * u_outScale0 + u_outBias0);\n";
267 
268 	src << "}\n";
269 
270 	return src.str();
271 }
272 
genTexture2DShaderDecl(const DataTypes & samplerTypes,glu::DataType outputType)273 static sglr::pdec::ShaderProgramDeclaration genTexture2DShaderDecl (const DataTypes& samplerTypes, glu::DataType outputType)
274 {
275 	sglr::pdec::ShaderProgramDeclaration decl;
276 
277 	decl << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT);
278 	decl << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT);
279 	decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
280 	decl << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType));
281 
282 	decl << sglr::pdec::VertexSource(
283 		"#version 300 es\n"
284 		"in highp vec4 a_position;\n"
285 		"in highp vec2 a_coord;\n"
286 		"out highp vec2 v_coord;\n"
287 		"void main(void)\n"
288 		"{\n"
289 		"	gl_Position = a_position;\n"
290 		"	v_coord = a_coord;\n"
291 		"}\n");
292 	decl << sglr::pdec::FragmentSource(genTexFragmentShader(samplerTypes.vec, outputType));
293 
294 	decl << sglr::pdec::Uniform("u_outScale0", glu::TYPE_FLOAT_VEC4);
295 	decl << sglr::pdec::Uniform("u_outBias0", glu::TYPE_FLOAT_VEC4);
296 
297 	for (size_t ndx = 0; ndx < samplerTypes.vec.size(); ++ndx)
298 	{
299 		decl << sglr::pdec::Uniform(std::string("u_sampler")  + de::toString(ndx), samplerTypes.vec[ndx]);
300 		decl << sglr::pdec::Uniform(std::string("u_texScale") + de::toString(ndx), glu::TYPE_FLOAT_VEC4);
301 		decl << sglr::pdec::Uniform(std::string("u_texBias")  + de::toString(ndx), glu::TYPE_FLOAT_VEC4);
302 	}
303 
304 	return decl;
305 }
306 
Texture2DShader(const DataTypes & samplerTypes,glu::DataType outputType,const Vec4 & outScale,const Vec4 & outBias)307 Texture2DShader::Texture2DShader (const DataTypes& samplerTypes, glu::DataType outputType, const Vec4& outScale, const Vec4& outBias)
308 	: sglr::ShaderProgram	(genTexture2DShaderDecl(samplerTypes, outputType))
309 	, m_outScale			(outScale)
310 	, m_outBias				(outBias)
311 	, m_outputType			(outputType)
312 {
313 	m_inputs.resize(samplerTypes.vec.size());
314 
315 	// Initialize units.
316 	for (int ndx = 0; ndx < (int)m_inputs.size(); ndx++)
317 	{
318 		m_inputs[ndx].unitNdx	= ndx;
319 		m_inputs[ndx].scale		= Vec4(1.0f);
320 		m_inputs[ndx].bias		= Vec4(0.0f);
321 	}
322 }
323 
setUnit(int inputNdx,int unitNdx)324 void Texture2DShader::setUnit (int inputNdx, int unitNdx)
325 {
326 	m_inputs[inputNdx].unitNdx = unitNdx;
327 }
328 
setTexScaleBias(int inputNdx,const Vec4 & scale,const Vec4 & bias)329 void Texture2DShader::setTexScaleBias (int inputNdx, const Vec4& scale, const Vec4& bias)
330 {
331 	m_inputs[inputNdx].scale	= scale;
332 	m_inputs[inputNdx].bias		= bias;
333 }
334 
setOutScaleBias(const Vec4 & scale,const Vec4 & bias)335 void Texture2DShader::setOutScaleBias (const Vec4& scale, const Vec4& bias)
336 {
337 	m_outScale	= scale;
338 	m_outBias	= bias;
339 }
340 
setUniforms(sglr::Context & gl,deUint32 program) const341 void Texture2DShader::setUniforms (sglr::Context& gl, deUint32 program) const
342 {
343 	gl.useProgram(program);
344 
345 	for (int texNdx = 0; texNdx < (int)m_inputs.size(); texNdx++)
346 	{
347 		string	samplerName	= string("u_sampler") + de::toString(texNdx);
348 		string	scaleName	= string("u_texScale") + de::toString(texNdx);
349 		string	biasName	= string("u_texBias") + de::toString(texNdx);
350 
351 		gl.uniform1i(gl.getUniformLocation(program, samplerName.c_str()), m_inputs[texNdx].unitNdx);
352 		gl.uniform4fv(gl.getUniformLocation(program, scaleName.c_str()), 1, m_inputs[texNdx].scale.getPtr());
353 		gl.uniform4fv(gl.getUniformLocation(program, biasName.c_str()), 1, m_inputs[texNdx].bias.getPtr());
354 	}
355 
356 	gl.uniform4fv(gl.getUniformLocation(program, "u_outScale0"), 1, m_outScale.getPtr());
357 	gl.uniform4fv(gl.getUniformLocation(program, "u_outBias0"), 1, m_outBias.getPtr());
358 }
359 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const360 void Texture2DShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
361 {
362 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
363 	{
364 		rr::VertexPacket& packet = *packets[packetNdx];
365 
366 		packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
367 		packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
368 	}
369 }
370 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const371 void Texture2DShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
372 {
373 	const tcu::Vec4 outScale (m_uniforms[0].value.f4);
374 	const tcu::Vec4 outBias	 (m_uniforms[1].value.f4);
375 
376 	tcu::Vec2 texCoords[4];
377 	tcu::Vec4 colors[4];
378 
379 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
380 	{
381 		// setup tex coords
382 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
383 		{
384 			const tcu::Vec4	coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
385 			texCoords[fragNdx] = tcu::Vec2(coord.x(), coord.y());
386 		}
387 
388 		// clear result
389 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
390 			colors[fragNdx] = tcu::Vec4(0.0f);
391 
392 		// sample each texture
393 		for (int ndx = 0; ndx < (int)m_inputs.size(); ndx++)
394 		{
395 			const sglr::rc::Texture2D*	tex		= m_uniforms[2 + ndx*3].sampler.tex2D;
396 			const tcu::Vec4				scale	(m_uniforms[2 + ndx*3 + 1].value.f4);
397 			const tcu::Vec4				bias	(m_uniforms[2 + ndx*3 + 2].value.f4);
398 			tcu::Vec4 tmpColors[4];
399 
400 			tex->sample4(tmpColors, texCoords);
401 
402 			for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
403 				colors[fragNdx] += tmpColors[fragNdx] * scale + bias;
404 		}
405 
406 		// write out
407 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
408 		{
409 			const tcu::Vec4		color	= colors[fragNdx] * outScale + outBias;
410 			const tcu::IVec4	icolor	= castVectorSaturate<deInt32>(color);
411 			const tcu::UVec4	uicolor	= castVectorSaturate<deUint32>(color);
412 
413 			if (m_outputType == glu::TYPE_FLOAT_VEC4)			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
414 			else if (m_outputType == glu::TYPE_INT_VEC4)		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
415 			else if (m_outputType == glu::TYPE_UINT_VEC4)		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
416 			else
417 				DE_ASSERT(DE_FALSE);
418 		}
419 	}
420 }
421 
TextureCubeShader(glu::DataType samplerType,glu::DataType outputType)422 TextureCubeShader::TextureCubeShader (glu::DataType samplerType, glu::DataType outputType)
423 	: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
424 							<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
425 							<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
426 							<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
427 							<< sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
428 							<< sglr::pdec::Uniform("u_coordMat", glu::TYPE_FLOAT_MAT3)
429 							<< sglr::pdec::Uniform("u_sampler0", samplerType)
430 							<< sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4)
431 							<< sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4)
432 							<< sglr::pdec::VertexSource(
433 									"#version 300 es\n"
434 									"in highp vec4 a_position;\n"
435 									"in mediump vec2 a_coord;\n"
436 									"uniform mat3 u_coordMat;\n"
437 									"out mediump vec3 v_coord;\n"
438 									"void main (void)\n"
439 									"{\n"
440 									"	gl_Position = a_position;\n"
441 									"	v_coord = u_coordMat * vec3(a_coord, 1.0);\n"
442 									"}\n")
443 							<< sglr::pdec::FragmentSource(
444 									string("") +
445 									"#version 300 es\n"
446 									"uniform highp " + glu::getDataTypeName(samplerType) + " u_sampler0;\n"
447 									"uniform highp vec4 u_scale;\n"
448 									"uniform highp vec4 u_bias;\n"
449 									"in mediump vec3 v_coord;\n"
450 									"layout(location = 0) out highp " + glu::getDataTypeName(outputType) + " o_color;\n"
451 									"void main (void)\n"
452 									"{\n"
453 									"	o_color = " + glu::getDataTypeName(outputType) + "(vec4(texture(u_sampler0, v_coord)) * u_scale + u_bias);\n"
454 									"}\n"))
455 	, m_texScale	(1.0f)
456 	, m_texBias		(0.0f)
457 	, m_outputType	(outputType)
458 {
459 }
460 
setFace(tcu::CubeFace face)461 void TextureCubeShader::setFace (tcu::CubeFace face)
462 {
463 	static const float s_cubeTransforms[][3*3] =
464 	{
465 		// Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
466 		{  0.0f,  0.0f, -1.0f,
467 		   0.0f, -2.0f,  1.0f,
468 		   2.0f,  0.0f, -1.0f },
469 		// Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
470 		{  0.0f,  0.0f,  1.0f,
471 		   0.0f, -2.0f,  1.0f,
472 		  -2.0f,  0.0f,  1.0f },
473 		// Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
474 		{  2.0f,  0.0f, -1.0f,
475 		   0.0f,  0.0f, -1.0f,
476 		   0.0f, -2.0f,  1.0f },
477 		// Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
478 		{  2.0f,  0.0f, -1.0f,
479 		   0.0f,  0.0f,  1.0f,
480 		   0.0f,  2.0f, -1.0f },
481 		// Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
482 		{ -2.0f,  0.0f,  1.0f,
483 		   0.0f, -2.0f,  1.0f,
484 		   0.0f,  0.0f, -1.0f },
485 		// Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
486 		{  2.0f,  0.0f, -1.0f,
487 		   0.0f, -2.0f,  1.0f,
488 		   0.0f,  0.0f,  1.0f }
489 	};
490 	DE_ASSERT(de::inBounds<int>(face, 0, tcu::CUBEFACE_LAST));
491 	m_coordMat = tcu::Mat3(s_cubeTransforms[face]);
492 }
493 
setTexScaleBias(const Vec4 & scale,const Vec4 & bias)494 void TextureCubeShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
495 {
496 	m_texScale	= scale;
497 	m_texBias	= bias;
498 }
499 
setUniforms(sglr::Context & gl,deUint32 program) const500 void TextureCubeShader::setUniforms (sglr::Context& gl, deUint32 program) const
501 {
502 	gl.useProgram(program);
503 
504 	gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), 0);
505 	gl.uniformMatrix3fv(gl.getUniformLocation(program, "u_coordMat"), 1, GL_FALSE, m_coordMat.getColumnMajorData().getPtr());
506 	gl.uniform4fv(gl.getUniformLocation(program, "u_scale"), 1, m_texScale.getPtr());
507 	gl.uniform4fv(gl.getUniformLocation(program, "u_bias"), 1, m_texBias.getPtr());
508 }
509 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const510 void TextureCubeShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
511 {
512 	tcu::Mat3 texCoordMat = tcu::Mat3(m_uniforms[0].value.m3);
513 
514 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
515 	{
516 		rr::VertexPacket&	packet	= *packets[packetNdx];
517 		tcu::Vec2			a_coord = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx).xy();
518 		tcu::Vec3			v_coord = texCoordMat * tcu::Vec3(a_coord.x(), a_coord.y(), 1.0f);
519 
520 		packet.position				= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
521 		packet.outputs[0]			= tcu::Vec4(v_coord.x(), v_coord.y(), v_coord.z(), 0.0f);
522 	}
523 }
524 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const525 void TextureCubeShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
526 {
527 	const tcu::Vec4 texScale (m_uniforms[2].value.f4);
528 	const tcu::Vec4 texBias	 (m_uniforms[3].value.f4);
529 
530 	tcu::Vec3 texCoords[4];
531 	tcu::Vec4 colors[4];
532 
533 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
534 	{
535 		const sglr::rc::TextureCube* tex = m_uniforms[1].sampler.texCube;
536 
537 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
538 		{
539 			const tcu::Vec4	coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
540 			texCoords[fragNdx] = tcu::Vec3(coord.x(), coord.y(), coord.z());
541 		}
542 
543 		tex->sample4(colors, texCoords);
544 
545 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
546 		{
547 			const tcu::Vec4		color	= colors[fragNdx] * texScale + texBias;
548 			const tcu::IVec4	icolor	= castVectorSaturate<deInt32>(color);
549 			const tcu::UVec4	uicolor	= castVectorSaturate<deUint32>(color);
550 
551 			if (m_outputType == glu::TYPE_FLOAT_VEC4)			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
552 			else if (m_outputType == glu::TYPE_INT_VEC4)		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
553 			else if (m_outputType == glu::TYPE_UINT_VEC4)		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
554 			else
555 				DE_ASSERT(DE_FALSE);
556 		}
557 	}
558 }
559 
Texture2DArrayShader(glu::DataType samplerType,glu::DataType outputType)560 Texture2DArrayShader::Texture2DArrayShader (glu::DataType samplerType, glu::DataType outputType)
561 	: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
562 							<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
563 							<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
564 							<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
565 							<< sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
566 							<< sglr::pdec::Uniform("u_sampler0", samplerType)
567 							<< sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4)
568 							<< sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4)
569 							<< sglr::pdec::Uniform("u_layer", glu::TYPE_INT)
570 							<< sglr::pdec::VertexSource(
571 									"#version 300 es\n"
572 									"in highp vec4 a_position;\n"
573 									"in highp vec2 a_coord;\n"
574 									"out highp vec2 v_coord;\n"
575 									"void main (void)\n"
576 									"{\n"
577 									"	gl_Position = a_position;\n"
578 									"	v_coord = a_coord;\n"
579 									"}\n")
580 							<< sglr::pdec::FragmentSource(
581 									string("") +
582 									"#version 300 es\n"
583 									"uniform highp " + glu::getDataTypeName(samplerType) + " u_sampler0;\n"
584 									"uniform highp vec4 u_scale;\n"
585 									"uniform highp vec4 u_bias;\n"
586 									"uniform highp int u_layer;\n"
587 									"in highp vec2 v_coord;\n"
588 									"layout(location = 0) out highp " + glu::getDataTypeName(outputType) + " o_color;\n"
589 									"void main (void)\n"
590 									"{\n"
591 									"	o_color = " + glu::getDataTypeName(outputType) + "(vec4(texture(u_sampler0, vec3(v_coord, u_layer))) * u_scale + u_bias);\n"
592 									"}\n"))
593 	, m_texScale	(1.0f)
594 	, m_texBias		(0.0f)
595 	, m_layer		(0)
596 	, m_outputType	(outputType)
597 {
598 }
599 
setLayer(int layer)600 void Texture2DArrayShader::setLayer (int layer)
601 {
602 	m_layer = layer;
603 }
604 
setTexScaleBias(const Vec4 & scale,const Vec4 & bias)605 void Texture2DArrayShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
606 {
607 	m_texScale	= scale;
608 	m_texBias	= bias;
609 }
610 
setUniforms(sglr::Context & gl,deUint32 program) const611 void Texture2DArrayShader::setUniforms (sglr::Context& gl, deUint32 program) const
612 {
613 	gl.useProgram(program);
614 
615 	gl.uniform1i	(gl.getUniformLocation(program, "u_sampler0"),	0);
616 	gl.uniform1i	(gl.getUniformLocation(program, "u_layer"),		m_layer);
617 	gl.uniform4fv	(gl.getUniformLocation(program, "u_scale"),		1, m_texScale.getPtr());
618 	gl.uniform4fv	(gl.getUniformLocation(program, "u_bias"),		1, m_texBias.getPtr());
619 }
620 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const621 void Texture2DArrayShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
622 {
623 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
624 	{
625 		rr::VertexPacket& packet = *packets[packetNdx];
626 
627 		packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
628 		packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
629 	}
630 }
631 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const632 void Texture2DArrayShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
633 {
634 	const tcu::Vec4 texScale	(m_uniforms[1].value.f4);
635 	const tcu::Vec4 texBias		(m_uniforms[2].value.f4);
636 	const int		layer		= m_uniforms[3].value.i;
637 
638 	tcu::Vec3 texCoords[4];
639 	tcu::Vec4 colors[4];
640 
641 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
642 	{
643 		const sglr::rc::Texture2DArray* tex = m_uniforms[0].sampler.tex2DArray;
644 
645 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
646 		{
647 			const tcu::Vec4	coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
648 			texCoords[fragNdx] = tcu::Vec3(coord.x(), coord.y(), float(layer));
649 		}
650 
651 		tex->sample4(colors, texCoords);
652 
653 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
654 		{
655 			const tcu::Vec4		color	= colors[fragNdx] * texScale + texBias;
656 			const tcu::IVec4	icolor	= castVectorSaturate<deInt32>(color);
657 			const tcu::UVec4	uicolor	= castVectorSaturate<deUint32>(color);
658 
659 			if (m_outputType == glu::TYPE_FLOAT_VEC4)			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
660 			else if (m_outputType == glu::TYPE_INT_VEC4)		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
661 			else if (m_outputType == glu::TYPE_UINT_VEC4)		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
662 			else
663 				DE_ASSERT(DE_FALSE);
664 		}
665 	}
666 }
667 
Texture3DShader(glu::DataType samplerType,glu::DataType outputType)668 Texture3DShader::Texture3DShader (glu::DataType samplerType, glu::DataType outputType)
669 	: sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
670 							<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
671 							<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
672 							<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
673 							<< sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
674 							<< sglr::pdec::Uniform("u_sampler0", samplerType)
675 							<< sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4)
676 							<< sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4)
677 							<< sglr::pdec::Uniform("u_depth", glu::TYPE_FLOAT)
678 							<< sglr::pdec::VertexSource(
679 									"#version 300 es\n"
680 									"in highp vec4 a_position;\n"
681 									"in highp vec2 a_coord;\n"
682 									"out highp vec2 v_coord;\n"
683 									"void main (void)\n"
684 									"{\n"
685 									"	gl_Position = a_position;\n"
686 									"	v_coord = a_coord;\n"
687 									"}\n")
688 							<< sglr::pdec::FragmentSource(
689 									string("") +
690 									"#version 300 es\n"
691 									"uniform highp " + glu::getDataTypeName(samplerType) + " u_sampler0;\n"
692 									"uniform highp vec4 u_scale;\n"
693 									"uniform highp vec4 u_bias;\n"
694 									"uniform highp float u_depth;\n"
695 									"in highp vec2 v_coord;\n"
696 									"layout(location = 0) out highp " + glu::getDataTypeName(outputType) + " o_color;\n"
697 									"void main (void)\n"
698 									"{\n"
699 									"	o_color = " + glu::getDataTypeName(outputType) + "(vec4(texture(u_sampler0, vec3(v_coord, u_depth))) * u_scale + u_bias);\n"
700 									"}\n"))
701 	, m_texScale	(1.0f)
702 	, m_texBias		(0.0f)
703 	, m_depth		(0.0f)
704 	, m_outputType	(outputType)
705 {
706 }
707 
setDepth(float depth)708 void Texture3DShader::setDepth (float depth)
709 {
710 	m_depth = depth;
711 }
712 
setTexScaleBias(const Vec4 & scale,const Vec4 & bias)713 void Texture3DShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
714 {
715 	m_texScale	= scale;
716 	m_texBias	= bias;
717 }
718 
setUniforms(sglr::Context & gl,deUint32 program) const719 void Texture3DShader::setUniforms (sglr::Context& gl, deUint32 program) const
720 {
721 	gl.useProgram(program);
722 
723 	gl.uniform1i	(gl.getUniformLocation(program, "u_sampler0"),	0);
724 	gl.uniform1f	(gl.getUniformLocation(program, "u_depth"),		m_depth);
725 	gl.uniform4fv	(gl.getUniformLocation(program, "u_scale"),		1, m_texScale.getPtr());
726 	gl.uniform4fv	(gl.getUniformLocation(program, "u_bias"),		1, m_texBias.getPtr());
727 }
728 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const729 void Texture3DShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
730 {
731 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
732 	{
733 		rr::VertexPacket& packet = *packets[packetNdx];
734 
735 		packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
736 		packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
737 	}
738 }
739 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const740 void Texture3DShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
741 {
742 	const tcu::Vec4 texScale	(m_uniforms[1].value.f4);
743 	const tcu::Vec4 texBias		(m_uniforms[2].value.f4);
744 	const float		depth		= m_uniforms[3].value.f;
745 
746 	tcu::Vec3 texCoords[4];
747 	tcu::Vec4 colors[4];
748 
749 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
750 	{
751 		const sglr::rc::Texture3D* tex = m_uniforms[0].sampler.tex3D;
752 
753 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
754 		{
755 			const tcu::Vec4	coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
756 			texCoords[fragNdx] = tcu::Vec3(coord.x(), coord.y(), depth);
757 		}
758 
759 		tex->sample4(colors, texCoords);
760 
761 		for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
762 		{
763 			const tcu::Vec4		color	= colors[fragNdx] * texScale + texBias;
764 			const tcu::IVec4	icolor	= castVectorSaturate<deInt32>(color);
765 			const tcu::UVec4	uicolor	= castVectorSaturate<deUint32>(color);
766 
767 			if (m_outputType == glu::TYPE_FLOAT_VEC4)			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
768 			else if (m_outputType == glu::TYPE_INT_VEC4)		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
769 			else if (m_outputType == glu::TYPE_UINT_VEC4)		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
770 			else
771 				DE_ASSERT(DE_FALSE);
772 		}
773 	}
774 }
775 
DepthGradientShader(glu::DataType outputType)776 DepthGradientShader::DepthGradientShader (glu::DataType outputType)
777 	: ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
778 					<< sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
779 					<< sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
780 					<< sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
781 					<< sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
782 					<< sglr::pdec::Uniform("u_maxGradient", glu::TYPE_FLOAT)
783 					<< sglr::pdec::Uniform("u_minGradient", glu::TYPE_FLOAT)
784 					<< sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4)
785 					<< sglr::pdec::VertexSource(
786 							"#version 300 es\n"
787 							"in highp vec4 a_position;\n"
788 							"in highp vec4 a_coord;\n"
789 							"out highp vec4 v_coord;\n"
790 							"void main (void)\n"
791 							"{\n"
792 							"	gl_Position = a_position;\n"
793 							"	v_coord = a_coord;\n"
794 							"}\n")
795 					<< sglr::pdec::FragmentSource(
796 							string(
797 								"#version 300 es\n"
798 								"in highp vec4 v_coord;\n"
799 								"uniform highp float u_minGradient;\n"
800 								"uniform highp float u_maxGradient;\n"
801 								"uniform highp vec4 u_color;\n"
802 								"layout(location = 0) out highp ") + glu::getDataTypeName(outputType) + " o_color;\n"
803 								"void main (void)\n"
804 								"{\n"
805 								"	highp float x = v_coord.x;\n"
806 								"	highp float y = v_coord.y;\n"
807 								"	highp float f0 = (x + y) * 0.5;\n"
808 								"	gl_FragDepth = u_minGradient + (u_maxGradient-u_minGradient)*f0;\n"
809 								"	o_color = " + glu::getDataTypeName(outputType) + "(u_color);\n"
810 								"}\n"))
811 	, m_outputType	(outputType)
812 	, u_minGradient	(getUniformByName("u_minGradient"))
813 	, u_maxGradient	(getUniformByName("u_maxGradient"))
814 	, u_color		(getUniformByName("u_color"))
815 {
816 }
817 
setUniforms(sglr::Context & ctx,deUint32 program,const float gradientMin,const float gradientMax,const tcu::Vec4 & color)818 void DepthGradientShader::setUniforms (sglr::Context& ctx, deUint32 program, const float gradientMin, const float gradientMax, const tcu::Vec4& color)
819 {
820 	ctx.useProgram(program);
821 	ctx.uniform1fv(ctx.getUniformLocation(program, "u_minGradient"), 1, &gradientMin);
822 	ctx.uniform1fv(ctx.getUniformLocation(program, "u_maxGradient"), 1, &gradientMax);
823 	ctx.uniform4fv(ctx.getUniformLocation(program, "u_color"), 1, color.getPtr());
824 }
825 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const826 void DepthGradientShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
827 {
828 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
829 	{
830 		rr::VertexPacket& packet = *packets[packetNdx];
831 
832 		packet.position		= rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
833 		packet.outputs[0]	= rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
834 	}
835 }
836 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const837 void DepthGradientShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
838 {
839 	const float			gradientMin	(u_minGradient.value.f);
840 	const float			gradientMax	(u_maxGradient.value.f);
841 	const tcu::Vec4		color		(u_color.value.f4);
842 	const tcu::IVec4	icolor		(castVectorSaturate<deInt32>(color));
843 	const tcu::UVec4	uicolor		(castVectorSaturate<deUint32>(color));
844 
845 	// running this shader without a depth buffer does not make any sense
846 	DE_ASSERT(context.fragmentDepths);
847 
848 	for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
849 	for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
850 	{
851 		const tcu::Vec4		coord	= rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
852 		const float			x		= coord.x();
853 		const float			y		= coord.y();
854 		const float			f0		= (x + y) * 0.5f;
855 
856 		rr::writeFragmentDepth(context, packetNdx, fragNdx, 0, gradientMin + (gradientMax-gradientMin) * f0);
857 
858 		if (m_outputType == glu::TYPE_FLOAT_VEC4)			rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
859 		else if (m_outputType == glu::TYPE_INT_VEC4)		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
860 		else if (m_outputType == glu::TYPE_UINT_VEC4)		rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
861 		else
862 			DE_ASSERT(DE_FALSE);
863 	}
864 }
865 
clearColorBuffer(sglr::Context & ctx,const tcu::TextureFormat & format,const tcu::Vec4 & value)866 void clearColorBuffer (sglr::Context& ctx, const tcu::TextureFormat& format, const tcu::Vec4& value)
867 {
868 	const tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(format.type);
869 
870 	switch (fmtClass)
871 	{
872 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
873 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
874 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
875 			ctx.clearBufferfv(GL_COLOR, 0, value.getPtr());
876 			break;
877 
878 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
879 			ctx.clearBufferuiv(GL_COLOR, 0, value.asUint().getPtr());
880 			break;
881 
882 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
883 			ctx.clearBufferiv(GL_COLOR, 0, value.asInt().getPtr());
884 			break;
885 
886 		default:
887 			DE_ASSERT(DE_FALSE);
888 	}
889 }
890 
readPixels(sglr::Context & ctx,tcu::Surface & dst,int x,int y,int width,int height,const tcu::TextureFormat & format,const tcu::Vec4 & scale,const tcu::Vec4 & bias)891 void readPixels (sglr::Context& ctx, tcu::Surface& dst, int x, int y, int width, int height, const tcu::TextureFormat& format, const tcu::Vec4& scale, const tcu::Vec4& bias)
892 {
893 	tcu::TextureFormat		readFormat		= getFramebufferReadFormat(format);
894 	glu::TransferFormat		transferFmt		= glu::getTransferFormat(readFormat);
895 	int						alignment		= 4; // \note GL_PACK_ALIGNMENT = 4 is assumed.
896 	int						rowSize			= deAlign32(readFormat.getPixelSize()*width, alignment);
897 	vector<deUint8>			data			(rowSize*height);
898 
899 	ctx.readPixels(x, y, width, height, transferFmt.format, transferFmt.dataType, &data[0]);
900 
901 	// Convert to surface.
902 	tcu::ConstPixelBufferAccess src(readFormat, width, height, 1, rowSize, 0, &data[0]);
903 
904 	dst.setSize(width, height);
905 	tcu::PixelBufferAccess dstAccess = dst.getAccess();
906 
907 	for (int yo = 0; yo < height; yo++)
908 	for (int xo = 0; xo < width; xo++)
909 		dstAccess.setPixel(src.getPixel(xo, yo) * scale + bias, xo, yo);
910 }
911 
getFboIncompleteReasonName(deUint32 reason)912 static const char* getFboIncompleteReasonName (deUint32 reason)
913 {
914 	switch (reason)
915 	{
916 		case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:			return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
917 		case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:	return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
918 		case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:			return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
919 		case GL_FRAMEBUFFER_UNSUPPORTED:					return "GL_FRAMEBUFFER_UNSUPPORTED";
920 		case GL_FRAMEBUFFER_COMPLETE:						return "GL_FRAMEBUFFER_COMPLETE";
921 		default:											return "UNKNOWN";
922 	}
923 }
924 
FboIncompleteException(deUint32 reason,const char * file,int line)925 FboIncompleteException::FboIncompleteException (deUint32 reason, const char* file, int line)
926 	: TestError		("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line)
927 	, m_reason		(reason)
928 {
929 }
930 
getFormatName(deUint32 format)931 const char* getFormatName (deUint32 format)
932 {
933 	switch (format)
934 	{
935 		case GL_RGB565:				return "rgb565";
936 		case GL_RGB5_A1:			return "rgb5_a1";
937 		case GL_RGBA4:				return "rgba4";
938 		case GL_DEPTH_COMPONENT16:	return "depth_component16";
939 		case GL_STENCIL_INDEX8:		return "stencil_index8";
940 		case GL_RGBA32F:			return "rgba32f";
941 		case GL_RGBA32I:			return "rgba32i";
942 		case GL_RGBA32UI:			return "rgba32ui";
943 		case GL_RGBA16F:			return "rgba16f";
944 		case GL_RGBA16I:			return "rgba16i";
945 		case GL_RGBA16UI:			return "rgba16ui";
946 		case GL_RGBA8:				return "rgba8";
947 		case GL_RGBA8I:				return "rgba8i";
948 		case GL_RGBA8UI:			return "rgba8ui";
949 		case GL_SRGB8_ALPHA8:		return "srgb8_alpha8";
950 		case GL_RGB10_A2:			return "rgb10_a2";
951 		case GL_RGB10_A2UI:			return "rgb10_a2ui";
952 		case GL_RGBA8_SNORM:		return "rgba8_snorm";
953 		case GL_RGB8:				return "rgb8";
954 		case GL_R11F_G11F_B10F:		return "r11f_g11f_b10f";
955 		case GL_RGB32F:				return "rgb32f";
956 		case GL_RGB32I:				return "rgb32i";
957 		case GL_RGB32UI:			return "rgb32ui";
958 		case GL_RGB16F:				return "rgb16f";
959 		case GL_RGB16I:				return "rgb16i";
960 		case GL_RGB16UI:			return "rgb16ui";
961 		case GL_RGB8_SNORM:			return "rgb8_snorm";
962 		case GL_RGB8I:				return "rgb8i";
963 		case GL_RGB8UI:				return "rgb8ui";
964 		case GL_SRGB8:				return "srgb8";
965 		case GL_RGB9_E5:			return "rgb9_e5";
966 		case GL_RG32F:				return "rg32f";
967 		case GL_RG32I:				return "rg32i";
968 		case GL_RG32UI:				return "rg32ui";
969 		case GL_RG16F:				return "rg16f";
970 		case GL_RG16I:				return "rg16i";
971 		case GL_RG16UI:				return "rg16ui";
972 		case GL_RG8:				return "rg8";
973 		case GL_RG8I:				return "rg8i";
974 		case GL_RG8UI:				return "rg8ui";
975 		case GL_RG8_SNORM:			return "rg8_snorm";
976 		case GL_R32F:				return "r32f";
977 		case GL_R32I:				return "r32i";
978 		case GL_R32UI:				return "r32ui";
979 		case GL_R16F:				return "r16f";
980 		case GL_R16I:				return "r16i";
981 		case GL_R16UI:				return "r16ui";
982 		case GL_R8:					return "r8";
983 		case GL_R8I:				return "r8i";
984 		case GL_R8UI:				return "r8ui";
985 		case GL_R8_SNORM:			return "r8_snorm";
986 		case GL_DEPTH_COMPONENT32F:	return "depth_component32f";
987 		case GL_DEPTH_COMPONENT24:	return "depth_component24";
988 		case GL_DEPTH32F_STENCIL8:	return "depth32f_stencil8";
989 		case GL_DEPTH24_STENCIL8:	return "depth24_stencil8";
990 
991 		default:
992 			TCU_FAIL("Unknown format");
993 	}
994 }
995 
getFragmentOutputType(const tcu::TextureFormat & format)996 glu::DataType getFragmentOutputType (const tcu::TextureFormat& format)
997 {
998 	switch (tcu::getTextureChannelClass(format.type))
999 	{
1000 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1001 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1002 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1003 			return glu::TYPE_FLOAT_VEC4;
1004 
1005 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1006 			return glu::TYPE_UINT_VEC4;
1007 
1008 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1009 			return glu::TYPE_INT_VEC4;
1010 
1011 		default:
1012 			DE_FATAL("Unknown format");
1013 			return glu::TYPE_LAST;
1014 	}
1015 }
1016 
getFramebufferReadFormat(const tcu::TextureFormat & format)1017 tcu::TextureFormat getFramebufferReadFormat (const tcu::TextureFormat& format)
1018 {
1019 	switch (tcu::getTextureChannelClass(format.type))
1020 	{
1021 		case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1022 			return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1023 
1024 		case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1025 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1026 			return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
1027 
1028 		case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1029 			return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
1030 
1031 		case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1032 			return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
1033 
1034 		default:
1035 			DE_FATAL("Unknown format");
1036 			return tcu::TextureFormat();
1037 	}
1038 }
1039 
calculateU8ConversionError(int srcBits)1040 static int calculateU8ConversionError (int srcBits)
1041 {
1042 	if (srcBits > 0)
1043 	{
1044 		const int clampedBits	= de::clamp<int>(srcBits, 0, 8);
1045 		const int srcMaxValue	= de::max((1<<clampedBits) - 1, 1);
1046 		const int error			= int(deFloatCeil(255.0f * 2.0f / float(srcMaxValue)));
1047 
1048 		return de::clamp<int>(error, 0, 255);
1049 	}
1050 	else
1051 		return 1;
1052 }
1053 
getFormatThreshold(const tcu::TextureFormat & format)1054 tcu::RGBA getFormatThreshold (const tcu::TextureFormat& format)
1055 {
1056 	const tcu::IVec4 bits = tcu::getTextureFormatMantissaBitDepth(format);
1057 
1058 	return tcu::RGBA(calculateU8ConversionError(bits.x()),
1059 					 calculateU8ConversionError(bits.y()),
1060 					 calculateU8ConversionError(bits.z()),
1061 					 calculateU8ConversionError(bits.w()));
1062 }
1063 
getFormatThreshold(deUint32 glFormat)1064 tcu::RGBA getFormatThreshold (deUint32 glFormat)
1065 {
1066 	const tcu::TextureFormat format = glu::mapGLInternalFormat(glFormat);
1067 
1068 	return getFormatThreshold(format);
1069 }
1070 
getToSRGB8ConversionError(int srcBits)1071 static int getToSRGB8ConversionError (int srcBits)
1072 {
1073 	// \note These are pre-computed based on simulation results.
1074 	static const int errors[] =
1075 	{
1076 		1,		// 0 bits - rounding
1077 		255,	// 1 bits
1078 		157,	// 2 bits
1079 		106,	// 3 bits
1080 		74,		// 4 bits
1081 		51,		// 5 bits
1082 		34,		// 6 bits
1083 		22,		// 7 bits
1084 		13,		// 8 bits
1085 		7,		// 9 bits
1086 		4,		// 10 bits
1087 		3,		// 11 bits
1088 		2,		// 12 bits
1089 		// 1 from this on
1090 	};
1091 
1092 	DE_ASSERT(srcBits >= 0);
1093 	if (srcBits < DE_LENGTH_OF_ARRAY(errors))
1094 		return errors[srcBits];
1095 	else
1096 		return 1;
1097 }
1098 
getToSRGBConversionThreshold(const tcu::TextureFormat & src,const tcu::TextureFormat & dst)1099 tcu::RGBA getToSRGBConversionThreshold (const tcu::TextureFormat& src, const tcu::TextureFormat& dst)
1100 {
1101 	// Only SRGB8 and SRGB8_ALPHA8 formats are supported.
1102 	DE_ASSERT(dst.type == tcu::TextureFormat::UNORM_INT8 && tcu::isSRGB(dst));
1103 
1104 	const tcu::IVec4	bits		= tcu::getTextureFormatMantissaBitDepth(src);
1105 	const bool			dstHasAlpha	= dst.order == tcu::TextureFormat::sRGBA;
1106 
1107 	return tcu::RGBA(getToSRGB8ConversionError(bits.x()),
1108 					 getToSRGB8ConversionError(bits.y()),
1109 					 getToSRGB8ConversionError(bits.z()),
1110 					 dstHasAlpha ? calculateU8ConversionError(bits.w()) : 0);
1111 }
1112 
1113 } // FboTestUtil
1114 } // Functional
1115 } // gles3
1116 } // deqp
1117