1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 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 "es3fFboTestUtil.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 gles3
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
mapDataTypeToGenericVecType(glu::DataType type)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>
castVectorSaturate(const tcu::Vec4 & in)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
FlatColorShader(glu::DataType outputType)77 FlatColorShader::FlatColorShader (glu::DataType outputType)
78 : ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
79 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
80 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
81 << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
82 << sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4)
83 << sglr::pdec::VertexSource(
84 "#version 300 es\n"
85 "in highp vec4 a_position;\n"
86 "void main (void)\n"
87 "{\n"
88 " gl_Position = a_position;\n"
89 "}\n")
90 << sglr::pdec::FragmentSource(
91 string(
92 "#version 300 es\n"
93 "uniform highp vec4 u_color;\n"
94 "layout(location = 0) out highp ") + glu::getDataTypeName(outputType) + " o_color;\n"
95 "void main (void)\n"
96 "{\n"
97 " o_color = " + glu::getDataTypeName(outputType) + "(u_color);\n"
98 "}\n"))
99 , m_outputType(outputType)
100 {
101 }
102
setColor(sglr::Context & context,deUint32 program,const tcu::Vec4 & color)103 void FlatColorShader::setColor (sglr::Context& context, deUint32 program, const tcu::Vec4& color)
104 {
105 deInt32 location = context.getUniformLocation(program, "u_color");
106
107 context.useProgram(program);
108 context.uniform4fv(location, 1, color.getPtr());
109 }
110
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const111 void FlatColorShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
112 {
113 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
114 {
115 rr::VertexPacket& packet = *packets[packetNdx];
116
117 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
118 }
119 }
120
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const121 void FlatColorShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
122 {
123 const tcu::Vec4 color (m_uniforms[0].value.f4);
124 const tcu::IVec4 icolor = castVectorSaturate<deInt32>(color);
125 const tcu::UVec4 uicolor = castVectorSaturate<deUint32>(color);
126
127 DE_UNREF(packets);
128
129 if (m_outputType == glu::TYPE_FLOAT_VEC4)
130 {
131 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
132 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
133 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
134 }
135 else if (m_outputType == glu::TYPE_INT_VEC4)
136 {
137 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
138 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
139 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
140 }
141 else if (m_outputType == glu::TYPE_UINT_VEC4)
142 {
143 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
144 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
145 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
146 }
147 else
148 DE_ASSERT(DE_FALSE);
149 }
150
GradientShader(glu::DataType outputType)151 GradientShader::GradientShader (glu::DataType outputType)
152 : ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
153 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
154 << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
155 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
156 << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
157 << sglr::pdec::Uniform("u_gradientMin", glu::TYPE_FLOAT_VEC4)
158 << sglr::pdec::Uniform("u_gradientMax", glu::TYPE_FLOAT_VEC4)
159 << sglr::pdec::VertexSource(
160 "#version 300 es\n"
161 "in highp vec4 a_position;\n"
162 "in highp vec4 a_coord;\n"
163 "out highp vec4 v_coord;\n"
164 "void main (void)\n"
165 "{\n"
166 " gl_Position = a_position;\n"
167 " v_coord = a_coord;\n"
168 "}\n")
169 << sglr::pdec::FragmentSource(
170 string(
171 "#version 300 es\n"
172 "in highp vec4 v_coord;\n"
173 "uniform highp vec4 u_gradientMin;\n"
174 "uniform highp vec4 u_gradientMax;\n"
175 "layout(location = 0) out highp ") + glu::getDataTypeName(outputType) + " o_color;\n"
176 "void main (void)\n"
177 "{\n"
178 " highp float x = v_coord.x;\n"
179 " highp float y = v_coord.y;\n"
180 " highp float f0 = (x + y) * 0.5;\n"
181 " highp float f1 = 0.5 + (x - y) * 0.5;\n"
182 " highp vec4 fv = vec4(f0, f1, 1.0f-f0, 1.0f-f1);\n"
183 " o_color = " + glu::getDataTypeName(outputType) + "(u_gradientMin + (u_gradientMax-u_gradientMin)*fv);\n"
184 "}\n"))
185 , m_outputType(outputType)
186 {
187 }
188
setGradient(sglr::Context & ctx,deUint32 program,const tcu::Vec4 & gradientMin,const tcu::Vec4 & gradientMax)189 void GradientShader::setGradient (sglr::Context& ctx, deUint32 program, const tcu::Vec4& gradientMin, const tcu::Vec4& gradientMax)
190 {
191 ctx.useProgram(program);
192 ctx.uniform4fv(ctx.getUniformLocation(program, "u_gradientMin"), 1, gradientMin.getPtr());
193 ctx.uniform4fv(ctx.getUniformLocation(program, "u_gradientMax"), 1, gradientMax.getPtr());
194 }
195
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const196 void GradientShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
197 {
198 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
199 {
200 rr::VertexPacket& packet = *packets[packetNdx];
201
202 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
203 packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
204 }
205 }
206
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const207 void GradientShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
208 {
209 const tcu::Vec4 gradientMin(m_uniforms[0].value.f4);
210 const tcu::Vec4 gradientMax(m_uniforms[1].value.f4);
211
212 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
213 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
214 {
215 const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
216 const float x = coord.x();
217 const float y = coord.y();
218 const float f0 = (x + y) * 0.5f;
219 const float f1 = 0.5f + (x - y) * 0.5f;
220 const tcu::Vec4 fv = Vec4(f0, f1, 1.0f-f0, 1.0f-f1);
221
222 const tcu::Vec4 color = gradientMin + (gradientMax-gradientMin) * fv;
223 const tcu::IVec4 icolor = castVectorSaturate<deInt32>(color);
224 const tcu::UVec4 uicolor = castVectorSaturate<deUint32>(color);
225
226 if (m_outputType == glu::TYPE_FLOAT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
227 else if (m_outputType == glu::TYPE_INT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
228 else if (m_outputType == glu::TYPE_UINT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
229 else
230 DE_ASSERT(DE_FALSE);
231 }
232 }
233
genTexFragmentShader(const vector<glu::DataType> & samplerTypes,glu::DataType outputType)234 static string genTexFragmentShader (const vector<glu::DataType>& samplerTypes, glu::DataType outputType)
235 {
236 const char* precision = "highp";
237 std::ostringstream src;
238
239 src << "#version 300 es\n"
240 << "layout(location = 0) out highp " << glu::getDataTypeName(outputType) << " o_color0;\n";
241
242 src << "in highp vec2 v_coord;\n";
243
244 for (int samplerNdx = 0; samplerNdx < (int)samplerTypes.size(); samplerNdx++)
245 {
246 src << "uniform " << precision << " " << glu::getDataTypeName(samplerTypes[samplerNdx]) << " u_sampler" << samplerNdx << ";\n";
247 src << "uniform " << precision << " vec4 u_texScale" << samplerNdx << ";\n";
248 src << "uniform " << precision << " vec4 u_texBias" << samplerNdx << ";\n";
249 }
250
251 // Output scale & bias
252 src << "uniform " << precision << " vec4 u_outScale0;\n"
253 << "uniform " << precision << " vec4 u_outBias0;\n";
254
255 src << "\n"
256 << "void main (void)\n"
257 << "{\n"
258 << " " << precision << " vec4 out0 = vec4(0.0);\n";
259
260 // Texture input fetch and combine.
261 for (int inNdx = 0; inNdx < (int)samplerTypes.size(); inNdx++)
262 src << "\tout0 += vec4("
263 << "texture(u_sampler" << inNdx << ", v_coord)) * u_texScale" << inNdx << " + u_texBias" << inNdx << ";\n";
264
265 // Write output.
266 src << " o_color0 = " << glu::getDataTypeName(outputType) << "(out0 * u_outScale0 + u_outBias0);\n";
267
268 src << "}\n";
269
270 return src.str();
271 }
272
genTexture2DShaderDecl(const DataTypes & samplerTypes,glu::DataType outputType)273 static sglr::pdec::ShaderProgramDeclaration genTexture2DShaderDecl (const DataTypes& samplerTypes, glu::DataType outputType)
274 {
275 sglr::pdec::ShaderProgramDeclaration decl;
276
277 decl << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT);
278 decl << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT);
279 decl << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT);
280 decl << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType));
281
282 decl << sglr::pdec::VertexSource(
283 "#version 300 es\n"
284 "in highp vec4 a_position;\n"
285 "in highp vec2 a_coord;\n"
286 "out highp vec2 v_coord;\n"
287 "void main(void)\n"
288 "{\n"
289 " gl_Position = a_position;\n"
290 " v_coord = a_coord;\n"
291 "}\n");
292 decl << sglr::pdec::FragmentSource(genTexFragmentShader(samplerTypes.vec, outputType));
293
294 decl << sglr::pdec::Uniform("u_outScale0", glu::TYPE_FLOAT_VEC4);
295 decl << sglr::pdec::Uniform("u_outBias0", glu::TYPE_FLOAT_VEC4);
296
297 for (size_t ndx = 0; ndx < samplerTypes.vec.size(); ++ndx)
298 {
299 decl << sglr::pdec::Uniform(std::string("u_sampler") + de::toString(ndx), samplerTypes.vec[ndx]);
300 decl << sglr::pdec::Uniform(std::string("u_texScale") + de::toString(ndx), glu::TYPE_FLOAT_VEC4);
301 decl << sglr::pdec::Uniform(std::string("u_texBias") + de::toString(ndx), glu::TYPE_FLOAT_VEC4);
302 }
303
304 return decl;
305 }
306
Texture2DShader(const DataTypes & samplerTypes,glu::DataType outputType,const Vec4 & outScale,const Vec4 & outBias)307 Texture2DShader::Texture2DShader (const DataTypes& samplerTypes, glu::DataType outputType, const Vec4& outScale, const Vec4& outBias)
308 : sglr::ShaderProgram (genTexture2DShaderDecl(samplerTypes, outputType))
309 , m_outScale (outScale)
310 , m_outBias (outBias)
311 , m_outputType (outputType)
312 {
313 m_inputs.resize(samplerTypes.vec.size());
314
315 // Initialize units.
316 for (int ndx = 0; ndx < (int)m_inputs.size(); ndx++)
317 {
318 m_inputs[ndx].unitNdx = ndx;
319 m_inputs[ndx].scale = Vec4(1.0f);
320 m_inputs[ndx].bias = Vec4(0.0f);
321 }
322 }
323
setUnit(int inputNdx,int unitNdx)324 void Texture2DShader::setUnit (int inputNdx, int unitNdx)
325 {
326 m_inputs[inputNdx].unitNdx = unitNdx;
327 }
328
setTexScaleBias(int inputNdx,const Vec4 & scale,const Vec4 & bias)329 void Texture2DShader::setTexScaleBias (int inputNdx, const Vec4& scale, const Vec4& bias)
330 {
331 m_inputs[inputNdx].scale = scale;
332 m_inputs[inputNdx].bias = bias;
333 }
334
setOutScaleBias(const Vec4 & scale,const Vec4 & bias)335 void Texture2DShader::setOutScaleBias (const Vec4& scale, const Vec4& bias)
336 {
337 m_outScale = scale;
338 m_outBias = bias;
339 }
340
setUniforms(sglr::Context & gl,deUint32 program) const341 void Texture2DShader::setUniforms (sglr::Context& gl, deUint32 program) const
342 {
343 gl.useProgram(program);
344
345 for (int texNdx = 0; texNdx < (int)m_inputs.size(); texNdx++)
346 {
347 string samplerName = string("u_sampler") + de::toString(texNdx);
348 string scaleName = string("u_texScale") + de::toString(texNdx);
349 string biasName = string("u_texBias") + de::toString(texNdx);
350
351 gl.uniform1i(gl.getUniformLocation(program, samplerName.c_str()), m_inputs[texNdx].unitNdx);
352 gl.uniform4fv(gl.getUniformLocation(program, scaleName.c_str()), 1, m_inputs[texNdx].scale.getPtr());
353 gl.uniform4fv(gl.getUniformLocation(program, biasName.c_str()), 1, m_inputs[texNdx].bias.getPtr());
354 }
355
356 gl.uniform4fv(gl.getUniformLocation(program, "u_outScale0"), 1, m_outScale.getPtr());
357 gl.uniform4fv(gl.getUniformLocation(program, "u_outBias0"), 1, m_outBias.getPtr());
358 }
359
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const360 void Texture2DShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
361 {
362 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
363 {
364 rr::VertexPacket& packet = *packets[packetNdx];
365
366 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
367 packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
368 }
369 }
370
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const371 void Texture2DShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
372 {
373 const tcu::Vec4 outScale (m_uniforms[0].value.f4);
374 const tcu::Vec4 outBias (m_uniforms[1].value.f4);
375
376 tcu::Vec2 texCoords[4];
377 tcu::Vec4 colors[4];
378
379 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
380 {
381 // setup tex coords
382 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
383 {
384 const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
385 texCoords[fragNdx] = tcu::Vec2(coord.x(), coord.y());
386 }
387
388 // clear result
389 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
390 colors[fragNdx] = tcu::Vec4(0.0f);
391
392 // sample each texture
393 for (int ndx = 0; ndx < (int)m_inputs.size(); ndx++)
394 {
395 const sglr::rc::Texture2D* tex = m_uniforms[2 + ndx*3].sampler.tex2D;
396 const tcu::Vec4 scale (m_uniforms[2 + ndx*3 + 1].value.f4);
397 const tcu::Vec4 bias (m_uniforms[2 + ndx*3 + 2].value.f4);
398 tcu::Vec4 tmpColors[4];
399
400 tex->sample4(tmpColors, texCoords);
401
402 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
403 colors[fragNdx] += tmpColors[fragNdx] * scale + bias;
404 }
405
406 // write out
407 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
408 {
409 const tcu::Vec4 color = colors[fragNdx] * outScale + outBias;
410 const tcu::IVec4 icolor = castVectorSaturate<deInt32>(color);
411 const tcu::UVec4 uicolor = castVectorSaturate<deUint32>(color);
412
413 if (m_outputType == glu::TYPE_FLOAT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
414 else if (m_outputType == glu::TYPE_INT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
415 else if (m_outputType == glu::TYPE_UINT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
416 else
417 DE_ASSERT(DE_FALSE);
418 }
419 }
420 }
421
TextureCubeShader(glu::DataType samplerType,glu::DataType outputType)422 TextureCubeShader::TextureCubeShader (glu::DataType samplerType, glu::DataType outputType)
423 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
424 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
425 << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
426 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
427 << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
428 << sglr::pdec::Uniform("u_coordMat", glu::TYPE_FLOAT_MAT3)
429 << sglr::pdec::Uniform("u_sampler0", samplerType)
430 << sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4)
431 << sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4)
432 << sglr::pdec::VertexSource(
433 "#version 300 es\n"
434 "in highp vec4 a_position;\n"
435 "in mediump vec2 a_coord;\n"
436 "uniform mat3 u_coordMat;\n"
437 "out mediump vec3 v_coord;\n"
438 "void main (void)\n"
439 "{\n"
440 " gl_Position = a_position;\n"
441 " v_coord = u_coordMat * vec3(a_coord, 1.0);\n"
442 "}\n")
443 << sglr::pdec::FragmentSource(
444 string("") +
445 "#version 300 es\n"
446 "uniform highp " + glu::getDataTypeName(samplerType) + " u_sampler0;\n"
447 "uniform highp vec4 u_scale;\n"
448 "uniform highp vec4 u_bias;\n"
449 "in mediump vec3 v_coord;\n"
450 "layout(location = 0) out highp " + glu::getDataTypeName(outputType) + " o_color;\n"
451 "void main (void)\n"
452 "{\n"
453 " o_color = " + glu::getDataTypeName(outputType) + "(vec4(texture(u_sampler0, v_coord)) * u_scale + u_bias);\n"
454 "}\n"))
455 , m_texScale (1.0f)
456 , m_texBias (0.0f)
457 , m_outputType (outputType)
458 {
459 }
460
setFace(tcu::CubeFace face)461 void TextureCubeShader::setFace (tcu::CubeFace face)
462 {
463 static const float s_cubeTransforms[][3*3] =
464 {
465 // Face -X: (x, y, 1) -> (-1, -(2*y-1), +(2*x-1))
466 { 0.0f, 0.0f, -1.0f,
467 0.0f, -2.0f, 1.0f,
468 2.0f, 0.0f, -1.0f },
469 // Face +X: (x, y, 1) -> (+1, -(2*y-1), -(2*x-1))
470 { 0.0f, 0.0f, 1.0f,
471 0.0f, -2.0f, 1.0f,
472 -2.0f, 0.0f, 1.0f },
473 // Face -Y: (x, y, 1) -> (+(2*x-1), -1, -(2*y-1))
474 { 2.0f, 0.0f, -1.0f,
475 0.0f, 0.0f, -1.0f,
476 0.0f, -2.0f, 1.0f },
477 // Face +Y: (x, y, 1) -> (+(2*x-1), +1, +(2*y-1))
478 { 2.0f, 0.0f, -1.0f,
479 0.0f, 0.0f, 1.0f,
480 0.0f, 2.0f, -1.0f },
481 // Face -Z: (x, y, 1) -> (-(2*x-1), -(2*y-1), -1)
482 { -2.0f, 0.0f, 1.0f,
483 0.0f, -2.0f, 1.0f,
484 0.0f, 0.0f, -1.0f },
485 // Face +Z: (x, y, 1) -> (+(2*x-1), -(2*y-1), +1)
486 { 2.0f, 0.0f, -1.0f,
487 0.0f, -2.0f, 1.0f,
488 0.0f, 0.0f, 1.0f }
489 };
490 DE_ASSERT(de::inBounds<int>(face, 0, tcu::CUBEFACE_LAST));
491 m_coordMat = tcu::Mat3(s_cubeTransforms[face]);
492 }
493
setTexScaleBias(const Vec4 & scale,const Vec4 & bias)494 void TextureCubeShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
495 {
496 m_texScale = scale;
497 m_texBias = bias;
498 }
499
setUniforms(sglr::Context & gl,deUint32 program) const500 void TextureCubeShader::setUniforms (sglr::Context& gl, deUint32 program) const
501 {
502 gl.useProgram(program);
503
504 gl.uniform1i(gl.getUniformLocation(program, "u_sampler0"), 0);
505 gl.uniformMatrix3fv(gl.getUniformLocation(program, "u_coordMat"), 1, GL_FALSE, m_coordMat.getColumnMajorData().getPtr());
506 gl.uniform4fv(gl.getUniformLocation(program, "u_scale"), 1, m_texScale.getPtr());
507 gl.uniform4fv(gl.getUniformLocation(program, "u_bias"), 1, m_texBias.getPtr());
508 }
509
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const510 void TextureCubeShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
511 {
512 tcu::Mat3 texCoordMat = tcu::Mat3(m_uniforms[0].value.m3);
513
514 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
515 {
516 rr::VertexPacket& packet = *packets[packetNdx];
517 tcu::Vec2 a_coord = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx).xy();
518 tcu::Vec3 v_coord = texCoordMat * tcu::Vec3(a_coord.x(), a_coord.y(), 1.0f);
519
520 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
521 packet.outputs[0] = tcu::Vec4(v_coord.x(), v_coord.y(), v_coord.z(), 0.0f);
522 }
523 }
524
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const525 void TextureCubeShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
526 {
527 const tcu::Vec4 texScale (m_uniforms[2].value.f4);
528 const tcu::Vec4 texBias (m_uniforms[3].value.f4);
529
530 tcu::Vec3 texCoords[4];
531 tcu::Vec4 colors[4];
532
533 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
534 {
535 const sglr::rc::TextureCube* tex = m_uniforms[1].sampler.texCube;
536
537 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
538 {
539 const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
540 texCoords[fragNdx] = tcu::Vec3(coord.x(), coord.y(), coord.z());
541 }
542
543 tex->sample4(colors, texCoords);
544
545 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
546 {
547 const tcu::Vec4 color = colors[fragNdx] * texScale + texBias;
548 const tcu::IVec4 icolor = castVectorSaturate<deInt32>(color);
549 const tcu::UVec4 uicolor = castVectorSaturate<deUint32>(color);
550
551 if (m_outputType == glu::TYPE_FLOAT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
552 else if (m_outputType == glu::TYPE_INT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
553 else if (m_outputType == glu::TYPE_UINT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
554 else
555 DE_ASSERT(DE_FALSE);
556 }
557 }
558 }
559
Texture2DArrayShader(glu::DataType samplerType,glu::DataType outputType)560 Texture2DArrayShader::Texture2DArrayShader (glu::DataType samplerType, glu::DataType outputType)
561 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
562 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
563 << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
564 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
565 << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
566 << sglr::pdec::Uniform("u_sampler0", samplerType)
567 << sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4)
568 << sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4)
569 << sglr::pdec::Uniform("u_layer", glu::TYPE_INT)
570 << sglr::pdec::VertexSource(
571 "#version 300 es\n"
572 "in highp vec4 a_position;\n"
573 "in highp vec2 a_coord;\n"
574 "out highp vec2 v_coord;\n"
575 "void main (void)\n"
576 "{\n"
577 " gl_Position = a_position;\n"
578 " v_coord = a_coord;\n"
579 "}\n")
580 << sglr::pdec::FragmentSource(
581 string("") +
582 "#version 300 es\n"
583 "uniform highp " + glu::getDataTypeName(samplerType) + " u_sampler0;\n"
584 "uniform highp vec4 u_scale;\n"
585 "uniform highp vec4 u_bias;\n"
586 "uniform highp int u_layer;\n"
587 "in highp vec2 v_coord;\n"
588 "layout(location = 0) out highp " + glu::getDataTypeName(outputType) + " o_color;\n"
589 "void main (void)\n"
590 "{\n"
591 " o_color = " + glu::getDataTypeName(outputType) + "(vec4(texture(u_sampler0, vec3(v_coord, u_layer))) * u_scale + u_bias);\n"
592 "}\n"))
593 , m_texScale (1.0f)
594 , m_texBias (0.0f)
595 , m_layer (0)
596 , m_outputType (outputType)
597 {
598 }
599
setLayer(int layer)600 void Texture2DArrayShader::setLayer (int layer)
601 {
602 m_layer = layer;
603 }
604
setTexScaleBias(const Vec4 & scale,const Vec4 & bias)605 void Texture2DArrayShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
606 {
607 m_texScale = scale;
608 m_texBias = bias;
609 }
610
setUniforms(sglr::Context & gl,deUint32 program) const611 void Texture2DArrayShader::setUniforms (sglr::Context& gl, deUint32 program) const
612 {
613 gl.useProgram(program);
614
615 gl.uniform1i (gl.getUniformLocation(program, "u_sampler0"), 0);
616 gl.uniform1i (gl.getUniformLocation(program, "u_layer"), m_layer);
617 gl.uniform4fv (gl.getUniformLocation(program, "u_scale"), 1, m_texScale.getPtr());
618 gl.uniform4fv (gl.getUniformLocation(program, "u_bias"), 1, m_texBias.getPtr());
619 }
620
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const621 void Texture2DArrayShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
622 {
623 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
624 {
625 rr::VertexPacket& packet = *packets[packetNdx];
626
627 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
628 packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
629 }
630 }
631
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const632 void Texture2DArrayShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
633 {
634 const tcu::Vec4 texScale (m_uniforms[1].value.f4);
635 const tcu::Vec4 texBias (m_uniforms[2].value.f4);
636 const int layer = m_uniforms[3].value.i;
637
638 tcu::Vec3 texCoords[4];
639 tcu::Vec4 colors[4];
640
641 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
642 {
643 const sglr::rc::Texture2DArray* tex = m_uniforms[0].sampler.tex2DArray;
644
645 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
646 {
647 const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
648 texCoords[fragNdx] = tcu::Vec3(coord.x(), coord.y(), float(layer));
649 }
650
651 tex->sample4(colors, texCoords);
652
653 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
654 {
655 const tcu::Vec4 color = colors[fragNdx] * texScale + texBias;
656 const tcu::IVec4 icolor = castVectorSaturate<deInt32>(color);
657 const tcu::UVec4 uicolor = castVectorSaturate<deUint32>(color);
658
659 if (m_outputType == glu::TYPE_FLOAT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
660 else if (m_outputType == glu::TYPE_INT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
661 else if (m_outputType == glu::TYPE_UINT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
662 else
663 DE_ASSERT(DE_FALSE);
664 }
665 }
666 }
667
Texture3DShader(glu::DataType samplerType,glu::DataType outputType)668 Texture3DShader::Texture3DShader (glu::DataType samplerType, glu::DataType outputType)
669 : sglr::ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
670 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
671 << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
672 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
673 << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
674 << sglr::pdec::Uniform("u_sampler0", samplerType)
675 << sglr::pdec::Uniform("u_scale", glu::TYPE_FLOAT_VEC4)
676 << sglr::pdec::Uniform("u_bias", glu::TYPE_FLOAT_VEC4)
677 << sglr::pdec::Uniform("u_depth", glu::TYPE_FLOAT)
678 << sglr::pdec::VertexSource(
679 "#version 300 es\n"
680 "in highp vec4 a_position;\n"
681 "in highp vec2 a_coord;\n"
682 "out highp vec2 v_coord;\n"
683 "void main (void)\n"
684 "{\n"
685 " gl_Position = a_position;\n"
686 " v_coord = a_coord;\n"
687 "}\n")
688 << sglr::pdec::FragmentSource(
689 string("") +
690 "#version 300 es\n"
691 "uniform highp " + glu::getDataTypeName(samplerType) + " u_sampler0;\n"
692 "uniform highp vec4 u_scale;\n"
693 "uniform highp vec4 u_bias;\n"
694 "uniform highp float u_depth;\n"
695 "in highp vec2 v_coord;\n"
696 "layout(location = 0) out highp " + glu::getDataTypeName(outputType) + " o_color;\n"
697 "void main (void)\n"
698 "{\n"
699 " o_color = " + glu::getDataTypeName(outputType) + "(vec4(texture(u_sampler0, vec3(v_coord, u_depth))) * u_scale + u_bias);\n"
700 "}\n"))
701 , m_texScale (1.0f)
702 , m_texBias (0.0f)
703 , m_depth (0.0f)
704 , m_outputType (outputType)
705 {
706 }
707
setDepth(float depth)708 void Texture3DShader::setDepth (float depth)
709 {
710 m_depth = depth;
711 }
712
setTexScaleBias(const Vec4 & scale,const Vec4 & bias)713 void Texture3DShader::setTexScaleBias (const Vec4& scale, const Vec4& bias)
714 {
715 m_texScale = scale;
716 m_texBias = bias;
717 }
718
setUniforms(sglr::Context & gl,deUint32 program) const719 void Texture3DShader::setUniforms (sglr::Context& gl, deUint32 program) const
720 {
721 gl.useProgram(program);
722
723 gl.uniform1i (gl.getUniformLocation(program, "u_sampler0"), 0);
724 gl.uniform1f (gl.getUniformLocation(program, "u_depth"), m_depth);
725 gl.uniform4fv (gl.getUniformLocation(program, "u_scale"), 1, m_texScale.getPtr());
726 gl.uniform4fv (gl.getUniformLocation(program, "u_bias"), 1, m_texBias.getPtr());
727 }
728
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const729 void Texture3DShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
730 {
731 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
732 {
733 rr::VertexPacket& packet = *packets[packetNdx];
734
735 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
736 packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
737 }
738 }
739
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const740 void Texture3DShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
741 {
742 const tcu::Vec4 texScale (m_uniforms[1].value.f4);
743 const tcu::Vec4 texBias (m_uniforms[2].value.f4);
744 const float depth = m_uniforms[3].value.f;
745
746 tcu::Vec3 texCoords[4];
747 tcu::Vec4 colors[4];
748
749 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
750 {
751 const sglr::rc::Texture3D* tex = m_uniforms[0].sampler.tex3D;
752
753 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
754 {
755 const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
756 texCoords[fragNdx] = tcu::Vec3(coord.x(), coord.y(), depth);
757 }
758
759 tex->sample4(colors, texCoords);
760
761 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
762 {
763 const tcu::Vec4 color = colors[fragNdx] * texScale + texBias;
764 const tcu::IVec4 icolor = castVectorSaturate<deInt32>(color);
765 const tcu::UVec4 uicolor = castVectorSaturate<deUint32>(color);
766
767 if (m_outputType == glu::TYPE_FLOAT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
768 else if (m_outputType == glu::TYPE_INT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
769 else if (m_outputType == glu::TYPE_UINT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
770 else
771 DE_ASSERT(DE_FALSE);
772 }
773 }
774 }
775
DepthGradientShader(glu::DataType outputType)776 DepthGradientShader::DepthGradientShader (glu::DataType outputType)
777 : ShaderProgram(sglr::pdec::ShaderProgramDeclaration()
778 << sglr::pdec::VertexAttribute("a_position", rr::GENERICVECTYPE_FLOAT)
779 << sglr::pdec::VertexAttribute("a_coord", rr::GENERICVECTYPE_FLOAT)
780 << sglr::pdec::VertexToFragmentVarying(rr::GENERICVECTYPE_FLOAT)
781 << sglr::pdec::FragmentOutput(mapDataTypeToGenericVecType(outputType))
782 << sglr::pdec::Uniform("u_maxGradient", glu::TYPE_FLOAT)
783 << sglr::pdec::Uniform("u_minGradient", glu::TYPE_FLOAT)
784 << sglr::pdec::Uniform("u_color", glu::TYPE_FLOAT_VEC4)
785 << sglr::pdec::VertexSource(
786 "#version 300 es\n"
787 "in highp vec4 a_position;\n"
788 "in highp vec4 a_coord;\n"
789 "out highp vec4 v_coord;\n"
790 "void main (void)\n"
791 "{\n"
792 " gl_Position = a_position;\n"
793 " v_coord = a_coord;\n"
794 "}\n")
795 << sglr::pdec::FragmentSource(
796 string(
797 "#version 300 es\n"
798 "in highp vec4 v_coord;\n"
799 "uniform highp float u_minGradient;\n"
800 "uniform highp float u_maxGradient;\n"
801 "uniform highp vec4 u_color;\n"
802 "layout(location = 0) out highp ") + glu::getDataTypeName(outputType) + " o_color;\n"
803 "void main (void)\n"
804 "{\n"
805 " highp float x = v_coord.x;\n"
806 " highp float y = v_coord.y;\n"
807 " highp float f0 = (x + y) * 0.5;\n"
808 " gl_FragDepth = u_minGradient + (u_maxGradient-u_minGradient)*f0;\n"
809 " o_color = " + glu::getDataTypeName(outputType) + "(u_color);\n"
810 "}\n"))
811 , m_outputType (outputType)
812 , u_minGradient (getUniformByName("u_minGradient"))
813 , u_maxGradient (getUniformByName("u_maxGradient"))
814 , u_color (getUniformByName("u_color"))
815 {
816 }
817
setUniforms(sglr::Context & ctx,deUint32 program,const float gradientMin,const float gradientMax,const tcu::Vec4 & color)818 void DepthGradientShader::setUniforms (sglr::Context& ctx, deUint32 program, const float gradientMin, const float gradientMax, const tcu::Vec4& color)
819 {
820 ctx.useProgram(program);
821 ctx.uniform1fv(ctx.getUniformLocation(program, "u_minGradient"), 1, &gradientMin);
822 ctx.uniform1fv(ctx.getUniformLocation(program, "u_maxGradient"), 1, &gradientMax);
823 ctx.uniform4fv(ctx.getUniformLocation(program, "u_color"), 1, color.getPtr());
824 }
825
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const826 void DepthGradientShader::shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
827 {
828 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
829 {
830 rr::VertexPacket& packet = *packets[packetNdx];
831
832 packet.position = rr::readVertexAttribFloat(inputs[0], packet.instanceNdx, packet.vertexNdx);
833 packet.outputs[0] = rr::readVertexAttribFloat(inputs[1], packet.instanceNdx, packet.vertexNdx);
834 }
835 }
836
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const837 void DepthGradientShader::shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
838 {
839 const float gradientMin (u_minGradient.value.f);
840 const float gradientMax (u_maxGradient.value.f);
841 const tcu::Vec4 color (u_color.value.f4);
842 const tcu::IVec4 icolor (castVectorSaturate<deInt32>(color));
843 const tcu::UVec4 uicolor (castVectorSaturate<deUint32>(color));
844
845 // running this shader without a depth buffer does not make any sense
846 DE_ASSERT(context.fragmentDepths);
847
848 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
849 for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
850 {
851 const tcu::Vec4 coord = rr::readTriangleVarying<float>(packets[packetNdx], context, 0, fragNdx);
852 const float x = coord.x();
853 const float y = coord.y();
854 const float f0 = (x + y) * 0.5f;
855
856 rr::writeFragmentDepth(context, packetNdx, fragNdx, 0, gradientMin + (gradientMax-gradientMin) * f0);
857
858 if (m_outputType == glu::TYPE_FLOAT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, color);
859 else if (m_outputType == glu::TYPE_INT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, icolor);
860 else if (m_outputType == glu::TYPE_UINT_VEC4) rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, uicolor);
861 else
862 DE_ASSERT(DE_FALSE);
863 }
864 }
865
clearColorBuffer(sglr::Context & ctx,const tcu::TextureFormat & format,const tcu::Vec4 & value)866 void clearColorBuffer (sglr::Context& ctx, const tcu::TextureFormat& format, const tcu::Vec4& value)
867 {
868 const tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(format.type);
869
870 switch (fmtClass)
871 {
872 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
873 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
874 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
875 ctx.clearBufferfv(GL_COLOR, 0, value.getPtr());
876 break;
877
878 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
879 ctx.clearBufferuiv(GL_COLOR, 0, value.asUint().getPtr());
880 break;
881
882 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
883 ctx.clearBufferiv(GL_COLOR, 0, value.asInt().getPtr());
884 break;
885
886 default:
887 DE_ASSERT(DE_FALSE);
888 }
889 }
890
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)891 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)
892 {
893 tcu::TextureFormat readFormat = getFramebufferReadFormat(format);
894 glu::TransferFormat transferFmt = glu::getTransferFormat(readFormat);
895 int alignment = 4; // \note GL_PACK_ALIGNMENT = 4 is assumed.
896 int rowSize = deAlign32(readFormat.getPixelSize()*width, alignment);
897 vector<deUint8> data (rowSize*height);
898
899 ctx.readPixels(x, y, width, height, transferFmt.format, transferFmt.dataType, &data[0]);
900
901 // Convert to surface.
902 tcu::ConstPixelBufferAccess src(readFormat, width, height, 1, rowSize, 0, &data[0]);
903
904 dst.setSize(width, height);
905 tcu::PixelBufferAccess dstAccess = dst.getAccess();
906
907 for (int yo = 0; yo < height; yo++)
908 for (int xo = 0; xo < width; xo++)
909 dstAccess.setPixel(src.getPixel(xo, yo) * scale + bias, xo, yo);
910 }
911
getFboIncompleteReasonName(deUint32 reason)912 static const char* getFboIncompleteReasonName (deUint32 reason)
913 {
914 switch (reason)
915 {
916 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT";
917 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: return "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT";
918 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: return "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS";
919 case GL_FRAMEBUFFER_UNSUPPORTED: return "GL_FRAMEBUFFER_UNSUPPORTED";
920 case GL_FRAMEBUFFER_COMPLETE: return "GL_FRAMEBUFFER_COMPLETE";
921 default: return "UNKNOWN";
922 }
923 }
924
FboIncompleteException(deUint32 reason,const char * file,int line)925 FboIncompleteException::FboIncompleteException (deUint32 reason, const char* file, int line)
926 : TestError ("Framebuffer is not complete", getFboIncompleteReasonName(reason), file, line)
927 , m_reason (reason)
928 {
929 }
930
getFormatName(deUint32 format)931 const char* getFormatName (deUint32 format)
932 {
933 switch (format)
934 {
935 case GL_RGB565: return "rgb565";
936 case GL_RGB5_A1: return "rgb5_a1";
937 case GL_RGBA4: return "rgba4";
938 case GL_DEPTH_COMPONENT16: return "depth_component16";
939 case GL_STENCIL_INDEX8: return "stencil_index8";
940 case GL_RGBA32F: return "rgba32f";
941 case GL_RGBA32I: return "rgba32i";
942 case GL_RGBA32UI: return "rgba32ui";
943 case GL_RGBA16F: return "rgba16f";
944 case GL_RGBA16I: return "rgba16i";
945 case GL_RGBA16UI: return "rgba16ui";
946 case GL_RGBA8: return "rgba8";
947 case GL_RGBA8I: return "rgba8i";
948 case GL_RGBA8UI: return "rgba8ui";
949 case GL_SRGB8_ALPHA8: return "srgb8_alpha8";
950 case GL_RGB10_A2: return "rgb10_a2";
951 case GL_RGB10_A2UI: return "rgb10_a2ui";
952 case GL_RGBA8_SNORM: return "rgba8_snorm";
953 case GL_RGB8: return "rgb8";
954 case GL_R11F_G11F_B10F: return "r11f_g11f_b10f";
955 case GL_RGB32F: return "rgb32f";
956 case GL_RGB32I: return "rgb32i";
957 case GL_RGB32UI: return "rgb32ui";
958 case GL_RGB16F: return "rgb16f";
959 case GL_RGB16I: return "rgb16i";
960 case GL_RGB16UI: return "rgb16ui";
961 case GL_RGB8_SNORM: return "rgb8_snorm";
962 case GL_RGB8I: return "rgb8i";
963 case GL_RGB8UI: return "rgb8ui";
964 case GL_SRGB8: return "srgb8";
965 case GL_RGB9_E5: return "rgb9_e5";
966 case GL_RG32F: return "rg32f";
967 case GL_RG32I: return "rg32i";
968 case GL_RG32UI: return "rg32ui";
969 case GL_RG16F: return "rg16f";
970 case GL_RG16I: return "rg16i";
971 case GL_RG16UI: return "rg16ui";
972 case GL_RG8: return "rg8";
973 case GL_RG8I: return "rg8i";
974 case GL_RG8UI: return "rg8ui";
975 case GL_RG8_SNORM: return "rg8_snorm";
976 case GL_R32F: return "r32f";
977 case GL_R32I: return "r32i";
978 case GL_R32UI: return "r32ui";
979 case GL_R16F: return "r16f";
980 case GL_R16I: return "r16i";
981 case GL_R16UI: return "r16ui";
982 case GL_R8: return "r8";
983 case GL_R8I: return "r8i";
984 case GL_R8UI: return "r8ui";
985 case GL_R8_SNORM: return "r8_snorm";
986 case GL_DEPTH_COMPONENT32F: return "depth_component32f";
987 case GL_DEPTH_COMPONENT24: return "depth_component24";
988 case GL_DEPTH32F_STENCIL8: return "depth32f_stencil8";
989 case GL_DEPTH24_STENCIL8: return "depth24_stencil8";
990
991 default:
992 TCU_FAIL("Unknown format");
993 }
994 }
995
getFragmentOutputType(const tcu::TextureFormat & format)996 glu::DataType getFragmentOutputType (const tcu::TextureFormat& format)
997 {
998 switch (tcu::getTextureChannelClass(format.type))
999 {
1000 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1001 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1002 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1003 return glu::TYPE_FLOAT_VEC4;
1004
1005 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1006 return glu::TYPE_UINT_VEC4;
1007
1008 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1009 return glu::TYPE_INT_VEC4;
1010
1011 default:
1012 DE_FATAL("Unknown format");
1013 return glu::TYPE_LAST;
1014 }
1015 }
1016
getFramebufferReadFormat(const tcu::TextureFormat & format)1017 tcu::TextureFormat getFramebufferReadFormat (const tcu::TextureFormat& format)
1018 {
1019 switch (tcu::getTextureChannelClass(format.type))
1020 {
1021 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT:
1022 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
1023
1024 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT:
1025 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT:
1026 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8);
1027
1028 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER:
1029 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
1030
1031 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER:
1032 return tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::SIGNED_INT32);
1033
1034 default:
1035 DE_FATAL("Unknown format");
1036 return tcu::TextureFormat();
1037 }
1038 }
1039
calculateU8ConversionError(int srcBits)1040 static int calculateU8ConversionError (int srcBits)
1041 {
1042 if (srcBits > 0)
1043 {
1044 const int clampedBits = de::clamp<int>(srcBits, 0, 8);
1045 const int srcMaxValue = de::max((1<<clampedBits) - 1, 1);
1046 const int error = int(deFloatCeil(255.0f * 2.0f / float(srcMaxValue)));
1047
1048 return de::clamp<int>(error, 0, 255);
1049 }
1050 else
1051 return 1;
1052 }
1053
getFormatThreshold(const tcu::TextureFormat & format)1054 tcu::RGBA getFormatThreshold (const tcu::TextureFormat& format)
1055 {
1056 const tcu::IVec4 bits = tcu::getTextureFormatMantissaBitDepth(format);
1057
1058 return tcu::RGBA(calculateU8ConversionError(bits.x()),
1059 calculateU8ConversionError(bits.y()),
1060 calculateU8ConversionError(bits.z()),
1061 calculateU8ConversionError(bits.w()));
1062 }
1063
getFormatThreshold(deUint32 glFormat)1064 tcu::RGBA getFormatThreshold (deUint32 glFormat)
1065 {
1066 const tcu::TextureFormat format = glu::mapGLInternalFormat(glFormat);
1067
1068 return getFormatThreshold(format);
1069 }
1070
getToSRGB8ConversionError(int srcBits)1071 static int getToSRGB8ConversionError (int srcBits)
1072 {
1073 // \note These are pre-computed based on simulation results.
1074 static const int errors[] =
1075 {
1076 1, // 0 bits - rounding
1077 255, // 1 bits
1078 157, // 2 bits
1079 106, // 3 bits
1080 74, // 4 bits
1081 51, // 5 bits
1082 34, // 6 bits
1083 22, // 7 bits
1084 13, // 8 bits
1085 7, // 9 bits
1086 4, // 10 bits
1087 3, // 11 bits
1088 2, // 12 bits
1089 // 1 from this on
1090 };
1091
1092 DE_ASSERT(srcBits >= 0);
1093 if (srcBits < DE_LENGTH_OF_ARRAY(errors))
1094 return errors[srcBits];
1095 else
1096 return 1;
1097 }
1098
getToSRGBConversionThreshold(const tcu::TextureFormat & src,const tcu::TextureFormat & dst)1099 tcu::RGBA getToSRGBConversionThreshold (const tcu::TextureFormat& src, const tcu::TextureFormat& dst)
1100 {
1101 // Only SRGB8 and SRGB8_ALPHA8 formats are supported.
1102 DE_ASSERT(dst.type == tcu::TextureFormat::UNORM_INT8 && tcu::isSRGB(dst));
1103
1104 const tcu::IVec4 bits = tcu::getTextureFormatMantissaBitDepth(src);
1105 const bool dstHasAlpha = dst.order == tcu::TextureFormat::sRGBA;
1106
1107 return tcu::RGBA(getToSRGB8ConversionError(bits.x()),
1108 getToSRGB8ConversionError(bits.y()),
1109 getToSRGB8ConversionError(bits.z()),
1110 dstHasAlpha ? calculateU8ConversionError(bits.w()) : 0);
1111 }
1112
1113 } // FboTestUtil
1114 } // Functional
1115 } // gles3
1116 } // deqp
1117