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