1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
5 * Copyright 2014 The Android Open Source Project
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
21 * \brief Vertex texture tests.
22 *//*--------------------------------------------------------------------*/
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"
57 using namespace gls::TextureTestUtil;
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;
69 static const int WIDTH_2D_ARRAY = 128;
70 static const int HEIGHT_2D_ARRAY = 128;
71 static const int LAYERS_2D_ARRAY = 8;
73 static const int WIDTH_3D = 64;
74 static const int HEIGHT_3D = 64;
75 static const int DEPTH_3D = 64;
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;
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;
85 static const int MAX_2D_ARRAY_RENDER_WIDTH = 128*2;
86 static const int MAX_2D_ARRAY_RENDER_HEIGHT = 128*2;
88 static const int MAX_3D_RENDER_WIDTH = 128*2;
89 static const int MAX_3D_RENDER_HEIGHT = 128*2;
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;
96 // Helpers for making texture coordinates "safe", i.e. move them further from coordinate bounary.
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.
100 static inline float moveTowardsFraction (float x, float targetFraction)
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;
109 static inline float safeCoord (float raw, int scale, float fraction)
111 const float scaleFloat = (float)scale;
112 return moveTowardsFraction(raw*scaleFloat, fraction) / scaleFloat;
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)
118 tcu::Vector<float, Size> result;
119 for (int i = 0; i < Size; i++)
120 result[i] = safeCoord(raw[i], scale[i], fraction[i]);
124 static inline Vec2 safe2DTexCoords (const Vec2& raw, const IVec2& textureSize)
126 return safeCoords(raw, textureSize, Vec2(0.5f));
129 static inline Vec3 safe2DArrayTexCoords (const Vec3& raw, const IVec3& textureSize)
131 return safeCoords(raw, textureSize, Vec3(0.5f, 0.5f, 0.0f));
134 static inline Vec3 safe3DTexCoords (const Vec3& raw, const IVec3& textureSize)
136 return safeCoords(raw, textureSize, Vec3(0.5f));
144 Rect (int x_, int y_, int w_, int h_) : x(x_), y(y_), w(w_), h(h_) {}
145 IVec2 pos (void) const { return IVec2(x, y); }
146 IVec2 size (void) const { return IVec2(w, h); }
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; };
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 }; };
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 }; };
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; };
175 template <TextureType> struct TexTypeCoordParams;
178 TexTypeCoordParams<TEXTURETYPE_2D>
183 TexTypeCoordParams (const Vec2& scale_, const Vec2& bias_) : scale(scale_), bias(bias_) {}
187 TexTypeCoordParams<TEXTURETYPE_CUBE>
193 TexTypeCoordParams (const Vec2& scale_, const Vec2& bias_, tcu::CubeFace face_) : scale(scale_), bias(bias_), face(face_) {}
197 TexTypeCoordParams<TEXTURETYPE_2D_ARRAY>
201 TexTypeCoordParams (const Mat3& transform_) : transform(transform_) {}
205 TexTypeCoordParams<TEXTURETYPE_3D>
209 TexTypeCoordParams (const Mat3& transform_) : transform(transform_) {}
212 /*--------------------------------------------------------------------*//*!
213 * \brief Quad grid class containing position and texture coordinate data.
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
223 * Pointers returned by get*Ptr() are suitable for gl calls such as
224 * glVertexAttribPointer() (for position and tex coord) or glDrawElements()
226 *//*--------------------------------------------------------------------*/
227 template <TextureType TexType>
228 class PosTexCoordQuadGrid
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;
237 PosTexCoordQuadGrid (int gridSize, const IVec2& renderSize, const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords);
239 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;
243 int getNumIndices (void) const { return m_gridSize*m_gridSize*3*2; }
244 const float* getPositionPtr (void) const { DE_STATIC_ASSERT(sizeof(Vec2) == 2*sizeof(float)); return (float*)&m_positions[0]; }
245 const float* getTexCoordPtr (void) const { DE_STATIC_ASSERT(sizeof(TexCoordVec) == TEX_COORD_DIMS*(int)sizeof(float)); return (float*)&m_texCoords[0]; }
246 const deUint16* getIndexPtr (void) const { return &m_indices[0]; }
249 void initializeTexCoords (const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords);
251 const int m_gridSize;
252 vector<Vec2> m_positions;
253 vector<TexCoordVec> m_texCoords;
254 vector<deUint16> m_indices;
257 template <TextureType TexType>
258 Vec4 PosTexCoordQuadGrid<TexType>::getQuadLDRU (int col, int row) const
260 int ndx00 = (row*m_gridSize + col) * 4;
261 int ndx11 = ndx00 + 3;
263 return Vec4(m_positions[ndx00].x(),
264 m_positions[ndx00].y(),
265 m_positions[ndx11].x(),
266 m_positions[ndx11].y());
269 template <TextureType TexType>
270 const typename TexTypeCoordVec<TexType>::t& PosTexCoordQuadGrid<TexType>::getQuadTexCoord (int col, int row) const
272 return m_texCoords[(row*m_gridSize + col) * 4];
275 template <TextureType TexType>
276 PosTexCoordQuadGrid<TexType>::PosTexCoordQuadGrid (int gridSize, const IVec2& renderSize, const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
277 : m_gridSize(gridSize)
279 DE_ASSERT(m_gridSize > 0 && m_gridSize*m_gridSize <= (int)std::numeric_limits<deUint16>::max() + 1);
281 const float gridSizeFloat = (float)m_gridSize;
283 m_positions.reserve(m_gridSize*m_gridSize*4);
284 m_indices.reserve(m_gridSize*m_gridSize*3*2);
286 for (int y = 0; y < m_gridSize; y++)
287 for (int x = 0; x < m_gridSize; x++)
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;
294 Vec2 quadVertices[4] = { Vec2(fx0, fy0), Vec2(fx1, fy0), Vec2(fx0, fy1), Vec2(fx1, fy1) };
296 int firstNdx = (int)m_positions.size();
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);
301 m_indices.push_back(deUint16(firstNdx + 0));
302 m_indices.push_back(deUint16(firstNdx + 1));
303 m_indices.push_back(deUint16(firstNdx + 2));
305 m_indices.push_back(deUint16(firstNdx + 1));
306 m_indices.push_back(deUint16(firstNdx + 3));
307 m_indices.push_back(deUint16(firstNdx + 2));
310 m_texCoords.reserve(m_gridSize*m_gridSize*4);
311 initializeTexCoords(textureSize, texCoordParams, useSafeTexCoords);
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);
319 void PosTexCoordQuadGrid<TEXTURETYPE_2D>::initializeTexCoords (const IVec2& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
321 DE_ASSERT(m_texCoords.empty());
323 const float gridSizeFloat = (float)m_gridSize;
325 for (int y = 0; y < m_gridSize; y++)
326 for (int x = 0; x < m_gridSize; x++)
328 Vec2 rawCoord = Vec2((float)x / gridSizeFloat, (float)y / gridSizeFloat) * texCoordParams.scale + texCoordParams.bias;
330 for (int i = 0; i < 4; i++)
331 m_texCoords.push_back(useSafeTexCoords ? safe2DTexCoords(rawCoord, textureSize) : rawCoord);
336 void PosTexCoordQuadGrid<TEXTURETYPE_CUBE>::initializeTexCoords (const IVec2& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
338 DE_ASSERT(m_texCoords.empty());
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;
349 for (int y = 0; y < m_gridSize; y++)
350 for (int x = 0; x < m_gridSize; x++)
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();
356 for (int i = 0; i < 4; i++)
357 m_texCoords.push_back(texCoord);
362 void PosTexCoordQuadGrid<TEXTURETYPE_2D_ARRAY>::initializeTexCoords (const IVec3& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
364 DE_ASSERT(m_texCoords.empty());
366 const float gridSizeFloat = (float)m_gridSize;
368 for (int y = 0; y < m_gridSize; y++)
369 for (int x = 0; x < m_gridSize; x++)
371 const Vec3 rawCoord = texCoordParams.transform * Vec3((float)x / gridSizeFloat, (float)y / gridSizeFloat, 1.0f);
373 for (int i = 0; i < 4; i++)
374 m_texCoords.push_back(useSafeTexCoords ? safe2DArrayTexCoords(rawCoord, textureSize) : rawCoord);
379 void PosTexCoordQuadGrid<TEXTURETYPE_3D>::initializeTexCoords (const IVec3& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
381 DE_ASSERT(m_texCoords.empty());
383 const float gridSizeFloat = (float)m_gridSize;
385 for (int y = 0; y < m_gridSize; y++)
386 for (int x = 0; x < m_gridSize; x++)
388 Vec3 rawCoord = texCoordParams.transform * Vec3((float)x / gridSizeFloat, (float)y / gridSizeFloat, 1.0f);
390 for (int i = 0; i < 4; i++)
391 m_texCoords.push_back(useSafeTexCoords ? safe3DTexCoords(rawCoord, textureSize) : rawCoord);
397 static inline bool isLevelNearest (deUint32 filter)
399 return filter == GL_NEAREST || filter == GL_NEAREST_MIPMAP_NEAREST || filter == GL_NEAREST_MIPMAP_LINEAR;
402 static inline IVec2 getTextureSize (const glu::Texture2D& tex)
404 const tcu::Texture2D& ref = tex.getRefTexture();
405 return IVec2(ref.getWidth(), ref.getHeight());
408 static inline IVec2 getTextureSize (const glu::TextureCube& tex)
410 const tcu::TextureCube& ref = tex.getRefTexture();
411 return IVec2(ref.getSize(), ref.getSize());
414 static inline IVec3 getTextureSize (const glu::Texture2DArray& tex)
416 const tcu::Texture2DArray& ref = tex.getRefTexture();
417 return IVec3(ref.getWidth(), ref.getHeight(), ref.getNumLayers());
420 static inline IVec3 getTextureSize (const glu::Texture3D& tex)
422 const tcu::Texture3D& ref = tex.getRefTexture();
423 return IVec3(ref.getWidth(), ref.getHeight(), ref.getDepth());
426 template <TextureType TexType>
427 static void setPixelColors (const vector<Vec4>& quadColors, const Rect& region, const PosTexCoordQuadGrid<TexType>& grid, tcu::Surface& dst)
429 const int gridSize = grid.getSize();
431 for (int y = 0; y < gridSize; y++)
432 for (int x = 0; x < gridSize; x++)
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);
441 for (int iy = iy0; iy < iy1; iy++)
442 for (int ix = ix0; ix < ix1; ix++)
444 DE_ASSERT(deInBounds32(ix + region.x, 0, dst.getWidth()));
445 DE_ASSERT(deInBounds32(iy + region.y, 0, dst.getHeight()));
447 dst.setPixel(ix + region.x, iy + region.y, tcu::RGBA(color));
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); }
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); }
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); }
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); }
457 template <TextureType TexType>
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)
460 const int gridSize = grid.getSize();
461 vector<Vec4> quadColors (gridSize*gridSize);
463 for (int y = 0; y < gridSize; y++)
464 for (int x = 0; x < gridSize; x++)
466 const int ndx = y*gridSize + x;
467 const typename TexTypeCoordVec<TexType>::t& coord = grid.getQuadTexCoord(x, y);
469 quadColors[ndx] = sample(texture, coord, lod, sampler);
472 setPixelColors(quadColors, dstRegion, grid, dst);
475 static bool compareImages (const glu::RenderContext& renderCtx, tcu::TestLog& log, const tcu::Surface& ref, const tcu::Surface& res)
477 DE_ASSERT(renderCtx.getRenderTarget().getNumSamples() == 0);
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);
483 class Vertex2DTextureCase : public TestCase
486 Vertex2DTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
487 ~Vertex2DTextureCase (void);
491 IterateResult iterate (void);
494 typedef PosTexCoordQuadGrid<TEXTURETYPE_2D> Grid;
496 Vertex2DTextureCase (const Vertex2DTextureCase& other);
497 Vertex2DTextureCase& operator= (const Vertex2DTextureCase& other);
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;
504 const deUint32 m_minFilter;
505 const deUint32 m_magFilter;
506 const deUint32 m_wrapS;
507 const deUint32 m_wrapT;
509 const glu::ShaderProgram* m_program;
510 glu::Texture2D* m_textures[2]; // 2 textures, a gradient texture and a grid texture.
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)
519 , m_program (DE_NULL)
521 m_textures[0] = DE_NULL;
522 m_textures[1] = DE_NULL;
525 Vertex2DTextureCase::~Vertex2DTextureCase(void)
527 Vertex2DTextureCase::deinit();
530 void Vertex2DTextureCase::init (void)
532 const char* const vertexShader =
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"
542 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
543 " v_color = textureLod(u_texture, a_texCoord, u_lod);\n"
546 const char* const fragmentShader =
548 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
549 "in mediump vec4 v_color;\n"
553 " dEQP_FragColor = v_color;\n"
556 if (m_context.getRenderTarget().getNumSamples() != 0)
557 throw tcu::NotSupportedError("MSAA config not supported by this test");
559 DE_ASSERT(!m_program);
560 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShader, fragmentShader));
562 if(!m_program->isOk())
564 m_testCtx.getLog() << *m_program;
566 GLint maxVertexTextures;
567 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
569 if (maxVertexTextures < 1)
570 throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
572 TCU_FAIL("Failed to compile shader");
575 // Make the textures.
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);
582 for (int i = 0; i < 2; i++)
584 DE_ASSERT(!m_textures[i]);
585 m_textures[i] = new glu::Texture2D(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
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;
594 // Fill first with gradient texture.
595 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
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;
600 m_textures[0]->getRefTexture().allocLevel(levelNdx);
601 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
604 // Fill second with grid texture.
605 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
607 const deUint32 step = 0x00ffffff / numLevels;
608 const deUint32 rgb = step*levelNdx;
609 const deUint32 colorA = 0xff000000 | rgb;
610 const deUint32 colorB = 0xff000000 | ~rgb;
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);
617 for (int i = 0; i < 2; i++)
618 m_textures[i]->upload();
620 catch (const std::exception&)
622 // Clean up to save memory.
623 Vertex2DTextureCase::deinit();
628 void Vertex2DTextureCase::deinit (void)
630 for (int i = 0; i < 2; i++)
632 delete m_textures[i];
633 m_textures[i] = DE_NULL;
640 float Vertex2DTextureCase::calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const
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;
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()));
650 Vertex2DTextureCase::IterateResult Vertex2DTextureCase::iterate (void)
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);
655 const int viewportXOffsetMax = m_context.getRenderTarget().getWidth() - viewportWidth;
656 const int viewportYOffsetMax = m_context.getRenderTarget().getHeight() - viewportHeight;
658 de::Random rnd (deStringHash(getName()));
660 const int viewportXOffset = rnd.getInt(0, viewportXOffsetMax);
661 const int viewportYOffset = rnd.getInt(0, viewportYOffsetMax);
663 glUseProgram(m_program->getProgram());
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;
672 glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
673 glClear(GL_COLOR_BUFFER_BIT);
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);
681 // Surface for the reference image.
682 tcu::Surface refImage(viewportWidth, viewportHeight);
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) {}
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)
700 for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
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);
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);
714 // Read back rendered results.
715 tcu::Surface resImage(viewportWidth, viewportHeight);
716 glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
722 const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
724 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
725 isOk ? "Pass" : "Image comparison failed");
731 void Vertex2DTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
733 const deUint32 programID = m_program->getProgram();
738 const int positionLoc = glGetAttribLocation(programID, "a_position");
739 if (positionLoc != -1)
741 glEnableVertexAttribArray(positionLoc);
742 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
747 const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
748 if (texCoordLoc != -1)
750 glEnableVertexAttribArray(texCoordLoc);
751 glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
758 const int lodLoc = glGetUniformLocation(programID, "u_lod");
760 glUniform1f(lodLoc, lod);
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);
771 const int texLoc = glGetUniformLocation(programID, "u_texture");
773 glUniform1i(texLoc, 0);
777 // Renders one sub-image with given parameters.
778 void Vertex2DTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
780 setupShaderInputs(textureNdx, lod, grid);
781 glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
784 void Vertex2DTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
786 computeReference(m_textures[textureNdx]->getRefTexture(), lod, glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter), grid, dst, dstRegion);
789 class VertexCubeTextureCase : public TestCase
792 VertexCubeTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
793 ~VertexCubeTextureCase (void);
797 IterateResult iterate (void);
800 typedef PosTexCoordQuadGrid<TEXTURETYPE_CUBE> Grid;
802 VertexCubeTextureCase (const VertexCubeTextureCase& other);
803 VertexCubeTextureCase& operator= (const VertexCubeTextureCase& other);
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;
810 const deUint32 m_minFilter;
811 const deUint32 m_magFilter;
812 const deUint32 m_wrapS;
813 const deUint32 m_wrapT;
815 const glu::ShaderProgram* m_program;
816 glu::TextureCube* m_textures[2]; // 2 textures, a gradient texture and a grid texture.
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)
825 , m_program (DE_NULL)
827 m_textures[0] = DE_NULL;
828 m_textures[1] = DE_NULL;
831 VertexCubeTextureCase::~VertexCubeTextureCase(void)
833 VertexCubeTextureCase::deinit();
836 void VertexCubeTextureCase::init (void)
838 const char* const vertexShader =
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"
848 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
849 " v_color = textureLod(u_texture, a_texCoord, u_lod);\n"
852 const char* const fragmentShader =
854 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
855 "in mediump vec4 v_color;\n"
859 " dEQP_FragColor = v_color;\n"
862 if (m_context.getRenderTarget().getNumSamples() != 0)
863 throw tcu::NotSupportedError("MSAA config not supported by this test");
865 DE_ASSERT(!m_program);
866 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShader, fragmentShader));
868 if(!m_program->isOk())
870 m_testCtx.getLog() << *m_program;
872 GLint maxVertexTextures;
873 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
875 if (maxVertexTextures < 1)
876 throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
878 TCU_FAIL("Failed to compile shader");
881 // Make the textures.
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);
888 DE_ASSERT(texWidth == texHeight);
891 for (int i = 0; i < 2; i++)
893 DE_ASSERT(!m_textures[i]);
894 m_textures[i] = new glu::TextureCube(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth);
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;
903 // Fill first with gradient texture.
904 static const Vec4 gradients[tcu::CUBEFACE_LAST][2] =
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
913 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
915 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
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);
922 // Fill second with grid texture.
923 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
925 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
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;
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);
938 for (int i = 0; i < 2; i++)
939 m_textures[i]->upload();
941 catch (const std::exception&)
943 // Clean up to save memory.
944 VertexCubeTextureCase::deinit();
949 void VertexCubeTextureCase::deinit (void)
951 for (int i = 0; i < 2; i++)
953 delete m_textures[i];
954 m_textures[i] = DE_NULL;
961 float VertexCubeTextureCase::calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const
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;
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()));
971 VertexCubeTextureCase::IterateResult VertexCubeTextureCase::iterate (void)
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);
976 const int viewportXOffsetMax = m_context.getRenderTarget().getWidth() - viewportWidth;
977 const int viewportYOffsetMax = m_context.getRenderTarget().getHeight() - viewportHeight;
979 de::Random rnd (deStringHash(getName()));
981 const int viewportXOffset = rnd.getInt(0, viewportXOffsetMax);
982 const int viewportYOffset = rnd.getInt(0, viewportYOffsetMax);
984 glUseProgram(m_program->getProgram());
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;
993 glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
994 glClear(GL_COLOR_BUFFER_BIT);
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);
1002 // Surface for the reference image.
1003 tcu::Surface refImage(viewportWidth, viewportHeight);
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;
1009 for (int i = 0; i < tcu::CUBEFACE_LAST; i++)
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;
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) {}
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)
1035 for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
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);
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);
1049 // Read back rendered results.
1050 tcu::Surface resImage(viewportWidth, viewportHeight);
1051 glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
1057 const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
1059 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1060 isOk ? "Pass" : "Image comparison failed");
1066 void VertexCubeTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
1068 const deUint32 programID = m_program->getProgram();
1070 // SETUP ATTRIBUTES.
1073 const int positionLoc = glGetAttribLocation(programID, "a_position");
1074 if (positionLoc != -1)
1076 glEnableVertexAttribArray(positionLoc);
1077 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
1082 const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
1083 if (texCoordLoc != -1)
1085 glEnableVertexAttribArray(texCoordLoc);
1086 glVertexAttribPointer(texCoordLoc, 3, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
1093 const int lodLoc = glGetUniformLocation(programID, "u_lod");
1095 glUniform1f(lodLoc, lod);
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);
1106 const int texLoc = glGetUniformLocation(programID, "u_texture");
1108 glUniform1i(texLoc, 0);
1112 // Renders one cube face with given parameters.
1113 void VertexCubeTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
1115 setupShaderInputs(textureNdx, lod, grid);
1116 glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
1119 // Computes reference for one cube face with given parameters.
1120 void VertexCubeTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
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);
1127 class Vertex2DArrayTextureCase : public TestCase
1130 Vertex2DArrayTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
1131 ~Vertex2DArrayTextureCase (void);
1135 IterateResult iterate (void);
1138 typedef PosTexCoordQuadGrid<TEXTURETYPE_2D_ARRAY> Grid;
1140 Vertex2DArrayTextureCase (const Vertex2DArrayTextureCase& other);
1141 Vertex2DArrayTextureCase& operator= (const Vertex2DArrayTextureCase& other);
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;
1148 const deUint32 m_minFilter;
1149 const deUint32 m_magFilter;
1150 const deUint32 m_wrapS;
1151 const deUint32 m_wrapT;
1153 const glu::ShaderProgram* m_program;
1154 glu::Texture2DArray* m_textures[2]; // 2 textures, a gradient texture and a grid texture.
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)
1163 , m_program (DE_NULL)
1165 m_textures[0] = DE_NULL;
1166 m_textures[1] = DE_NULL;
1169 Vertex2DArrayTextureCase::~Vertex2DArrayTextureCase(void)
1171 Vertex2DArrayTextureCase::deinit();
1174 void Vertex2DArrayTextureCase::init (void)
1176 const char* const vertexShaderSource =
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"
1186 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
1187 " v_color = textureLod(u_texture, a_texCoord, u_lod);\n"
1190 const char* const fragmentShaderSource =
1192 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
1193 "in mediump vec4 v_color;\n"
1197 " dEQP_FragColor = v_color;\n"
1200 if (m_context.getRenderTarget().getNumSamples() != 0)
1201 throw tcu::NotSupportedError("MSAA config not supported by this test");
1205 DE_ASSERT(!m_program);
1206 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
1208 if(!m_program->isOk())
1210 m_testCtx.getLog() << *m_program;
1212 GLint maxVertexTextures;
1213 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
1215 if (maxVertexTextures < 1)
1216 throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
1218 TCU_FAIL("Failed to compile shader");
1221 // Make the textures.
1225 const int texWidth = WIDTH_2D_ARRAY;
1226 const int texHeight = HEIGHT_2D_ARRAY;
1227 const int texLayers = LAYERS_2D_ARRAY;
1229 for (int i = 0; i < 2; i++)
1231 DE_ASSERT(!m_textures[i]);
1232 m_textures[i] = new glu::Texture2DArray(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight, texLayers);
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;
1240 // Fill first with gradient texture.
1241 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
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;
1246 m_textures[0]->getRefTexture().allocLevel(levelNdx);
1247 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
1250 // Fill second with grid texture.
1251 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1253 const deUint32 step = 0x00ffffff / numLevels;
1254 const deUint32 rgb = step*levelNdx;
1255 const deUint32 colorA = 0xff000000 | rgb;
1256 const deUint32 colorB = 0xff000000 | ~rgb;
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);
1263 for (int i = 0; i < 2; i++)
1264 m_textures[i]->upload();
1266 catch (const std::exception&)
1268 // Clean up to save memory.
1269 Vertex2DArrayTextureCase::deinit();
1274 void Vertex2DArrayTextureCase::deinit (void)
1276 for (int i = 0; i < 2; i++)
1278 delete m_textures[i];
1279 m_textures[i] = DE_NULL;
1283 m_program = DE_NULL;
1286 float Vertex2DArrayTextureCase::calculateLod (const Mat3& transf, const Vec2& dstSize, int textureNdx) const
1288 const tcu::Texture2DArray& refTexture = m_textures[textureNdx]->getRefTexture();
1289 const int texWidth = refTexture.getWidth();
1290 const int texHeight = refTexture.getHeight();
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();
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();
1303 return deFloatLog2(deFloatSqrt(de::max(dudx*dudx + dvdx*dvdx, dudy*dudy + dvdy*dvdy)));
1306 Vertex2DArrayTextureCase::IterateResult Vertex2DArrayTextureCase::iterate (void)
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);
1311 const int viewportXOffsetMax = m_context.getRenderTarget().getWidth() - viewportWidth;
1312 const int viewportYOffsetMax = m_context.getRenderTarget().getHeight() - viewportHeight;
1314 de::Random rnd (deStringHash(getName()));
1316 const int viewportXOffset = rnd.getInt(0, viewportXOffsetMax);
1317 const int viewportYOffset = rnd.getInt(0, viewportYOffsetMax);
1319 glUseProgram(m_program->getProgram());
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;
1328 glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
1329 glClear(GL_COLOR_BUFFER_BIT);
1331 // Shear by layer count to get all layers visible.
1332 static const float layerShearTransfData[] =
1336 (float)LAYERS_2D_ARRAY, 0.0f, 0.0f
1339 // Minification and magnification transformations.
1340 static const float texMinTransfData[] =
1346 static const float texMagTransfData[] =
1353 // Transformation matrices for minification and magnification.
1354 const Mat3 texMinTransf = Mat3(layerShearTransfData) * Mat3(texMinTransfData);
1355 const Mat3 texMagTransf = Mat3(layerShearTransfData) * Mat3(texMagTransfData);
1357 // Surface for the reference image.
1358 tcu::Surface refImage(viewportWidth, viewportHeight);
1365 const Mat3 texTransform;
1366 Render (const Rect& r, int tN, const Mat3& tT) : region(r), textureNdx(tN), texTransform(tT) {}
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)
1375 for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
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);
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);
1389 // Read back rendered results.
1390 tcu::Surface resImage(viewportWidth, viewportHeight);
1391 glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
1397 const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
1399 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1400 isOk ? "Pass" : "Image comparison failed");
1406 void Vertex2DArrayTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
1408 const deUint32 programID = m_program->getProgram();
1410 // SETUP ATTRIBUTES.
1413 const int positionLoc = glGetAttribLocation(programID, "a_position");
1414 if (positionLoc != -1)
1416 glEnableVertexAttribArray(positionLoc);
1417 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
1422 const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
1423 if (texCoordLoc != -1)
1425 glEnableVertexAttribArray(texCoordLoc);
1426 glVertexAttribPointer(texCoordLoc, 3, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
1433 const int lodLoc = glGetUniformLocation(programID, "u_lod");
1435 glUniform1f(lodLoc, lod);
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);
1446 const int texLoc = glGetUniformLocation(programID, "u_texture");
1448 glUniform1i(texLoc, 0);
1452 // Renders one sub-image with given parameters.
1453 void Vertex2DArrayTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
1455 setupShaderInputs(textureNdx, lod, grid);
1456 glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
1459 // Computes reference for one sub-image with given parameters.
1460 void Vertex2DArrayTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
1462 computeReference(m_textures[textureNdx]->getRefTexture(), lod, glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter), grid, dst, dstRegion);
1465 class Vertex3DTextureCase : public TestCase
1468 Vertex3DTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT, deUint32 wrapR);
1469 ~Vertex3DTextureCase (void);
1473 IterateResult iterate (void);
1476 typedef PosTexCoordQuadGrid<TEXTURETYPE_3D> Grid;
1478 Vertex3DTextureCase (const Vertex3DTextureCase& other);
1479 Vertex3DTextureCase& operator= (const Vertex3DTextureCase& other);
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;
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;
1492 const glu::ShaderProgram* m_program;
1493 glu::Texture3D* m_textures[2]; // 2 textures, a gradient texture and a grid texture.
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)
1503 , m_program (DE_NULL)
1505 m_textures[0] = DE_NULL;
1506 m_textures[1] = DE_NULL;
1509 Vertex3DTextureCase::~Vertex3DTextureCase(void)
1511 Vertex3DTextureCase::deinit();
1514 void Vertex3DTextureCase::init (void)
1516 const char* const vertexShaderSource =
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"
1526 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
1527 " v_color = textureLod(u_texture, a_texCoord, u_lod);\n"
1530 const char* const fragmentShaderSource =
1532 "layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
1533 "in mediump vec4 v_color;\n"
1537 " dEQP_FragColor = v_color;\n"
1540 if (m_context.getRenderTarget().getNumSamples() != 0)
1541 throw tcu::NotSupportedError("MSAA config not supported by this test");
1545 DE_ASSERT(!m_program);
1546 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShaderSource, fragmentShaderSource));
1548 if(!m_program->isOk())
1550 m_testCtx.getLog() << *m_program;
1552 GLint maxVertexTextures;
1553 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
1555 if (maxVertexTextures < 1)
1556 throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
1558 TCU_FAIL("Failed to compile shader");
1561 // Make the textures.
1565 const int texWidth = WIDTH_3D;
1566 const int texHeight = HEIGHT_3D;
1567 const int texDepth = DEPTH_3D;
1569 for (int i = 0; i < 2; i++)
1571 DE_ASSERT(!m_textures[i]);
1572 m_textures[i] = new glu::Texture3D(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight, texDepth);
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;
1580 // Fill first with gradient texture.
1581 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
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;
1586 m_textures[0]->getRefTexture().allocLevel(levelNdx);
1587 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
1590 // Fill second with grid texture.
1591 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
1593 const deUint32 step = 0x00ffffff / numLevels;
1594 const deUint32 rgb = step*levelNdx;
1595 const deUint32 colorA = 0xff000000 | rgb;
1596 const deUint32 colorB = 0xff000000 | ~rgb;
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);
1603 for (int i = 0; i < 2; i++)
1604 m_textures[i]->upload();
1606 catch (const std::exception&)
1608 // Clean up to save memory.
1609 Vertex3DTextureCase::deinit();
1614 void Vertex3DTextureCase::deinit (void)
1616 for (int i = 0; i < 2; i++)
1618 delete m_textures[i];
1619 m_textures[i] = DE_NULL;
1623 m_program = DE_NULL;
1626 float Vertex3DTextureCase::calculateLod (const Mat3& transf, const Vec2& dstSize, int textureNdx) const
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();
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);
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();
1646 return deFloatLog2(deFloatSqrt(de::max(dudx*dudx + dvdx*dvdx + dwdx*dwdx, dudy*dudy + dvdy*dvdy + dwdy*dwdy)));
1649 Vertex3DTextureCase::IterateResult Vertex3DTextureCase::iterate (void)
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);
1654 const int viewportXOffsetMax = m_context.getRenderTarget().getWidth() - viewportWidth;
1655 const int viewportYOffsetMax = m_context.getRenderTarget().getHeight() - viewportHeight;
1657 de::Random rnd (deStringHash(getName()));
1659 const int viewportXOffset = rnd.getInt(0, viewportXOffsetMax);
1660 const int viewportYOffset = rnd.getInt(0, viewportYOffsetMax);
1662 glUseProgram(m_program->getProgram());
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;
1671 glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
1672 glClear(GL_COLOR_BUFFER_BIT);
1674 // Shear to get all slices visible.
1675 static const float depthShearTransfData[] =
1682 // Minification and magnification transformations.
1683 static const float texMinTransfData[] =
1689 static const float texMagTransfData[] =
1696 // Transformation matrices for minification and magnification.
1697 const Mat3 texMinTransf = Mat3(depthShearTransfData) * Mat3(texMinTransfData);
1698 const Mat3 texMagTransf = Mat3(depthShearTransfData) * Mat3(texMagTransfData);
1700 // Surface for the reference image.
1701 tcu::Surface refImage(viewportWidth, viewportHeight);
1708 const Mat3 texTransform;
1709 Render (const Rect& r, int tN, const Mat3& tT) : region(r), textureNdx(tN), texTransform(tT) {}
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)
1718 for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
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);
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);
1732 // Read back rendered results.
1733 tcu::Surface resImage(viewportWidth, viewportHeight);
1734 glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
1740 const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
1742 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
1743 isOk ? "Pass" : "Image comparison failed");
1749 void Vertex3DTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
1751 const deUint32 programID = m_program->getProgram();
1753 // SETUP ATTRIBUTES.
1756 const int positionLoc = glGetAttribLocation(programID, "a_position");
1757 if (positionLoc != -1)
1759 glEnableVertexAttribArray(positionLoc);
1760 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
1765 const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
1766 if (texCoordLoc != -1)
1768 glEnableVertexAttribArray(texCoordLoc);
1769 glVertexAttribPointer(texCoordLoc, 3, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
1776 const int lodLoc = glGetUniformLocation(programID, "u_lod");
1778 glUniform1f(lodLoc, lod);
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);
1790 const int texLoc = glGetUniformLocation(programID, "u_texture");
1792 glUniform1i(texLoc, 0);
1796 // Renders one sub-image with given parameters.
1797 void Vertex3DTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
1799 setupShaderInputs(textureNdx, lod, grid);
1800 glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
1803 // Computes reference for one sub-image with given parameters.
1804 void Vertex3DTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
1806 computeReference(m_textures[textureNdx]->getRefTexture(), lod, glu::mapGLSampler(m_wrapS, m_wrapT, m_wrapR, m_minFilter, m_magFilter), grid, dst, dstRegion);
1809 VertexTextureTests::VertexTextureTests (Context& context)
1810 : TestCaseGroup(context, "vertex", "Vertex Texture Tests")
1814 VertexTextureTests::~VertexTextureTests(void)
1818 void VertexTextureTests::init (void)
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");
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);
1844 addChild(groupCube);
1845 addChild(group2DArray);
1854 { "clamp", GL_CLAMP_TO_EDGE },
1855 { "repeat", GL_REPEAT },
1856 { "mirror", GL_MIRRORED_REPEAT }
1863 } minFilterModes[] =
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 }
1877 } magFilterModes[] =
1879 { "nearest", GL_NEAREST },
1880 { "linear", GL_LINEAR }
1883 #define FOR_EACH(ITERATOR, ARRAY, BODY) \
1884 for (int ITERATOR = 0; ITERATOR < DE_LENGTH_OF_ARRAY(ARRAY); ITERATOR++) \
1889 FOR_EACH(minFilter, minFilterModes,
1890 FOR_EACH(magFilter, magFilterModes,
1891 FOR_EACH(wrapMode, wrapModes,
1893 const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1895 filteringGroup2D->addChild(new Vertex2DTextureCase(m_context,
1897 minFilterModes[minFilter].mode,
1898 magFilterModes[magFilter].mode,
1899 wrapModes[wrapMode].mode,
1900 wrapModes[wrapMode].mode));
1903 FOR_EACH(wrapSMode, wrapModes,
1904 FOR_EACH(wrapTMode, wrapModes,
1906 const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
1908 wrapGroup2D->addChild(new Vertex2DTextureCase(m_context,
1910 GL_LINEAR_MIPMAP_LINEAR,
1912 wrapModes[wrapSMode].mode,
1913 wrapModes[wrapTMode].mode));
1918 FOR_EACH(minFilter, minFilterModes,
1919 FOR_EACH(magFilter, magFilterModes,
1920 FOR_EACH(wrapMode, wrapModes,
1922 const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1924 filteringGroupCube->addChild(new VertexCubeTextureCase(m_context,
1926 minFilterModes[minFilter].mode,
1927 magFilterModes[magFilter].mode,
1928 wrapModes[wrapMode].mode,
1929 wrapModes[wrapMode].mode));
1932 FOR_EACH(wrapSMode, wrapModes,
1933 FOR_EACH(wrapTMode, wrapModes,
1935 const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
1937 wrapGroupCube->addChild(new VertexCubeTextureCase(m_context,
1939 GL_LINEAR_MIPMAP_LINEAR,
1941 wrapModes[wrapSMode].mode,
1942 wrapModes[wrapTMode].mode));
1947 FOR_EACH(minFilter, minFilterModes,
1948 FOR_EACH(magFilter, magFilterModes,
1949 FOR_EACH(wrapMode, wrapModes,
1951 const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1953 filteringGroup2DArray->addChild(new Vertex2DArrayTextureCase(m_context,
1955 minFilterModes[minFilter].mode,
1956 magFilterModes[magFilter].mode,
1957 wrapModes[wrapMode].mode,
1958 wrapModes[wrapMode].mode));
1961 FOR_EACH(wrapSMode, wrapModes,
1962 FOR_EACH(wrapTMode, wrapModes,
1964 const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
1966 wrapGroup2DArray->addChild(new Vertex2DArrayTextureCase(m_context,
1968 GL_LINEAR_MIPMAP_LINEAR,
1970 wrapModes[wrapSMode].mode,
1971 wrapModes[wrapTMode].mode));
1976 FOR_EACH(minFilter, minFilterModes,
1977 FOR_EACH(magFilter, magFilterModes,
1978 FOR_EACH(wrapMode, wrapModes,
1980 const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1982 filteringGroup3D->addChild(new Vertex3DTextureCase(m_context,
1984 minFilterModes[minFilter].mode,
1985 magFilterModes[magFilter].mode,
1986 wrapModes[wrapMode].mode,
1987 wrapModes[wrapMode].mode,
1988 wrapModes[wrapMode].mode));
1991 FOR_EACH(wrapSMode, wrapModes,
1992 FOR_EACH(wrapTMode, wrapModes,
1993 FOR_EACH(wrapRMode, wrapModes,
1995 const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name + "_" + wrapModes[wrapRMode].name;
1997 wrapGroup3D->addChild(new Vertex3DTextureCase(m_context,
1999 GL_LINEAR_MIPMAP_LINEAR,
2001 wrapModes[wrapSMode].mode,
2002 wrapModes[wrapTMode].mode,
2003 wrapModes[wrapRMode].mode));