xref: /aosp_15_r20/external/deqp/external/openglcts/modules/common/glcTextureFilterAnisotropicTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2017 The Khronos Group Inc.
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
22  */ /*-------------------------------------------------------------------*/
23 
24 /**
25  */ /*!
26  * \file  glcTextureFilterAnisotropicTests.cpp
27  * \brief Conformance tests for the GL_EXT_texture_filter_anisotropic functionality.
28  */ /*-------------------------------------------------------------------*/
29 
30 #include "deMath.h"
31 
32 #include "glcTextureFilterAnisotropicTests.hpp"
33 #include "gluContextInfo.hpp"
34 #include "gluDefs.hpp"
35 #include "gluShaderProgram.hpp"
36 #include "gluStrUtil.hpp"
37 #include "gluTextureUtil.hpp"
38 #include "glwEnums.hpp"
39 #include "glwFunctions.hpp"
40 #include "tcuRGBA.hpp"
41 #include "tcuRenderTarget.hpp"
42 #include "tcuTestLog.hpp"
43 #include "tcuTexture.hpp"
44 
45 using namespace glw;
46 using namespace glu;
47 
48 namespace glcts
49 {
50 
51 namespace TextureFilterAnisotropicUtils
52 {
53 
54 /** Replace all occurrence of <token> with <text> in <str>
55  *
56  * @param token           Token string
57  * @param text            String that will be used as replacement for <token>
58  * @param string          String to work on
59  **/
replaceToken(const GLchar * token,const GLchar * text,std::string & str)60 void replaceToken(const GLchar *token, const GLchar *text, std::string &str)
61 {
62     const size_t text_length  = strlen(text);
63     const size_t token_length = strlen(token);
64 
65     size_t token_position;
66     while ((token_position = str.find(token, 0)) != std::string::npos)
67     {
68         str.replace(token_position, token_length, text, text_length);
69     }
70 }
71 
72 /** Allocate storage for texture
73  *
74  * @param target           Texture target
75  * @param refTexCoordType  GLSL texture coord type
76  * @param refSamplerType   GLSL texture sampler type
77  **/
generateTokens(GLenum target,std::string & refTexCoordType,std::string & refSamplerType)78 void generateTokens(GLenum target, std::string &refTexCoordType, std::string &refSamplerType)
79 {
80     switch (target)
81     {
82     case GL_TEXTURE_2D:
83         refTexCoordType = "vec2";
84         refSamplerType  = "sampler2D";
85         break;
86     case GL_TEXTURE_2D_ARRAY:
87         refTexCoordType = "vec3";
88         refSamplerType  = "sampler2DArray";
89         break;
90     default:
91         refTexCoordType = "vec2";
92         refSamplerType  = "sampler2D";
93         break;
94     }
95 }
96 
97 /** Set contents of texture
98  *
99  * @param gl              GL functions
100  * @param target          Texture target
101  * @param level           Mipmap level
102  * @param internal_format Format of data
103  * @param width           Width of texture
104  * @param height          Height of texture
105  * @param depth           Depth of texture
106  * @param format          Format of data
107  * @param type            Type of data
108  * @param data            Buffer with image data
109  **/
texImage(const Functions & gl,GLenum target,GLint level,GLenum internal_format,GLuint width,GLuint height,GLuint depth,GLenum format,GLenum type,const GLvoid * data)110 void texImage(const Functions &gl, GLenum target, GLint level, GLenum internal_format, GLuint width, GLuint height,
111               GLuint depth, GLenum format, GLenum type, const GLvoid *data)
112 {
113     switch (target)
114     {
115     case GL_TEXTURE_2D:
116         gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
117         GLU_EXPECT_NO_ERROR(gl.getError(), "texImage");
118         break;
119     case GL_TEXTURE_2D_ARRAY:
120         gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
121         GLU_EXPECT_NO_ERROR(gl.getError(), "texImage");
122         break;
123     default:
124         TCU_FAIL("Invalid enum");
125     }
126 }
127 
128 /** Set contents of texture
129  *
130  * @param gl              GL functions
131  * @param target          Texture target
132  * @param level           Mipmap level
133  * @param x               X offset
134  * @param y               Y offset
135  * @param z               Z offset
136  * @param width           Width of texture
137  * @param height          Height of texture
138  * @param depth           Depth of texture
139  * @param format          Format of data
140  * @param type            Type of data
141  * @param pixels          Buffer with image data
142  **/
subImage(const Functions & gl,GLenum target,GLint level,GLint x,GLint y,GLint z,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const GLvoid * pixels)143 void subImage(const Functions &gl, GLenum target, GLint level, GLint x, GLint y, GLint z, GLsizei width, GLsizei height,
144               GLsizei depth, GLenum format, GLenum type, const GLvoid *pixels)
145 {
146     switch (target)
147     {
148     case GL_TEXTURE_2D:
149         gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
150         GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
151         break;
152     case GL_TEXTURE_2D_ARRAY:
153         gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
154         GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
155         break;
156     default:
157         TCU_FAIL("Invalid enum");
158     }
159 }
160 
161 } // namespace TextureFilterAnisotropicUtils
162 
163 /** Constructor.
164  *
165  *  @param context     Rendering context
166  */
TextureFilterAnisotropicQueriesTestCase(deqp::Context & context)167 TextureFilterAnisotropicQueriesTestCase::TextureFilterAnisotropicQueriesTestCase(deqp::Context &context)
168     : TestCase(context, "queries", "Verifies if queries for GL_EXT_texture_filter_anisotropic tokens works as expected")
169 {
170     /* Left blank intentionally */
171 }
172 
173 /** Stub deinit method. */
deinit()174 void TextureFilterAnisotropicQueriesTestCase::deinit()
175 {
176 }
177 
178 /** Stub init method */
init()179 void TextureFilterAnisotropicQueriesTestCase::init()
180 {
181     glu::ContextType contextType = m_context.getRenderContext().getType();
182     if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
183         !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_filter_anisotropic") &&
184         !m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_filter_anisotropic"))
185     {
186         TCU_THROW(NotSupportedError, "texture filter anisotropic functionality not supported");
187     }
188 }
189 
190 /** Executes test iteration.
191  *
192  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
193  */
iterate()194 tcu::TestNode::IterateResult TextureFilterAnisotropicQueriesTestCase::iterate()
195 {
196     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
197 
198     GLuint texture;
199     gl.genTextures(1, &texture);
200     GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
201     gl.bindTexture(GL_TEXTURE_2D, texture);
202     GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
203     TextureFilterAnisotropicUtils::texImage(gl, GL_TEXTURE_2D, 0, GL_RGBA8, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
204 
205     if (verifyTexParameters(gl) && verifyGet(gl))
206         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
207     else
208         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
209 
210     gl.deleteTextures(1, &texture);
211     GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
212 
213     return STOP;
214 }
215 
216 /** Verify if texParameter*, getTexParameter* queries for GL_TEXTURE_MAX_ANISOTROPY_EXT pname works as expected.
217  *
218  *  @param gl   OpenGL functions wrapper
219  *
220  *  @return Returns true if queries test passed, false otherwise.
221  */
verifyTexParameters(const glw::Functions & gl)222 bool TextureFilterAnisotropicQueriesTestCase::verifyTexParameters(const glw::Functions &gl)
223 {
224     GLint iValue;
225     gl.getTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
226     GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv");
227 
228     // Verify initial integer value which should be equal to 1
229     if (iValue != 1)
230     {
231         m_testCtx.getLog() << tcu::TestLog::Message
232                            << "GetTexParameteriv failed. Expected value: 1, Queried value: " << iValue
233                            << tcu::TestLog::EndMessage;
234         return false;
235     }
236 
237     GLfloat fValue;
238     gl.getTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
239     GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterfv");
240 
241     // Verify initial float value which should be equal to 1.0f
242     if (fValue != 1.0f)
243     {
244         m_testCtx.getLog() << tcu::TestLog::Message
245                            << "GetTexParameterfv failed. Expected value: 1.0, Queried value: " << iValue
246                            << tcu::TestLog::EndMessage;
247         return false;
248     }
249 
250     // Set custom integer value and verify it
251     iValue = 2;
252     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, iValue);
253     GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri");
254 
255     gl.getTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
256     GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv");
257 
258     if (iValue != 2)
259     {
260         m_testCtx.getLog() << tcu::TestLog::Message
261                            << "texParameteri failed. Expected value: 2, Queried value: " << iValue
262                            << tcu::TestLog::EndMessage;
263         return false;
264     }
265 
266     // Set custom float value and verify it
267     fValue = 1.5f;
268     gl.texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fValue);
269     GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterf");
270 
271     gl.getTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
272     GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterfv");
273 
274     if (fValue != 1.5f)
275     {
276         m_testCtx.getLog() << tcu::TestLog::Message
277                            << "texParameterf failed. Expected value: 1.5, Queried value: " << fValue
278                            << tcu::TestLog::EndMessage;
279         return false;
280     }
281 
282     // Set custom integer value and verify it
283     iValue = 1;
284     gl.texParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
285     GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteriv");
286 
287     gl.getTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
288     GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv");
289 
290     if (iValue != 1)
291     {
292         m_testCtx.getLog() << tcu::TestLog::Message
293                            << "texParameteriv failed. Expected value: 1, Queried value: " << iValue
294                            << tcu::TestLog::EndMessage;
295         return false;
296     }
297 
298     // Set custom float value and verify it
299     fValue = 2.0f;
300     gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
301     GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterfv");
302 
303     gl.getTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
304     GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterfv");
305 
306     if (fValue != 2.0f)
307     {
308         m_testCtx.getLog() << tcu::TestLog::Message
309                            << "texParameterfv failed. Expected value: 2.0, Queried value: " << fValue
310                            << tcu::TestLog::EndMessage;
311         return false;
312     }
313 
314     // Set texture filter anisotropic to 0.9f and check if INVALID_VALUE error is generated
315     fValue = 0.9f;
316     gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
317     GLint error = gl.getError();
318     if (error != GL_INVALID_VALUE)
319     {
320         m_testCtx.getLog()
321             << tcu::TestLog::Message
322             << "texParameterfv failed for values less then 1.0f. Expected INVALID_VALUE error. Generated error: "
323             << glu::getErrorName(error) << tcu::TestLog::EndMessage;
324         return false;
325     }
326 
327     return true;
328 }
329 
330 /** Verify if get* queries for GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT pname works as expected.
331  *
332  *  @param gl   OpenGL functions wrapper
333  *
334  *  @return Returns true if queries test passed, false otherwise.
335  */
verifyGet(const glw::Functions & gl)336 bool TextureFilterAnisotropicQueriesTestCase::verifyGet(const glw::Functions &gl)
337 {
338     GLboolean bValue;
339     GLint iValue;
340     GLfloat fValue;
341     GLdouble dValue;
342 
343     gl.getBooleanv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &bValue);
344     GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv");
345 
346     gl.getIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
347     GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
348 
349     gl.getFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
350     GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv");
351 
352     if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
353     {
354         gl.getDoublev(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dValue);
355         GLU_EXPECT_NO_ERROR(gl.getError(), "getDoublev");
356     }
357 
358     return true;
359 }
360 
361 /** Constructor.
362  *
363  *  @param context     Rendering context
364  */
TextureFilterAnisotropicDrawingTestCase(deqp::Context & context)365 TextureFilterAnisotropicDrawingTestCase::TextureFilterAnisotropicDrawingTestCase(deqp::Context &context)
366     : TestCase(context, "drawing", "Verifies if drawing texture with anisotropic filtering is performed as expected")
367     , m_vertex(DE_NULL)
368     , m_fragment(DE_NULL)
369     , m_texture(0)
370 {
371     /* Left blank intentionally */
372 }
373 
374 /** Stub deinit method. */
deinit()375 void TextureFilterAnisotropicDrawingTestCase::deinit()
376 {
377     /* Left blank intentionally */
378 }
379 
380 /** Stub init method */
init()381 void TextureFilterAnisotropicDrawingTestCase::init()
382 {
383     glu::ContextType contextType = m_context.getRenderContext().getType();
384     if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
385         !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_filter_anisotropic") &&
386         !m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_filter_anisotropic"))
387     {
388         TCU_THROW(NotSupportedError, "texture filter anisotropic functionality not supported");
389     }
390 
391     const tcu::RenderTarget &rt = m_context.getRenderTarget();
392 
393     GLint width  = rt.getWidth();
394     GLint height = rt.getHeight();
395 
396     if (width < 32 || height < 32)
397         TCU_THROW(NotSupportedError, "Config not supported - render buffer size should be at least 32x32");
398 
399     m_vertex = "#version <VERSION>\n"
400                "\n"
401                "in highp vec3 vertex;\n"
402                "in highp <TEXCOORD_TYPE> inTexCoord;\n"
403                "out highp <TEXCOORD_TYPE> commonTexCoord;\n"
404                "\n"
405                "uniform highp mat4 projectionMatrix;\n"
406                "\n"
407                "void main()\n"
408                "{\n"
409                "    commonTexCoord = inTexCoord;\n"
410                "    gl_Position = vec4(vertex, 1.0) * projectionMatrix;\n"
411                "}\n";
412 
413     m_fragment = "#version <VERSION>\n"
414                  "\n"
415                  "in highp <TEXCOORD_TYPE> commonTexCoord;\n"
416                  "out highp vec4 fragColor;\n"
417                  "\n"
418                  "uniform highp <SAMPLER_TYPE> tex;\n"
419                  "\n"
420                  "void main()\n"
421                  "{\n"
422                  "    fragColor = texture(tex, commonTexCoord);\n"
423                  "}\n"
424                  "\n";
425 
426     m_supportedTargets.clear();
427     m_supportedTargets.push_back(GL_TEXTURE_2D);
428     m_supportedTargets.push_back(GL_TEXTURE_2D_ARRAY);
429 
430     m_supportedInternalFormats.clear();
431     m_supportedInternalFormats.push_back(GL_R8);
432     m_supportedInternalFormats.push_back(GL_R8_SNORM);
433     m_supportedInternalFormats.push_back(GL_RG8);
434     m_supportedInternalFormats.push_back(GL_RG8_SNORM);
435     m_supportedInternalFormats.push_back(GL_RGB8);
436     m_supportedInternalFormats.push_back(GL_RGB8_SNORM);
437     m_supportedInternalFormats.push_back(GL_RGB565);
438     m_supportedInternalFormats.push_back(GL_RGBA4);
439     m_supportedInternalFormats.push_back(GL_RGB5_A1);
440     m_supportedInternalFormats.push_back(GL_RGBA8);
441     m_supportedInternalFormats.push_back(GL_RGBA8_SNORM);
442     m_supportedInternalFormats.push_back(GL_RGB10_A2);
443     m_supportedInternalFormats.push_back(GL_SRGB8);
444     m_supportedInternalFormats.push_back(GL_SRGB8_ALPHA8);
445     m_supportedInternalFormats.push_back(GL_R16F);
446     m_supportedInternalFormats.push_back(GL_RG16F);
447     m_supportedInternalFormats.push_back(GL_RGB16F);
448     m_supportedInternalFormats.push_back(GL_RGBA16F);
449     m_supportedInternalFormats.push_back(GL_R11F_G11F_B10F);
450     m_supportedInternalFormats.push_back(GL_RGB9_E5);
451 }
452 
453 /** Executes test iteration.
454  *
455  *  @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
456  */
iterate()457 tcu::TestNode::IterateResult TextureFilterAnisotropicDrawingTestCase::iterate()
458 {
459     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
460 
461     bool result = true;
462 
463     GLfloat maxAnisoDegree = 2.0;
464 
465     gl.getFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisoDegree);
466     GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv");
467 
468     std::vector<GLfloat> anisoVec;
469     anisoVec.push_back(1.0f);
470     anisoVec.push_back(2.0f);
471 
472     for (uint32_t iTarget = 0; iTarget < m_supportedTargets.size(); ++iTarget)
473     {
474         GLenum target = m_supportedTargets[iTarget];
475 
476         for (uint32_t iFormat = 0; iFormat < m_supportedInternalFormats.size(); ++iFormat)
477         {
478             GLenum format = m_supportedInternalFormats[iFormat];
479 
480             // Generate texture
481             generateTexture(gl, target);
482 
483             // Fill texture with strips pattern
484             fillTexture(gl, target, format);
485 
486             // Draw scene
487             GLuint lastPoints = 0xFFFFFFFF;
488             for (uint32_t i = 0; i < anisoVec.size(); ++i)
489             {
490                 GLfloat aniso = anisoVec[i];
491 
492                 if (result)
493                     result = result && drawTexture(gl, target, aniso);
494 
495                 // Verify result
496                 if (result)
497                 {
498                     GLuint currentPoints = verifyScene(gl);
499 
500                     if (lastPoints <= currentPoints)
501                     {
502                         m_testCtx.getLog()
503                             << tcu::TestLog::Message
504                             << "Anisotropy verification failed (lastPoints <= currentPoints) for "
505                             << "anisotropy: " << aniso << ", "
506                             << "target: " << glu::getTextureTargetName(target) << ", "
507                             << "internalFormat: " << glu::getUncompressedTextureFormatName(format) << ", "
508                             << "lastPoints: " << lastPoints << ", "
509                             << "currentPoints: " << currentPoints << tcu::TestLog::EndMessage;
510 
511                         result = false;
512                         break;
513                     }
514 
515                     lastPoints = currentPoints;
516                 }
517             }
518 
519             // Release texture
520             releaseTexture(gl);
521 
522             if (!result)
523             {
524                 // Stop loops
525                 iTarget = static_cast<uint32_t>(m_supportedTargets.size());
526                 iFormat = static_cast<uint32_t>(m_supportedInternalFormats.size());
527             }
528         }
529     }
530 
531     if (result)
532         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
533     else
534         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
535     return STOP;
536 }
537 
538 /** Generate texture and set filtering parameters.
539  *
540  *  @param gl              OpenGL functions wrapper
541  *  @param target          Texture target
542  *  @param internalFormat  Texture internal format
543  */
generateTexture(const glw::Functions & gl,GLenum target)544 void TextureFilterAnisotropicDrawingTestCase::generateTexture(const glw::Functions &gl, GLenum target)
545 {
546     gl.genTextures(1, &m_texture);
547     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures");
548     gl.bindTexture(target, m_texture);
549     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
550 
551     gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
552     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
553     gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
554     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
555     gl.texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
556     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
557     gl.texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
558     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
559     gl.texParameteri(target, GL_TEXTURE_MAX_LEVEL, 1);
560     GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
561 }
562 
563 /** Fill texture with strips pattern.
564  *
565  *  @param gl              OpenGL functions wrapper
566  *  @param target          Texture target
567  *  @param internalFormat  Texture internal format
568  */
fillTexture(const glw::Functions & gl,GLenum target,GLenum internalFormat)569 void TextureFilterAnisotropicDrawingTestCase::fillTexture(const glw::Functions &gl, GLenum target,
570                                                           GLenum internalFormat)
571 {
572     tcu::TextureFormat texFormat    = glu::mapGLInternalFormat(internalFormat);
573     glu::TransferFormat transFormat = glu::getTransferFormat(texFormat);
574 
575     for (int l = 0; l < 2; ++l)
576     {
577         GLuint texSize = 32 / (l + 1);
578 
579         std::vector<GLubyte> vecData;
580         vecData.resize(texSize * texSize * texFormat.getPixelSize() * 2);
581 
582         tcu::PixelBufferAccess bufferAccess(texFormat, texSize, texSize, 1, vecData.data());
583 
584         for (GLuint x = 0; x < texSize; ++x)
585         {
586             for (GLuint y = 0; y < texSize; ++y)
587             {
588                 int value = ((x * (l + 1)) % 8 < 4) ? 255 : 0;
589                 tcu::RGBA rgbaColor(value, value, value, 255);
590                 tcu::Vec4 color = rgbaColor.toVec();
591                 bufferAccess.setPixel(color, x, y);
592             }
593         }
594 
595         TextureFilterAnisotropicUtils::texImage(gl, target, l, internalFormat, texSize, texSize, 1, transFormat.format,
596                                                 transFormat.dataType, vecData.data());
597     }
598 }
599 
600 /** Render polygon with anisotropic filtering.
601  *
602  *  @param gl           OpenGL functions wrapper
603  *  @param target       Texture target
604  *  @param anisoDegree  Degree of anisotropy
605  *
606  *  @return Returns true if no error occured, false otherwise.
607  */
drawTexture(const glw::Functions & gl,GLenum target,GLfloat anisoDegree)608 bool TextureFilterAnisotropicDrawingTestCase::drawTexture(const glw::Functions &gl, GLenum target, GLfloat anisoDegree)
609 {
610     const GLfloat vertices2[] = {-1.0f, 0.0f, -0.5f, 0.0f, 0.0f, -4.0f, 4.0f, -2.0f, 0.0f, 1.0f,
611                                  1.0f,  0.0f, -0.5f, 1.0f, 0.0f, -2.0f, 4.0f, -2.0f, 1.0f, 1.0f};
612     const GLfloat vertices3[] = {-1.0f, 0.0f, -0.5f, 0.0f, 0.0f, 0.0f, -4.0f, 4.0f, -2.0f, 0.0f, 1.0f, 0.0f,
613                                  1.0f,  0.0f, -0.5f, 1.0f, 0.0f, 0.0f, -2.0f, 4.0f, -2.0f, 1.0f, 1.0f, 0.0f};
614 
615     // Projection values.
616     const GLfloat projectionMatrix[] = {0.5f, 0.0f, 0.0f,         0.0f,         0.0f, 0.5f, 0.0f,  0.0f,
617                                         0.0f, 0.0f, -2.5f / 1.5f, -2.0f / 1.5f, 0.0f, 0.0f, -1.0f, 0.0f};
618 
619     gl.viewport(0, 0, 32, 32);
620 
621     std::string vertexShader   = m_vertex;
622     std::string fragmentShader = m_fragment;
623 
624     std::string texCoordType;
625     std::string samplerType;
626     TextureFilterAnisotropicUtils::generateTokens(target, texCoordType, samplerType);
627 
628     TextureFilterAnisotropicUtils::replaceToken("<TEXCOORD_TYPE>", texCoordType.c_str(), vertexShader);
629     TextureFilterAnisotropicUtils::replaceToken("<TEXCOORD_TYPE>", texCoordType.c_str(), fragmentShader);
630     TextureFilterAnisotropicUtils::replaceToken("<SAMPLER_TYPE>", samplerType.c_str(), vertexShader);
631     TextureFilterAnisotropicUtils::replaceToken("<SAMPLER_TYPE>", samplerType.c_str(), fragmentShader);
632 
633     if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
634     {
635         TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "130", vertexShader);
636         TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "130", fragmentShader);
637     }
638     else
639     {
640         TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "300 es", vertexShader);
641         TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "300 es", fragmentShader);
642     }
643 
644     ProgramSources sources = makeVtxFragSources(vertexShader, fragmentShader);
645     ShaderProgram program(gl, sources);
646 
647     if (!program.isOk())
648     {
649         m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
650                            << "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
651                            << vertexShader << "\n"
652                            << "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
653                            << fragmentShader << "\n"
654                            << "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
655         return false;
656     }
657 
658     GLuint vao;
659     gl.genVertexArrays(1, &vao);
660     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
661     gl.bindVertexArray(vao);
662     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
663 
664     GLuint vbo;
665     gl.genBuffers(1, &vbo);
666     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
667     gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
668     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
669 
670     std::vector<GLfloat> vboData;
671     vboData.resize(24);
672 
673     GLuint texCoordDim;
674     if (texCoordType == "vec2")
675     {
676         texCoordDim = 2;
677         deMemcpy((void *)vboData.data(), (void *)vertices2, sizeof(vertices2));
678     }
679     else
680     {
681         texCoordDim = 3;
682         deMemcpy((void *)vboData.data(), (void *)vertices3, sizeof(vertices3));
683     }
684 
685     gl.bufferData(GL_ARRAY_BUFFER, vboData.size() * sizeof(GLfloat), (GLvoid *)vboData.data(), GL_DYNAMIC_DRAW);
686     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
687 
688     gl.useProgram(program.getProgram());
689     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
690 
691     GLuint matrixLocation = gl.getUniformLocation(program.getProgram(), "projectionMatrix");
692     GLuint texLocation    = gl.getUniformLocation(program.getProgram(), "tex");
693 
694     gl.activeTexture(GL_TEXTURE0);
695     GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
696     gl.bindTexture(target, m_texture);
697     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
698     gl.uniformMatrix4fv(matrixLocation, 1, GL_FALSE, projectionMatrix);
699     GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformMatrix4fv");
700     gl.uniform1i(texLocation, 0);
701     GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
702 
703     gl.texParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoDegree);
704     GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterfv");
705 
706     gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
707     GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
708     gl.clear(GL_COLOR_BUFFER_BIT);
709     GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
710 
711     gl.enableVertexAttribArray(0);
712     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
713     gl.enableVertexAttribArray(1);
714     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
715 
716     GLint attrLocationVertex = gl.getAttribLocation(program.getProgram(), "vertex");
717     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation");
718     GLint attrLocationInTexCoord = gl.getAttribLocation(program.getProgram(), "inTexCoord");
719     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation");
720 
721     GLuint strideSize = (3 + texCoordDim) * sizeof(GLfloat);
722     gl.vertexAttribPointer(attrLocationVertex, 3, GL_FLOAT, GL_FALSE, strideSize, DE_NULL);
723     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
724     gl.vertexAttribPointer(attrLocationInTexCoord, texCoordDim, GL_FLOAT, GL_FALSE, strideSize,
725                            (GLvoid *)(3 * sizeof(GLfloat)));
726     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
727 
728     gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
729     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
730 
731     gl.disableVertexAttribArray(0);
732     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
733     gl.disableVertexAttribArray(1);
734     GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
735 
736     if (vbo)
737     {
738         gl.deleteBuffers(1, &vbo);
739         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
740     }
741 
742     if (vao)
743     {
744         gl.deleteVertexArrays(1, &vao);
745         GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
746     }
747 
748     return true;
749 }
750 
751 /** Verify rendered polygon anisotropy.
752  *
753  *  @param gl  OpenGL functions wrapper
754  *
755  *  @return Returns points value. Less points means better anisotropy (smoother strips).
756  */
verifyScene(const glw::Functions & gl)757 GLuint TextureFilterAnisotropicDrawingTestCase::verifyScene(const glw::Functions &gl)
758 {
759     std::vector<GLubyte> pixels;
760     pixels.resize(32 * 8 * 4);
761 
762     gl.readPixels(0, 23, 32, 8, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
763     GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
764 
765     GLuint sum = 0;
766 
767     GLubyte last    = 0;
768     GLubyte current = 0;
769     for (int j = 0; j < 8; ++j)
770     {
771         for (int i = 0; i < 32; ++i)
772         {
773             current = pixels[(i + j * 32) * 4];
774 
775             if (i > 0)
776                 sum += deAbs32((int)current - (int)last);
777 
778             last = current;
779         }
780     }
781 
782     return sum;
783 }
784 
785 /** Release texture.
786  *
787  *  @param gl  OpenGL functions wrapper
788  */
releaseTexture(const glw::Functions & gl)789 void TextureFilterAnisotropicDrawingTestCase::releaseTexture(const glw::Functions &gl)
790 {
791     if (m_texture)
792         gl.deleteTextures(1, &m_texture);
793 
794     m_texture = 0;
795 }
796 
797 /** Constructor.
798  *
799  *  @param context Rendering context.
800  */
TextureFilterAnisotropicTests(deqp::Context & context)801 TextureFilterAnisotropicTests::TextureFilterAnisotropicTests(deqp::Context &context)
802     : TestCaseGroup(context, "texture_filter_anisotropic",
803                     "Verify conformance of CTS_EXT_texture_filter_anisotropic implementation")
804 {
805 }
806 
807 /** Initializes the test group contents. */
init()808 void TextureFilterAnisotropicTests::init()
809 {
810     addChild(new TextureFilterAnisotropicQueriesTestCase(m_context));
811     addChild(new TextureFilterAnisotropicDrawingTestCase(m_context));
812 }
813 
814 } // namespace glcts
815