1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
21 * \brief FBO test utilities.
22 *//*--------------------------------------------------------------------*/
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"
32 #include "glwEnums.hpp"
33 #include "glwFunctions.hpp"
55 static rr::GenericVecType mapDataTypeToGenericVecType(glu::DataType type)
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;
64 return rr::GENERICVECTYPE_LAST;
69 static tcu::Vector<T, 4> castVectorSaturate (const tcu::Vec4& in)
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()))));
77 static string genTexFragmentShader (const vector<glu::DataType>& samplerTypes, glu::DataType outputType)
79 const char* precision = "highp";
80 std::ostringstream src;
82 src << "#version 300 es\n"
83 << "layout(location = 0) out highp " << glu::getDataTypeName(outputType) << " o_color0;\n";
85 src << "in highp vec2 v_coord;\n";
87 for (int samplerNdx = 0; samplerNdx < (int)samplerTypes.size(); samplerNdx++)
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";
94 // Output scale & bias
95 src << "uniform " << precision << " vec4 u_outScale0;\n"
96 << "uniform " << precision << " vec4 u_outBias0;\n";
99 << "void main (void)\n"
101 << " " << precision << " vec4 out0 = vec4(0.0);\n";
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";
109 src << " o_color0 = " << glu::getDataTypeName(outputType) << "(out0 * u_outScale0 + u_outBias0);\n";
116 static sglr::pdec::ShaderProgramDeclaration genTexture2DShaderDecl (const DataTypes& samplerTypes, glu::DataType outputType)
118 sglr::pdec::ShaderProgramDeclaration decl;
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));
125 decl << sglr::pdec::VertexSource(
127 "in highp vec4 a_position;\n"
128 "in highp vec2 a_coord;\n"
129 "out highp vec2 v_coord;\n"
132 " gl_Position = a_position;\n"
133 " v_coord = a_coord;\n"
135 decl << sglr::pdec::FragmentSource(genTexFragmentShader(samplerTypes.vec, outputType));
137 decl << sglr::pdec::Uniform("u_outScale0", glu::TYPE_FLOAT_VEC4);
138 decl << sglr::pdec::Uniform("u_outBias0", glu::TYPE_FLOAT_VEC4);
140 for (size_t ndx = 0; ndx < samplerTypes.vec.size(); ++ndx)
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);
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)
156 m_inputs.resize(samplerTypes.vec.size());
159 for (int ndx = 0; ndx < (int)m_inputs.size(); ndx++)
161 m_inputs[ndx].unitNdx = ndx;
162 m_inputs[ndx].scale = Vec4(1.0f);
163 m_inputs[ndx].bias = Vec4(0.0f);
167 void Texture2DShader::setUnit (int inputNdx, int unitNdx)
169 m_inputs[inputNdx].unitNdx = unitNdx;
172 void Texture2DShader::setTexScaleBias (int inputNdx, const Vec4& scale, const Vec4& bias)
174 m_inputs[inputNdx].scale = scale;
175 m_inputs[inputNdx].bias = bias;
178 void Texture2DShader::setOutScaleBias (const Vec4& scale, const Vec4& bias)
184 void Texture2DShader::setUniforms (sglr::Context& gl, deUint32 program) const
186 gl.useProgram(program);
188 for (int texNdx = 0; texNdx < (int)m_inputs.size(); texNdx++)
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);
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());
199 gl.uniform4fv(gl.getUniformLocation(program, "u_outScale0"), 1, m_outScale.getPtr());
200 gl.uniform4fv(gl.getUniformLocation(program, "u_outBias0"), 1, m_outBias.getPtr());
203 void Texture2DShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
205 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
207 rr::VertexPacket& packet = *packets[packetNdx];
209 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
210 packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
214 void Texture2DShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
216 const tcu::Vec4 outScale (m_uniforms[0].value.f4);
217 const tcu::Vec4 outBias (m_uniforms[1].value.f4);
219 tcu::Vec2 texCoords[4];
222 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
225 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
227 const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
228 texCoords[fragNdx] = tcu::Vec2(coord.x(), coord.y());
232 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
233 colors[fragNdx] = tcu::Vec4(0.0f);
235 // sample each texture
236 for (int ndx = 0; ndx < (int)m_inputs.size(); ndx++)
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];
243 tex->sample4(tmpColors, texCoords);
245 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
246 colors[fragNdx] += tmpColors[fragNdx] * scale + bias;
250 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
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);
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);
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(
278 ((glslVersion == glu::GLSL_VERSION_310_ES) ?
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"
288 " gl_Position = a_position;\n"
289 " v_coord = u_coordMat * vec3(a_coord, 1.0);\n"
291 << sglr::pdec::FragmentSource(
293 ((glslVersion == glu::GLSL_VERSION_310_ES) ?
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"
305 " o_color = " + glu::getDataTypeName(outputType) + "(vec4(texture(u_sampler0, vec4(v_coord, u_layer))) * u_scale + u_bias);\n"
310 , m_outputType (outputType)
312 TCU_CHECK_INTERNAL(glslVersion == glu::GLSL_VERSION_310_ES || glslVersion == glu::GLSL_VERSION_320_ES);
315 void TextureCubeArrayShader::setLayer (int layer)
320 void TextureCubeArrayShader::setFace (tcu::CubeFace face)
322 static const float s_cubeTransforms[][3*3] =
324 // Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
328 // Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
332 // Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
336 // Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
340 // Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
344 // Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
349 DE_ASSERT(de::inBounds<int>(face, 0, tcu::CUBEFACE_LAST));
350 m_coordMat = tcu::Mat3(s_cubeTransforms[face]);
353 void TextureCubeArrayShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
359 void TextureCubeArrayShader::setUniforms (sglr::Context& gl, deUint32 program) const
361 gl.useProgram(program);
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());
370 void TextureCubeArrayShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
372 tcu::Mat3 texCoordMat = tcu::Mat3(m_uniforms[0].value.m3);
374 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
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);
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);
385 void TextureCubeArrayShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
387 const tcu::Vec4 texScale (m_uniforms[2].value.f4);
388 const tcu::Vec4 texBias (m_uniforms[3].value.f4);
390 tcu::Vec4 texCoords[4];
393 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
395 const sglr::rc::TextureCubeArray* tex = m_uniforms[1].sampler.texCubeArray;
397 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
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);
403 tex->sample4(colors, texCoords);
405 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
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);
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);
420 void clearColorBuffer (sglr::Context& ctx, const tcu::TextureFormat& format, const tcu::Vec4& value)
422 const tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(format.type);
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());
432 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
433 ctx.clearBufferuiv(GL_COLOR, 0, value.asUint().getPtr());
436 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
437 ctx.clearBufferiv(GL_COLOR, 0, value.asInt().getPtr());
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)
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);
453 ctx.readPixels(x, y, width, height, transferFmt.format, transferFmt.dataType, &data[0]);
455 // Convert to surface.
456 tcu::ConstPixelBufferAccess src(readFormat, width, height, 1, rowSize, 0, &data[0]);
458 dst.setSize(width, height);
459 tcu::PixelBufferAccess dstAccess = dst.getAccess();
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);
466 static const char* getFboIncompleteReasonName (deUint32 reason)
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";
479 FboIncompleteException::FboIncompleteException (deUint32 reason, const char* file, int line)
480 : TestError ("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line)
485 const char* getFormatName (deUint32 format)
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";
546 TCU_FAIL("Unknown format");
550 glu::DataType getFragmentOutputType (const tcu::TextureFormat& format)
552 switch (tcu::getTextureChannelClass(format.type))
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;
559 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
560 return glu::TYPE_UINT_VEC4;
562 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
563 return glu::TYPE_INT_VEC4;
566 DE_FATAL("Unknown format");
567 return glu::TYPE_LAST;
571 tcu::TextureFormat getFramebufferReadFormat (const tcu::TextureFormat& format)
573 switch (tcu::getTextureChannelClass(format.type))
575 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
576 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
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);
582 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
583 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
585 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
586 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
589 DE_FATAL("Unknown format");
590 return tcu::TextureFormat();
594 static int calculateU8ConversionError (int srcBits)
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)));
602 return de::clamp<int>(error, 0, 255);
608 tcu::RGBA getFormatThreshold (const tcu::TextureFormat& format)
610 const tcu::IVec4 bits = tcu::getTextureFormatBitDepth(format);
612 return tcu::RGBA(calculateU8ConversionError(bits.x()),
613 calculateU8ConversionError(bits.y()),
614 calculateU8ConversionError(bits.z()),
615 calculateU8ConversionError(bits.w()));
618 tcu::RGBA getFormatThreshold (deUint32 glFormat)
620 const tcu::TextureFormat format = glu::mapGLInternalFormat(glFormat);
622 return getFormatThreshold(format);