Merge "Fix color change verification in dithering tests" into nougat-cts-dev am:...
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fFboTestUtil.cpp
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_FATAL("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_FATAL("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 && 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