blob: 50204799b2e0f98b1a25e437f32e2c0bd3f56add [file] [log] [blame]
/*-------------------------------------------------------------------------
* OpenGL Conformance Test Suite
* -----------------------------
*
* Copyright (c) 2017 The Khronos Group Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/ /*!
* \file
* \brief
*/ /*-------------------------------------------------------------------*/
/**
*/ /*!
* \file glcTextureFilterAnisotropicTests.cpp
* \brief Conformance tests for the GL_EXT_texture_filter_anisotropic functionality.
*/ /*-------------------------------------------------------------------*/
#include "deMath.h"
#include "glcTextureFilterAnisotropicTests.hpp"
#include "gluContextInfo.hpp"
#include "gluDefs.hpp"
#include "gluShaderProgram.hpp"
#include "gluStrUtil.hpp"
#include "gluTextureUtil.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "tcuRGBA.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuTestLog.hpp"
#include "tcuTexture.hpp"
using namespace glw;
using namespace glu;
namespace glcts
{
namespace TextureFilterAnisotropicUtils
{
/** Replace all occurrence of <token> with <text> in <str>
*
* @param token Token string
* @param text String that will be used as replacement for <token>
* @param string String to work on
**/
void replaceToken(const GLchar* token, const GLchar* text, std::string& str)
{
const size_t text_length = strlen(text);
const size_t token_length = strlen(token);
size_t token_position;
while ((token_position = str.find(token, 0)) != std::string::npos)
{
str.replace(token_position, token_length, text, text_length);
}
}
/** Allocate storage for texture
*
* @param target Texture target
* @param refTexCoordType GLSL texture coord type
* @param refSamplerType GLSL texture sampler type
**/
void generateTokens(GLenum target, std::string& refTexCoordType, std::string& refSamplerType)
{
switch (target)
{
case GL_TEXTURE_2D:
refTexCoordType = "vec2";
refSamplerType = "sampler2D";
break;
case GL_TEXTURE_2D_ARRAY:
refTexCoordType = "vec3";
refSamplerType = "sampler2DArray";
break;
default:
refTexCoordType = "vec2";
refSamplerType = "sampler2D";
break;
}
}
/** Set contents of texture
*
* @param gl GL functions
* @param target Texture target
* @param level Mipmap level
* @param internal_format Format of data
* @param width Width of texture
* @param height Height of texture
* @param depth Depth of texture
* @param format Format of data
* @param type Type of data
* @param data Buffer with image data
**/
void texImage(const Functions& gl, GLenum target, GLint level, GLenum internal_format, GLuint width, GLuint height,
GLuint depth, GLenum format, GLenum type, const GLvoid* data)
{
switch (target)
{
case GL_TEXTURE_2D:
gl.texImage2D(target, level, internal_format, width, height, 0 /* border */, format, type, data);
GLU_EXPECT_NO_ERROR(gl.getError(), "texImage");
break;
case GL_TEXTURE_2D_ARRAY:
gl.texImage3D(target, level, internal_format, width, height, depth, 0 /* border */, format, type, data);
GLU_EXPECT_NO_ERROR(gl.getError(), "texImage");
break;
default:
TCU_FAIL("Invalid enum");
break;
}
}
/** Set contents of texture
*
* @param gl GL functions
* @param target Texture target
* @param level Mipmap level
* @param x X offset
* @param y Y offset
* @param z Z offset
* @param width Width of texture
* @param height Height of texture
* @param depth Depth of texture
* @param format Format of data
* @param type Type of data
* @param pixels Buffer with image data
**/
void 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)
{
switch (target)
{
case GL_TEXTURE_2D:
gl.texSubImage2D(target, level, x, y, width, height, format, type, pixels);
GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage2D");
break;
case GL_TEXTURE_2D_ARRAY:
gl.texSubImage3D(target, level, x, y, z, width, height, depth, format, type, pixels);
GLU_EXPECT_NO_ERROR(gl.getError(), "TexSubImage3D");
break;
default:
TCU_FAIL("Invalid enum");
break;
}
}
} // TextureFilterAnisotropicUtils namespace
/** Constructor.
*
* @param context Rendering context
*/
TextureFilterAnisotropicQueriesTestCase::TextureFilterAnisotropicQueriesTestCase(deqp::Context& context)
: TestCase(context, "queries", "Verifies if queries for GL_EXT_texture_filter_anisotropic tokens works as expected")
{
/* Left blank intentionally */
}
/** Stub deinit method. */
void TextureFilterAnisotropicQueriesTestCase::deinit()
{
}
/** Stub init method */
void TextureFilterAnisotropicQueriesTestCase::init()
{
glu::ContextType contextType = m_context.getRenderContext().getType();
if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_filter_anisotropic") &&
!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_filter_anisotropic"))
{
TCU_THROW(NotSupportedError, "texture filter anisotropic functionality not supported");
}
}
/** Executes test iteration.
*
* @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
*/
tcu::TestNode::IterateResult TextureFilterAnisotropicQueriesTestCase::iterate()
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
GLuint texture;
gl.genTextures(1, &texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "genTextures");
gl.bindTexture(GL_TEXTURE_2D, texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "bindTexture");
TextureFilterAnisotropicUtils::texImage(gl, GL_TEXTURE_2D, 0, GL_RGBA8, 16, 16, 1, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
if (verifyTexParameters(gl) && verifyGet(gl))
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
gl.deleteTextures(1, &texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTextures");
return STOP;
}
/** Verify if texParameter*, getTexParameter* queries for GL_TEXTURE_MAX_ANISOTROPY_EXT pname works as expected.
*
* @param gl OpenGL functions wrapper
*
* @return Returns true if queries test passed, false otherwise.
*/
bool TextureFilterAnisotropicQueriesTestCase::verifyTexParameters(const glw::Functions& gl)
{
GLint iValue;
gl.getTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv");
// Verify initial integer value which should be equal to 1
if (iValue != 1)
{
m_testCtx.getLog() << tcu::TestLog::Message
<< "GetTexParameteriv failed. Expected value: 1, Queried value: " << iValue
<< tcu::TestLog::EndMessage;
return false;
}
GLfloat fValue;
gl.getTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterfv");
// Verify initial float value which should be equal to 1.0f
if (fValue != 1.0f)
{
m_testCtx.getLog() << tcu::TestLog::Message
<< "GetTexParameterfv failed. Expected value: 1.0, Queried value: " << iValue
<< tcu::TestLog::EndMessage;
return false;
}
// Set custom integer value and verify it
iValue = 2;
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, iValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteri");
gl.getTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv");
if (iValue != 2)
{
m_testCtx.getLog() << tcu::TestLog::Message
<< "texParameteri failed. Expected value: 2, Queried value: " << iValue
<< tcu::TestLog::EndMessage;
return false;
}
// Set custom float value and verify it
fValue = 1.5f;
gl.texParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterf");
gl.getTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterfv");
if (fValue != 1.5f)
{
m_testCtx.getLog() << tcu::TestLog::Message
<< "texParameterf failed. Expected value: 1.5, Queried value: " << fValue
<< tcu::TestLog::EndMessage;
return false;
}
// Set custom integer value and verify it
iValue = 1;
gl.texParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "texParameteriv");
gl.getTexParameteriv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameteriv");
if (iValue != 1)
{
m_testCtx.getLog() << tcu::TestLog::Message
<< "texParameteriv failed. Expected value: 1, Queried value: " << iValue
<< tcu::TestLog::EndMessage;
return false;
}
// Set custom float value and verify it
fValue = 2.0f;
gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterfv");
gl.getTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getTexParameterfv");
if (fValue != 2.0f)
{
m_testCtx.getLog() << tcu::TestLog::Message
<< "texParameterfv failed. Expected value: 2.0, Queried value: " << fValue
<< tcu::TestLog::EndMessage;
return false;
}
// Set texture filter anisotropic to 0.9f and check if INVALID_VALUE error is generated
fValue = 0.9f;
gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
GLint error = gl.getError();
if (error != GL_INVALID_VALUE)
{
m_testCtx.getLog()
<< tcu::TestLog::Message
<< "texParameterfv failed for values less then 1.0f. Expected INVALID_VALUE error. Generated error: "
<< glu::getErrorName(error) << tcu::TestLog::EndMessage;
return false;
}
return true;
}
/** Verify if get* queries for GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT pname works as expected.
*
* @param gl OpenGL functions wrapper
*
* @return Returns true if queries test passed, false otherwise.
*/
bool TextureFilterAnisotropicQueriesTestCase::verifyGet(const glw::Functions& gl)
{
GLboolean bValue;
GLint iValue;
GLfloat fValue;
GLdouble dValue;
gl.getBooleanv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &bValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv");
gl.getIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &iValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
gl.getFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv");
if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
{
gl.getDoublev(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &dValue);
GLU_EXPECT_NO_ERROR(gl.getError(), "getDoublev");
}
return true;
}
/** Constructor.
*
* @param context Rendering context
*/
TextureFilterAnisotropicDrawingTestCase::TextureFilterAnisotropicDrawingTestCase(deqp::Context& context)
: TestCase(context, "drawing", "Verifies if drawing texture with anisotropic filtering is performed as expected")
, m_vertex(DE_NULL)
, m_fragment(DE_NULL)
, m_texture(0)
{
/* Left blank intentionally */
}
/** Stub deinit method. */
void TextureFilterAnisotropicDrawingTestCase::deinit()
{
/* Left blank intentionally */
}
/** Stub init method */
void TextureFilterAnisotropicDrawingTestCase::init()
{
glu::ContextType contextType = m_context.getRenderContext().getType();
if (!glu::contextSupports(contextType, glu::ApiType::core(4, 6)) &&
!m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_filter_anisotropic") &&
!m_context.getContextInfo().isExtensionSupported("GL_ARB_texture_filter_anisotropic"))
{
TCU_THROW(NotSupportedError, "texture filter anisotropic functionality not supported");
}
const tcu::RenderTarget& rt = m_context.getRenderTarget();
GLint width = rt.getWidth();
GLint height = rt.getHeight();
if (width < 32 || height < 32)
TCU_THROW(NotSupportedError, "Config not supported - render buffer size should be at least 32x32");
m_vertex = "#version <VERSION>\n"
"\n"
"in highp vec3 vertex;\n"
"in highp <TEXCOORD_TYPE> inTexCoord;\n"
"out highp <TEXCOORD_TYPE> commonTexCoord;\n"
"\n"
"uniform highp mat4 projectionMatrix;\n"
"\n"
"void main()\n"
"{\n"
" commonTexCoord = inTexCoord;\n"
" gl_Position = vec4(vertex, 1.0) * projectionMatrix;\n"
"}\n";
m_fragment = "#version <VERSION>\n"
"\n"
"in highp <TEXCOORD_TYPE> commonTexCoord;\n"
"out highp vec4 fragColor;\n"
"\n"
"uniform highp <SAMPLER_TYPE> tex;\n"
"\n"
"void main()\n"
"{\n"
" fragColor = texture(tex, commonTexCoord);\n"
"}\n"
"\n";
m_supportedTargets.clear();
m_supportedTargets.push_back(GL_TEXTURE_2D);
m_supportedTargets.push_back(GL_TEXTURE_2D_ARRAY);
m_supportedInternalFormats.clear();
m_supportedInternalFormats.push_back(GL_R8);
m_supportedInternalFormats.push_back(GL_R8_SNORM);
m_supportedInternalFormats.push_back(GL_RG8);
m_supportedInternalFormats.push_back(GL_RG8_SNORM);
m_supportedInternalFormats.push_back(GL_RGB8);
m_supportedInternalFormats.push_back(GL_RGB8_SNORM);
m_supportedInternalFormats.push_back(GL_RGB565);
m_supportedInternalFormats.push_back(GL_RGBA4);
m_supportedInternalFormats.push_back(GL_RGB5_A1);
m_supportedInternalFormats.push_back(GL_RGBA8);
m_supportedInternalFormats.push_back(GL_RGBA8_SNORM);
m_supportedInternalFormats.push_back(GL_RGB10_A2);
m_supportedInternalFormats.push_back(GL_SRGB8);
m_supportedInternalFormats.push_back(GL_SRGB8_ALPHA8);
m_supportedInternalFormats.push_back(GL_R16F);
m_supportedInternalFormats.push_back(GL_RG16F);
m_supportedInternalFormats.push_back(GL_RGB16F);
m_supportedInternalFormats.push_back(GL_RGBA16F);
m_supportedInternalFormats.push_back(GL_R11F_G11F_B10F);
m_supportedInternalFormats.push_back(GL_RGB9_E5);
}
/** Executes test iteration.
*
* @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
*/
tcu::TestNode::IterateResult TextureFilterAnisotropicDrawingTestCase::iterate()
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
bool result = true;
GLfloat maxAnisoDegree = 2.0;
gl.getFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisoDegree);
GLU_EXPECT_NO_ERROR(gl.getError(), "getFloatv");
std::vector<GLfloat> anisoVec;
anisoVec.push_back(1.0f);
anisoVec.push_back(2.0f);
for (deUint32 iTarget = 0; iTarget < m_supportedTargets.size(); ++iTarget)
{
GLenum target = m_supportedTargets[iTarget];
for (deUint32 iFormat = 0; iFormat < m_supportedInternalFormats.size(); ++iFormat)
{
GLenum format = m_supportedInternalFormats[iFormat];
// Generate texture
generateTexture(gl, target);
// Fill texture with strips pattern
fillTexture(gl, target, format);
// Draw scene
GLuint lastPoints = 0xFFFFFFFF;
for (deUint32 i = 0; i < anisoVec.size(); ++i)
{
GLfloat aniso = anisoVec[i];
if (result)
result = result && drawTexture(gl, target, aniso);
// Verify result
if (result)
{
GLuint currentPoints = verifyScene(gl);
if (lastPoints <= currentPoints)
{
m_testCtx.getLog()
<< tcu::TestLog::Message
<< "Anisotropy verification failed (lastPoints <= currentPoints) for "
<< "anisotropy: " << aniso << ", "
<< "target: " << glu::getTextureTargetName(target) << ", "
<< "internalFormat: " << glu::getUncompressedTextureFormatName(format) << ", "
<< "lastPoints: " << lastPoints << ", "
<< "currentPoints: " << currentPoints << tcu::TestLog::EndMessage;
result = false;
break;
}
lastPoints = currentPoints;
}
}
// Release texture
releaseTexture(gl);
if (!result)
{
// Stop loops
iTarget = m_supportedTargets.size();
iFormat = m_supportedInternalFormats.size();
}
}
}
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
/** Generate texture and set filtering parameters.
*
* @param gl OpenGL functions wrapper
* @param target Texture target
* @param internalFormat Texture internal format
*/
void TextureFilterAnisotropicDrawingTestCase::generateTexture(const glw::Functions& gl, GLenum target)
{
gl.genTextures(1, &m_texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures");
gl.bindTexture(target, m_texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
gl.texParameteri(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
gl.texParameteri(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
gl.texParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
gl.texParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
gl.texParameteri(target, GL_TEXTURE_MAX_LEVEL, 1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
}
/** Fill texture with strips pattern.
*
* @param gl OpenGL functions wrapper
* @param target Texture target
* @param internalFormat Texture internal format
*/
void TextureFilterAnisotropicDrawingTestCase::fillTexture(const glw::Functions& gl, GLenum target,
GLenum internalFormat)
{
tcu::TextureFormat texFormat = glu::mapGLInternalFormat(internalFormat);
glu::TransferFormat transFormat = glu::getTransferFormat(texFormat);
for (int l = 0; l < 2; ++l)
{
GLuint texSize = 32 / (l + 1);
std::vector<GLubyte> vecData;
vecData.resize(texSize * texSize * texFormat.getPixelSize() * 2);
tcu::PixelBufferAccess bufferAccess(texFormat, texSize, texSize, 1, vecData.data());
for (GLuint x = 0; x < texSize; ++x)
{
for (GLuint y = 0; y < texSize; ++y)
{
int value = ((x * (l + 1)) % 8 < 4) ? 255 : 0;
tcu::RGBA rgbaColor(value, value, value, 255);
tcu::Vec4 color = rgbaColor.toVec();
bufferAccess.setPixel(color, x, y);
}
}
TextureFilterAnisotropicUtils::texImage(gl, target, l, internalFormat, texSize, texSize, 1, transFormat.format,
transFormat.dataType, vecData.data());
}
}
/** Render polygon with anisotropic filtering.
*
* @param gl OpenGL functions wrapper
* @param target Texture target
* @param anisoDegree Degree of anisotropy
*
* @return Returns true if no error occured, false otherwise.
*/
bool TextureFilterAnisotropicDrawingTestCase::drawTexture(const glw::Functions& gl, GLenum target, GLfloat anisoDegree)
{
const GLfloat vertices2[] = { -1.0f, 0.0f, -0.5f, 0.0f, 0.0f, -4.0f, 4.0f, -2.0f, 0.0f, 1.0f,
1.0f, 0.0f, -0.5f, 1.0f, 0.0f, -2.0f, 4.0f, -2.0f, 1.0f, 1.0f };
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,
1.0f, 0.0f, -0.5f, 1.0f, 0.0f, 0.0f, -2.0f, 4.0f, -2.0f, 1.0f, 1.0f, 0.0f };
// Projection values.
const GLfloat projectionMatrix[] = { 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f,
0.0f, 0.0f, -2.5f / 1.5f, -2.0f / 1.5f, 0.0f, 0.0f, -1.0f, 0.0f };
gl.viewport(0, 0, 32, 32);
std::string vertexShader = m_vertex;
std::string fragmentShader = m_fragment;
std::string texCoordType;
std::string samplerType;
TextureFilterAnisotropicUtils::generateTokens(target, texCoordType, samplerType);
TextureFilterAnisotropicUtils::replaceToken("<TEXCOORD_TYPE>", texCoordType.c_str(), vertexShader);
TextureFilterAnisotropicUtils::replaceToken("<TEXCOORD_TYPE>", texCoordType.c_str(), fragmentShader);
TextureFilterAnisotropicUtils::replaceToken("<SAMPLER_TYPE>", samplerType.c_str(), vertexShader);
TextureFilterAnisotropicUtils::replaceToken("<SAMPLER_TYPE>", samplerType.c_str(), fragmentShader);
if (glu::isContextTypeGLCore(m_context.getRenderContext().getType()))
{
TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "130", vertexShader);
TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "130", fragmentShader);
}
else
{
TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "300 es", vertexShader);
TextureFilterAnisotropicUtils::replaceToken("<VERSION>", "300 es", fragmentShader);
}
ProgramSources sources = makeVtxFragSources(vertexShader, fragmentShader);
ShaderProgram program(gl, sources);
if (!program.isOk())
{
m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
<< "Vertex: " << program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
<< vertexShader << "\n"
<< "Fragment: " << program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
<< fragmentShader << "\n"
<< "Program: " << program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
return false;
}
GLuint vao;
gl.genVertexArrays(1, &vao);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays");
gl.bindVertexArray(vao);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray");
GLuint vbo;
gl.genBuffers(1, &vbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers");
gl.bindBuffer(GL_ARRAY_BUFFER, vbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer");
std::vector<GLfloat> vboData;
vboData.resize(24);
GLuint texCoordDim;
if (texCoordType == "vec2")
{
texCoordDim = 2;
deMemcpy((void*)vboData.data(), (void*)vertices2, sizeof(vertices2));
}
else
{
texCoordDim = 3;
deMemcpy((void*)vboData.data(), (void*)vertices3, sizeof(vertices3));
}
gl.bufferData(GL_ARRAY_BUFFER, vboData.size() * sizeof(GLfloat), (GLvoid*)vboData.data(), GL_DYNAMIC_DRAW);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData");
gl.useProgram(program.getProgram());
GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram");
GLuint matrixLocation = gl.getUniformLocation(program.getProgram(), "projectionMatrix");
GLuint texLocation = gl.getUniformLocation(program.getProgram(), "tex");
gl.activeTexture(GL_TEXTURE0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glActiveTexture");
gl.bindTexture(target, m_texture);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture");
gl.uniformMatrix4fv(matrixLocation, 1, GL_FALSE, projectionMatrix);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformMatrix4fv");
gl.uniform1i(texLocation, 0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform1i");
gl.texParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisoDegree);
GLU_EXPECT_NO_ERROR(gl.getError(), "texParameterfv");
gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor");
gl.clear(GL_COLOR_BUFFER_BIT);
GLU_EXPECT_NO_ERROR(gl.getError(), "glClear");
gl.enableVertexAttribArray(0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
gl.enableVertexAttribArray(1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray");
GLint attrLocationVertex = gl.getAttribLocation(program.getProgram(), "vertex");
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation");
GLint attrLocationInTexCoord = gl.getAttribLocation(program.getProgram(), "inTexCoord");
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation");
GLuint strideSize = (3 + texCoordDim) * sizeof(GLfloat);
gl.vertexAttribPointer(attrLocationVertex, 3, GL_FLOAT, GL_FALSE, strideSize, DE_NULL);
GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
gl.vertexAttribPointer(attrLocationInTexCoord, texCoordDim, GL_FLOAT, GL_FALSE, strideSize,
(GLvoid*)(3 * sizeof(GLfloat)));
GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer");
gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArray");
gl.disableVertexAttribArray(0);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
gl.disableVertexAttribArray(1);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDisableVertexAttribArray");
if (vbo)
{
gl.deleteBuffers(1, &vbo);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteBuffers");
}
if (vao)
{
gl.deleteVertexArrays(1, &vao);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteVertexArrays");
}
return true;
}
/** Verify rendered polygon anisotropy.
*
* @param gl OpenGL functions wrapper
*
* @return Returns points value. Less points means better anisotropy (smoother strips).
*/
GLuint TextureFilterAnisotropicDrawingTestCase::verifyScene(const glw::Functions& gl)
{
std::vector<GLubyte> pixels;
pixels.resize(32 * 8 * 4);
gl.readPixels(0, 23, 32, 8, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels");
GLuint sum = 0;
GLubyte last = 0;
GLubyte current = 0;
for (int j = 0; j < 8; ++j)
{
for (int i = 0; i < 32; ++i)
{
current = pixels[(i + j * 32) * 4];
if (i > 0)
sum += deAbs32((int)current - (int)last);
last = current;
}
}
return sum;
}
/** Release texture.
*
* @param gl OpenGL functions wrapper
*/
void TextureFilterAnisotropicDrawingTestCase::releaseTexture(const glw::Functions& gl)
{
if (m_texture)
gl.deleteTextures(1, &m_texture);
m_texture = 0;
}
/** Constructor.
*
* @param context Rendering context.
*/
TextureFilterAnisotropicTests::TextureFilterAnisotropicTests(deqp::Context& context)
: TestCaseGroup(context, "texture_filter_anisotropic",
"Verify conformance of CTS_EXT_texture_filter_anisotropic implementation")
{
}
/** Initializes the test group contents. */
void TextureFilterAnisotropicTests::init()
{
addChild(new TextureFilterAnisotropicQueriesTestCase(m_context));
addChild(new TextureFilterAnisotropicDrawingTestCase(m_context));
}
} /* glcts namespace */