b484e9f7def6582543a45bb7f443bf109e5e0c01
[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)
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                                                                         "#version 310 es\n"
278                                                                         "#extension GL_EXT_texture_cube_map_array : require\n"
279                                                                         "in highp vec4 a_position;\n"
280                                                                         "in mediump vec2 a_coord;\n"
281                                                                         "uniform mat3 u_coordMat;\n"
282                                                                         "out highp vec3 v_coord;\n"
283                                                                         "void main (void)\n"
284                                                                         "{\n"
285                                                                         "       gl_Position = a_position;\n"
286                                                                         "       v_coord = u_coordMat * vec3(a_coord, 1.0);\n"
287                                                                         "}\n")
288                                                         << sglr::pdec::FragmentSource(
289                                                                         string("") +
290                                                                         "#version 310 es\n"
291                                                                         "#extension GL_EXT_texture_cube_map_array : require\n"
292                                                                         "uniform highp " + glu::getDataTypeName(samplerType) + " u_sampler0;\n"
293                                                                         "uniform highp vec4 u_scale;\n"
294                                                                         "uniform highp vec4 u_bias;\n"
295                                                                         "uniform highp int u_layer;\n"
296                                                                         "in highp vec3 v_coord;\n"
297                                                                         "layout(location = 0) out highp " + glu::getDataTypeName(outputType) + " o_color;\n"
298                                                                         "void main (void)\n"
299                                                                         "{\n"
300                                                                         "       o_color = " + glu::getDataTypeName(outputType) + "(vec4(texture(u_sampler0, vec4(v_coord, u_layer))) * u_scale + u_bias);\n"
301                                                                         "}\n"))
302         , m_texScale    (1.0f)
303         , m_texBias             (0.0f)
304         , m_layer               (0)
305         , m_outputType  (outputType)
306 {
307 }
308
309 void TextureCubeArrayShader::setLayer (int layer)
310 {
311         m_layer = layer;
312 }
313
314 void TextureCubeArrayShader::setFace (tcu::CubeFace face)
315 {
316         static const float s_cubeTransforms[][3*3] =
317         {
318                 // Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
319                 {  0.0f,  0.0f, -1.0f,
320                    0.0f, -2.0f,  1.0f,
321                    2.0f,  0.0f, -1.0f },
322                 // Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
323                 {  0.0f,  0.0f,  1.0f,
324                    0.0f, -2.0f,  1.0f,
325                   -2.0f,  0.0f,  1.0f },
326                 // Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
327                 {  2.0f,  0.0f, -1.0f,
328                    0.0f,  0.0f, -1.0f,
329                    0.0f, -2.0f,  1.0f },
330                 // Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
331                 {  2.0f,  0.0f, -1.0f,
332                    0.0f,  0.0f,  1.0f,
333                    0.0f,  2.0f, -1.0f },
334                 // Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
335                 { -2.0f,  0.0f,  1.0f,
336                    0.0f, -2.0f,  1.0f,
337                    0.0f,  0.0f, -1.0f },
338                 // Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
339                 {  2.0f,  0.0f, -1.0f,
340                    0.0f, -2.0f,  1.0f,
341                    0.0f,  0.0f,  1.0f }
342         };
343         DE_ASSERT(de::inBounds<int>(face, 0, tcu::CUBEFACE_LAST));
344         m_coordMat = tcu::Mat3(s_cubeTransforms[face]);
345 }
346
347 void TextureCubeArrayShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
348 {
349         m_texScale      = scale;
350         m_texBias       = bias;
351 }
352
353 void TextureCubeArrayShader::setUniforms (sglr::Context& gl, deUint32 program) const
354 {
355         gl.useProgram(program);
356
357         gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), 0);
358         gl.uniformMatrix3fv(gl.getUniformLocation(program, "u_coordMat"), 1, GL_FALSE, m_coordMat.getColumnMajorData().getPtr());
359         gl.uniform1i(gl.getUniformLocation(program, "u_layer"), m_layer);
360         gl.uniform4fv(gl.getUniformLocation(program, "u_scale"), 1, m_texScale.getPtr());
361         gl.uniform4fv(gl.getUniformLocation(program, "u_bias"), 1, m_texBias.getPtr());
362 }
363
364 void TextureCubeArrayShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
365 {
366         tcu::Mat3 texCoordMat = tcu::Mat3(m_uniforms[0].value.m3);
367
368         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
369         {
370                 rr::VertexPacket&       packet  = *packets[packetNdx];
371                 const tcu::Vec2         a_coord = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx).xy();
372                 const tcu::Vec3         v_coord = texCoordMat * tcu::Vec3(a_coord.x(), a_coord.y(), 1.0f);
373
374                 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
375                 packet.outputs[0] = tcu::Vec4(v_coord.x(), v_coord.y(), v_coord.z(), 0.0f);
376         }
377 }
378
379 void TextureCubeArrayShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
380 {
381         const tcu::Vec4 texScale (m_uniforms[2].value.f4);
382         const tcu::Vec4 texBias  (m_uniforms[3].value.f4);
383
384         tcu::Vec4 texCoords[4];
385         tcu::Vec4 colors[4];
386
387         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
388         {
389                 const sglr::rc::TextureCubeArray* tex = m_uniforms[1].sampler.texCubeArray;
390
391                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
392                 {
393                         const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
394                         texCoords[fragNdx] = tcu::Vec4(coord.x(), coord.y(), coord.z(), (float)m_layer);
395                 }
396
397                 tex->sample4(colors, texCoords);
398
399                 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
400                 {
401                         const tcu::Vec4         color   = colors[fragNdx] * texScale + texBias;
402                         const tcu::IVec4        icolor  = castVectorSaturate<deInt32>(color);
403                         const tcu::UVec4        uicolor = castVectorSaturate<deUint32>(color);
404
405                         if (m_outputType == glu::TYPE_FLOAT_VEC4)               rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
406                         else if (m_outputType == glu::TYPE_INT_VEC4)    rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
407                         else if (m_outputType == glu::TYPE_UINT_VEC4)   rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
408                         else
409                                 DE_ASSERT(DE_FALSE);
410                 }
411         }
412 }
413
414 void clearColorBuffer (sglr::Context& ctx, const tcu::TextureFormat& format, const tcu::Vec4& value)
415 {
416         const tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(format.type);
417
418         switch (fmtClass)
419         {
420                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
421                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
422                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
423                         ctx.clearBufferfv(GL_COLOR, 0, value.getPtr());
424                         break;
425
426                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
427                         ctx.clearBufferuiv(GL_COLOR, 0, value.asUint().getPtr());
428                         break;
429
430                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
431                         ctx.clearBufferiv(GL_COLOR, 0, value.asInt().getPtr());
432                         break;
433
434                 default:
435                         DE_ASSERT(DE_FALSE);
436         }
437 }
438
439 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)
440 {
441         tcu::TextureFormat              readFormat              = getFramebufferReadFormat(format);
442         glu::TransferFormat             transferFmt             = glu::getTransferFormat(readFormat);
443         int                                             alignment               = 4; // \note GL_PACK_ALIGNMENT = 4 is assumed.
444         int                                             rowSize                 = deAlign32(readFormat.getPixelSize()*width, alignment);
445         vector<deUint8>                 data                    (rowSize*height);
446
447         ctx.readPixels(x, y, width, height, transferFmt.format, transferFmt.dataType, &data[0]);
448
449         // Convert to surface.
450         tcu::ConstPixelBufferAccess src(readFormat, width, height, 1, rowSize, 0, &data[0]);
451
452         dst.setSize(width, height);
453         tcu::PixelBufferAccess dstAccess = dst.getAccess();
454
455         for (int yo = 0; yo < height; yo++)
456         for (int xo = 0; xo < width; xo++)
457                 dstAccess.setPixel(src.getPixel(xo, yo) * scale + bias, xo, yo);
458 }
459
460 static const char* getFboIncompleteReasonName (deUint32 reason)
461 {
462         switch (reason)
463         {
464                 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:                      return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
465                 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:      return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
466                 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:                      return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
467                 case GL_FRAMEBUFFER_UNSUPPORTED:                                        return "GL_FRAMEBUFFER_UNSUPPORTED";
468                 case GL_FRAMEBUFFER_COMPLETE:                                           return "GL_FRAMEBUFFER_COMPLETE";
469                 default:                                                                                        return "UNKNOWN";
470         }
471 }
472
473 FboIncompleteException::FboIncompleteException (deUint32 reason, const char* file, int line)
474         : TestError             ("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line)
475         , m_reason              (reason)
476 {
477 }
478
479 const char* getFormatName (deUint32 format)
480 {
481         switch (format)
482         {
483                 case GL_RGB565:                         return "rgb565";
484                 case GL_RGB5_A1:                        return "rgb5_a1";
485                 case GL_RGBA4:                          return "rgba4";
486                 case GL_DEPTH_COMPONENT16:      return "depth_component16";
487                 case GL_STENCIL_INDEX8:         return "stencil_index8";
488                 case GL_RGBA32F:                        return "rgba32f";
489                 case GL_RGBA32I:                        return "rgba32i";
490                 case GL_RGBA32UI:                       return "rgba32ui";
491                 case GL_RGBA16F:                        return "rgba16f";
492                 case GL_RGBA16I:                        return "rgba16i";
493                 case GL_RGBA16UI:                       return "rgba16ui";
494                 case GL_RGBA8:                          return "rgba8";
495                 case GL_RGBA8I:                         return "rgba8i";
496                 case GL_RGBA8UI:                        return "rgba8ui";
497                 case GL_SRGB8_ALPHA8:           return "srgb8_alpha8";
498                 case GL_RGB10_A2:                       return "rgb10_a2";
499                 case GL_RGB10_A2UI:                     return "rgb10_a2ui";
500                 case GL_RGBA8_SNORM:            return "rgba8_snorm";
501                 case GL_RGB8:                           return "rgb8";
502                 case GL_R11F_G11F_B10F:         return "r11f_g11f_b10f";
503                 case GL_RGB32F:                         return "rgb32f";
504                 case GL_RGB32I:                         return "rgb32i";
505                 case GL_RGB32UI:                        return "rgb32ui";
506                 case GL_RGB16F:                         return "rgb16f";
507                 case GL_RGB16I:                         return "rgb16i";
508                 case GL_RGB16UI:                        return "rgb16ui";
509                 case GL_RGB8_SNORM:                     return "rgb8_snorm";
510                 case GL_RGB8I:                          return "rgb8i";
511                 case GL_RGB8UI:                         return "rgb8ui";
512                 case GL_SRGB8:                          return "srgb8";
513                 case GL_RGB9_E5:                        return "rgb9_e5";
514                 case GL_RG32F:                          return "rg32f";
515                 case GL_RG32I:                          return "rg32i";
516                 case GL_RG32UI:                         return "rg32ui";
517                 case GL_RG16F:                          return "rg16f";
518                 case GL_RG16I:                          return "rg16i";
519                 case GL_RG16UI:                         return "rg16ui";
520                 case GL_RG8:                            return "rg8";
521                 case GL_RG8I:                           return "rg8i";
522                 case GL_RG8UI:                          return "rg8ui";
523                 case GL_RG8_SNORM:                      return "rg8_snorm";
524                 case GL_R32F:                           return "r32f";
525                 case GL_R32I:                           return "r32i";
526                 case GL_R32UI:                          return "r32ui";
527                 case GL_R16F:                           return "r16f";
528                 case GL_R16I:                           return "r16i";
529                 case GL_R16UI:                          return "r16ui";
530                 case GL_R8:                                     return "r8";
531                 case GL_R8I:                            return "r8i";
532                 case GL_R8UI:                           return "r8ui";
533                 case GL_R8_SNORM:                       return "r8_snorm";
534                 case GL_DEPTH_COMPONENT32F:     return "depth_component32f";
535                 case GL_DEPTH_COMPONENT24:      return "depth_component24";
536                 case GL_DEPTH32F_STENCIL8:      return "depth32f_stencil8";
537                 case GL_DEPTH24_STENCIL8:       return "depth24_stencil8";
538
539                 default:
540                         TCU_FAIL("Unknown format");
541         }
542 }
543
544 glu::DataType getFragmentOutputType (const tcu::TextureFormat& format)
545 {
546         switch (tcu::getTextureChannelClass(format.type))
547         {
548                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
549                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
550                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
551                         return glu::TYPE_FLOAT_VEC4;
552
553                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
554                         return glu::TYPE_UINT_VEC4;
555
556                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
557                         return glu::TYPE_INT_VEC4;
558
559                 default:
560                         DE_FATAL("Unknown format");
561                         return glu::TYPE_LAST;
562         }
563 }
564
565 tcu::TextureFormat getFramebufferReadFormat (const tcu::TextureFormat& format)
566 {
567         switch (tcu::getTextureChannelClass(format.type))
568         {
569                 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
570                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
571
572                 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
573                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
574                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
575
576                 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
577                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
578
579                 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
580                         return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
581
582                 default:
583                         DE_FATAL("Unknown format");
584                         return tcu::TextureFormat();
585         }
586 }
587
588 static int calculateU8ConversionError (int srcBits)
589 {
590         if (srcBits > 0)
591         {
592                 const int clampedBits   = de::clamp<int>(srcBits, 0, 8);
593                 const int srcMaxValue   = de::max((1<<clampedBits) - 1, 1);
594                 const int error                 = int(deFloatCeil(255.0f * 2.0f / float(srcMaxValue)));
595
596                 return de::clamp<int>(error, 0, 255);
597         }
598         else
599                 return 1;
600 }
601
602 tcu::RGBA getFormatThreshold (const tcu::TextureFormat& format)
603 {
604         const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(format);
605
606         return tcu::RGBA(calculateU8ConversionError(bits.x()),
607                                          calculateU8ConversionError(bits.y()),
608                                          calculateU8ConversionError(bits.z()),
609                                          calculateU8ConversionError(bits.w()));
610 }
611
612 tcu::RGBA getFormatThreshold (deUint32 glFormat)
613 {
614         const tcu::TextureFormat format = glu::mapGLInternalFormat(glFormat);
615
616         return getFormatThreshold(format);
617 }
618
619 } // FboTestUtil
620 } // Functional
621 } // gles31
622 } // deqp