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 Vertex texture tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3fVertexTextureTests.hpp"
25 #include "glsTextureTestUtil.hpp"
26 #include "gluTexture.hpp"
27 #include "gluPixelTransfer.hpp"
28 #include "gluTextureUtil.hpp"
29 #include "tcuVector.hpp"
30 #include "tcuMatrix.hpp"
31 #include "tcuTextureUtil.hpp"
32 #include "tcuImageCompare.hpp"
33 #include "deMath.h"
34 #include "deRandom.hpp"
35 #include "deString.h"
36
37 #include <string>
38 #include <vector>
39
40 #include <limits>
41
42 #include "glw.h"
43
44 using tcu::TestLog;
45 using tcu::Vec2;
46 using tcu::Vec3;
47 using tcu::Vec4;
48 using tcu::IVec2;
49 using tcu::IVec3;
50 using tcu::IVec4;
51 using tcu::Mat3;
52 using std::string;
53 using std::vector;
54
55 namespace deqp
56 {
57
58 using namespace gls::TextureTestUtil;
59 using namespace glu::TextureTestUtil;
60
61 using glu::TextureTestUtil::TEXTURETYPE_2D;
62 using glu::TextureTestUtil::TEXTURETYPE_CUBE;
63 using glu::TextureTestUtil::TEXTURETYPE_2D_ARRAY;
64 using glu::TextureTestUtil::TEXTURETYPE_3D;
65
66 namespace gles3
67 {
68 namespace Functional
69 {
70
71 static const int WIDTH_2D_ARRAY = 128;
72 static const int HEIGHT_2D_ARRAY = 128;
73 static const int LAYERS_2D_ARRAY = 8;
74
75 static const int WIDTH_3D = 64;
76 static const int HEIGHT_3D = 64;
77 static const int DEPTH_3D = 64;
78
79 // The 2D case draws four images.
80 static const int MAX_2D_RENDER_WIDTH = 128*2;
81 static const int MAX_2D_RENDER_HEIGHT = 128*2;
82
83 // The cube map case draws four 3-by-2 image groups.
84 static const int MAX_CUBE_RENDER_WIDTH = 28*2*3;
85 static const int MAX_CUBE_RENDER_HEIGHT = 28*2*2;
86
87 static const int MAX_2D_ARRAY_RENDER_WIDTH = 128*2;
88 static const int MAX_2D_ARRAY_RENDER_HEIGHT = 128*2;
89
90 static const int MAX_3D_RENDER_WIDTH = 128*2;
91 static const int MAX_3D_RENDER_HEIGHT = 128*2;
92
93 static const int GRID_SIZE_2D = 127;
94 static const int GRID_SIZE_CUBE = 63;
95 static const int GRID_SIZE_2D_ARRAY = 127;
96 static const int GRID_SIZE_3D = 127;
97
98 // Helpers for making texture coordinates "safe", i.e. move them further from coordinate bounary.
99
100 // Moves x towards the closest K+targetFraction, where K is an integer.
101 // E.g. moveTowardsFraction(x, 0.5f) moves x away from integer boundaries.
moveTowardsFraction(float x,float targetFraction)102 static inline float moveTowardsFraction (float x, float targetFraction)
103 {
104 const float strictness = 0.5f;
105 DE_ASSERT(0.0f < strictness && strictness <= 1.0f);
106 DE_ASSERT(de::inBounds(targetFraction, 0.0f, 1.0f));
107 const float y = x + 0.5f - targetFraction;
108 return deFloatFloor(y) + deFloatFrac(y)*(1.0f-strictness) + strictness*0.5f - 0.5f + targetFraction;
109 }
110
safeCoord(float raw,int scale,float fraction)111 static inline float safeCoord (float raw, int scale, float fraction)
112 {
113 const float scaleFloat = (float)scale;
114 return moveTowardsFraction(raw*scaleFloat, fraction) / scaleFloat;
115 }
116
117 template <int Size>
safeCoords(const tcu::Vector<float,Size> & raw,const tcu::Vector<int,Size> & scale,const tcu::Vector<float,Size> & fraction)118 static inline tcu::Vector<float, Size> safeCoords (const tcu::Vector<float, Size>& raw, const tcu::Vector<int, Size>& scale, const tcu::Vector<float, Size>& fraction)
119 {
120 tcu::Vector<float, Size> result;
121 for (int i = 0; i < Size; i++)
122 result[i] = safeCoord(raw[i], scale[i], fraction[i]);
123 return result;
124 }
125
safe2DTexCoords(const Vec2 & raw,const IVec2 & textureSize)126 static inline Vec2 safe2DTexCoords (const Vec2& raw, const IVec2& textureSize)
127 {
128 return safeCoords(raw, textureSize, Vec2(0.5f));
129 }
130
safe2DArrayTexCoords(const Vec3 & raw,const IVec3 & textureSize)131 static inline Vec3 safe2DArrayTexCoords (const Vec3& raw, const IVec3& textureSize)
132 {
133 return safeCoords(raw, textureSize, Vec3(0.5f, 0.5f, 0.0f));
134 }
135
safe3DTexCoords(const Vec3 & raw,const IVec3 & textureSize)136 static inline Vec3 safe3DTexCoords (const Vec3& raw, const IVec3& textureSize)
137 {
138 return safeCoords(raw, textureSize, Vec3(0.5f));
139 }
140
141 namespace
142 {
143
144 struct Rect
145 {
Rectdeqp::gles3::Functional::__anon936a6fe40111::Rect146 Rect (int x_, int y_, int w_, int h_) : x(x_), y(y_), w(w_), h(h_) {}
posdeqp::gles3::Functional::__anon936a6fe40111::Rect147 IVec2 pos (void) const { return IVec2(x, y); }
sizedeqp::gles3::Functional::__anon936a6fe40111::Rect148 IVec2 size (void) const { return IVec2(w, h); }
149
150 int x;
151 int y;
152 int w;
153 int h;
154 };
155
156 template <TextureType> struct TexTypeTcuClass;
157 template <> struct TexTypeTcuClass<TEXTURETYPE_2D> { typedef tcu::Texture2D t; };
158 template <> struct TexTypeTcuClass<TEXTURETYPE_CUBE> { typedef tcu::TextureCube t; };
159 template <> struct TexTypeTcuClass<TEXTURETYPE_2D_ARRAY> { typedef tcu::Texture2DArray t; };
160 template <> struct TexTypeTcuClass<TEXTURETYPE_3D> { typedef tcu::Texture3D t; };
161
162 template <TextureType> struct TexTypeSizeDims;
163 template <> struct TexTypeSizeDims<TEXTURETYPE_2D> { enum { V = 2 }; };
164 template <> struct TexTypeSizeDims<TEXTURETYPE_CUBE> { enum { V = 2 }; };
165 template <> struct TexTypeSizeDims<TEXTURETYPE_2D_ARRAY> { enum { V = 3 }; };
166 template <> struct TexTypeSizeDims<TEXTURETYPE_3D> { enum { V = 3 }; };
167
168 template <TextureType> struct TexTypeCoordDims;
169 template <> struct TexTypeCoordDims<TEXTURETYPE_2D> { enum { V = 2 }; };
170 template <> struct TexTypeCoordDims<TEXTURETYPE_CUBE> { enum { V = 3 }; };
171 template <> struct TexTypeCoordDims<TEXTURETYPE_2D_ARRAY> { enum { V = 3 }; };
172 template <> struct TexTypeCoordDims<TEXTURETYPE_3D> { enum { V = 3 }; };
173
174 template <TextureType TexType> struct TexTypeSizeIVec { typedef tcu::Vector<int, TexTypeSizeDims<TexType>::V> t; };
175 template <TextureType TexType> struct TexTypeCoordVec { typedef tcu::Vector<float, TexTypeCoordDims<TexType>::V> t; };
176
177 template <TextureType> struct TexTypeCoordParams;
178
179 template <> struct
180 TexTypeCoordParams<TEXTURETYPE_2D>
181 {
182 Vec2 scale;
183 Vec2 bias;
184
TexTypeCoordParamsdeqp::gles3::Functional::__anon936a6fe40111::TexTypeCoordParams185 TexTypeCoordParams (const Vec2& scale_, const Vec2& bias_) : scale(scale_), bias(bias_) {}
186 };
187
188 template <> struct
189 TexTypeCoordParams<TEXTURETYPE_CUBE>
190 {
191 Vec2 scale;
192 Vec2 bias;
193 tcu::CubeFace face;
194
TexTypeCoordParamsdeqp::gles3::Functional::__anon936a6fe40111::TexTypeCoordParams195 TexTypeCoordParams (const Vec2& scale_, const Vec2& bias_, tcu::CubeFace face_) : scale(scale_), bias(bias_), face(face_) {}
196 };
197
198 template <> struct
199 TexTypeCoordParams<TEXTURETYPE_2D_ARRAY>
200 {
201 Mat3 transform;
202
TexTypeCoordParamsdeqp::gles3::Functional::__anon936a6fe40111::TexTypeCoordParams203 TexTypeCoordParams (const Mat3& transform_) : transform(transform_) {}
204 };
205
206 template <> struct
207 TexTypeCoordParams<TEXTURETYPE_3D>
208 {
209 Mat3 transform;
210
TexTypeCoordParamsdeqp::gles3::Functional::__anon936a6fe40111::TexTypeCoordParams211 TexTypeCoordParams (const Mat3& transform_) : transform(transform_) {}
212 };
213
214 /*--------------------------------------------------------------------*//*!
215 * \brief Quad grid class containing position and texture coordinate data.
216 *
217 * A quad grid of size S means a grid consisting of S*S quads (S rows and
218 * S columns). The quads are rectangles with main axis aligned sides, and
219 * each consists of two triangles. Note that although there are only
220 * (S+1)*(S+1) distinct vertex positions, there are S*S*4 distinct vertices
221 * because we want texture coordinates to be constant across the vertices
222 * of a quad (to avoid interpolation issues), and thus each quad needs its
223 * own 4 vertices.
224 *
225 * Pointers returned by get*Ptr() are suitable for gl calls such as
226 * glVertexAttribPointer() (for position and tex coord) or glDrawElements()
227 * (for indices).
228 *//*--------------------------------------------------------------------*/
229 template <TextureType TexType>
230 class PosTexCoordQuadGrid
231 {
232 private:
233 enum { TEX_COORD_DIMS = TexTypeCoordDims <TexType>::V };
234 typedef typename TexTypeCoordVec<TexType>::t TexCoordVec;
235 typedef typename TexTypeSizeIVec<TexType>::t TexSizeIVec;
236 typedef TexTypeCoordParams<TexType> TexCoordParams;
237
238 public:
239 PosTexCoordQuadGrid (int gridSize, const IVec2& renderSize, const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords);
240
getSize(void) const241 int getSize (void) const { return m_gridSize; }
242 Vec4 getQuadLDRU (int col, int row) const; //!< Vec4(leftX, downY, rightX, upY)
243 const TexCoordVec& getQuadTexCoord (int col, int row) const;
244
getNumIndices(void) const245 int getNumIndices (void) const { return m_gridSize*m_gridSize*3*2; }
getPositionPtr(void) const246 const float* getPositionPtr (void) const { DE_STATIC_ASSERT(sizeof(Vec2) == 2*sizeof(float)); return (float*)&m_positions[0]; }
getTexCoordPtr(void) const247 const float* getTexCoordPtr (void) const { DE_STATIC_ASSERT(sizeof(TexCoordVec) == TEX_COORD_DIMS*(int)sizeof(float)); return (float*)&m_texCoords[0]; }
getIndexPtr(void) const248 const deUint16* getIndexPtr (void) const { return &m_indices[0]; }
249
250 private:
251 void initializeTexCoords (const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords);
252
253 const int m_gridSize;
254 vector<Vec2> m_positions;
255 vector<TexCoordVec> m_texCoords;
256 vector<deUint16> m_indices;
257 };
258
259 template <TextureType TexType>
getQuadLDRU(int col,int row) const260 Vec4 PosTexCoordQuadGrid<TexType>::getQuadLDRU (int col, int row) const
261 {
262 int ndx00 = (row*m_gridSize + col) * 4;
263 int ndx11 = ndx00 + 3;
264
265 return Vec4(m_positions[ndx00].x(),
266 m_positions[ndx00].y(),
267 m_positions[ndx11].x(),
268 m_positions[ndx11].y());
269 }
270
271 template <TextureType TexType>
getQuadTexCoord(int col,int row) const272 const typename TexTypeCoordVec<TexType>::t& PosTexCoordQuadGrid<TexType>::getQuadTexCoord (int col, int row) const
273 {
274 return m_texCoords[(row*m_gridSize + col) * 4];
275 }
276
277 template <TextureType TexType>
PosTexCoordQuadGrid(int gridSize,const IVec2 & renderSize,const TexSizeIVec & textureSize,const TexCoordParams & texCoordParams,bool useSafeTexCoords)278 PosTexCoordQuadGrid<TexType>::PosTexCoordQuadGrid (int gridSize, const IVec2& renderSize, const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
279 : m_gridSize(gridSize)
280 {
281 DE_ASSERT(m_gridSize > 0 && m_gridSize*m_gridSize <= (int)std::numeric_limits<deUint16>::max() + 1);
282
283 const float gridSizeFloat = (float)m_gridSize;
284
285 m_positions.reserve(m_gridSize*m_gridSize*4);
286 m_indices.reserve(m_gridSize*m_gridSize*3*2);
287
288 for (int y = 0; y < m_gridSize; y++)
289 for (int x = 0; x < m_gridSize; x++)
290 {
291 float fx0 = (float)(x+0) / gridSizeFloat;
292 float fx1 = (float)(x+1) / gridSizeFloat;
293 float fy0 = (float)(y+0) / gridSizeFloat;
294 float fy1 = (float)(y+1) / gridSizeFloat;
295
296 Vec2 quadVertices[4] = { Vec2(fx0, fy0), Vec2(fx1, fy0), Vec2(fx0, fy1), Vec2(fx1, fy1) };
297
298 int firstNdx = (int)m_positions.size();
299
300 for (int i = 0; i < DE_LENGTH_OF_ARRAY(quadVertices); i++)
301 m_positions.push_back(safeCoords(quadVertices[i], renderSize, Vec2(0.0f)) * 2.0f - 1.0f);
302
303 m_indices.push_back(deUint16(firstNdx + 0));
304 m_indices.push_back(deUint16(firstNdx + 1));
305 m_indices.push_back(deUint16(firstNdx + 2));
306
307 m_indices.push_back(deUint16(firstNdx + 1));
308 m_indices.push_back(deUint16(firstNdx + 3));
309 m_indices.push_back(deUint16(firstNdx + 2));
310 }
311
312 m_texCoords.reserve(m_gridSize*m_gridSize*4);
313 initializeTexCoords(textureSize, texCoordParams, useSafeTexCoords);
314
315 DE_ASSERT((int)m_positions.size() == m_gridSize*m_gridSize*4);
316 DE_ASSERT((int)m_indices.size() == m_gridSize*m_gridSize*3*2);
317 DE_ASSERT((int)m_texCoords.size() == m_gridSize*m_gridSize*4);
318 }
319
320 template <>
initializeTexCoords(const IVec2 & textureSize,const TexCoordParams & texCoordParams,bool useSafeTexCoords)321 void PosTexCoordQuadGrid<TEXTURETYPE_2D>::initializeTexCoords (const IVec2& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
322 {
323 DE_ASSERT(m_texCoords.empty());
324
325 const float gridSizeFloat = (float)m_gridSize;
326
327 for (int y = 0; y < m_gridSize; y++)
328 for (int x = 0; x < m_gridSize; x++)
329 {
330 Vec2 rawCoord = Vec2((float)x / gridSizeFloat, (float)y / gridSizeFloat) * texCoordParams.scale + texCoordParams.bias;
331
332 for (int i = 0; i < 4; i++)
333 m_texCoords.push_back(useSafeTexCoords ? safe2DTexCoords(rawCoord, textureSize) : rawCoord);
334 }
335 }
336
337 template <>
initializeTexCoords(const IVec2 & textureSize,const TexCoordParams & texCoordParams,bool useSafeTexCoords)338 void PosTexCoordQuadGrid<TEXTURETYPE_CUBE>::initializeTexCoords (const IVec2& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
339 {
340 DE_ASSERT(m_texCoords.empty());
341
342 const float gridSizeFloat = (float)m_gridSize;
343 vector<float> texBoundaries;
344 computeQuadTexCoordCube(texBoundaries, texCoordParams.face);
345 const Vec3 coordA = Vec3(texBoundaries[0], texBoundaries[1], texBoundaries[2]);
346 const Vec3 coordB = Vec3(texBoundaries[3], texBoundaries[4], texBoundaries[5]);
347 const Vec3 coordC = Vec3(texBoundaries[6], texBoundaries[7], texBoundaries[8]);
348 const Vec3 coordAB = coordB - coordA;
349 const Vec3 coordAC = coordC - coordA;
350
351 for (int y = 0; y < m_gridSize; y++)
352 for (int x = 0; x < m_gridSize; x++)
353 {
354 const Vec2 rawFaceCoord = texCoordParams.scale * Vec2((float)x / gridSizeFloat, (float)y / gridSizeFloat) + texCoordParams.bias;
355 const Vec2 safeFaceCoord = useSafeTexCoords ? safe2DTexCoords(rawFaceCoord, textureSize) : rawFaceCoord;
356 const Vec3 texCoord = coordA + coordAC*safeFaceCoord.x() + coordAB*safeFaceCoord.y();
357
358 for (int i = 0; i < 4; i++)
359 m_texCoords.push_back(texCoord);
360 }
361 }
362
363 template <>
initializeTexCoords(const IVec3 & textureSize,const TexCoordParams & texCoordParams,bool useSafeTexCoords)364 void PosTexCoordQuadGrid<TEXTURETYPE_2D_ARRAY>::initializeTexCoords (const IVec3& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
365 {
366 DE_ASSERT(m_texCoords.empty());
367
368 const float gridSizeFloat = (float)m_gridSize;
369
370 for (int y = 0; y < m_gridSize; y++)
371 for (int x = 0; x < m_gridSize; x++)
372 {
373 const Vec3 rawCoord = texCoordParams.transform * Vec3((float)x / gridSizeFloat, (float)y / gridSizeFloat, 1.0f);
374
375 for (int i = 0; i < 4; i++)
376 m_texCoords.push_back(useSafeTexCoords ? safe2DArrayTexCoords(rawCoord, textureSize) : rawCoord);
377 }
378 }
379
380 template <>
initializeTexCoords(const IVec3 & textureSize,const TexCoordParams & texCoordParams,bool useSafeTexCoords)381 void PosTexCoordQuadGrid<TEXTURETYPE_3D>::initializeTexCoords (const IVec3& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
382 {
383 DE_ASSERT(m_texCoords.empty());
384
385 const float gridSizeFloat = (float)m_gridSize;
386
387 for (int y = 0; y < m_gridSize; y++)
388 for (int x = 0; x < m_gridSize; x++)
389 {
390 Vec3 rawCoord = texCoordParams.transform * Vec3((float)x / gridSizeFloat, (float)y / gridSizeFloat, 1.0f);
391
392 for (int i = 0; i < 4; i++)
393 m_texCoords.push_back(useSafeTexCoords ? safe3DTexCoords(rawCoord, textureSize) : rawCoord);
394 }
395 }
396
397 } // anonymous
398
isLevelNearest(deUint32 filter)399 static inline bool isLevelNearest (deUint32 filter)
400 {
401 return filter == GL_NEAREST || filter == GL_NEAREST_MIPMAP_NEAREST || filter == GL_NEAREST_MIPMAP_LINEAR;
402 }
403
getTextureSize(const glu::Texture2D & tex)404 static inline IVec2 getTextureSize (const glu::Texture2D& tex)
405 {
406 const tcu::Texture2D& ref = tex.getRefTexture();
407 return IVec2(ref.getWidth(), ref.getHeight());
408 }
409
getTextureSize(const glu::TextureCube & tex)410 static inline IVec2 getTextureSize (const glu::TextureCube& tex)
411 {
412 const tcu::TextureCube& ref = tex.getRefTexture();
413 return IVec2(ref.getSize(), ref.getSize());
414 }
415
getTextureSize(const glu::Texture2DArray & tex)416 static inline IVec3 getTextureSize (const glu::Texture2DArray& tex)
417 {
418 const tcu::Texture2DArray& ref = tex.getRefTexture();
419 return IVec3(ref.getWidth(), ref.getHeight(), ref.getNumLayers());
420 }
421
getTextureSize(const glu::Texture3D & tex)422 static inline IVec3 getTextureSize (const glu::Texture3D& tex)
423 {
424 const tcu::Texture3D& ref = tex.getRefTexture();
425 return IVec3(ref.getWidth(), ref.getHeight(), ref.getDepth());
426 }
427
428 template <TextureType TexType>
setPixelColors(const vector<Vec4> & quadColors,const Rect & region,const PosTexCoordQuadGrid<TexType> & grid,tcu::Surface & dst)429 static void setPixelColors (const vector<Vec4>& quadColors, const Rect& region, const PosTexCoordQuadGrid<TexType>& grid, tcu::Surface& dst)
430 {
431 const int gridSize = grid.getSize();
432
433 for (int y = 0; y < gridSize; y++)
434 for (int x = 0; x < gridSize; x++)
435 {
436 const Vec4 color = quadColors[y*gridSize + x];
437 const Vec4 ldru = grid.getQuadLDRU(x, y) * 0.5f + 0.5f; // [-1, 1] -> [0, 1]
438 const int ix0 = deCeilFloatToInt32(ldru.x() * (float)region.w - 0.5f);
439 const int ix1 = deCeilFloatToInt32(ldru.z() * (float)region.w - 0.5f);
440 const int iy0 = deCeilFloatToInt32(ldru.y() * (float)region.h - 0.5f);
441 const int iy1 = deCeilFloatToInt32(ldru.w() * (float)region.h - 0.5f);
442
443 for (int iy = iy0; iy < iy1; iy++)
444 for (int ix = ix0; ix < ix1; ix++)
445 {
446 DE_ASSERT(deInBounds32(ix + region.x, 0, dst.getWidth()));
447 DE_ASSERT(deInBounds32(iy + region.y, 0, dst.getHeight()));
448
449 dst.setPixel(ix + region.x, iy + region.y, tcu::RGBA(color));
450 }
451 }
452 }
453
sample(const tcu::Texture2D & tex,const Vec2 & coord,float lod,const tcu::Sampler & sam)454 static inline Vec4 sample (const tcu::Texture2D& tex, const Vec2& coord, float lod, const tcu::Sampler& sam) { return tex.sample(sam, coord.x(), coord.y(), lod); }
sample(const tcu::TextureCube & tex,const Vec3 & coord,float lod,const tcu::Sampler & sam)455 static inline Vec4 sample (const tcu::TextureCube& tex, const Vec3& coord, float lod, const tcu::Sampler& sam) { return tex.sample(sam, coord.x(), coord.y(), coord.z(), lod); }
sample(const tcu::Texture2DArray & tex,const Vec3 & coord,float lod,const tcu::Sampler & sam)456 static inline Vec4 sample (const tcu::Texture2DArray& tex, const Vec3& coord, float lod, const tcu::Sampler& sam) { return tex.sample(sam, coord.x(), coord.y(), coord.z(), lod); }
sample(const tcu::Texture3D & tex,const Vec3 & coord,float lod,const tcu::Sampler & sam)457 static inline Vec4 sample (const tcu::Texture3D& tex, const Vec3& coord, float lod, const tcu::Sampler& sam) { return tex.sample(sam, coord.x(), coord.y(), coord.z(), lod); }
458
459 template <TextureType TexType>
computeReference(const typename TexTypeTcuClass<TexType>::t & texture,float lod,const tcu::Sampler & sampler,const PosTexCoordQuadGrid<TexType> & grid,tcu::Surface & dst,const Rect & dstRegion)460 void computeReference (const typename TexTypeTcuClass<TexType>::t& texture, float lod, const tcu::Sampler& sampler, const PosTexCoordQuadGrid<TexType>& grid, tcu::Surface& dst, const Rect& dstRegion)
461 {
462 const int gridSize = grid.getSize();
463 vector<Vec4> quadColors (gridSize*gridSize);
464
465 for (int y = 0; y < gridSize; y++)
466 for (int x = 0; x < gridSize; x++)
467 {
468 const int ndx = y*gridSize + x;
469 const typename TexTypeCoordVec<TexType>::t& coord = grid.getQuadTexCoord(x, y);
470
471 quadColors[ndx] = sample(texture, coord, lod, sampler);
472 }
473
474 setPixelColors(quadColors, dstRegion, grid, dst);
475 }
476
compareImages(const glu::RenderContext & renderCtx,tcu::TestLog & log,const tcu::Surface & ref,const tcu::Surface & res)477 static bool compareImages (const glu::RenderContext& renderCtx, tcu::TestLog& log, const tcu::Surface& ref, const tcu::Surface& res)
478 {
479 DE_ASSERT(renderCtx.getRenderTarget().getNumSamples() == 0);
480
481 const tcu::RGBA threshold = renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(15,15,15,15);
482 return tcu::pixelThresholdCompare(log, "Result", "Image compare result", ref, res, threshold, tcu::COMPARE_LOG_RESULT);
483 }
484
485 class Vertex2DTextureCase : public TestCase
486 {
487 public:
488 Vertex2DTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
489 ~Vertex2DTextureCase (void);
490
491 void init (void);
492 void deinit (void);
493 IterateResult iterate (void);
494
495 private:
496 typedef PosTexCoordQuadGrid<TEXTURETYPE_2D> Grid;
497
498 Vertex2DTextureCase (const Vertex2DTextureCase& other);
499 Vertex2DTextureCase& operator= (const Vertex2DTextureCase& other);
500
501 float calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const;
502 void setupShaderInputs (int textureNdx, float lod, const Grid& grid) const;
503 void renderCell (int textureNdx, float lod, const Grid& grid) const;
504 void computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const;
505
506 const deUint32 m_minFilter;
507 const deUint32 m_magFilter;
508 const deUint32 m_wrapS;
509 const deUint32 m_wrapT;
510
511 const glu::ShaderProgram* m_program;
512 glu::Texture2D* m_textures[2]; // 2 textures, a gradient texture and a grid texture.
513 };
514
Vertex2DTextureCase(Context & testCtx,const char * name,const char * desc,deUint32 minFilter,deUint32 magFilter,deUint32 wrapS,deUint32 wrapT)515 Vertex2DTextureCase::Vertex2DTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT)
516 : TestCase (testCtx, tcu::NODETYPE_SELF_VALIDATE, name, desc)
517 , m_minFilter (minFilter)
518 , m_magFilter (magFilter)
519 , m_wrapS (wrapS)
520 , m_wrapT (wrapT)
521 , m_program (DE_NULL)
522 {
523 m_textures[0] = DE_NULL;
524 m_textures[1] = DE_NULL;
525 }
526
~Vertex2DTextureCase(void)527 Vertex2DTextureCase::~Vertex2DTextureCase(void)
528 {
529 Vertex2DTextureCase::deinit();
530 }
531
init(void)532 void Vertex2DTextureCase::init (void)
533 {
534 const char* const vertexShader =
535 "#version 300 es\n"
536 "in highp vec2 a_position;\n"
537 "in highp vec2 a_texCoord;\n"
538 "uniform highp sampler2D u_texture;\n"
539 "uniform highp float u_lod;\n"
540 "out mediump vec4 v_color;\n"
541 "\n"
542 "void main()\n"
543 "{\n"
544 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
545 " v_color = textureLod(u_texture, a_texCoord, u_lod);\n"
546 "}\n";
547
548 const char* const fragmentShader =
549 "#version 300 es\n"
550 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
551 "in mediump vec4 v_color;\n"
552 "\n"
553 "void main()\n"
554 "{\n"
555 " dEQP_FragColor = v_color;\n"
556 "}\n";
557
558 if (m_context.getRenderTarget().getNumSamples() != 0)
559 throw tcu::NotSupportedError("MSAA config not supported by this test");
560
561 DE_ASSERT(!m_program);
562 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShader, fragmentShader));
563
564 if(!m_program->isOk())
565 {
566 m_testCtx.getLog() << *m_program;
567
568 GLint maxVertexTextures;
569 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
570
571 if (maxVertexTextures < 1)
572 throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
573 else
574 TCU_FAIL("Failed to compile shader");
575 }
576
577 // Make the textures.
578 try
579 {
580 // Compute suitable power-of-two sizes (for mipmaps).
581 const int texWidth = 1 << deLog2Ceil32(MAX_2D_RENDER_WIDTH / 2);
582 const int texHeight = 1 << deLog2Ceil32(MAX_2D_RENDER_HEIGHT / 2);
583
584 for (int i = 0; i < 2; i++)
585 {
586 DE_ASSERT(!m_textures[i]);
587 m_textures[i] = new glu::Texture2D(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
588 }
589
590 const bool mipmaps = (deIsPowerOfTwo32(texWidth) && deIsPowerOfTwo32(texHeight));
591 const int numLevels = mipmaps ? deLog2Floor32(de::max(texWidth, texHeight))+1 : 1;
592 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
593 const Vec4 cBias = fmtInfo.valueMin;
594 const Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
595
596 // Fill first with gradient texture.
597 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
598 {
599 const Vec4 gMin = Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
600 const Vec4 gMax = Vec4( 1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias;
601
602 m_textures[0]->getRefTexture().allocLevel(levelNdx);
603 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
604 }
605
606 // Fill second with grid texture.
607 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
608 {
609 const deUint32 step = 0x00ffffff / numLevels;
610 const deUint32 rgb = step*levelNdx;
611 const deUint32 colorA = 0xff000000 | rgb;
612 const deUint32 colorB = 0xff000000 | ~rgb;
613
614 m_textures[1]->getRefTexture().allocLevel(levelNdx);
615 tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
616 }
617
618 // Upload.
619 for (int i = 0; i < 2; i++)
620 m_textures[i]->upload();
621 }
622 catch (const std::exception&)
623 {
624 // Clean up to save memory.
625 Vertex2DTextureCase::deinit();
626 throw;
627 }
628 }
629
deinit(void)630 void Vertex2DTextureCase::deinit (void)
631 {
632 for (int i = 0; i < 2; i++)
633 {
634 delete m_textures[i];
635 m_textures[i] = DE_NULL;
636 }
637
638 delete m_program;
639 m_program = DE_NULL;
640 }
641
calculateLod(const Vec2 & texScale,const Vec2 & dstSize,int textureNdx) const642 float Vertex2DTextureCase::calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const
643 {
644 const tcu::Texture2D& refTexture = m_textures[textureNdx]->getRefTexture();
645 const Vec2 srcSize = Vec2((float)refTexture.getWidth(), (float)refTexture.getHeight());
646 const Vec2 sizeRatio = texScale*srcSize / dstSize;
647
648 // \note In this particular case dv/dx and du/dy are zero, simplifying the expression.
649 return deFloatLog2(de::max(sizeRatio.x(), sizeRatio.y()));
650 }
651
iterate(void)652 Vertex2DTextureCase::IterateResult Vertex2DTextureCase::iterate (void)
653 {
654 const int viewportWidth = deMin32(m_context.getRenderTarget().getWidth(), MAX_2D_RENDER_WIDTH);
655 const int viewportHeight = deMin32(m_context.getRenderTarget().getHeight(), MAX_2D_RENDER_HEIGHT);
656
657 const int viewportXOffsetMax = m_context.getRenderTarget().getWidth() - viewportWidth;
658 const int viewportYOffsetMax = m_context.getRenderTarget().getHeight() - viewportHeight;
659
660 de::Random rnd (deStringHash(getName()));
661
662 const int viewportXOffset = rnd.getInt(0, viewportXOffsetMax);
663 const int viewportYOffset = rnd.getInt(0, viewportYOffsetMax);
664
665 glUseProgram(m_program->getProgram());
666
667 // Divide viewport into 4 cells.
668 const int leftWidth = viewportWidth / 2;
669 const int rightWidth = viewportWidth - leftWidth;
670 const int bottomHeight = viewportHeight / 2;
671 const int topHeight = viewportHeight - bottomHeight;
672
673 // Clear.
674 glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
675 glClear(GL_COLOR_BUFFER_BIT);
676
677 // Texture scaling and offsetting vectors.
678 const Vec2 texMinScale (+1.8f, +1.8f);
679 const Vec2 texMinOffset (-0.3f, -0.2f);
680 const Vec2 texMagScale (+0.3f, +0.3f);
681 const Vec2 texMagOffset (+0.9f, +0.8f);
682
683 // Surface for the reference image.
684 tcu::Surface refImage(viewportWidth, viewportHeight);
685
686 {
687 const struct Render
688 {
689 const Rect region;
690 int textureNdx;
691 const Vec2 texCoordScale;
692 const Vec2 texCoordOffset;
693 Render (const Rect& r, int tN, const Vec2& tS, const Vec2& tO) : region(r), textureNdx(tN), texCoordScale(tS), texCoordOffset(tO) {}
694 } renders[] =
695 {
696 Render(Rect(0, 0, leftWidth, bottomHeight), 0, texMinScale, texMinOffset),
697 Render(Rect(leftWidth, 0, rightWidth, bottomHeight), 0, texMagScale, texMagOffset),
698 Render(Rect(0, bottomHeight, leftWidth, topHeight), 1, texMinScale, texMinOffset),
699 Render(Rect(leftWidth, bottomHeight, rightWidth, topHeight), 1, texMagScale, texMagOffset)
700 };
701
702 for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
703 {
704 const Render& rend = renders[renderNdx];
705 const float lod = calculateLod(rend.texCoordScale, rend.region.size().asFloat(), rend.textureNdx);
706 const bool useSafeTexCoords = isLevelNearest(lod > 0.0f ? m_minFilter : m_magFilter);
707 const Grid grid (GRID_SIZE_2D, rend.region.size(), getTextureSize(*m_textures[rend.textureNdx]),
708 TexTypeCoordParams<TEXTURETYPE_2D>(rend.texCoordScale, rend.texCoordOffset), useSafeTexCoords);
709
710 glViewport(viewportXOffset + rend.region.x, viewportYOffset + rend.region.y, rend.region.w, rend.region.h);
711 renderCell (rend.textureNdx, lod, grid);
712 computeReferenceCell (rend.textureNdx, lod, grid, refImage, rend.region);
713 }
714 }
715
716 // Read back rendered results.
717 tcu::Surface resImage(viewportWidth, viewportHeight);
718 glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
719
720 glUseProgram(0);
721
722 // Compare and log.
723 {
724 const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
725
726 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
727 isOk ? "Pass" : "Image comparison failed");
728 }
729
730 return STOP;
731 }
732
setupShaderInputs(int textureNdx,float lod,const Grid & grid) const733 void Vertex2DTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
734 {
735 const deUint32 programID = m_program->getProgram();
736
737 // SETUP ATTRIBUTES.
738
739 {
740 const int positionLoc = glGetAttribLocation(programID, "a_position");
741 if (positionLoc != -1)
742 {
743 glEnableVertexAttribArray(positionLoc);
744 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
745 }
746 }
747
748 {
749 const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
750 if (texCoordLoc != -1)
751 {
752 glEnableVertexAttribArray(texCoordLoc);
753 glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
754 }
755 }
756
757 // SETUP UNIFORMS.
758
759 {
760 const int lodLoc = glGetUniformLocation(programID, "u_lod");
761 if (lodLoc != -1)
762 glUniform1f(lodLoc, lod);
763 }
764
765 glActiveTexture(GL_TEXTURE0);
766 glBindTexture(GL_TEXTURE_2D, m_textures[textureNdx]->getGLTexture());
767 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS);
768 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT);
769 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter);
770 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_magFilter);
771
772 {
773 const int texLoc = glGetUniformLocation(programID, "u_texture");
774 if (texLoc != -1)
775 glUniform1i(texLoc, 0);
776 }
777 }
778
779 // Renders one sub-image with given parameters.
renderCell(int textureNdx,float lod,const Grid & grid) const780 void Vertex2DTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
781 {
782 setupShaderInputs(textureNdx, lod, grid);
783 glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
784 }
785
computeReferenceCell(int textureNdx,float lod,const Grid & grid,tcu::Surface & dst,const Rect & dstRegion) const786 void Vertex2DTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
787 {
788 computeReference(m_textures[textureNdx]->getRefTexture(), lod, glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter), grid, dst, dstRegion);
789 }
790
791 class VertexCubeTextureCase : public TestCase
792 {
793 public:
794 VertexCubeTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
795 ~VertexCubeTextureCase (void);
796
797 void init (void);
798 void deinit (void);
799 IterateResult iterate (void);
800
801 private:
802 typedef PosTexCoordQuadGrid<TEXTURETYPE_CUBE> Grid;
803
804 VertexCubeTextureCase (const VertexCubeTextureCase& other);
805 VertexCubeTextureCase& operator= (const VertexCubeTextureCase& other);
806
807 float calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const;
808 void setupShaderInputs (int textureNdx, float lod, const Grid& grid) const;
809 void renderCell (int textureNdx, float lod, const Grid& grid) const;
810 void computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const;
811
812 const deUint32 m_minFilter;
813 const deUint32 m_magFilter;
814 const deUint32 m_wrapS;
815 const deUint32 m_wrapT;
816
817 const glu::ShaderProgram* m_program;
818 glu::TextureCube* m_textures[2]; // 2 textures, a gradient texture and a grid texture.
819 };
820
VertexCubeTextureCase(Context & testCtx,const char * name,const char * desc,deUint32 minFilter,deUint32 magFilter,deUint32 wrapS,deUint32 wrapT)821 VertexCubeTextureCase::VertexCubeTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT)
822 : TestCase (testCtx, tcu::NODETYPE_SELF_VALIDATE, name, desc)
823 , m_minFilter (minFilter)
824 , m_magFilter (magFilter)
825 , m_wrapS (wrapS)
826 , m_wrapT (wrapT)
827 , m_program (DE_NULL)
828 {
829 m_textures[0] = DE_NULL;
830 m_textures[1] = DE_NULL;
831 }
832
~VertexCubeTextureCase(void)833 VertexCubeTextureCase::~VertexCubeTextureCase(void)
834 {
835 VertexCubeTextureCase::deinit();
836 }
837
init(void)838 void VertexCubeTextureCase::init (void)
839 {
840 const char* const vertexShader =
841 "#version 300 es\n"
842 "in highp vec2 a_position;\n"
843 "in highp vec3 a_texCoord;\n"
844 "uniform highp samplerCube u_texture;\n"
845 "uniform highp float u_lod;\n"
846 "out mediump vec4 v_color;\n"
847 "\n"
848 "void main()\n"
849 "{\n"
850 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
851 " v_color = textureLod(u_texture, a_texCoord, u_lod);\n"
852 "}\n";
853
854 const char* const fragmentShader =
855 "#version 300 es\n"
856 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
857 "in mediump vec4 v_color;\n"
858 "\n"
859 "void main()\n"
860 "{\n"
861 " dEQP_FragColor = v_color;\n"
862 "}\n";
863
864 if (m_context.getRenderTarget().getNumSamples() != 0)
865 throw tcu::NotSupportedError("MSAA config not supported by this test");
866
867 DE_ASSERT(!m_program);
868 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShader, fragmentShader));
869
870 if(!m_program->isOk())
871 {
872 m_testCtx.getLog() << *m_program;
873
874 GLint maxVertexTextures;
875 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
876
877 if (maxVertexTextures < 1)
878 throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
879 else
880 TCU_FAIL("Failed to compile shader");
881 }
882
883 // Make the textures.
884 try
885 {
886 // Compute suitable power-of-two sizes (for mipmaps).
887 const int texWidth = 1 << deLog2Ceil32(MAX_CUBE_RENDER_WIDTH / 3 / 2);
888 const int texHeight = 1 << deLog2Ceil32(MAX_CUBE_RENDER_HEIGHT / 2 / 2);
889
890 DE_ASSERT(texWidth == texHeight);
891 DE_UNREF(texHeight);
892
893 for (int i = 0; i < 2; i++)
894 {
895 DE_ASSERT(!m_textures[i]);
896 m_textures[i] = new glu::TextureCube(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth);
897 }
898
899 const bool mipmaps = deIsPowerOfTwo32(texWidth) != DE_FALSE;
900 const int numLevels = mipmaps ? deLog2Floor32(texWidth)+1 : 1;
901 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
902 const Vec4 cBias = fmtInfo.valueMin;
903 const Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
904
905 // Fill first with gradient texture.
906 static const Vec4 gradients[tcu::CUBEFACE_LAST][2] =
907 {
908 { Vec4(-1.0f, -1.0f, -1.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
909 { Vec4( 0.0f, -1.0f, -1.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
910 { Vec4(-1.0f, 0.0f, -1.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
911 { Vec4(-1.0f, -1.0f, 0.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
912 { Vec4(-1.0f, -1.0f, -1.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
913 { Vec4( 0.0f, 0.0f, 0.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) } // positive z
914 };
915 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
916 {
917 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
918 {
919 m_textures[0]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
920 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias);
921 }
922 }
923
924 // Fill second with grid texture.
925 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
926 {
927 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
928 {
929 const deUint32 step = 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
930 const deUint32 rgb = step*levelNdx*face;
931 const deUint32 colorA = 0xff000000 | rgb;
932 const deUint32 colorB = 0xff000000 | ~rgb;
933
934 m_textures[1]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
935 tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
936 }
937 }
938
939 // Upload.
940 for (int i = 0; i < 2; i++)
941 m_textures[i]->upload();
942 }
943 catch (const std::exception&)
944 {
945 // Clean up to save memory.
946 VertexCubeTextureCase::deinit();
947 throw;
948 }
949 }
950
deinit(void)951 void VertexCubeTextureCase::deinit (void)
952 {
953 for (int i = 0; i < 2; i++)
954 {
955 delete m_textures[i];
956 m_textures[i] = DE_NULL;
957 }
958
959 delete m_program;
960 m_program = DE_NULL;
961 }
962
calculateLod(const Vec2 & texScale,const Vec2 & dstSize,int textureNdx) const963 float VertexCubeTextureCase::calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const
964 {
965 const tcu::TextureCube& refTexture = m_textures[textureNdx]->getRefTexture();
966 const Vec2 srcSize = Vec2((float)refTexture.getSize(), (float)refTexture.getSize());
967 const Vec2 sizeRatio = texScale*srcSize / dstSize;
968
969 // \note In this particular case, dv/dx and du/dy are zero, simplifying the expression.
970 return deFloatLog2(de::max(sizeRatio.x(), sizeRatio.y()));
971 }
972
iterate(void)973 VertexCubeTextureCase::IterateResult VertexCubeTextureCase::iterate (void)
974 {
975 const int viewportWidth = deMin32(m_context.getRenderTarget().getWidth(), MAX_CUBE_RENDER_WIDTH);
976 const int viewportHeight = deMin32(m_context.getRenderTarget().getHeight(), MAX_CUBE_RENDER_HEIGHT);
977
978 const int viewportXOffsetMax = m_context.getRenderTarget().getWidth() - viewportWidth;
979 const int viewportYOffsetMax = m_context.getRenderTarget().getHeight() - viewportHeight;
980
981 de::Random rnd (deStringHash(getName()));
982
983 const int viewportXOffset = rnd.getInt(0, viewportXOffsetMax);
984 const int viewportYOffset = rnd.getInt(0, viewportYOffsetMax);
985
986 glUseProgram(m_program->getProgram());
987
988 // Divide viewport into 4 areas.
989 const int leftWidth = viewportWidth / 2;
990 const int rightWidth = viewportWidth - leftWidth;
991 const int bottomHeight = viewportHeight / 2;
992 const int topHeight = viewportHeight - bottomHeight;
993
994 // Clear.
995 glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
996 glClear(GL_COLOR_BUFFER_BIT);
997
998 // Texture scaling and offsetting vectors.
999 const Vec2 texMinScale (1.0f, 1.0f);
1000 const Vec2 texMinOffset (0.0f, 0.0f);
1001 const Vec2 texMagScale (0.3f, 0.3f);
1002 const Vec2 texMagOffset (0.5f, 0.3f);
1003
1004 // Surface for the reference image.
1005 tcu::Surface refImage(viewportWidth, viewportHeight);
1006
1007 // Each of the four areas is divided into 6 cells.
1008 const int defCellWidth = viewportWidth / 2 / 3;
1009 const int defCellHeight = viewportHeight / 2 / 2;
1010
1011 for (int i = 0; i < tcu::CUBEFACE_LAST; i++)
1012 {
1013 const int cellOffsetX = defCellWidth * (i % 3);
1014 const int cellOffsetY = defCellHeight * (i / 3);
1015 const bool isRightmostCell = i == 2 || i == 5;
1016 const bool isTopCell = i >= 3;
1017 const int leftCellWidth = isRightmostCell ? leftWidth - cellOffsetX : defCellWidth;
1018 const int rightCellWidth = isRightmostCell ? rightWidth - cellOffsetX : defCellWidth;
1019 const int bottomCellHeight = isTopCell ? bottomHeight - cellOffsetY : defCellHeight;
1020 const int topCellHeight = isTopCell ? topHeight - cellOffsetY : defCellHeight;
1021
1022 const struct Render
1023 {
1024 const Rect region;
1025 int textureNdx;
1026 const Vec2 texCoordScale;
1027 const Vec2 texCoordOffset;
1028 Render (const Rect& r, int tN, const Vec2& tS, const Vec2& tO) : region(r), textureNdx(tN), texCoordScale(tS), texCoordOffset(tO) {}
1029 } renders[] =
1030 {
1031 Render(Rect(cellOffsetX + 0, cellOffsetY + 0, leftCellWidth, bottomCellHeight), 0, texMinScale, texMinOffset),
1032 Render(Rect(cellOffsetX + leftWidth, cellOffsetY + 0, rightCellWidth, bottomCellHeight), 0, texMagScale, texMagOffset),
1033 Render(Rect(cellOffsetX + 0, cellOffsetY + bottomHeight, leftCellWidth, topCellHeight), 1, texMinScale, texMinOffset),
1034 Render(Rect(cellOffsetX + leftWidth, cellOffsetY + bottomHeight, rightCellWidth, topCellHeight), 1, texMagScale, texMagOffset)
1035 };
1036
1037 for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
1038 {
1039 const Render& rend = renders[renderNdx];
1040 const float lod = calculateLod(rend.texCoordScale, rend.region.size().asFloat(), rend.textureNdx);
1041 const bool useSafeTexCoords = isLevelNearest(lod > 0.0f ? m_minFilter : m_magFilter);
1042 const Grid grid (GRID_SIZE_CUBE, rend.region.size(), getTextureSize(*m_textures[rend.textureNdx]),
1043 TexTypeCoordParams<TEXTURETYPE_CUBE>(rend.texCoordScale, rend.texCoordOffset, (tcu::CubeFace)i), useSafeTexCoords);
1044
1045 glViewport(viewportXOffset + rend.region.x, viewportYOffset + rend.region.y, rend.region.w, rend.region.h);
1046 renderCell (rend.textureNdx, lod, grid);
1047 computeReferenceCell (rend.textureNdx, lod, grid, refImage, rend.region);
1048 }
1049 }
1050
1051 // Read back rendered results.
1052 tcu::Surface resImage(viewportWidth, viewportHeight);
1053 glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
1054
1055 glUseProgram(0);
1056
1057 // Compare and log.
1058 {
1059 const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
1060
1061 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1062 isOk ? "Pass" : "Image comparison failed");
1063 }
1064
1065 return STOP;
1066 }
1067
setupShaderInputs(int textureNdx,float lod,const Grid & grid) const1068 void VertexCubeTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
1069 {
1070 const deUint32 programID = m_program->getProgram();
1071
1072 // SETUP ATTRIBUTES.
1073
1074 {
1075 const int positionLoc = glGetAttribLocation(programID, "a_position");
1076 if (positionLoc != -1)
1077 {
1078 glEnableVertexAttribArray(positionLoc);
1079 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
1080 }
1081 }
1082
1083 {
1084 const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
1085 if (texCoordLoc != -1)
1086 {
1087 glEnableVertexAttribArray(texCoordLoc);
1088 glVertexAttribPointer(texCoordLoc, 3, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
1089 }
1090 }
1091
1092 // SETUP UNIFORMS.
1093
1094 {
1095 const int lodLoc = glGetUniformLocation(programID, "u_lod");
1096 if (lodLoc != -1)
1097 glUniform1f(lodLoc, lod);
1098 }
1099
1100 glActiveTexture(GL_TEXTURE0);
1101 glBindTexture(GL_TEXTURE_CUBE_MAP, m_textures[textureNdx]->getGLTexture());
1102 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS);
1103 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT);
1104 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter);
1105 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, m_magFilter);
1106
1107 {
1108 const int texLoc = glGetUniformLocation(programID, "u_texture");
1109 if (texLoc != -1)
1110 glUniform1i(texLoc, 0);
1111 }
1112 }
1113
1114 // Renders one cube face with given parameters.
renderCell(int textureNdx,float lod,const Grid & grid) const1115 void VertexCubeTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
1116 {
1117 setupShaderInputs(textureNdx, lod, grid);
1118 glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
1119 }
1120
1121 // Computes reference for one cube face with given parameters.
computeReferenceCell(int textureNdx,float lod,const Grid & grid,tcu::Surface & dst,const Rect & dstRegion) const1122 void VertexCubeTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
1123 {
1124 tcu::Sampler sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter);
1125 sampler.seamlessCubeMap = true;
1126 computeReference(m_textures[textureNdx]->getRefTexture(), lod, sampler, grid, dst, dstRegion);
1127 }
1128
1129 class Vertex2DArrayTextureCase : public TestCase
1130 {
1131 public:
1132 Vertex2DArrayTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
1133 ~Vertex2DArrayTextureCase (void);
1134
1135 void init (void);
1136 void deinit (void);
1137 IterateResult iterate (void);
1138
1139 private:
1140 typedef PosTexCoordQuadGrid<TEXTURETYPE_2D_ARRAY> Grid;
1141
1142 Vertex2DArrayTextureCase (const Vertex2DArrayTextureCase& other);
1143 Vertex2DArrayTextureCase& operator= (const Vertex2DArrayTextureCase& other);
1144
1145 float calculateLod (const Mat3& transf, const Vec2& dstSize, int textureNdx) const;
1146 void setupShaderInputs (int textureNdx, float lod, const Grid& grid) const;
1147 void renderCell (int textureNdx, float lod, const Grid& grid) const;
1148 void computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const;
1149
1150 const deUint32 m_minFilter;
1151 const deUint32 m_magFilter;
1152 const deUint32 m_wrapS;
1153 const deUint32 m_wrapT;
1154
1155 const glu::ShaderProgram* m_program;
1156 glu::Texture2DArray* m_textures[2]; // 2 textures, a gradient texture and a grid texture.
1157 };
1158
Vertex2DArrayTextureCase(Context & testCtx,const char * name,const char * desc,deUint32 minFilter,deUint32 magFilter,deUint32 wrapS,deUint32 wrapT)1159 Vertex2DArrayTextureCase::Vertex2DArrayTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT)
1160 : TestCase (testCtx, tcu::NODETYPE_SELF_VALIDATE, name, desc)
1161 , m_minFilter (minFilter)
1162 , m_magFilter (magFilter)
1163 , m_wrapS (wrapS)
1164 , m_wrapT (wrapT)
1165 , m_program (DE_NULL)
1166 {
1167 m_textures[0] = DE_NULL;
1168 m_textures[1] = DE_NULL;
1169 }
1170
~Vertex2DArrayTextureCase(void)1171 Vertex2DArrayTextureCase::~Vertex2DArrayTextureCase(void)
1172 {
1173 Vertex2DArrayTextureCase::deinit();
1174 }
1175
init(void)1176 void Vertex2DArrayTextureCase::init (void)
1177 {
1178 const char* const vertexShaderSource =
1179 "#version 300 es\n"
1180 "in highp vec2 a_position;\n"
1181 "in highp vec3 a_texCoord;\n"
1182 "uniform highp sampler2DArray u_texture;\n"
1183 "uniform highp float u_lod;\n"
1184 "out mediump vec4 v_color;\n"
1185 "\n"
1186 "void main()\n"
1187 "{\n"
1188 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
1189 " v_color = textureLod(u_texture, a_texCoord, u_lod);\n"
1190 "}\n";
1191
1192 const char* const fragmentShaderSource =
1193 "#version 300 es\n"
1194 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
1195 "in mediump vec4 v_color;\n"
1196 "\n"
1197 "void main()\n"
1198 "{\n"
1199 " dEQP_FragColor = v_color;\n"
1200 "}\n";
1201
1202 if (m_context.getRenderTarget().getNumSamples() != 0)
1203 throw tcu::NotSupportedError("MSAA config not supported by this test");
1204
1205 // Create shader.
1206
1207 DE_ASSERT(!m_program);
1208 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
1209
1210 if(!m_program->isOk())
1211 {
1212 m_testCtx.getLog() << *m_program;
1213
1214 GLint maxVertexTextures;
1215 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
1216
1217 if (maxVertexTextures < 1)
1218 throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
1219 else
1220 TCU_FAIL("Failed to compile shader");
1221 }
1222
1223 // Make the textures.
1224
1225 try
1226 {
1227 const int texWidth = WIDTH_2D_ARRAY;
1228 const int texHeight = HEIGHT_2D_ARRAY;
1229 const int texLayers = LAYERS_2D_ARRAY;
1230
1231 for (int i = 0; i < 2; i++)
1232 {
1233 DE_ASSERT(!m_textures[i]);
1234 m_textures[i] = new glu::Texture2DArray(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight, texLayers);
1235 }
1236
1237 const int numLevels = deLog2Floor32(de::max(texWidth, texHeight)) + 1;
1238 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
1239 const Vec4 cBias = fmtInfo.valueMin;
1240 const Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
1241
1242 // Fill first with gradient texture.
1243 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1244 {
1245 const Vec4 gMin = Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
1246 const Vec4 gMax = Vec4( 1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias;
1247
1248 m_textures[0]->getRefTexture().allocLevel(levelNdx);
1249 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
1250 }
1251
1252 // Fill second with grid texture.
1253 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1254 {
1255 const deUint32 step = 0x00ffffff / numLevels;
1256 const deUint32 rgb = step*levelNdx;
1257 const deUint32 colorA = 0xff000000 | rgb;
1258 const deUint32 colorB = 0xff000000 | ~rgb;
1259
1260 m_textures[1]->getRefTexture().allocLevel(levelNdx);
1261 tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
1262 }
1263
1264 // Upload.
1265 for (int i = 0; i < 2; i++)
1266 m_textures[i]->upload();
1267 }
1268 catch (const std::exception&)
1269 {
1270 // Clean up to save memory.
1271 Vertex2DArrayTextureCase::deinit();
1272 throw;
1273 }
1274 }
1275
deinit(void)1276 void Vertex2DArrayTextureCase::deinit (void)
1277 {
1278 for (int i = 0; i < 2; i++)
1279 {
1280 delete m_textures[i];
1281 m_textures[i] = DE_NULL;
1282 }
1283
1284 delete m_program;
1285 m_program = DE_NULL;
1286 }
1287
calculateLod(const Mat3 & transf,const Vec2 & dstSize,int textureNdx) const1288 float Vertex2DArrayTextureCase::calculateLod (const Mat3& transf, const Vec2& dstSize, int textureNdx) const
1289 {
1290 const tcu::Texture2DArray& refTexture = m_textures[textureNdx]->getRefTexture();
1291 const int texWidth = refTexture.getWidth();
1292 const int texHeight = refTexture.getHeight();
1293
1294 // Calculate transformed coordinates of three screen corners.
1295 const Vec2 trans00 = (transf * Vec3(0.0f, 0.0f, 1.0f)).xy();
1296 const Vec2 trans01 = (transf * Vec3(0.0f, 1.0f, 1.0f)).xy();
1297 const Vec2 trans10 = (transf * Vec3(1.0f, 0.0f, 1.0f)).xy();
1298
1299 // Derivates.
1300 const float dudx = (trans10.x() - trans00.x()) * (float)texWidth / dstSize.x();
1301 const float dudy = (trans01.x() - trans00.x()) * (float)texWidth / dstSize.y();
1302 const float dvdx = (trans10.y() - trans00.y()) * (float)texHeight / dstSize.x();
1303 const float dvdy = (trans01.y() - trans00.y()) * (float)texHeight / dstSize.y();
1304
1305 return deFloatLog2(deFloatSqrt(de::max(dudx*dudx + dvdx*dvdx, dudy*dudy + dvdy*dvdy)));
1306 }
1307
iterate(void)1308 Vertex2DArrayTextureCase::IterateResult Vertex2DArrayTextureCase::iterate (void)
1309 {
1310 const int viewportWidth = deMin32(m_context.getRenderTarget().getWidth(), MAX_2D_ARRAY_RENDER_WIDTH);
1311 const int viewportHeight = deMin32(m_context.getRenderTarget().getHeight(), MAX_2D_ARRAY_RENDER_HEIGHT);
1312
1313 const int viewportXOffsetMax = m_context.getRenderTarget().getWidth() - viewportWidth;
1314 const int viewportYOffsetMax = m_context.getRenderTarget().getHeight() - viewportHeight;
1315
1316 de::Random rnd (deStringHash(getName()));
1317
1318 const int viewportXOffset = rnd.getInt(0, viewportXOffsetMax);
1319 const int viewportYOffset = rnd.getInt(0, viewportYOffsetMax);
1320
1321 glUseProgram(m_program->getProgram());
1322
1323 // Divide viewport into 4 cells.
1324 const int leftWidth = viewportWidth / 2;
1325 const int rightWidth = viewportWidth - leftWidth;
1326 const int bottomHeight = viewportHeight / 2;
1327 const int topHeight = viewportHeight - bottomHeight;
1328
1329 // Clear.
1330 glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
1331 glClear(GL_COLOR_BUFFER_BIT);
1332
1333 // Shear by layer count to get all layers visible.
1334 static const float layerShearTransfData[] =
1335 {
1336 1.0f, 0.0f, 0.0f,
1337 0.0f, 1.0f, 0.0f,
1338 (float)LAYERS_2D_ARRAY, 0.0f, 0.0f
1339 };
1340
1341 // Minification and magnification transformations.
1342 static const float texMinTransfData[] =
1343 {
1344 2.1f, 0.0f, -0.3f,
1345 0.0f, 2.1f, -0.3f,
1346 0.0f, 0.0f, 1.0f
1347 };
1348 static const float texMagTransfData[] =
1349 {
1350 0.4f, 0.0f, 0.8f,
1351 0.0f, 0.4f, 0.8f,
1352 0.0f, 0.0f, 1.0f
1353 };
1354
1355 // Transformation matrices for minification and magnification.
1356 const Mat3 texMinTransf = Mat3(layerShearTransfData) * Mat3(texMinTransfData);
1357 const Mat3 texMagTransf = Mat3(layerShearTransfData) * Mat3(texMagTransfData);
1358
1359 // Surface for the reference image.
1360 tcu::Surface refImage(viewportWidth, viewportHeight);
1361
1362 {
1363 const struct Render
1364 {
1365 const Rect region;
1366 int textureNdx;
1367 const Mat3 texTransform;
1368 Render (const Rect& r, int tN, const Mat3& tT) : region(r), textureNdx(tN), texTransform(tT) {}
1369 } renders[] =
1370 {
1371 Render(Rect(0, 0, leftWidth, bottomHeight), 0, texMinTransf),
1372 Render(Rect(leftWidth, 0, rightWidth, bottomHeight), 0, texMagTransf),
1373 Render(Rect(0, bottomHeight, leftWidth, topHeight), 1, texMinTransf),
1374 Render(Rect(leftWidth, bottomHeight, rightWidth, topHeight), 1, texMagTransf)
1375 };
1376
1377 for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
1378 {
1379 const Render& rend = renders[renderNdx];
1380 const float lod = calculateLod(rend.texTransform, rend.region.size().asFloat(), rend.textureNdx);
1381 const bool useSafeTexCoords = isLevelNearest(lod > 0.0f ? m_minFilter : m_magFilter);
1382 const Grid grid (GRID_SIZE_2D_ARRAY, rend.region.size(), getTextureSize(*m_textures[rend.textureNdx]),
1383 TexTypeCoordParams<TEXTURETYPE_2D_ARRAY>(rend.texTransform), useSafeTexCoords);
1384
1385 glViewport(viewportXOffset + rend.region.x, viewportYOffset + rend.region.y, rend.region.w, rend.region.h);
1386 renderCell (rend.textureNdx, lod, grid);
1387 computeReferenceCell (rend.textureNdx, lod, grid, refImage, rend.region);
1388 }
1389 }
1390
1391 // Read back rendered results.
1392 tcu::Surface resImage(viewportWidth, viewportHeight);
1393 glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
1394
1395 glUseProgram(0);
1396
1397 // Compare and log.
1398 {
1399 const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
1400
1401 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1402 isOk ? "Pass" : "Image comparison failed");
1403 }
1404
1405 return STOP;
1406 }
1407
setupShaderInputs(int textureNdx,float lod,const Grid & grid) const1408 void Vertex2DArrayTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
1409 {
1410 const deUint32 programID = m_program->getProgram();
1411
1412 // SETUP ATTRIBUTES.
1413
1414 {
1415 const int positionLoc = glGetAttribLocation(programID, "a_position");
1416 if (positionLoc != -1)
1417 {
1418 glEnableVertexAttribArray(positionLoc);
1419 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
1420 }
1421 }
1422
1423 {
1424 const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
1425 if (texCoordLoc != -1)
1426 {
1427 glEnableVertexAttribArray(texCoordLoc);
1428 glVertexAttribPointer(texCoordLoc, 3, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
1429 }
1430 }
1431
1432 // SETUP UNIFORMS.
1433
1434 {
1435 const int lodLoc = glGetUniformLocation(programID, "u_lod");
1436 if (lodLoc != -1)
1437 glUniform1f(lodLoc, lod);
1438 }
1439
1440 glActiveTexture(GL_TEXTURE0);
1441 glBindTexture(GL_TEXTURE_2D_ARRAY, m_textures[textureNdx]->getGLTexture());
1442 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, m_wrapS);
1443 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, m_wrapT);
1444 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, m_minFilter);
1445 glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, m_magFilter);
1446
1447 {
1448 const int texLoc = glGetUniformLocation(programID, "u_texture");
1449 if (texLoc != -1)
1450 glUniform1i(texLoc, 0);
1451 }
1452 }
1453
1454 // Renders one sub-image with given parameters.
renderCell(int textureNdx,float lod,const Grid & grid) const1455 void Vertex2DArrayTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
1456 {
1457 setupShaderInputs(textureNdx, lod, grid);
1458 glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
1459 }
1460
1461 // Computes reference for one sub-image with given parameters.
computeReferenceCell(int textureNdx,float lod,const Grid & grid,tcu::Surface & dst,const Rect & dstRegion) const1462 void Vertex2DArrayTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
1463 {
1464 computeReference(m_textures[textureNdx]->getRefTexture(), lod, glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter), grid, dst, dstRegion);
1465 }
1466
1467 class Vertex3DTextureCase : public TestCase
1468 {
1469 public:
1470 Vertex3DTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 wrapR);
1471 ~Vertex3DTextureCase (void);
1472
1473 void init (void);
1474 void deinit (void);
1475 IterateResult iterate (void);
1476
1477 private:
1478 typedef PosTexCoordQuadGrid<TEXTURETYPE_3D> Grid;
1479
1480 Vertex3DTextureCase (const Vertex3DTextureCase& other);
1481 Vertex3DTextureCase& operator= (const Vertex3DTextureCase& other);
1482
1483 float calculateLod (const Mat3& transf, const Vec2& dstSize, int textureNdx) const;
1484 void setupShaderInputs (int textureNdx, float lod, const Grid& grid) const;
1485 void renderCell (int textureNdx, float lod, const Grid& grid) const;
1486 void computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const;
1487
1488 const deUint32 m_minFilter;
1489 const deUint32 m_magFilter;
1490 const deUint32 m_wrapS;
1491 const deUint32 m_wrapT;
1492 const deUint32 m_wrapR;
1493
1494 const glu::ShaderProgram* m_program;
1495 glu::Texture3D* m_textures[2]; // 2 textures, a gradient texture and a grid texture.
1496 };
1497
Vertex3DTextureCase(Context & testCtx,const char * name,const char * desc,deUint32 minFilter,deUint32 magFilter,deUint32 wrapS,deUint32 wrapT,deUint32 wrapR)1498 Vertex3DTextureCase::Vertex3DTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 wrapR)
1499 : TestCase (testCtx, tcu::NODETYPE_SELF_VALIDATE, name, desc)
1500 , m_minFilter (minFilter)
1501 , m_magFilter (magFilter)
1502 , m_wrapS (wrapS)
1503 , m_wrapT (wrapT)
1504 , m_wrapR (wrapR)
1505 , m_program (DE_NULL)
1506 {
1507 m_textures[0] = DE_NULL;
1508 m_textures[1] = DE_NULL;
1509 }
1510
~Vertex3DTextureCase(void)1511 Vertex3DTextureCase::~Vertex3DTextureCase(void)
1512 {
1513 Vertex3DTextureCase::deinit();
1514 }
1515
init(void)1516 void Vertex3DTextureCase::init (void)
1517 {
1518 const char* const vertexShaderSource =
1519 "#version 300 es\n"
1520 "in highp vec2 a_position;\n"
1521 "in highp vec3 a_texCoord;\n"
1522 "uniform highp sampler3D u_texture;\n"
1523 "uniform highp float u_lod;\n"
1524 "out mediump vec4 v_color;\n"
1525 "\n"
1526 "void main()\n"
1527 "{\n"
1528 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
1529 " v_color = textureLod(u_texture, a_texCoord, u_lod);\n"
1530 "}\n";
1531
1532 const char* const fragmentShaderSource =
1533 "#version 300 es\n"
1534 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
1535 "in mediump vec4 v_color;\n"
1536 "\n"
1537 "void main()\n"
1538 "{\n"
1539 " dEQP_FragColor = v_color;\n"
1540 "}\n";
1541
1542 if (m_context.getRenderTarget().getNumSamples() != 0)
1543 throw tcu::NotSupportedError("MSAA config not supported by this test");
1544
1545 // Create shader.
1546
1547 DE_ASSERT(!m_program);
1548 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
1549
1550 if(!m_program->isOk())
1551 {
1552 m_testCtx.getLog() << *m_program;
1553
1554 GLint maxVertexTextures;
1555 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
1556
1557 if (maxVertexTextures < 1)
1558 throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
1559 else
1560 TCU_FAIL("Failed to compile shader");
1561 }
1562
1563 // Make the textures.
1564
1565 try
1566 {
1567 const int texWidth = WIDTH_3D;
1568 const int texHeight = HEIGHT_3D;
1569 const int texDepth = DEPTH_3D;
1570
1571 for (int i = 0; i < 2; i++)
1572 {
1573 DE_ASSERT(!m_textures[i]);
1574 m_textures[i] = new glu::Texture3D(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight, texDepth);
1575 }
1576
1577 const int numLevels = deLog2Floor32(de::max(de::max(texWidth, texHeight), texDepth)) + 1;
1578 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
1579 const Vec4 cBias = fmtInfo.valueMin;
1580 const Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
1581
1582 // Fill first with gradient texture.
1583 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1584 {
1585 const Vec4 gMin = Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
1586 const Vec4 gMax = Vec4( 1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias;
1587
1588 m_textures[0]->getRefTexture().allocLevel(levelNdx);
1589 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
1590 }
1591
1592 // Fill second with grid texture.
1593 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1594 {
1595 const deUint32 step = 0x00ffffff / numLevels;
1596 const deUint32 rgb = step*levelNdx;
1597 const deUint32 colorA = 0xff000000 | rgb;
1598 const deUint32 colorB = 0xff000000 | ~rgb;
1599
1600 m_textures[1]->getRefTexture().allocLevel(levelNdx);
1601 tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
1602 }
1603
1604 // Upload.
1605 for (int i = 0; i < 2; i++)
1606 m_textures[i]->upload();
1607 }
1608 catch (const std::exception&)
1609 {
1610 // Clean up to save memory.
1611 Vertex3DTextureCase::deinit();
1612 throw;
1613 }
1614 }
1615
deinit(void)1616 void Vertex3DTextureCase::deinit (void)
1617 {
1618 for (int i = 0; i < 2; i++)
1619 {
1620 delete m_textures[i];
1621 m_textures[i] = DE_NULL;
1622 }
1623
1624 delete m_program;
1625 m_program = DE_NULL;
1626 }
1627
calculateLod(const Mat3 & transf,const Vec2 & dstSize,int textureNdx) const1628 float Vertex3DTextureCase::calculateLod (const Mat3& transf, const Vec2& dstSize, int textureNdx) const
1629 {
1630 const tcu::Texture3D& refTexture = m_textures[textureNdx]->getRefTexture();
1631 const int srcWidth = refTexture.getWidth();
1632 const int srcHeight = refTexture.getHeight();
1633 const int srcDepth = refTexture.getDepth();
1634
1635 // Calculate transformed coordinates of three screen corners.
1636 const Vec3 trans00 = transf * Vec3(0.0f, 0.0f, 1.0f);
1637 const Vec3 trans01 = transf * Vec3(0.0f, 1.0f, 1.0f);
1638 const Vec3 trans10 = transf * Vec3(1.0f, 0.0f, 1.0f);
1639
1640 // Derivates.
1641 const float dudx = (trans10.x() - trans00.x()) * (float)srcWidth / dstSize.x();
1642 const float dudy = (trans01.x() - trans00.x()) * (float)srcWidth / dstSize.y();
1643 const float dvdx = (trans10.y() - trans00.y()) * (float)srcHeight / dstSize.x();
1644 const float dvdy = (trans01.y() - trans00.y()) * (float)srcHeight / dstSize.y();
1645 const float dwdx = (trans10.z() - trans00.z()) * (float)srcDepth / dstSize.x();
1646 const float dwdy = (trans01.z() - trans00.z()) * (float)srcDepth / dstSize.y();
1647
1648 return deFloatLog2(deFloatSqrt(de::max(dudx*dudx + dvdx*dvdx + dwdx*dwdx, dudy*dudy + dvdy*dvdy + dwdy*dwdy)));
1649 }
1650
iterate(void)1651 Vertex3DTextureCase::IterateResult Vertex3DTextureCase::iterate (void)
1652 {
1653 const int viewportWidth = deMin32(m_context.getRenderTarget().getWidth(), MAX_3D_RENDER_WIDTH);
1654 const int viewportHeight = deMin32(m_context.getRenderTarget().getHeight(), MAX_3D_RENDER_HEIGHT);
1655
1656 const int viewportXOffsetMax = m_context.getRenderTarget().getWidth() - viewportWidth;
1657 const int viewportYOffsetMax = m_context.getRenderTarget().getHeight() - viewportHeight;
1658
1659 de::Random rnd (deStringHash(getName()));
1660
1661 const int viewportXOffset = rnd.getInt(0, viewportXOffsetMax);
1662 const int viewportYOffset = rnd.getInt(0, viewportYOffsetMax);
1663
1664 glUseProgram(m_program->getProgram());
1665
1666 // Divide viewport into 4 cells.
1667 const int leftWidth = viewportWidth / 2;
1668 const int rightWidth = viewportWidth - leftWidth;
1669 const int bottomHeight = viewportHeight / 2;
1670 const int topHeight = viewportHeight - bottomHeight;
1671
1672 // Clear.
1673 glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
1674 glClear(GL_COLOR_BUFFER_BIT);
1675
1676 // Shear to get all slices visible.
1677 static const float depthShearTransfData[] =
1678 {
1679 1.0f, 0.0f, 0.0f,
1680 0.0f, 1.0f, 0.0f,
1681 1.0f, 1.0f, 0.0f
1682 };
1683
1684 // Minification and magnification transformations.
1685 static const float texMinTransfData[] =
1686 {
1687 2.2f, 0.0f, -0.3f,
1688 0.0f, 2.2f, -0.3f,
1689 0.0f, 0.0f, 1.0f
1690 };
1691 static const float texMagTransfData[] =
1692 {
1693 0.4f, 0.0f, 0.8f,
1694 0.0f, 0.4f, 0.8f,
1695 0.0f, 0.0f, 1.0f
1696 };
1697
1698 // Transformation matrices for minification and magnification.
1699 const Mat3 texMinTransf = Mat3(depthShearTransfData) * Mat3(texMinTransfData);
1700 const Mat3 texMagTransf = Mat3(depthShearTransfData) * Mat3(texMagTransfData);
1701
1702 // Surface for the reference image.
1703 tcu::Surface refImage(viewportWidth, viewportHeight);
1704
1705 {
1706 const struct Render
1707 {
1708 const Rect region;
1709 int textureNdx;
1710 const Mat3 texTransform;
1711 Render (const Rect& r, int tN, const Mat3& tT) : region(r), textureNdx(tN), texTransform(tT) {}
1712 } renders[] =
1713 {
1714 Render(Rect(0, 0, leftWidth, bottomHeight), 0, texMinTransf),
1715 Render(Rect(leftWidth, 0, rightWidth, bottomHeight), 0, texMagTransf),
1716 Render(Rect(0, bottomHeight, leftWidth, topHeight), 1, texMinTransf),
1717 Render(Rect(leftWidth, bottomHeight, rightWidth, topHeight), 1, texMagTransf)
1718 };
1719
1720 for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
1721 {
1722 const Render& rend = renders[renderNdx];
1723 const float lod = calculateLod(rend.texTransform, rend.region.size().asFloat(), rend.textureNdx);
1724 const bool useSafeTexCoords = isLevelNearest(lod > 0.0f ? m_minFilter : m_magFilter);
1725 const Grid grid (GRID_SIZE_3D, rend.region.size(), getTextureSize(*m_textures[rend.textureNdx]),
1726 TexTypeCoordParams<TEXTURETYPE_3D>(rend.texTransform), useSafeTexCoords);
1727
1728 glViewport(viewportXOffset + rend.region.x, viewportYOffset + rend.region.y, rend.region.w, rend.region.h);
1729 renderCell (rend.textureNdx, lod, grid);
1730 computeReferenceCell (rend.textureNdx, lod, grid, refImage, rend.region);
1731 }
1732 }
1733
1734 // Read back rendered results.
1735 tcu::Surface resImage(viewportWidth, viewportHeight);
1736 glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
1737
1738 glUseProgram(0);
1739
1740 // Compare and log.
1741 {
1742 const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
1743
1744 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1745 isOk ? "Pass" : "Image comparison failed");
1746 }
1747
1748 return STOP;
1749 }
1750
setupShaderInputs(int textureNdx,float lod,const Grid & grid) const1751 void Vertex3DTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
1752 {
1753 const deUint32 programID = m_program->getProgram();
1754
1755 // SETUP ATTRIBUTES.
1756
1757 {
1758 const int positionLoc = glGetAttribLocation(programID, "a_position");
1759 if (positionLoc != -1)
1760 {
1761 glEnableVertexAttribArray(positionLoc);
1762 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
1763 }
1764 }
1765
1766 {
1767 const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
1768 if (texCoordLoc != -1)
1769 {
1770 glEnableVertexAttribArray(texCoordLoc);
1771 glVertexAttribPointer(texCoordLoc, 3, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
1772 }
1773 }
1774
1775 // SETUP UNIFORMS.
1776
1777 {
1778 const int lodLoc = glGetUniformLocation(programID, "u_lod");
1779 if (lodLoc != -1)
1780 glUniform1f(lodLoc, lod);
1781 }
1782
1783 glActiveTexture(GL_TEXTURE0);
1784 glBindTexture(GL_TEXTURE_3D, m_textures[textureNdx]->getGLTexture());
1785 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, m_wrapS);
1786 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, m_wrapT);
1787 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, m_wrapR);
1788 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, m_minFilter);
1789 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, m_magFilter);
1790
1791 {
1792 const int texLoc = glGetUniformLocation(programID, "u_texture");
1793 if (texLoc != -1)
1794 glUniform1i(texLoc, 0);
1795 }
1796 }
1797
1798 // Renders one sub-image with given parameters.
renderCell(int textureNdx,float lod,const Grid & grid) const1799 void Vertex3DTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
1800 {
1801 setupShaderInputs(textureNdx, lod, grid);
1802 glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
1803 }
1804
1805 // Computes reference for one sub-image with given parameters.
computeReferenceCell(int textureNdx,float lod,const Grid & grid,tcu::Surface & dst,const Rect & dstRegion) const1806 void Vertex3DTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
1807 {
1808 computeReference(m_textures[textureNdx]->getRefTexture(), lod, glu::mapGLSampler(m_wrapS, m_wrapT, m_wrapR, m_minFilter, m_magFilter), grid, dst, dstRegion);
1809 }
1810
VertexTextureTests(Context & context)1811 VertexTextureTests::VertexTextureTests (Context& context)
1812 : TestCaseGroup(context, "vertex", "Vertex Texture Tests")
1813 {
1814 }
1815
~VertexTextureTests(void)1816 VertexTextureTests::~VertexTextureTests(void)
1817 {
1818 }
1819
init(void)1820 void VertexTextureTests::init (void)
1821 {
1822 // 2D and cube map groups, and their filtering and wrap sub-groups.
1823 TestCaseGroup* const group2D = new TestCaseGroup(m_context, "2d", "2D Vertex Texture Tests");
1824 TestCaseGroup* const groupCube = new TestCaseGroup(m_context, "cube", "Cube Map Vertex Texture Tests");
1825 TestCaseGroup* const group2DArray = new TestCaseGroup(m_context, "2d_array", "2D Array Vertex Texture Tests");
1826 TestCaseGroup* const group3D = new TestCaseGroup(m_context, "3d", "3D Vertex Texture Tests");
1827 TestCaseGroup* const filteringGroup2D = new TestCaseGroup(m_context, "filtering", "2D Vertex Texture Filtering Tests");
1828 TestCaseGroup* const wrapGroup2D = new TestCaseGroup(m_context, "wrap", "2D Vertex Texture Wrap Tests");
1829 TestCaseGroup* const filteringGroupCube = new TestCaseGroup(m_context, "filtering", "Cube Map Vertex Texture Filtering Tests");
1830 TestCaseGroup* const wrapGroupCube = new TestCaseGroup(m_context, "wrap", "Cube Map Vertex Texture Wrap Tests");
1831 TestCaseGroup* const filteringGroup2DArray = new TestCaseGroup(m_context, "filtering", "2D Array Vertex Texture Filtering Tests");
1832 TestCaseGroup* const wrapGroup2DArray = new TestCaseGroup(m_context, "wrap", "2D Array Vertex Texture Wrap Tests");
1833 TestCaseGroup* const filteringGroup3D = new TestCaseGroup(m_context, "filtering", "3D Vertex Texture Filtering Tests");
1834 TestCaseGroup* const wrapGroup3D = new TestCaseGroup(m_context, "wrap", "3D Vertex Texture Wrap Tests");
1835
1836 group2D->addChild(filteringGroup2D);
1837 group2D->addChild(wrapGroup2D);
1838 groupCube->addChild(filteringGroupCube);
1839 groupCube->addChild(wrapGroupCube);
1840 group2DArray->addChild(filteringGroup2DArray);
1841 group2DArray->addChild(wrapGroup2DArray);
1842 group3D->addChild(filteringGroup3D);
1843 group3D->addChild(wrapGroup3D);
1844
1845 addChild(group2D);
1846 addChild(groupCube);
1847 addChild(group2DArray);
1848 addChild(group3D);
1849
1850 static const struct
1851 {
1852 const char* name;
1853 GLenum mode;
1854 } wrapModes[] =
1855 {
1856 { "clamp", GL_CLAMP_TO_EDGE },
1857 { "repeat", GL_REPEAT },
1858 { "mirror", GL_MIRRORED_REPEAT }
1859 };
1860
1861 static const struct
1862 {
1863 const char* name;
1864 GLenum mode;
1865 } minFilterModes[] =
1866 {
1867 { "nearest", GL_NEAREST },
1868 { "linear", GL_LINEAR },
1869 { "nearest_mipmap_nearest", GL_NEAREST_MIPMAP_NEAREST },
1870 { "linear_mipmap_nearest", GL_LINEAR_MIPMAP_NEAREST },
1871 { "nearest_mipmap_linear", GL_NEAREST_MIPMAP_LINEAR },
1872 { "linear_mipmap_linear", GL_LINEAR_MIPMAP_LINEAR }
1873 };
1874
1875 static const struct
1876 {
1877 const char* name;
1878 GLenum mode;
1879 } magFilterModes[] =
1880 {
1881 { "nearest", GL_NEAREST },
1882 { "linear", GL_LINEAR }
1883 };
1884
1885 #define FOR_EACH(ITERATOR, ARRAY, BODY) \
1886 for (int (ITERATOR) = 0; (ITERATOR) < DE_LENGTH_OF_ARRAY(ARRAY); (ITERATOR)++) \
1887 BODY
1888
1889 // 2D cases.
1890
1891 FOR_EACH(minFilter, minFilterModes,
1892 FOR_EACH(magFilter, magFilterModes,
1893 FOR_EACH(wrapMode, wrapModes,
1894 {
1895 const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1896
1897 filteringGroup2D->addChild(new Vertex2DTextureCase(m_context,
1898 name.c_str(), "",
1899 minFilterModes[minFilter].mode,
1900 magFilterModes[magFilter].mode,
1901 wrapModes[wrapMode].mode,
1902 wrapModes[wrapMode].mode));
1903 })));
1904
1905 FOR_EACH(wrapSMode, wrapModes,
1906 FOR_EACH(wrapTMode, wrapModes,
1907 {
1908 const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
1909
1910 wrapGroup2D->addChild(new Vertex2DTextureCase(m_context,
1911 name.c_str(), "",
1912 GL_LINEAR_MIPMAP_LINEAR,
1913 GL_LINEAR,
1914 wrapModes[wrapSMode].mode,
1915 wrapModes[wrapTMode].mode));
1916 }));
1917
1918 // Cube map cases.
1919
1920 FOR_EACH(minFilter, minFilterModes,
1921 FOR_EACH(magFilter, magFilterModes,
1922 FOR_EACH(wrapMode, wrapModes,
1923 {
1924 const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1925
1926 filteringGroupCube->addChild(new VertexCubeTextureCase(m_context,
1927 name.c_str(), "",
1928 minFilterModes[minFilter].mode,
1929 magFilterModes[magFilter].mode,
1930 wrapModes[wrapMode].mode,
1931 wrapModes[wrapMode].mode));
1932 })));
1933
1934 FOR_EACH(wrapSMode, wrapModes,
1935 FOR_EACH(wrapTMode, wrapModes,
1936 {
1937 const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
1938
1939 wrapGroupCube->addChild(new VertexCubeTextureCase(m_context,
1940 name.c_str(), "",
1941 GL_LINEAR_MIPMAP_LINEAR,
1942 GL_LINEAR,
1943 wrapModes[wrapSMode].mode,
1944 wrapModes[wrapTMode].mode));
1945 }));
1946
1947 // 2D array cases.
1948
1949 FOR_EACH(minFilter, minFilterModes,
1950 FOR_EACH(magFilter, magFilterModes,
1951 FOR_EACH(wrapMode, wrapModes,
1952 {
1953 const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1954
1955 filteringGroup2DArray->addChild(new Vertex2DArrayTextureCase(m_context,
1956 name.c_str(), "",
1957 minFilterModes[minFilter].mode,
1958 magFilterModes[magFilter].mode,
1959 wrapModes[wrapMode].mode,
1960 wrapModes[wrapMode].mode));
1961 })));
1962
1963 FOR_EACH(wrapSMode, wrapModes,
1964 FOR_EACH(wrapTMode, wrapModes,
1965 {
1966 const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
1967
1968 wrapGroup2DArray->addChild(new Vertex2DArrayTextureCase(m_context,
1969 name.c_str(), "",
1970 GL_LINEAR_MIPMAP_LINEAR,
1971 GL_LINEAR,
1972 wrapModes[wrapSMode].mode,
1973 wrapModes[wrapTMode].mode));
1974 }));
1975
1976 // 3D cases.
1977
1978 FOR_EACH(minFilter, minFilterModes,
1979 FOR_EACH(magFilter, magFilterModes,
1980 FOR_EACH(wrapMode, wrapModes,
1981 {
1982 const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1983
1984 filteringGroup3D->addChild(new Vertex3DTextureCase(m_context,
1985 name.c_str(), "",
1986 minFilterModes[minFilter].mode,
1987 magFilterModes[magFilter].mode,
1988 wrapModes[wrapMode].mode,
1989 wrapModes[wrapMode].mode,
1990 wrapModes[wrapMode].mode));
1991 })));
1992
1993 FOR_EACH(wrapSMode, wrapModes,
1994 FOR_EACH(wrapTMode, wrapModes,
1995 FOR_EACH(wrapRMode, wrapModes,
1996 {
1997 const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name + "_" + wrapModes[wrapRMode].name;
1998
1999 wrapGroup3D->addChild(new Vertex3DTextureCase(m_context,
2000 name.c_str(), "",
2001 GL_LINEAR_MIPMAP_LINEAR,
2002 GL_LINEAR,
2003 wrapModes[wrapSMode].mode,
2004 wrapModes[wrapTMode].mode,
2005 wrapModes[wrapRMode].mode));
2006 })));
2007 }
2008
2009 } // Functional
2010 } // gles3
2011 } // deqp
2012