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