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