1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 2.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 "es2fVertexTextureTests.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 "tcuTexVerifierUtil.hpp"
33 #include "tcuImageCompare.hpp"
34 #include "deRandom.hpp"
35 #include "deString.h"
36 #include "deMath.h"
37
38 #include <string>
39 #include <vector>
40
41 #include <limits>
42
43 #include "glw.h"
44
45 using tcu::TestLog;
46 using tcu::Vec2;
47 using tcu::Vec3;
48 using tcu::Vec4;
49 using tcu::IVec2;
50 using tcu::IVec3;
51 using tcu::IVec4;
52 using tcu::Mat3;
53 using std::string;
54 using std::vector;
55
56 namespace deqp
57 {
58
59 using namespace gls::TextureTestUtil;
60 using namespace glu::TextureTestUtil;
61
62 using glu::TextureTestUtil::TEXTURETYPE_2D;
63 using glu::TextureTestUtil::TEXTURETYPE_CUBE;
64
65 namespace gles2
66 {
67 namespace Functional
68 {
69
70 // The 2D case draws four images.
71 static const int MAX_2D_RENDER_WIDTH = 128*2;
72 static const int MAX_2D_RENDER_HEIGHT = 128*2;
73
74 // The cube map case draws four 3-by-2 image groups.
75 static const int MAX_CUBE_RENDER_WIDTH = 28*2*3;
76 static const int MAX_CUBE_RENDER_HEIGHT = 28*2*2;
77
78 static const int GRID_SIZE_2D = 127;
79 static const int GRID_SIZE_CUBE = 63;
80
81 // Helpers for making texture coordinates "safe", i.e. move them further from coordinate bounary.
82
83 // Moves x towards the closest K+targetFraction, where K is an integer.
84 // E.g. moveTowardsFraction(x, 0.5f) moves x away from integer boundaries.
moveTowardsFraction(float x,float targetFraction)85 static inline float moveTowardsFraction (float x, float targetFraction)
86 {
87 const float strictness = 0.5f;
88 DE_ASSERT(0.0f < strictness && strictness <= 1.0f);
89 DE_ASSERT(de::inBounds(targetFraction, 0.0f, 1.0f));
90 const float y = x + 0.5f - targetFraction;
91 return deFloatFloor(y) + deFloatFrac(y)*(1.0f-strictness) + strictness*0.5f - 0.5f + targetFraction;
92 }
93
safeCoord(float raw,int scale,float fraction)94 static inline float safeCoord (float raw, int scale, float fraction)
95 {
96 const float scaleFloat = (float)scale;
97 return moveTowardsFraction(raw*scaleFloat, fraction) / scaleFloat;
98 }
99
100 template <int Size>
safeCoords(const tcu::Vector<float,Size> & raw,const tcu::Vector<int,Size> & scale,const tcu::Vector<float,Size> & fraction)101 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)
102 {
103 tcu::Vector<float, Size> result;
104 for (int i = 0; i < Size; i++)
105 result[i] = safeCoord(raw[i], scale[i], fraction[i]);
106 return result;
107 }
108
safe2DTexCoords(const Vec2 & raw,const IVec2 & textureSize)109 static inline Vec2 safe2DTexCoords (const Vec2& raw, const IVec2& textureSize)
110 {
111 return safeCoords(raw, textureSize, Vec2(0.5f));
112 }
113
114 namespace
115 {
116
117 struct Rect
118 {
Rectdeqp::gles2::Functional::__anonc2e8d0630111::Rect119 Rect (int x_, int y_, int w_, int h_) : x(x_), y(y_), w(w_), h(h_) {}
posdeqp::gles2::Functional::__anonc2e8d0630111::Rect120 IVec2 pos (void) const { return IVec2(x, y); }
sizedeqp::gles2::Functional::__anonc2e8d0630111::Rect121 IVec2 size (void) const { return IVec2(w, h); }
122
123 int x;
124 int y;
125 int w;
126 int h;
127 };
128
129 template <TextureType> struct TexTypeTcuClass;
130 template <> struct TexTypeTcuClass<TEXTURETYPE_2D> { typedef tcu::Texture2D t; };
131 template <> struct TexTypeTcuClass<TEXTURETYPE_CUBE> { typedef tcu::TextureCube t; };
132
133 template <TextureType> struct TexTypeSizeDims;
134 template <> struct TexTypeSizeDims<TEXTURETYPE_2D> { enum { V = 2 }; };
135 template <> struct TexTypeSizeDims<TEXTURETYPE_CUBE> { enum { V = 2 }; };
136
137 template <TextureType> struct TexTypeCoordDims;
138 template <> struct TexTypeCoordDims<TEXTURETYPE_2D> { enum { V = 2 }; };
139 template <> struct TexTypeCoordDims<TEXTURETYPE_CUBE> { enum { V = 3 }; };
140
141 template <TextureType TexType> struct TexTypeSizeIVec { typedef tcu::Vector<int, TexTypeSizeDims<TexType>::V> t; };
142 template <TextureType TexType> struct TexTypeCoordVec { typedef tcu::Vector<float, TexTypeCoordDims<TexType>::V> t; };
143
144 template <TextureType> struct TexTypeCoordParams;
145
146 template <> struct
147 TexTypeCoordParams<TEXTURETYPE_2D>
148 {
149 Vec2 scale;
150 Vec2 bias;
151
TexTypeCoordParamsdeqp::gles2::Functional::__anonc2e8d0630111::TexTypeCoordParams152 TexTypeCoordParams (const Vec2& scale_, const Vec2& bias_) : scale(scale_), bias(bias_) {}
153 };
154
155 template <> struct
156 TexTypeCoordParams<TEXTURETYPE_CUBE>
157 {
158 Vec2 scale;
159 Vec2 bias;
160 tcu::CubeFace face;
161
TexTypeCoordParamsdeqp::gles2::Functional::__anonc2e8d0630111::TexTypeCoordParams162 TexTypeCoordParams (const Vec2& scale_, const Vec2& bias_, tcu::CubeFace face_) : scale(scale_), bias(bias_), face(face_) {}
163 };
164
165 /*--------------------------------------------------------------------*//*!
166 * \brief Quad grid class containing position and texture coordinate data.
167 *
168 * A quad grid of size S means a grid consisting of S*S quads (S rows and
169 * S columns). The quads are rectangles with main axis aligned sides, and
170 * each consists of two triangles. Note that although there are only
171 * (S+1)*(S+1) distinct vertex positions, there are S*S*4 distinct vertices
172 * because we want texture coordinates to be constant across the vertices
173 * of a quad (to avoid interpolation issues), and thus each quad needs its
174 * own 4 vertices.
175 *
176 * Pointers returned by get*Ptr() are suitable for gl calls such as
177 * glVertexAttribPointer() (for position and tex coord) or glDrawElements()
178 * (for indices).
179 *//*--------------------------------------------------------------------*/
180 template <TextureType TexType>
181 class PosTexCoordQuadGrid
182 {
183 private:
184 enum { TEX_COORD_DIMS = TexTypeCoordDims <TexType>::V };
185 typedef typename TexTypeCoordVec<TexType>::t TexCoordVec;
186 typedef typename TexTypeSizeIVec<TexType>::t TexSizeIVec;
187 typedef TexTypeCoordParams<TexType> TexCoordParams;
188
189 public:
190 PosTexCoordQuadGrid (int gridSize, const IVec2& renderSize, const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords);
191
getSize(void) const192 int getSize (void) const { return m_gridSize; }
193 Vec4 getQuadLDRU (int col, int row) const; //!< Vec4(leftX, downY, rightX, upY)
194 const TexCoordVec& getQuadTexCoord (int col, int row) const;
195
getNumIndices(void) const196 int getNumIndices (void) const { return m_gridSize*m_gridSize*3*2; }
getPositionPtr(void) const197 const float* getPositionPtr (void) const { DE_STATIC_ASSERT(sizeof(Vec2) == 2*sizeof(float)); return (float*)&m_positions[0]; }
getTexCoordPtr(void) const198 const float* getTexCoordPtr (void) const { DE_STATIC_ASSERT(sizeof(TexCoordVec) == TEX_COORD_DIMS*(int)sizeof(float)); return (float*)&m_texCoords[0]; }
getIndexPtr(void) const199 const deUint16* getIndexPtr (void) const { return &m_indices[0]; }
200
201 private:
202 void initializeTexCoords (const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords);
203
204 const int m_gridSize;
205 vector<Vec2> m_positions;
206 vector<TexCoordVec> m_texCoords;
207 vector<deUint16> m_indices;
208 };
209
210 template <TextureType TexType>
getQuadLDRU(int col,int row) const211 Vec4 PosTexCoordQuadGrid<TexType>::getQuadLDRU (int col, int row) const
212 {
213 int ndx00 = (row*m_gridSize + col) * 4;
214 int ndx11 = ndx00 + 3;
215
216 return Vec4(m_positions[ndx00].x(),
217 m_positions[ndx00].y(),
218 m_positions[ndx11].x(),
219 m_positions[ndx11].y());
220 }
221
222 template <TextureType TexType>
getQuadTexCoord(int col,int row) const223 const typename TexTypeCoordVec<TexType>::t& PosTexCoordQuadGrid<TexType>::getQuadTexCoord (int col, int row) const
224 {
225 return m_texCoords[(row*m_gridSize + col) * 4];
226 }
227
228 template <TextureType TexType>
PosTexCoordQuadGrid(int gridSize,const IVec2 & renderSize,const TexSizeIVec & textureSize,const TexCoordParams & texCoordParams,bool useSafeTexCoords)229 PosTexCoordQuadGrid<TexType>::PosTexCoordQuadGrid (int gridSize, const IVec2& renderSize, const TexSizeIVec& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
230 : m_gridSize(gridSize)
231 {
232 DE_ASSERT(m_gridSize > 0 && m_gridSize*m_gridSize <= (int)std::numeric_limits<deUint16>::max() + 1);
233
234 const float gridSizeFloat = (float)m_gridSize;
235
236 m_positions.reserve(m_gridSize*m_gridSize*4);
237 m_indices.reserve(m_gridSize*m_gridSize*3*2);
238
239 for (int y = 0; y < m_gridSize; y++)
240 for (int x = 0; x < m_gridSize; x++)
241 {
242 float fx0 = (float)(x+0) / gridSizeFloat;
243 float fx1 = (float)(x+1) / gridSizeFloat;
244 float fy0 = (float)(y+0) / gridSizeFloat;
245 float fy1 = (float)(y+1) / gridSizeFloat;
246
247 Vec2 quadVertices[4] = { Vec2(fx0, fy0), Vec2(fx1, fy0), Vec2(fx0, fy1), Vec2(fx1, fy1) };
248
249 int firstNdx = (int)m_positions.size();
250
251 for (int i = 0; i < DE_LENGTH_OF_ARRAY(quadVertices); i++)
252 m_positions.push_back(safeCoords(quadVertices[i], renderSize, Vec2(0.0f)) * 2.0f - 1.0f);
253
254 m_indices.push_back(deUint16(firstNdx + 0));
255 m_indices.push_back(deUint16(firstNdx + 1));
256 m_indices.push_back(deUint16(firstNdx + 2));
257
258 m_indices.push_back(deUint16(firstNdx + 1));
259 m_indices.push_back(deUint16(firstNdx + 3));
260 m_indices.push_back(deUint16(firstNdx + 2));
261 }
262
263 m_texCoords.reserve(m_gridSize*m_gridSize*4);
264 initializeTexCoords(textureSize, texCoordParams, useSafeTexCoords);
265
266 DE_ASSERT((int)m_positions.size() == m_gridSize*m_gridSize*4);
267 DE_ASSERT((int)m_indices.size() == m_gridSize*m_gridSize*3*2);
268 DE_ASSERT((int)m_texCoords.size() == m_gridSize*m_gridSize*4);
269 }
270
271 template <>
initializeTexCoords(const IVec2 & textureSize,const TexCoordParams & texCoordParams,bool useSafeTexCoords)272 void PosTexCoordQuadGrid<TEXTURETYPE_2D>::initializeTexCoords (const IVec2& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
273 {
274 DE_ASSERT(m_texCoords.empty());
275
276 const float gridSizeFloat = (float)m_gridSize;
277
278 for (int y = 0; y < m_gridSize; y++)
279 for (int x = 0; x < m_gridSize; x++)
280 {
281 Vec2 rawCoord = Vec2((float)x / gridSizeFloat, (float)y / gridSizeFloat) * texCoordParams.scale + texCoordParams.bias;
282
283 for (int i = 0; i < 4; i++)
284 m_texCoords.push_back(useSafeTexCoords ? safe2DTexCoords(rawCoord, textureSize) : rawCoord);
285 }
286 }
287
288 template <>
initializeTexCoords(const IVec2 & textureSize,const TexCoordParams & texCoordParams,bool useSafeTexCoords)289 void PosTexCoordQuadGrid<TEXTURETYPE_CUBE>::initializeTexCoords (const IVec2& textureSize, const TexCoordParams& texCoordParams, bool useSafeTexCoords)
290 {
291 DE_ASSERT(m_texCoords.empty());
292
293 const float gridSizeFloat = (float)m_gridSize;
294 vector<float> texBoundaries;
295 computeQuadTexCoordCube(texBoundaries, texCoordParams.face);
296 const Vec3 coordA = Vec3(texBoundaries[0], texBoundaries[1], texBoundaries[2]);
297 const Vec3 coordB = Vec3(texBoundaries[3], texBoundaries[4], texBoundaries[5]);
298 const Vec3 coordC = Vec3(texBoundaries[6], texBoundaries[7], texBoundaries[8]);
299 const Vec3 coordAB = coordB - coordA;
300 const Vec3 coordAC = coordC - coordA;
301
302 for (int y = 0; y < m_gridSize; y++)
303 for (int x = 0; x < m_gridSize; x++)
304 {
305 const Vec2 rawFaceCoord = texCoordParams.scale * Vec2((float)x / gridSizeFloat, (float)y / gridSizeFloat) + texCoordParams.bias;
306 const Vec2 safeFaceCoord = useSafeTexCoords ? safe2DTexCoords(rawFaceCoord, textureSize) : rawFaceCoord;
307 const Vec3 texCoord = coordA + coordAC*safeFaceCoord.x() + coordAB*safeFaceCoord.y();
308
309 for (int i = 0; i < 4; i++)
310 m_texCoords.push_back(texCoord);
311 }
312 }
313
314 } // anonymous
315
isLevelNearest(deUint32 filter)316 static inline bool isLevelNearest (deUint32 filter)
317 {
318 return filter == GL_NEAREST || filter == GL_NEAREST_MIPMAP_NEAREST || filter == GL_NEAREST_MIPMAP_LINEAR;
319 }
320
getTextureSize(const glu::Texture2D & tex)321 static inline IVec2 getTextureSize (const glu::Texture2D& tex)
322 {
323 const tcu::Texture2D& ref = tex.getRefTexture();
324 return IVec2(ref.getWidth(), ref.getHeight());
325 }
326
getTextureSize(const glu::TextureCube & tex)327 static inline IVec2 getTextureSize (const glu::TextureCube& tex)
328 {
329 const tcu::TextureCube& ref = tex.getRefTexture();
330 return IVec2(ref.getSize(), ref.getSize());
331 }
332
333 template <TextureType TexType>
setPixelColors(const vector<Vec4> & quadColors,const Rect & region,const PosTexCoordQuadGrid<TexType> & grid,tcu::Surface & dst)334 static void setPixelColors (const vector<Vec4>& quadColors, const Rect& region, const PosTexCoordQuadGrid<TexType>& grid, tcu::Surface& dst)
335 {
336 const int gridSize = grid.getSize();
337
338 for (int y = 0; y < gridSize; y++)
339 for (int x = 0; x < gridSize; x++)
340 {
341 const Vec4 color = quadColors[y*gridSize + x];
342 const Vec4 ldru = grid.getQuadLDRU(x, y) * 0.5f + 0.5f; // [-1, 1] -> [0, 1]
343 const int ix0 = deCeilFloatToInt32(ldru.x() * (float)region.w - 0.5f);
344 const int ix1 = deCeilFloatToInt32(ldru.z() * (float)region.w - 0.5f);
345 const int iy0 = deCeilFloatToInt32(ldru.y() * (float)region.h - 0.5f);
346 const int iy1 = deCeilFloatToInt32(ldru.w() * (float)region.h - 0.5f);
347
348 for (int iy = iy0; iy < iy1; iy++)
349 for (int ix = ix0; ix < ix1; ix++)
350 {
351 DE_ASSERT(deInBounds32(ix + region.x, 0, dst.getWidth()));
352 DE_ASSERT(deInBounds32(iy + region.y, 0, dst.getHeight()));
353
354 dst.setPixel(ix + region.x, iy + region.y, tcu::RGBA(color));
355 }
356 }
357 }
358
sample(const tcu::Texture2D & tex,const Vec2 & coord,float lod,const tcu::Sampler & sam)359 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)360 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); }
361
362 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)363 void computeReference (const typename TexTypeTcuClass<TexType>::t& texture, float lod, const tcu::Sampler& sampler, const PosTexCoordQuadGrid<TexType>& grid, tcu::Surface& dst, const Rect& dstRegion)
364 {
365 const int gridSize = grid.getSize();
366 vector<Vec4> quadColors (gridSize*gridSize);
367
368 for (int y = 0; y < gridSize; y++)
369 for (int x = 0; x < gridSize; x++)
370 {
371 const int ndx = y*gridSize + x;
372 const typename TexTypeCoordVec<TexType>::t& coord = grid.getQuadTexCoord(x, y);
373
374 quadColors[ndx] = sample(texture, coord, lod, sampler);
375 }
376
377 setPixelColors(quadColors, dstRegion, grid, dst);
378 }
379
compareImages(const glu::RenderContext & renderCtx,tcu::TestLog & log,const tcu::Surface & ref,const tcu::Surface & res)380 static bool compareImages (const glu::RenderContext& renderCtx, tcu::TestLog& log, const tcu::Surface& ref, const tcu::Surface& res)
381 {
382 DE_ASSERT(renderCtx.getRenderTarget().getNumSamples() == 0);
383
384 const tcu::RGBA threshold = renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(15,15,15,15);
385 return tcu::pixelThresholdCompare(log, "Result", "Image compare result", ref, res, threshold, tcu::COMPARE_LOG_RESULT);
386 }
387
388 class Vertex2DTextureCase : public TestCase
389 {
390 public:
391 Vertex2DTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
392 ~Vertex2DTextureCase (void);
393
394 void init (void);
395 void deinit (void);
396 IterateResult iterate (void);
397
398 private:
399 typedef PosTexCoordQuadGrid<TEXTURETYPE_2D> Grid;
400
401 Vertex2DTextureCase (const Vertex2DTextureCase& other);
402 Vertex2DTextureCase& operator= (const Vertex2DTextureCase& other);
403
404 float calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const;
405 void setupShaderInputs (int textureNdx, float lod, const Grid& grid) const;
406 void renderCell (int textureNdx, float lod, const Grid& grid) const;
407 void computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const;
408
409 const deUint32 m_minFilter;
410 const deUint32 m_magFilter;
411 const deUint32 m_wrapS;
412 const deUint32 m_wrapT;
413
414 const glu::ShaderProgram* m_program;
415 glu::Texture2D* m_textures[2]; // 2 textures, a gradient texture and a grid texture.
416 };
417
Vertex2DTextureCase(Context & testCtx,const char * name,const char * desc,deUint32 minFilter,deUint32 magFilter,deUint32 wrapS,deUint32 wrapT)418 Vertex2DTextureCase::Vertex2DTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT)
419 : TestCase (testCtx, tcu::NODETYPE_SELF_VALIDATE, name, desc)
420 , m_minFilter (minFilter)
421 , m_magFilter (magFilter)
422 , m_wrapS (wrapS)
423 , m_wrapT (wrapT)
424 , m_program (DE_NULL)
425 {
426 m_textures[0] = DE_NULL;
427 m_textures[1] = DE_NULL;
428 }
429
~Vertex2DTextureCase(void)430 Vertex2DTextureCase::~Vertex2DTextureCase(void)
431 {
432 Vertex2DTextureCase::deinit();
433 }
434
init(void)435 void Vertex2DTextureCase::init (void)
436 {
437 const char* const vertexShader =
438 "attribute highp vec2 a_position;\n"
439 "attribute highp vec2 a_texCoord;\n"
440 "uniform highp sampler2D u_texture;\n"
441 "uniform highp float u_lod;\n"
442 "varying mediump vec4 v_color;\n"
443 "\n"
444 "void main()\n"
445 "{\n"
446 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
447 " v_color = texture2DLod(u_texture, a_texCoord, u_lod);\n"
448 "}\n";
449
450 const char* const fragmentShader =
451 "varying mediump vec4 v_color;\n"
452 "\n"
453 "void main()\n"
454 "{\n"
455 " gl_FragColor = v_color;\n"
456 "}\n";
457
458 if (m_context.getRenderTarget().getNumSamples() != 0)
459 throw tcu::NotSupportedError("MSAA config not supported by this test");
460
461 DE_ASSERT(!m_program);
462 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShader, fragmentShader));
463
464 if(!m_program->isOk())
465 {
466 m_testCtx.getLog() << *m_program;
467
468 GLint maxVertexTextures;
469 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
470
471 if (maxVertexTextures < 1)
472 throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
473 else
474 TCU_FAIL("Failed to compile shader");
475 }
476
477 // Make the textures.
478 try
479 {
480 // Compute suitable power-of-two sizes (for mipmaps).
481 const int texWidth = 1 << deLog2Ceil32(MAX_2D_RENDER_WIDTH / 2);
482 const int texHeight = 1 << deLog2Ceil32(MAX_2D_RENDER_HEIGHT / 2);
483
484 for (int i = 0; i < 2; i++)
485 {
486 DE_ASSERT(!m_textures[i]);
487 m_textures[i] = new glu::Texture2D(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth, texHeight);
488 }
489
490 const bool mipmaps = (deIsPowerOfTwo32(texWidth) && deIsPowerOfTwo32(texHeight));
491 const int numLevels = mipmaps ? deLog2Floor32(de::max(texWidth, texHeight))+1 : 1;
492 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
493 const Vec4 cBias = fmtInfo.valueMin;
494 const Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
495
496 // Fill first with gradient texture.
497 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
498 {
499 const Vec4 gMin = Vec4(-0.5f, -0.5f, -0.5f, 2.0f)*cScale + cBias;
500 const Vec4 gMax = Vec4( 1.0f, 1.0f, 1.0f, 0.0f)*cScale + cBias;
501
502 m_textures[0]->getRefTexture().allocLevel(levelNdx);
503 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevel(levelNdx), gMin, gMax);
504 }
505
506 // Fill second with grid texture.
507 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
508 {
509 const deUint32 step = 0x00ffffff / numLevels;
510 const deUint32 rgb = step*levelNdx;
511 const deUint32 colorA = 0xff000000 | rgb;
512 const deUint32 colorB = 0xff000000 | ~rgb;
513
514 m_textures[1]->getRefTexture().allocLevel(levelNdx);
515 tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevel(levelNdx), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
516 }
517
518 // Upload.
519 for (int i = 0; i < 2; i++)
520 m_textures[i]->upload();
521 }
522 catch (const std::exception&)
523 {
524 // Clean up to save memory.
525 Vertex2DTextureCase::deinit();
526 throw;
527 }
528 }
529
deinit(void)530 void Vertex2DTextureCase::deinit (void)
531 {
532 for (int i = 0; i < 2; i++)
533 {
534 delete m_textures[i];
535 m_textures[i] = DE_NULL;
536 }
537
538 delete m_program;
539 m_program = DE_NULL;
540 }
541
calculateLod(const Vec2 & texScale,const Vec2 & dstSize,int textureNdx) const542 float Vertex2DTextureCase::calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const
543 {
544 const tcu::Texture2D& refTexture = m_textures[textureNdx]->getRefTexture();
545 const Vec2 srcSize = Vec2((float)refTexture.getWidth(), (float)refTexture.getHeight());
546 const Vec2 sizeRatio = texScale*srcSize / dstSize;
547
548 // \note In this particular case dv/dx and du/dy are zero, simplifying the expression.
549 return deFloatLog2(de::max(sizeRatio.x(), sizeRatio.y()));
550 }
551
iterate(void)552 Vertex2DTextureCase::IterateResult Vertex2DTextureCase::iterate (void)
553 {
554 const int viewportWidth = deMin32(m_context.getRenderTarget().getWidth(), MAX_2D_RENDER_WIDTH);
555 const int viewportHeight = deMin32(m_context.getRenderTarget().getHeight(), MAX_2D_RENDER_HEIGHT);
556
557 const int viewportXOffsetMax = m_context.getRenderTarget().getWidth() - viewportWidth;
558 const int viewportYOffsetMax = m_context.getRenderTarget().getHeight() - viewportHeight;
559
560 de::Random rnd (deStringHash(getName()));
561
562 const int viewportXOffset = rnd.getInt(0, viewportXOffsetMax);
563 const int viewportYOffset = rnd.getInt(0, viewportYOffsetMax);
564
565 glUseProgram(m_program->getProgram());
566
567 // Divide viewport into 4 cells.
568 const int leftWidth = viewportWidth / 2;
569 const int rightWidth = viewportWidth - leftWidth;
570 const int bottomHeight = viewportHeight / 2;
571 const int topHeight = viewportHeight - bottomHeight;
572
573 // Clear.
574 glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
575 glClear(GL_COLOR_BUFFER_BIT);
576
577 // Texture scaling and offsetting vectors.
578 const Vec2 texMinScale (+1.8f, +1.8f);
579 const Vec2 texMinOffset (-0.3f, -0.2f);
580 const Vec2 texMagScale (+0.3f, +0.3f);
581 const Vec2 texMagOffset (+0.9f, +0.8f);
582
583 // Surface for the reference image.
584 tcu::Surface refImage(viewportWidth, viewportHeight);
585
586 {
587 const struct Render
588 {
589 const Rect region;
590 int textureNdx;
591 const Vec2 texCoordScale;
592 const Vec2 texCoordOffset;
593 Render (const Rect& r, int tN, const Vec2& tS, const Vec2& tO) : region(r), textureNdx(tN), texCoordScale(tS), texCoordOffset(tO) {}
594 } renders[] =
595 {
596 Render(Rect(0, 0, leftWidth, bottomHeight), 0, texMinScale, texMinOffset),
597 Render(Rect(leftWidth, 0, rightWidth, bottomHeight), 0, texMagScale, texMagOffset),
598 Render(Rect(0, bottomHeight, leftWidth, topHeight), 1, texMinScale, texMinOffset),
599 Render(Rect(leftWidth, bottomHeight, rightWidth, topHeight), 1, texMagScale, texMagOffset)
600 };
601
602 for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
603 {
604 const Render& rend = renders[renderNdx];
605 const float lod = calculateLod(rend.texCoordScale, rend.region.size().asFloat(), rend.textureNdx);
606 const bool useSafeTexCoords = isLevelNearest(lod > 0.0f ? m_minFilter : m_magFilter);
607 const Grid grid (GRID_SIZE_2D, rend.region.size(), getTextureSize(*m_textures[rend.textureNdx]),
608 TexTypeCoordParams<TEXTURETYPE_2D>(rend.texCoordScale, rend.texCoordOffset), useSafeTexCoords);
609
610 glViewport(viewportXOffset + rend.region.x, viewportYOffset + rend.region.y, rend.region.w, rend.region.h);
611 renderCell (rend.textureNdx, lod, grid);
612 computeReferenceCell (rend.textureNdx, lod, grid, refImage, rend.region);
613 }
614 }
615
616 // Read back rendered results.
617 tcu::Surface resImage(viewportWidth, viewportHeight);
618 glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
619
620 glUseProgram(0);
621
622 // Compare and log.
623 {
624 const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
625
626 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
627 isOk ? "Pass" : "Image comparison failed");
628 }
629
630 return STOP;
631 }
632
setupShaderInputs(int textureNdx,float lod,const Grid & grid) const633 void Vertex2DTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
634 {
635 const deUint32 programID = m_program->getProgram();
636
637 // SETUP ATTRIBUTES.
638
639 {
640 const int positionLoc = glGetAttribLocation(programID, "a_position");
641 if (positionLoc != -1)
642 {
643 glEnableVertexAttribArray(positionLoc);
644 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
645 }
646 }
647
648 {
649 const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
650 if (texCoordLoc != -1)
651 {
652 glEnableVertexAttribArray(texCoordLoc);
653 glVertexAttribPointer(texCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
654 }
655 }
656
657 // SETUP UNIFORMS.
658
659 {
660 const int lodLoc = glGetUniformLocation(programID, "u_lod");
661 if (lodLoc != -1)
662 glUniform1f(lodLoc, lod);
663 }
664
665 glActiveTexture(GL_TEXTURE0);
666 glBindTexture(GL_TEXTURE_2D, m_textures[textureNdx]->getGLTexture());
667 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, m_wrapS);
668 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, m_wrapT);
669 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, m_minFilter);
670 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, m_magFilter);
671
672 {
673 const int texLoc = glGetUniformLocation(programID, "u_texture");
674 if (texLoc != -1)
675 glUniform1i(texLoc, 0);
676 }
677 }
678
679 // Renders one sub-image with given parameters.
renderCell(int textureNdx,float lod,const Grid & grid) const680 void Vertex2DTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
681 {
682 setupShaderInputs(textureNdx, lod, grid);
683 glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
684 }
685
computeReferenceCell(int textureNdx,float lod,const Grid & grid,tcu::Surface & dst,const Rect & dstRegion) const686 void Vertex2DTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
687 {
688 computeReference(m_textures[textureNdx]->getRefTexture(), lod, glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter), grid, dst, dstRegion);
689 }
690
691 class VertexCubeTextureCase : public TestCase
692 {
693 public:
694 VertexCubeTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT);
695 ~VertexCubeTextureCase (void);
696
697 void init (void);
698 void deinit (void);
699 IterateResult iterate (void);
700
701 private:
702 typedef PosTexCoordQuadGrid<TEXTURETYPE_CUBE> Grid;
703
704 VertexCubeTextureCase (const VertexCubeTextureCase& other);
705 VertexCubeTextureCase& operator= (const VertexCubeTextureCase& other);
706
707 float calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const;
708 void setupShaderInputs (int textureNdx, float lod, const Grid& grid) const;
709 void renderCell (int textureNdx, float lod, const Grid& grid) const;
710 void computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const;
711
712 const deUint32 m_minFilter;
713 const deUint32 m_magFilter;
714 const deUint32 m_wrapS;
715 const deUint32 m_wrapT;
716
717 const glu::ShaderProgram* m_program;
718 glu::TextureCube* m_textures[2]; // 2 textures, a gradient texture and a grid texture.
719 };
720
VertexCubeTextureCase(Context & testCtx,const char * name,const char * desc,deUint32 minFilter,deUint32 magFilter,deUint32 wrapS,deUint32 wrapT)721 VertexCubeTextureCase::VertexCubeTextureCase (Context& testCtx, const char* name, const char* desc, deUint32 minFilter, deUint32 magFilter, deUint32 wrapS, deUint32 wrapT)
722 : TestCase (testCtx, tcu::NODETYPE_SELF_VALIDATE, name, desc)
723 , m_minFilter (minFilter)
724 , m_magFilter (magFilter)
725 , m_wrapS (wrapS)
726 , m_wrapT (wrapT)
727 , m_program (DE_NULL)
728 {
729 m_textures[0] = DE_NULL;
730 m_textures[1] = DE_NULL;
731 }
732
~VertexCubeTextureCase(void)733 VertexCubeTextureCase::~VertexCubeTextureCase(void)
734 {
735 VertexCubeTextureCase::deinit();
736 }
737
init(void)738 void VertexCubeTextureCase::init (void)
739 {
740 const char* const vertexShader =
741 "attribute highp vec2 a_position;\n"
742 "attribute highp vec3 a_texCoord;\n"
743 "uniform highp samplerCube u_texture;\n"
744 "uniform highp float u_lod;\n"
745 "varying mediump vec4 v_color;\n"
746 "\n"
747 "void main()\n"
748 "{\n"
749 " gl_Position = vec4(a_position, 0.0, 1.0);\n"
750 " v_color = textureCubeLod(u_texture, a_texCoord, u_lod);\n"
751 "}\n";
752
753 const char* const fragmentShader =
754 "varying mediump vec4 v_color;\n"
755 "\n"
756 "void main()\n"
757 "{\n"
758 " gl_FragColor = v_color;\n"
759 "}\n";
760
761 if (m_context.getRenderTarget().getNumSamples() != 0)
762 throw tcu::NotSupportedError("MSAA config not supported by this test");
763
764 DE_ASSERT(!m_program);
765 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(vertexShader, fragmentShader));
766
767 if(!m_program->isOk())
768 {
769 m_testCtx.getLog() << *m_program;
770
771 GLint maxVertexTextures;
772 glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &maxVertexTextures);
773
774 if (maxVertexTextures < 1)
775 throw tcu::NotSupportedError("Vertex texture image units not supported", "", __FILE__, __LINE__);
776 else
777 TCU_FAIL("Failed to compile shader");
778 }
779
780 // Make the textures.
781 try
782 {
783 // Compute suitable power-of-two sizes (for mipmaps).
784 const int texWidth = 1 << deLog2Ceil32(MAX_CUBE_RENDER_WIDTH / 3 / 2);
785 const int texHeight = 1 << deLog2Ceil32(MAX_CUBE_RENDER_HEIGHT / 2 / 2);
786
787 DE_ASSERT(texWidth == texHeight);
788 DE_UNREF(texHeight);
789
790 for (int i = 0; i < 2; i++)
791 {
792 DE_ASSERT(!m_textures[i]);
793 m_textures[i] = new glu::TextureCube(m_context.getRenderContext(), GL_RGB, GL_UNSIGNED_BYTE, texWidth);
794 }
795
796 const bool mipmaps = deIsPowerOfTwo32(texWidth) != DE_FALSE;
797 const int numLevels = mipmaps ? deLog2Floor32(texWidth)+1 : 1;
798 const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(m_textures[0]->getRefTexture().getFormat());
799 const Vec4 cBias = fmtInfo.valueMin;
800 const Vec4 cScale = fmtInfo.valueMax-fmtInfo.valueMin;
801
802 // Fill first with gradient texture.
803 static const Vec4 gradients[tcu::CUBEFACE_LAST][2] =
804 {
805 { Vec4(-1.0f, -1.0f, -1.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative x
806 { Vec4( 0.0f, -1.0f, -1.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive x
807 { Vec4(-1.0f, 0.0f, -1.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // negative y
808 { Vec4(-1.0f, -1.0f, 0.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) }, // positive y
809 { Vec4(-1.0f, -1.0f, -1.0f, 0.0f), Vec4(1.0f, 1.0f, 1.0f, 1.0f) }, // negative z
810 { Vec4( 0.0f, 0.0f, 0.0f, 2.0f), Vec4(1.0f, 1.0f, 1.0f, 0.0f) } // positive z
811 };
812 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
813 {
814 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
815 {
816 m_textures[0]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
817 tcu::fillWithComponentGradients(m_textures[0]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), gradients[face][0]*cScale + cBias, gradients[face][1]*cScale + cBias);
818 }
819 }
820
821 // Fill second with grid texture.
822 for (int face = 0; face < tcu::CUBEFACE_LAST; face++)
823 {
824 for (int levelNdx = 0; levelNdx < numLevels; levelNdx++)
825 {
826 const deUint32 step = 0x00ffffff / (numLevels*tcu::CUBEFACE_LAST);
827 const deUint32 rgb = step*levelNdx*face;
828 const deUint32 colorA = 0xff000000 | rgb;
829 const deUint32 colorB = 0xff000000 | ~rgb;
830
831 m_textures[1]->getRefTexture().allocLevel((tcu::CubeFace)face, levelNdx);
832 tcu::fillWithGrid(m_textures[1]->getRefTexture().getLevelFace(levelNdx, (tcu::CubeFace)face), 4, tcu::RGBA(colorA).toVec()*cScale + cBias, tcu::RGBA(colorB).toVec()*cScale + cBias);
833 }
834 }
835
836 // Upload.
837 for (int i = 0; i < 2; i++)
838 m_textures[i]->upload();
839 }
840 catch (const std::exception&)
841 {
842 // Clean up to save memory.
843 VertexCubeTextureCase::deinit();
844 throw;
845 }
846 }
847
deinit(void)848 void VertexCubeTextureCase::deinit (void)
849 {
850 for (int i = 0; i < 2; i++)
851 {
852 delete m_textures[i];
853 m_textures[i] = DE_NULL;
854 }
855
856 delete m_program;
857 m_program = DE_NULL;
858 }
859
calculateLod(const Vec2 & texScale,const Vec2 & dstSize,int textureNdx) const860 float VertexCubeTextureCase::calculateLod (const Vec2& texScale, const Vec2& dstSize, int textureNdx) const
861 {
862 const tcu::TextureCube& refTexture = m_textures[textureNdx]->getRefTexture();
863 const Vec2 srcSize = Vec2((float)refTexture.getSize(), (float)refTexture.getSize());
864 const Vec2 sizeRatio = texScale*srcSize / dstSize;
865
866 // \note In this particular case, dv/dx and du/dy are zero, simplifying the expression.
867 return deFloatLog2(de::max(sizeRatio.x(), sizeRatio.y()));
868 }
869
iterate(void)870 VertexCubeTextureCase::IterateResult VertexCubeTextureCase::iterate (void)
871 {
872 const int viewportWidth = deMin32(m_context.getRenderTarget().getWidth(), MAX_CUBE_RENDER_WIDTH);
873 const int viewportHeight = deMin32(m_context.getRenderTarget().getHeight(), MAX_CUBE_RENDER_HEIGHT);
874
875 const int viewportXOffsetMax = m_context.getRenderTarget().getWidth() - viewportWidth;
876 const int viewportYOffsetMax = m_context.getRenderTarget().getHeight() - viewportHeight;
877
878 de::Random rnd (deStringHash(getName()));
879
880 const int viewportXOffset = rnd.getInt(0, viewportXOffsetMax);
881 const int viewportYOffset = rnd.getInt(0, viewportYOffsetMax);
882
883 glUseProgram(m_program->getProgram());
884
885 // Divide viewport into 4 areas.
886 const int leftWidth = viewportWidth / 2;
887 const int rightWidth = viewportWidth - leftWidth;
888 const int bottomHeight = viewportHeight / 2;
889 const int topHeight = viewportHeight - bottomHeight;
890
891 // Clear.
892 glClearColor(0.125f, 0.25f, 0.5f, 1.0f);
893 glClear(GL_COLOR_BUFFER_BIT);
894
895 // Texture scaling and offsetting vectors.
896 const Vec2 texMinScale (1.0f, 1.0f);
897 const Vec2 texMinOffset (0.0f, 0.0f);
898 const Vec2 texMagScale (0.3f, 0.3f);
899 const Vec2 texMagOffset (0.5f, 0.3f);
900
901 // Surface for the reference image.
902 tcu::Surface refImage(viewportWidth, viewportHeight);
903
904 // Each of the four areas is divided into 6 cells.
905 const int defCellWidth = viewportWidth / 2 / 3;
906 const int defCellHeight = viewportHeight / 2 / 2;
907
908 for (int i = 0; i < tcu::CUBEFACE_LAST; i++)
909 {
910 const int cellOffsetX = defCellWidth * (i % 3);
911 const int cellOffsetY = defCellHeight * (i / 3);
912 const bool isRightmostCell = i == 2 || i == 5;
913 const bool isTopCell = i >= 3;
914 const int leftCellWidth = isRightmostCell ? leftWidth - cellOffsetX : defCellWidth;
915 const int rightCellWidth = isRightmostCell ? rightWidth - cellOffsetX : defCellWidth;
916 const int bottomCellHeight = isTopCell ? bottomHeight - cellOffsetY : defCellHeight;
917 const int topCellHeight = isTopCell ? topHeight - cellOffsetY : defCellHeight;
918
919 const struct Render
920 {
921 const Rect region;
922 int textureNdx;
923 const Vec2 texCoordScale;
924 const Vec2 texCoordOffset;
925 Render (const Rect& r, int tN, const Vec2& tS, const Vec2& tO) : region(r), textureNdx(tN), texCoordScale(tS), texCoordOffset(tO) {}
926 } renders[] =
927 {
928 Render(Rect(cellOffsetX + 0, cellOffsetY + 0, leftCellWidth, bottomCellHeight), 0, texMinScale, texMinOffset),
929 Render(Rect(cellOffsetX + leftWidth, cellOffsetY + 0, rightCellWidth, bottomCellHeight), 0, texMagScale, texMagOffset),
930 Render(Rect(cellOffsetX + 0, cellOffsetY + bottomHeight, leftCellWidth, topCellHeight), 1, texMinScale, texMinOffset),
931 Render(Rect(cellOffsetX + leftWidth, cellOffsetY + bottomHeight, rightCellWidth, topCellHeight), 1, texMagScale, texMagOffset)
932 };
933
934 for (int renderNdx = 0; renderNdx < DE_LENGTH_OF_ARRAY(renders); renderNdx++)
935 {
936 const Render& rend = renders[renderNdx];
937 const float lod = calculateLod(rend.texCoordScale, rend.region.size().asFloat(), rend.textureNdx);
938 const bool useSafeTexCoords = isLevelNearest(lod > 0.0f ? m_minFilter : m_magFilter);
939 const Grid grid (GRID_SIZE_CUBE, rend.region.size(), getTextureSize(*m_textures[rend.textureNdx]),
940 TexTypeCoordParams<TEXTURETYPE_CUBE>(rend.texCoordScale, rend.texCoordOffset, (tcu::CubeFace)i), useSafeTexCoords);
941
942 glViewport(viewportXOffset + rend.region.x, viewportYOffset + rend.region.y, rend.region.w, rend.region.h);
943 renderCell (rend.textureNdx, lod, grid);
944 computeReferenceCell (rend.textureNdx, lod, grid, refImage, rend.region);
945 }
946 }
947
948 // Read back rendered results.
949 tcu::Surface resImage(viewportWidth, viewportHeight);
950 glu::readPixels(m_context.getRenderContext(), viewportXOffset, viewportYOffset, resImage.getAccess());
951
952 glUseProgram(0);
953
954 // Compare and log.
955 {
956 const bool isOk = compareImages(m_context.getRenderContext(), m_testCtx.getLog(), refImage, resImage);
957
958 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
959 isOk ? "Pass" : "Image comparison failed");
960 }
961
962 return STOP;
963 }
964
setupShaderInputs(int textureNdx,float lod,const Grid & grid) const965 void VertexCubeTextureCase::setupShaderInputs (int textureNdx, float lod, const Grid& grid) const
966 {
967 const deUint32 programID = m_program->getProgram();
968
969 // SETUP ATTRIBUTES.
970
971 {
972 const int positionLoc = glGetAttribLocation(programID, "a_position");
973 if (positionLoc != -1)
974 {
975 glEnableVertexAttribArray(positionLoc);
976 glVertexAttribPointer(positionLoc, 2, GL_FLOAT, GL_FALSE, 0, grid.getPositionPtr());
977 }
978 }
979
980 {
981 const int texCoordLoc = glGetAttribLocation(programID, "a_texCoord");
982 if (texCoordLoc != -1)
983 {
984 glEnableVertexAttribArray(texCoordLoc);
985 glVertexAttribPointer(texCoordLoc, 3, GL_FLOAT, GL_FALSE, 0, grid.getTexCoordPtr());
986 }
987 }
988
989 // SETUP UNIFORMS.
990
991 {
992 const int lodLoc = glGetUniformLocation(programID, "u_lod");
993 if (lodLoc != -1)
994 glUniform1f(lodLoc, lod);
995 }
996
997 glActiveTexture(GL_TEXTURE0);
998 glBindTexture(GL_TEXTURE_CUBE_MAP, m_textures[textureNdx]->getGLTexture());
999 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, m_wrapS);
1000 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, m_wrapT);
1001 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, m_minFilter);
1002 glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, m_magFilter);
1003
1004 {
1005 const int texLoc = glGetUniformLocation(programID, "u_texture");
1006 if (texLoc != -1)
1007 glUniform1i(texLoc, 0);
1008 }
1009 }
1010
1011 // Renders one cube face with given parameters.
renderCell(int textureNdx,float lod,const Grid & grid) const1012 void VertexCubeTextureCase::renderCell (int textureNdx, float lod, const Grid& grid) const
1013 {
1014 setupShaderInputs(textureNdx, lod, grid);
1015 glDrawElements(GL_TRIANGLES, grid.getNumIndices(), GL_UNSIGNED_SHORT, grid.getIndexPtr());
1016 }
1017
1018 // Computes reference for one cube face with given parameters.
computeReferenceCell(int textureNdx,float lod,const Grid & grid,tcu::Surface & dst,const Rect & dstRegion) const1019 void VertexCubeTextureCase::computeReferenceCell (int textureNdx, float lod, const Grid& grid, tcu::Surface& dst, const Rect& dstRegion) const
1020 {
1021 tcu::Sampler sampler = glu::mapGLSampler(m_wrapS, m_wrapT, m_minFilter, m_magFilter);
1022 computeReference(m_textures[textureNdx]->getRefTexture(), lod, sampler, grid, dst, dstRegion);
1023 }
1024
VertexTextureTests(Context & context)1025 VertexTextureTests::VertexTextureTests (Context& context)
1026 : TestCaseGroup(context, "vertex", "Vertex Texture Tests")
1027 {
1028 }
1029
~VertexTextureTests(void)1030 VertexTextureTests::~VertexTextureTests(void)
1031 {
1032 }
1033
init(void)1034 void VertexTextureTests::init (void)
1035 {
1036 // 2D and cube map groups, and their filtering and wrap sub-groups.
1037 TestCaseGroup* const group2D = new TestCaseGroup(m_context, "2d", "2D Vertex Texture Tests");
1038 TestCaseGroup* const groupCube = new TestCaseGroup(m_context, "cube", "Cube Map Vertex Texture Tests");
1039 TestCaseGroup* const filteringGroup2D = new TestCaseGroup(m_context, "filtering", "2D Vertex Texture Filtering Tests");
1040 TestCaseGroup* const wrapGroup2D = new TestCaseGroup(m_context, "wrap", "2D Vertex Texture Wrap Tests");
1041 TestCaseGroup* const filteringGroupCube = new TestCaseGroup(m_context, "filtering", "Cube Map Vertex Texture Filtering Tests");
1042 TestCaseGroup* const wrapGroupCube = new TestCaseGroup(m_context, "wrap", "Cube Map Vertex Texture Wrap Tests");
1043
1044 group2D->addChild(filteringGroup2D);
1045 group2D->addChild(wrapGroup2D);
1046 groupCube->addChild(filteringGroupCube);
1047 groupCube->addChild(wrapGroupCube);
1048
1049 addChild(group2D);
1050 addChild(groupCube);
1051
1052 static const struct
1053 {
1054 const char* name;
1055 GLenum mode;
1056 } wrapModes[] =
1057 {
1058 { "clamp", GL_CLAMP_TO_EDGE },
1059 { "repeat", GL_REPEAT },
1060 { "mirror", GL_MIRRORED_REPEAT }
1061 };
1062
1063 static const struct
1064 {
1065 const char* name;
1066 GLenum mode;
1067 } minFilterModes[] =
1068 {
1069 { "nearest", GL_NEAREST },
1070 { "linear", GL_LINEAR },
1071 { "nearest_mipmap_nearest", GL_NEAREST_MIPMAP_NEAREST },
1072 { "linear_mipmap_nearest", GL_LINEAR_MIPMAP_NEAREST },
1073 { "nearest_mipmap_linear", GL_NEAREST_MIPMAP_LINEAR },
1074 { "linear_mipmap_linear", GL_LINEAR_MIPMAP_LINEAR }
1075 };
1076
1077 static const struct
1078 {
1079 const char* name;
1080 GLenum mode;
1081 } magFilterModes[] =
1082 {
1083 { "nearest", GL_NEAREST },
1084 { "linear", GL_LINEAR }
1085 };
1086
1087 #define FOR_EACH(ITERATOR, ARRAY, BODY) \
1088 for (int (ITERATOR) = 0; (ITERATOR) < DE_LENGTH_OF_ARRAY(ARRAY); (ITERATOR)++) \
1089 BODY
1090
1091 // 2D cases.
1092
1093 FOR_EACH(minFilter, minFilterModes,
1094 FOR_EACH(magFilter, magFilterModes,
1095 FOR_EACH(wrapMode, wrapModes,
1096 {
1097 const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1098
1099 filteringGroup2D->addChild(new Vertex2DTextureCase(m_context,
1100 name.c_str(), "",
1101 minFilterModes[minFilter].mode,
1102 magFilterModes[magFilter].mode,
1103 wrapModes[wrapMode].mode,
1104 wrapModes[wrapMode].mode));
1105 })));
1106
1107 FOR_EACH(wrapSMode, wrapModes,
1108 FOR_EACH(wrapTMode, wrapModes,
1109 {
1110 const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
1111
1112 wrapGroup2D->addChild(new Vertex2DTextureCase(m_context,
1113 name.c_str(), "",
1114 GL_LINEAR_MIPMAP_LINEAR,
1115 GL_LINEAR,
1116 wrapModes[wrapSMode].mode,
1117 wrapModes[wrapTMode].mode));
1118 }));
1119
1120 // Cube map cases.
1121
1122 FOR_EACH(minFilter, minFilterModes,
1123 FOR_EACH(magFilter, magFilterModes,
1124 FOR_EACH(wrapMode, wrapModes,
1125 {
1126 const string name = string("") + minFilterModes[minFilter].name + "_" + magFilterModes[magFilter].name + "_" + wrapModes[wrapMode].name;
1127
1128 filteringGroupCube->addChild(new VertexCubeTextureCase(m_context,
1129 name.c_str(), "",
1130 minFilterModes[minFilter].mode,
1131 magFilterModes[magFilter].mode,
1132 wrapModes[wrapMode].mode,
1133 wrapModes[wrapMode].mode));
1134 })));
1135
1136 FOR_EACH(wrapSMode, wrapModes,
1137 FOR_EACH(wrapTMode, wrapModes,
1138 {
1139 const string name = string("") + wrapModes[wrapSMode].name + "_" + wrapModes[wrapTMode].name;
1140
1141 wrapGroupCube->addChild(new VertexCubeTextureCase(m_context,
1142 name.c_str(), "",
1143 GL_LINEAR_MIPMAP_LINEAR,
1144 GL_LINEAR,
1145 wrapModes[wrapSMode].mode,
1146 wrapModes[wrapTMode].mode));
1147 }));
1148 }
1149
1150 } // Functional
1151 } // gles2
1152 } // deqp
1153