Fix PIPELINE_STAGE_TOP_OF_PIPE_BIT usage in api tests
[platform/upstream/VK-GL-CTS.git] / modules / gles31 / functional / es31fFboTestUtil.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.1 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 "es31fFboTestUtil.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 gles31
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>(((double)in.x() + 0.5 >= (double)std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : (((double)in.x() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.x()))),
72                                  ((double)in.y() + 0.5 >= (double)std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : (((double)in.y() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.y()))),
73                                                          ((double)in.z() + 0.5 >= (double)std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : (((double)in.z() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.z()))),
74                                                          ((double)in.w() + 0.5 >= (double)std::numeric_limits<T>::max()) ? (std::numeric_limits<T>::max()) : (((double)in.w() - 0.5 <= (double)std::numeric_limits<T>::min()) ? (std::numeric_limits<T>::min()) : (T(in.w()))));
75 }
76
77 static string genTexFragmentShader (const vector<glu::DataType>& samplerTypes, glu::DataType outputType)
78 {
79         const char*                     precision       = "highp";
80         std::ostringstream      src;
81
82         src << "#version 300 es\n"
83                 << "layout(location = 0) out highp " << glu::getDataTypeName(outputType) << " o_color0;\n";
84
85         src << "in highp vec2 v_coord;\n";
86
87         for (int samplerNdx = 0; samplerNdx < (int)samplerTypes.size(); samplerNdx++)
88         {
89                 src << "uniform " << precision << " " << glu::getDataTypeName(samplerTypes[samplerNdx]) << " u_sampler" << samplerNdx << ";\n";
90                 src << "uniform " << precision << " vec4 u_texScale" << samplerNdx << ";\n";
91                 src << "uniform " << precision << " vec4 u_texBias" << samplerNdx << ";\n";
92         }
93
94         // Output scale & bias
95         src << "uniform " << precision << " vec4 u_outScale0;\n"
96                 << "uniform " << precision << " vec4 u_outBias0;\n";
97
98         src << "\n"
99                 << "void main (void)\n"
100                 << "{\n"
101                 << "    " << precision << " vec4 out0 = vec4(0.0);\n";
102
103         // Texture input fetch and combine.
104         for (int inNdx = 0; inNdx < (int)samplerTypes.size(); inNdx++)
105                 src << "\tout0 += vec4("
106                         << "texture(u_sampler" << inNdx << ", v_coord)) * u_texScale" << inNdx << " + u_texBias" << inNdx << ";\n";
107
108         // Write output.
109         src << "        o_color0 = " << glu::getDataTypeName(outputType) << "(out0 * u_outScale0 + u_outBias0);\n";
110
111         src << "}\n";
112
113         return src.str();
114 }
115
116 static sglr::pdec::ShaderProgramDeclaration genTexture2DShaderDecl (const DataTypes& samplerTypes, glu::DataType outputType)
117 {
118         sglr::pdec::ShaderProgramDeclaration decl;
119
120         decl << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT);
121         decl << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT);
122         decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
123         decl << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType));
124
125         decl << sglr::pdec::VertexSource(
126                 "#version 300 es\n"
127                 "in highp vec4 a_position;\n"
128                 "in highp vec2 a_coord;\n"
129                 "out highp vec2 v_coord;\n"
130                 "void main(void)\n"
131                 "{\n"
132                 "       gl_Position = a_position;\n"
133                 "       v_coord = a_coord;\n"
134                 "}\n");
135         decl << sglr::pdec::FragmentSource(genTexFragmentShader(samplerTypes.vec, outputType));
136
137         decl << sglr::pdec::Uniform("u_outScale0", glu::TYPE_FLOAT_VEC4);
138         decl << sglr::pdec::Uniform("u_outBias0", glu::TYPE_FLOAT_VEC4);
139
140         for (size_t ndx = 0; ndx < samplerTypes.vec.size(); ++ndx)
141         {
142                 decl << sglr::pdec::Uniform(std::string("u_sampler")  + de::toString(ndx), samplerTypes.vec[ndx]);
143                 decl << sglr::pdec::Uniform(std::string("u_texScale") + de::toString(ndx), glu::TYPE_FLOAT_VEC4);
144                 decl << sglr::pdec::Uniform(std::string("u_texBias")  + de::toString(ndx), glu::TYPE_FLOAT_VEC4);
145         }
146
147         return decl;
148 }
149
150 Texture2DShader::Texture2DShader (const DataTypes& samplerTypes, glu::DataType outputType, const Vec4& outScale, const Vec4& outBias)
151         : sglr::ShaderProgram   (genTexture2DShaderDecl(samplerTypes, outputType))
152         , m_outScale                    (outScale)
153         , m_outBias                             (outBias)
154         , m_outputType                  (outputType)
155 {
156         m_inputs.resize(samplerTypes.vec.size());
157
158         // Initialize units.
159         for (int ndx = 0; ndx < (int)m_inputs.size(); ndx++)
160         {
161                 m_inputs[ndx].unitNdx   = ndx;
162                 m_inputs[ndx].scale             = Vec4(1.0f);
163                 m_inputs[ndx].bias              = Vec4(0.0f);
164         }
165 }
166
167 void Texture2DShader::setUnit (int inputNdx, int unitNdx)
168 {
169         m_inputs[inputNdx].unitNdx = unitNdx;
170 }
171
172 void Texture2DShader::setTexScaleBias (int inputNdx, const Vec4& scale, const Vec4& bias)
173 {
174         m_inputs[inputNdx].scale        = scale;
175         m_inputs[inputNdx].bias         = bias;
176 }
177
178 void Texture2DShader::setOutScaleBias (const Vec4& scale, const Vec4& bias)
179 {
180         m_outScale      = scale;
181         m_outBias       = bias;
182 }
183
184 void Texture2DShader::setUniforms (sglr::Context& gl, deUint32 program) const
185 {
186         gl.useProgram(program);
187
188         for (int texNdx = 0; texNdx < (int)m_inputs.size(); texNdx++)
189         {
190                 string  samplerName     = string("u_sampler") + de::toString(texNdx);
191                 string  scaleName       = string("u_texScale") + de::toString(texNdx);
192                 string  biasName        = string("u_texBias") + de::toString(texNdx);
193
194                 gl.uniform1i(gl.getUniformLocation(program, samplerName.c_str()), m_inputs[texNdx].unitNdx);
195                 gl.uniform4fv(gl.getUniformLocation(program, scaleName.c_str()), 1, m_inputs[texNdx].scale.getPtr());
196                 gl.uniform4fv(gl.getUniformLocation(program, biasName.c_str()), 1, m_inputs[texNdx].bias.getPtr());
197         }
198
199         gl.uniform4fv(gl.getUniformLocation(program, "u_outScale0"), 1, m_outScale.getPtr());
200         gl.uniform4fv(gl.getUniformLocation(program, "u_outBias0"), 1, m_outBias.getPtr());
201 }
202
203 void Texture2DShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
204 {
205         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
206         {
207                 rr::VertexPacket& packet = *packets[packetNdx];
208
209                 packet.position         = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
210                 packet.outputs[0]       = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
211         }
212 }
213
214 void Texture2DShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
215 {
216         const tcu::Vec4 outScale (m_uniforms[0].value.f4);
217         const tcu::Vec4 outBias  (m_uniforms[1].value.f4);
218
219         tcu::Vec2 texCoords[4];
220         tcu::Vec4 colors[4];
221
222         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
223         {
224                 // setup tex coords
225                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
226                 {
227                         const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
228                         texCoords[fragNdx] = tcu::Vec2(coord.x(), coord.y());
229                 }
230
231                 // clear result
232                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
233                         colors[fragNdx] = tcu::Vec4(0.0f);
234
235                 // sample each texture
236                 for (int ndx = 0; ndx < (int)m_inputs.size(); ndx++)
237                 {
238                         const sglr::rc::Texture2D*      tex             = m_uniforms[2 + ndx*3].sampler.tex2D;
239                         const tcu::Vec4                         scale   (m_uniforms[2 + ndx*3 + 1].value.f4);
240                         const tcu::Vec4                         bias    (m_uniforms[2 + ndx*3 + 2].value.f4);
241                         tcu::Vec4 tmpColors[4];
242
243                         tex->sample4(tmpColors, texCoords);
244
245                         for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
246                                 colors[fragNdx] += tmpColors[fragNdx] * scale + bias;
247                 }
248
249                 // write out
250                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
251                 {
252                         const tcu::Vec4         color   = colors[fragNdx] * outScale + outBias;
253                         const tcu::IVec4        icolor  = castVectorSaturate<deInt32>(color);
254                         const tcu::UVec4        uicolor = castVectorSaturate<deUint32>(color);
255
256                         if (m_outputType == glu::TYPE_FLOAT_VEC4)                       rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
257                         else if (m_outputType == glu::TYPE_INT_VEC4)            rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
258                         else if (m_outputType == glu::TYPE_UINT_VEC4)           rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
259                         else
260                                 DE_ASSERT(DE_FALSE);
261                 }
262         }
263 }
264
265 TextureCubeArrayShader::TextureCubeArrayShader (glu::DataType samplerType, glu::DataType outputType, glu::GLSLVersion glslVersion)
266         : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
267                                                         << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
268                                                         << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
269                                                         << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
270                                                         << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
271                                                         << sglr::pdec::Uniform("u_coordMat", glu::TYPE_FLOAT_MAT3)
272                                                         << sglr::pdec::Uniform("u_sampler0", samplerType)
273                                                         << sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4)
274                                                         << sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4)
275                                                         << sglr::pdec::Uniform("u_layer", glu::TYPE_INT)
276                                                         << sglr::pdec::VertexSource(
277                                                                         string("") +
278                                                                         ((glslVersion == glu::GLSL_VERSION_310_ES) ?
279                                                                         "#version 310 es\n"
280                                                                         "#extension GL_EXT_texture_cube_map_array : require\n"
281                                                                          : "#version 320 es\n") +
282                                                                         "in highp vec4 a_position;\n"
283                                                                         "in mediump vec2 a_coord;\n"
284                                                                         "uniform mat3 u_coordMat;\n"
285                                                                         "out highp vec3 v_coord;\n"
286                                                                         "void main (void)\n"
287                                                                         "{\n"
288                                                                         "       gl_Position = a_position;\n"
289                                                                         "       v_coord = u_coordMat * vec3(a_coord, 1.0);\n"
290                                                                         "}\n")
291                                                         << sglr::pdec::FragmentSource(
292                                                                         string("") +
293                                                                         ((glslVersion == glu::GLSL_VERSION_310_ES) ?
294                                                                         "#version 310 es\n"
295                                                                         "#extension GL_EXT_texture_cube_map_array : require\n"
296                                                                          : "#version 320 es\n") +
297                                                                         "uniform highp " + glu::getDataTypeName(samplerType) + " u_sampler0;\n"
298                                                                         "uniform highp vec4 u_scale;\n"
299                                                                         "uniform highp vec4 u_bias;\n"
300                                                                         "uniform highp int u_layer;\n"
301                                                                         "in highp vec3 v_coord;\n"
302                                                                         "layout(location = 0) out highp " + glu::getDataTypeName(outputType) + " o_color;\n"
303                                                                         "void main (void)\n"
304                                                                         "{\n"
305                                                                         "       o_color = " + glu::getDataTypeName(outputType) + "(vec4(texture(u_sampler0, vec4(v_coord, u_layer))) * u_scale + u_bias);\n"
306                                                                         "}\n"))
307         , m_texScale    (1.0f)
308         , m_texBias             (0.0f)
309         , m_layer               (0)
310         , m_outputType  (outputType)
311 {
312         TCU_CHECK_INTERNAL(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion == glu::GLSL_VERSION_320_ES);
313 }
314
315 void TextureCubeArrayShader::setLayer (int layer)
316 {
317         m_layer = layer;
318 }
319
320 void TextureCubeArrayShader::setFace (tcu::CubeFace face)
321 {
322         static const float s_cubeTransforms[][3*3] =
323         {
324                 // Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
325                 {  0.0f,  0.0f, -1.0f,
326                    0.0f, -2.0f,  1.0f,
327                    2.0f,  0.0f, -1.0f },
328                 // Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
329                 {  0.0f,  0.0f,  1.0f,
330                    0.0f, -2.0f,  1.0f,
331                   -2.0f,  0.0f,  1.0f },
332                 // Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
333                 {  2.0f,  0.0f, -1.0f,
334                    0.0f,  0.0f, -1.0f,
335                    0.0f, -2.0f,  1.0f },
336                 // Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
337                 {  2.0f,  0.0f, -1.0f,
338                    0.0f,  0.0f,  1.0f,
339                    0.0f,  2.0f, -1.0f },
340                 // Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
341                 { -2.0f,  0.0f,  1.0f,
342                    0.0f, -2.0f,  1.0f,
343                    0.0f,  0.0f, -1.0f },
344                 // Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
345                 {  2.0f,  0.0f, -1.0f,
346                    0.0f, -2.0f,  1.0f,
347                    0.0f,  0.0f,  1.0f }
348         };
349         DE_ASSERT(de::inBounds<int>(face, 0, tcu::CUBEFACE_LAST));
350         m_coordMat = tcu::Mat3(s_cubeTransforms[face]);
351 }
352
353 void TextureCubeArrayShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
354 {
355         m_texScale      = scale;
356         m_texBias       = bias;
357 }
358
359 void TextureCubeArrayShader::setUniforms (sglr::Context& gl, deUint32 program) const
360 {
361         gl.useProgram(program);
362
363         gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), 0);
364         gl.uniformMatrix3fv(gl.getUniformLocation(program, "u_coordMat"), 1, GL_FALSE, m_coordMat.getColumnMajorData().getPtr());
365         gl.uniform1i(gl.getUniformLocation(program, "u_layer"), m_layer);
366         gl.uniform4fv(gl.getUniformLocation(program, "u_scale"), 1, m_texScale.getPtr());
367         gl.uniform4fv(gl.getUniformLocation(program, "u_bias"), 1, m_texBias.getPtr());
368 }
369
370 void TextureCubeArrayShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
371 {
372         tcu::Mat3 texCoordMat = tcu::Mat3(m_uniforms[0].value.m3);
373
374         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
375         {
376                 rr::VertexPacket&       packet  = *packets[packetNdx];
377                 const tcu::Vec2         a_coord = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx).xy();
378                 const tcu::Vec3         v_coord = texCoordMat * tcu::Vec3(a_coord.x(), a_coord.y(), 1.0f);
379
380                 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
381                 packet.outputs[0] = tcu::Vec4(v_coord.x(), v_coord.y(), v_coord.z(), 0.0f);
382         }
383 }
384
385 void TextureCubeArrayShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
386 {
387         const tcu::Vec4 texScale (m_uniforms[2].value.f4);
388         const tcu::Vec4 texBias  (m_uniforms[3].value.f4);
389
390         tcu::Vec4 texCoords[4];
391         tcu::Vec4 colors[4];
392
393         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
394         {
395                 const sglr::rc::TextureCubeArray* tex = m_uniforms[1].sampler.texCubeArray;
396
397                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
398                 {
399                         const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
400                         texCoords[fragNdx] = tcu::Vec4(coord.x(), coord.y(), coord.z(), (float)m_layer);
401                 }
402
403                 tex->sample4(colors, texCoords);
404
405                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
406                 {
407                         const tcu::Vec4         color   = colors[fragNdx] * texScale + texBias;
408                         const tcu::IVec4        icolor  = castVectorSaturate<deInt32>(color);
409                         const tcu::UVec4        uicolor = castVectorSaturate<deUint32>(color);
410
411                         if (m_outputType == glu::TYPE_FLOAT_VEC4)               rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
412                         else if (m_outputType == glu::TYPE_INT_VEC4)    rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
413                         else if (m_outputType == glu::TYPE_UINT_VEC4)   rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
414                         else
415                                 DE_ASSERT(DE_FALSE);
416                 }
417         }
418 }
419
420 void clearColorBuffer (sglr::Context& ctx, const tcu::TextureFormat& format, const tcu::Vec4& value)
421 {
422         const tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(format.type);
423
424         switch (fmtClass)
425         {
426                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
427                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
428                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
429                         ctx.clearBufferfv(GL_COLOR, 0, value.getPtr());
430                         break;
431
432                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
433                         ctx.clearBufferuiv(GL_COLOR, 0, value.asUint().getPtr());
434                         break;
435
436                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
437                         ctx.clearBufferiv(GL_COLOR, 0, value.asInt().getPtr());
438                         break;
439
440                 default:
441                         DE_ASSERT(DE_FALSE);
442         }
443 }
444
445 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)
446 {
447         tcu::TextureFormat              readFormat              = getFramebufferReadFormat(format);
448         glu::TransferFormat             transferFmt             = glu::getTransferFormat(readFormat);
449         int                                             alignment               = 4; // \note GL_PACK_ALIGNMENT = 4 is assumed.
450         int                                             rowSize                 = deAlign32(readFormat.getPixelSize()*width, alignment);
451         vector<deUint8>                 data                    (rowSize*height);
452
453         ctx.readPixels(x, y, width, height, transferFmt.format, transferFmt.dataType, &data[0]);
454
455         // Convert to surface.
456         tcu::ConstPixelBufferAccess src(readFormat, width, height, 1, rowSize, 0, &data[0]);
457
458         dst.setSize(width, height);
459         tcu::PixelBufferAccess dstAccess = dst.getAccess();
460
461         for (int yo = 0; yo < height; yo++)
462         for (int xo = 0; xo < width; xo++)
463                 dstAccess.setPixel(src.getPixel(xo, yo) * scale + bias, xo, yo);
464 }
465
466 static const char* getFboIncompleteReasonName (deUint32 reason)
467 {
468         switch (reason)
469         {
470                 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:                      return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
471                 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:      return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
472                 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:                      return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
473                 case GL_FRAMEBUFFER_UNSUPPORTED:                                        return "GL_FRAMEBUFFER_UNSUPPORTED";
474                 case GL_FRAMEBUFFER_COMPLETE:                                           return "GL_FRAMEBUFFER_COMPLETE";
475                 default:                                                                                        return "UNKNOWN";
476         }
477 }
478
479 FboIncompleteException::FboIncompleteException (deUint32 reason, const char* file, int line)
480         : TestError             ("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line)
481         , m_reason              (reason)
482 {
483 }
484
485 const char* getFormatName (deUint32 format)
486 {
487         switch (format)
488         {
489                 case GL_RGB565:                         return "rgb565";
490                 case GL_RGB5_A1:                        return "rgb5_a1";
491                 case GL_RGBA4:                          return "rgba4";
492                 case GL_DEPTH_COMPONENT16:      return "depth_component16";
493                 case GL_STENCIL_INDEX8:         return "stencil_index8";
494                 case GL_RGBA32F:                        return "rgba32f";
495                 case GL_RGBA32I:                        return "rgba32i";
496                 case GL_RGBA32UI:                       return "rgba32ui";
497                 case GL_RGBA16F:                        return "rgba16f";
498                 case GL_RGBA16I:                        return "rgba16i";
499                 case GL_RGBA16UI:                       return "rgba16ui";
500                 case GL_RGBA8:                          return "rgba8";
501                 case GL_RGBA8I:                         return "rgba8i";
502                 case GL_RGBA8UI:                        return "rgba8ui";
503                 case GL_SRGB8_ALPHA8:           return "srgb8_alpha8";
504                 case GL_RGB10_A2:                       return "rgb10_a2";
505                 case GL_RGB10_A2UI:                     return "rgb10_a2ui";
506                 case GL_RGBA8_SNORM:            return "rgba8_snorm";
507                 case GL_RGB8:                           return "rgb8";
508                 case GL_R11F_G11F_B10F:         return "r11f_g11f_b10f";
509                 case GL_RGB32F:                         return "rgb32f";
510                 case GL_RGB32I:                         return "rgb32i";
511                 case GL_RGB32UI:                        return "rgb32ui";
512                 case GL_RGB16F:                         return "rgb16f";
513                 case GL_RGB16I:                         return "rgb16i";
514                 case GL_RGB16UI:                        return "rgb16ui";
515                 case GL_RGB8_SNORM:                     return "rgb8_snorm";
516                 case GL_RGB8I:                          return "rgb8i";
517                 case GL_RGB8UI:                         return "rgb8ui";
518                 case GL_SRGB8:                          return "srgb8";
519                 case GL_RGB9_E5:                        return "rgb9_e5";
520                 case GL_RG32F:                          return "rg32f";
521                 case GL_RG32I:                          return "rg32i";
522                 case GL_RG32UI:                         return "rg32ui";
523                 case GL_RG16F:                          return "rg16f";
524                 case GL_RG16I:                          return "rg16i";
525                 case GL_RG16UI:                         return "rg16ui";
526                 case GL_RG8:                            return "rg8";
527                 case GL_RG8I:                           return "rg8i";
528                 case GL_RG8UI:                          return "rg8ui";
529                 case GL_RG8_SNORM:                      return "rg8_snorm";
530                 case GL_R32F:                           return "r32f";
531                 case GL_R32I:                           return "r32i";
532                 case GL_R32UI:                          return "r32ui";
533                 case GL_R16F:                           return "r16f";
534                 case GL_R16I:                           return "r16i";
535                 case GL_R16UI:                          return "r16ui";
536                 case GL_R8:                                     return "r8";
537                 case GL_R8I:                            return "r8i";
538                 case GL_R8UI:                           return "r8ui";
539                 case GL_R8_SNORM:                       return "r8_snorm";
540                 case GL_DEPTH_COMPONENT32F:     return "depth_component32f";
541                 case GL_DEPTH_COMPONENT24:      return "depth_component24";
542                 case GL_DEPTH32F_STENCIL8:      return "depth32f_stencil8";
543                 case GL_DEPTH24_STENCIL8:       return "depth24_stencil8";
544
545                 default:
546                         TCU_FAIL("Unknown format");
547         }
548 }
549
550 glu::DataType getFragmentOutputType (const tcu::TextureFormat& format)
551 {
552         switch (tcu::getTextureChannelClass(format.type))
553         {
554                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
555                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
556                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
557                         return glu::TYPE_FLOAT_VEC4;
558
559                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
560                         return glu::TYPE_UINT_VEC4;
561
562                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
563                         return glu::TYPE_INT_VEC4;
564
565                 default:
566                         DE_FATAL("Unknown format");
567                         return glu::TYPE_LAST;
568         }
569 }
570
571 tcu::TextureFormat getFramebufferReadFormat (const tcu::TextureFormat& format)
572 {
573         switch (tcu::getTextureChannelClass(format.type))
574         {
575                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
576                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
577
578                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
579                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
580                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
581
582                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
583                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
584
585                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
586                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
587
588                 default:
589                         DE_FATAL("Unknown format");
590                         return tcu::TextureFormat();
591         }
592 }
593
594 static int calculateU8ConversionError (int srcBits)
595 {
596         if (srcBits > 0)
597         {
598                 const int clampedBits   = de::clamp<int>(srcBits, 0, 8);
599                 const int srcMaxValue   = de::max((1<<clampedBits) - 1, 1);
600                 const int error                 = int(deFloatCeil(255.0f * 2.0f / float(srcMaxValue)));
601
602                 return de::clamp<int>(error, 0, 255);
603         }
604         else
605                 return 1;
606 }
607
608 tcu::RGBA getFormatThreshold (const tcu::TextureFormat& format)
609 {
610         const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(format);
611
612         return tcu::RGBA(calculateU8ConversionError(bits.x()),
613                                          calculateU8ConversionError(bits.y()),
614                                          calculateU8ConversionError(bits.z()),
615                                          calculateU8ConversionError(bits.w()));
616 }
617
618 tcu::RGBA getFormatThreshold (deUint32 glFormat)
619 {
620         const tcu::TextureFormat format = glu::mapGLInternalFormat(glFormat);
621
622         return getFormatThreshold(format);
623 }
624
625 } // FboTestUtil
626 } // Functional
627 } // gles31
628 } // deqp