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