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