Home | History | Annotate | Download | only in functional
      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 
     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>
     69 static tcu::Vector<T, 4> castVectorSaturate (const tcu::Vec4& in)
     70 {
     71 	return tcu::Vector<T, 4>((in.x() + 0.5f >= std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : ((in.x() - 0.5f <= std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.x()))),
     72 	                         (in.y() + 0.5f >= std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : ((in.y() - 0.5f <= std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.y()))),
     73 							 (in.z() + 0.5f >= std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : ((in.z() - 0.5f <= std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.z()))),
     74 							 (in.w() + 0.5f >= std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : ((in.w() - 0.5f <= std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.w()))));
     75 }
     76 
     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 
    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 
    111 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 
    121 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 
    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 
    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 
    196 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 
    207 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 
    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 
    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 
    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 
    324 void Texture2DShader::setUnit (int inputNdx, int unitNdx)
    325 {
    326 	m_inputs[inputNdx].unitNdx = unitNdx;
    327 }
    328 
    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 
    335 void Texture2DShader::setOutScaleBias (const Vec4& scale, const Vec4& bias)
    336 {
    337 	m_outScale	= scale;
    338 	m_outBias	= bias;
    339 }
    340 
    341 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 
    360 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 
    371 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 
    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 
    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 
    494 void TextureCubeShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
    495 {
    496 	m_texScale	= scale;
    497 	m_texBias	= bias;
    498 }
    499 
    500 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 
    510 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 
    525 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 
    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 
    600 void Texture2DArrayShader::setLayer (int layer)
    601 {
    602 	m_layer = layer;
    603 }
    604 
    605 void Texture2DArrayShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
    606 {
    607 	m_texScale	= scale;
    608 	m_texBias	= bias;
    609 }
    610 
    611 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 
    621 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 
    632 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 
    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 
    708 void Texture3DShader::setDepth (float depth)
    709 {
    710 	m_depth = depth;
    711 }
    712 
    713 void Texture3DShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
    714 {
    715 	m_texScale	= scale;
    716 	m_texBias	= bias;
    717 }
    718 
    719 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 
    729 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 
    740 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 
    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 
    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 
    826 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 
    837 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 
    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 
    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 
    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 
    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 
    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 
    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_ASSERT(!"Unknown format");
   1013 			return glu::TYPE_LAST;
   1014 	}
   1015 }
   1016 
   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_ASSERT(!"Unknown format");
   1036 			return tcu::TextureFormat();
   1037 	}
   1038 }
   1039 
   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 
   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 
   1064 tcu::RGBA getFormatThreshold (deUint32 glFormat)
   1065 {
   1066 	const tcu::TextureFormat format = glu::mapGLInternalFormat(glFormat);
   1067 
   1068 	return getFormatThreshold(format);
   1069 }
   1070 
   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 
   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 && (dst.order == tcu::TextureFormat::sRGB || dst.order == tcu::TextureFormat::sRGBA));
   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