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