blob: f49eb7057855db1e574984523ab56873c052adf4 [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 glcPackedDepthStencilTests.cpp
* \brief
*/ /*-------------------------------------------------------------------*/
#include "glcPackedDepthStencilTests.hpp"
#include "deMath.h"
#include "gluContextInfo.hpp"
#include "gluDrawUtil.hpp"
#include "gluRenderContext.hpp"
#include "gluShaderProgram.hpp"
#include "gluStrUtil.hpp"
#include "glwEnums.hpp"
#include "glwFunctions.hpp"
#include "tcuRenderTarget.hpp"
#include "tcuTestLog.hpp"
#include <algorithm>
#include <cstring>
#include <stdio.h>
using namespace glw;
using namespace glu;
namespace glcts
{
#define TEX_SIZE 256
#define TOLERANCE_LOW 0.48
#define TOLERANCE_HIGH 0.52
#define EPSILON 0.01
enum DrawMode
{
DEFAULT,
DEPTH_SPAN1,
DEPTH_SPAN2,
};
struct D32F_S8
{
GLfloat d;
GLuint s;
};
// Reference texture names for the described 5 textures and framebuffers
// and also for identifying other cases' reference textures
enum TextureNames
{
packedTexImage,
packedTexRender,
packedTexRenderInitStencil,
packedTexRenderDepthStep,
packedTexRenderStencilStep,
NUM_TEXTURES,
verifyCopyTexImage,
verifyPartialAttachments,
verifyMixedAttachments,
verifyClearBufferDepth,
verifyClearBufferStencil,
verifyClearBufferDepthStencil,
verifyBlit,
};
struct TypeFormat
{
GLenum type;
GLenum format;
const char* formatName;
int size;
int d;
int s;
};
#define NUM_TEXTURE_TYPES 2
static const TypeFormat TextureTypes[NUM_TEXTURE_TYPES] = {
{ GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8, "depth24_stencil8", sizeof(GLuint), 24, 8 },
{ GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8, "depth32f_stencil8", sizeof(GLuint) + sizeof(GLfloat),
32, 8 },
};
// Texture targets for initial state checking
static const GLenum coreTexTargets[] = {
GL_TEXTURE_2D,
GL_TEXTURE_3D,
GL_TEXTURE_2D_ARRAY,
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
GL_TEXTURE_1D,
GL_TEXTURE_1D_ARRAY,
GL_TEXTURE_CUBE_MAP_ARRAY,
GL_TEXTURE_RECTANGLE,
GL_TEXTURE_2D_MULTISAMPLE,
GL_TEXTURE_2D_MULTISAMPLE_ARRAY,
GL_PROXY_TEXTURE_1D,
GL_PROXY_TEXTURE_2D,
GL_PROXY_TEXTURE_3D,
GL_PROXY_TEXTURE_1D_ARRAY,
GL_PROXY_TEXTURE_2D_ARRAY,
GL_PROXY_TEXTURE_CUBE_MAP_ARRAY,
GL_PROXY_TEXTURE_RECTANGLE,
GL_PROXY_TEXTURE_CUBE_MAP,
GL_PROXY_TEXTURE_2D_MULTISAMPLE,
GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY,
};
static const GLenum esTexTargets[] = {
GL_TEXTURE_2D,
GL_TEXTURE_3D,
GL_TEXTURE_2D_ARRAY,
GL_TEXTURE_CUBE_MAP_POSITIVE_X,
GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
};
// Listing of non-depth_stencil types for error tests
static const GLenum coreNonDepthStencilTypes[] = {
GL_UNSIGNED_BYTE,
GL_BYTE,
GL_UNSIGNED_SHORT,
GL_SHORT,
GL_UNSIGNED_INT,
GL_INT,
GL_HALF_FLOAT,
GL_FLOAT,
GL_UNSIGNED_SHORT_5_6_5,
GL_UNSIGNED_SHORT_4_4_4_4,
GL_UNSIGNED_SHORT_5_5_5_1,
GL_UNSIGNED_INT_2_10_10_10_REV,
GL_UNSIGNED_INT_10F_11F_11F_REV,
GL_UNSIGNED_INT_5_9_9_9_REV,
GL_UNSIGNED_BYTE_3_3_2,
GL_UNSIGNED_BYTE_2_3_3_REV,
GL_UNSIGNED_SHORT_5_6_5_REV,
GL_UNSIGNED_SHORT_4_4_4_4_REV,
GL_UNSIGNED_SHORT_1_5_5_5_REV,
GL_UNSIGNED_INT_8_8_8_8,
GL_UNSIGNED_INT_8_8_8_8_REV,
GL_UNSIGNED_INT_10_10_10_2,
};
static const GLenum esNonDepthStencilTypes[] = {
GL_UNSIGNED_BYTE,
GL_BYTE,
GL_UNSIGNED_SHORT,
GL_SHORT,
GL_UNSIGNED_INT,
GL_INT,
GL_HALF_FLOAT,
GL_FLOAT,
GL_UNSIGNED_SHORT_5_6_5,
GL_UNSIGNED_SHORT_4_4_4_4,
GL_UNSIGNED_SHORT_5_5_5_1,
GL_UNSIGNED_INT_2_10_10_10_REV,
GL_UNSIGNED_INT_10F_11F_11F_REV,
GL_UNSIGNED_INT_5_9_9_9_REV,
};
// Listing of non-depth_stencil formats for error tests
static const GLenum coreNonDepthStencilFormats[] = {
GL_STENCIL_INDEX, GL_RED, GL_GREEN, GL_BLUE, GL_RG, GL_RGB, GL_RGBA,
GL_BGR, GL_BGRA, GL_RED_INTEGER, GL_GREEN_INTEGER, GL_BLUE_INTEGER, GL_RG_INTEGER, GL_RGB_INTEGER,
GL_RGBA_INTEGER, GL_BGR_INTEGER, GL_BGRA_INTEGER,
};
static const GLenum esNonDepthStencilFormats[] = {
GL_RED,
GL_RG,
GL_RGB,
GL_RGBA,
GL_LUMINANCE, // for es3+
GL_ALPHA, // for es3+
GL_LUMINANCE_ALPHA, // for es3+
GL_RED_INTEGER,
GL_RG_INTEGER,
GL_RGB_INTEGER,
GL_RGBA_INTEGER,
};
// Listing of non-depth_stencil base formats for error tests
static const GLenum coreOtherBaseFormats[] = {
GL_RED, GL_RG, GL_RGB, GL_RGBA,
};
static const GLenum esOtherBaseFormats[] = {
GL_RED, GL_RG, GL_RGB, GL_RGBA, GL_LUMINANCE, GL_ALPHA, GL_LUMINANCE_ALPHA,
};
struct AttachmentParam
{
GLenum pname;
GLint value;
};
#define NUM_ATTACHMENT_PARAMS_CORE 13
#define NUM_ATTACHMENT_PARAMS_ES 12
static const AttachmentParam coreAttachmentParams[NUM_TEXTURE_TYPES][NUM_ATTACHMENT_PARAMS_CORE] = {
{
{ GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, 24 },
{ GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, 8 },
{ GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, GL_UNSIGNED_NORMALIZED },
{ GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_LINEAR },
{ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, -1 },
{ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_LAYERED, 0 },
},
{
{ GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, 32 },
{ GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, 8 },
{ GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, GL_FLOAT },
{ GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_LINEAR },
{ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, -1 },
{ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_LAYERED, 0 },
},
};
static const AttachmentParam esAttachmentParams[NUM_TEXTURE_TYPES][NUM_ATTACHMENT_PARAMS_ES] = {
{
{ GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, 24 },
{ GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, 8 },
{ GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, GL_UNSIGNED_NORMALIZED },
{ GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_LINEAR },
{ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, -1 },
{ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, 0 },
},
{
{ GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, 32 },
{ GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, 8 },
{ GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, GL_FLOAT },
{ GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_LINEAR },
{ GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, -1 },
{ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, 0 },
{ GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, 0 },
},
};
enum ColorFunction
{
COLOR_CHECK_DEFAULT,
COLOR_CHECK_DEPTH,
COLOR_CHECK_STENCIL,
};
class BaseTest : public deqp::TestCase
{
public:
BaseTest(deqp::Context& context, const TypeFormat& tf);
virtual ~BaseTest();
void init(void);
virtual tcu::TestNode::IterateResult iterate(void);
const AttachmentParam* getAttachmentParams() const;
void createGradient(std::vector<GLbyte>& data);
void setDrawReadBuffer(GLenum draw, GLenum read);
void restoreDrawReadBuffer();
void createTextures();
void setupTexture();
void destroyTextures();
GLuint createProgram(const char* vsCode, const char* fsCode);
void setupColorProgram(GLint& uColor);
bool setupTextureProgram();
bool setupStencilProgram();
bool setTextureUniform(GLuint programId);
void drawQuad(DrawMode drawMode, GLuint program);
void renderToTextures();
bool verifyDepthStencilGradient(GLvoid* data, unsigned int texIndex, int width, int height);
bool verifyColorGradient(GLvoid* data, unsigned int texIndex, int function, int width, int height);
bool doReadPixels(GLuint texture, int function);
protected:
GLuint m_defaultFBO;
GLuint m_drawBuffer;
GLuint m_readBuffer;
const GLenum* m_textureTargets;
GLuint m_textureTargetsCount;
const GLenum* m_nonDepthStencilTypes;
GLuint m_nonDepthStencilTypesCount;
const GLenum* m_nonDepthStencilFormats;
GLuint m_nonDepthStencilFormatsCount;
const GLenum* m_otherBaseFormats;
GLuint m_otherBaseFormatsCount;
const AttachmentParam* m_attachmentParams[NUM_TEXTURE_TYPES];
GLuint m_attachmentParamsCount;
const TypeFormat& m_typeFormat;
GLuint m_textureProgram;
GLuint m_colorProgram;
GLuint m_stencilProgram;
GLuint m_textures[NUM_TEXTURES];
GLuint m_framebuffers[NUM_TEXTURES];
};
BaseTest::BaseTest(deqp::Context& context, const TypeFormat& tf)
: deqp::TestCase(context, tf.formatName, "")
, m_defaultFBO(0)
, m_drawBuffer(GL_COLOR_ATTACHMENT0)
, m_readBuffer(GL_COLOR_ATTACHMENT0)
, m_textureTargets(coreTexTargets)
, m_textureTargetsCount(DE_LENGTH_OF_ARRAY(coreTexTargets))
, m_nonDepthStencilTypes(coreNonDepthStencilTypes)
, m_nonDepthStencilTypesCount(DE_LENGTH_OF_ARRAY(coreNonDepthStencilTypes))
, m_nonDepthStencilFormats(coreNonDepthStencilFormats)
, m_nonDepthStencilFormatsCount(DE_LENGTH_OF_ARRAY(coreNonDepthStencilFormats))
, m_otherBaseFormats(coreOtherBaseFormats)
, m_otherBaseFormatsCount(DE_LENGTH_OF_ARRAY(coreOtherBaseFormats))
, m_attachmentParamsCount(0)
, m_typeFormat(tf)
, m_textureProgram(0)
, m_colorProgram(0)
, m_stencilProgram(0)
{
}
BaseTest::~BaseTest()
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
if (m_textureProgram)
gl.deleteProgram(m_textureProgram);
if (m_colorProgram)
gl.deleteProgram(m_colorProgram);
if (m_stencilProgram)
gl.deleteProgram(m_stencilProgram);
}
void BaseTest::init(void)
{
if (glu::isContextTypeES(m_context.getRenderContext().getType()))
{
m_textureTargets = esTexTargets;
m_textureTargetsCount = DE_LENGTH_OF_ARRAY(esTexTargets);
m_nonDepthStencilTypes = esNonDepthStencilTypes;
m_nonDepthStencilTypesCount = DE_LENGTH_OF_ARRAY(esNonDepthStencilTypes);
m_nonDepthStencilFormats = esNonDepthStencilFormats;
m_nonDepthStencilFormatsCount = DE_LENGTH_OF_ARRAY(esNonDepthStencilFormats);
m_otherBaseFormats = esOtherBaseFormats;
m_otherBaseFormatsCount = DE_LENGTH_OF_ARRAY(esOtherBaseFormats);
for (int i = 0; i < NUM_TEXTURE_TYPES; i++)
m_attachmentParams[i] = esAttachmentParams[i];
m_attachmentParamsCount = NUM_ATTACHMENT_PARAMS_ES;
}
else
{
for (int i = 0; i < NUM_TEXTURE_TYPES; i++)
m_attachmentParams[i] = coreAttachmentParams[i];
m_attachmentParamsCount = NUM_ATTACHMENT_PARAMS_CORE;
}
}
tcu::TestNode::IterateResult BaseTest::iterate(void)
{
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
const AttachmentParam* BaseTest::getAttachmentParams() const
{
// find type index
int index = 0;
for (; index < NUM_TEXTURE_TYPES; index++)
{
if (TextureTypes[index].format == m_typeFormat.format)
break;
}
if (index >= NUM_TEXTURE_TYPES)
TCU_FAIL("Missing attachment definition");
return m_attachmentParams[index];
}
// Creates a gradient texture data in the given type parameter format
void BaseTest::createGradient(std::vector<GLbyte>& data)
{
switch (m_typeFormat.type)
{
case GL_UNSIGNED_INT_24_8:
{
data.resize(TEX_SIZE * TEX_SIZE * sizeof(GLuint));
GLuint* dataPtr = reinterpret_cast<GLuint*>(&data[0]);
for (int j = 0; j < TEX_SIZE; j++)
{
for (int i = 0; i < TEX_SIZE; i++)
{
GLuint d = static_cast<GLuint>(static_cast<float>(i) / (TEX_SIZE - 1) * 0x00ffffff);
GLubyte s = i & 0xff;
dataPtr[TEX_SIZE * j + i] = (d << 8) + s;
}
}
return;
}
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
{
data.resize(TEX_SIZE * TEX_SIZE * sizeof(D32F_S8));
D32F_S8* dataPtr = reinterpret_cast<D32F_S8*>(&data[0]);
for (int j = 0; j < TEX_SIZE; j++)
{
for (int i = 0; i < TEX_SIZE; i++)
{
D32F_S8 v = { static_cast<float>(i) / (TEX_SIZE - 1), static_cast<GLuint>(i & 0xff) };
dataPtr[TEX_SIZE * j + i] = v;
}
}
return;
}
default:
TCU_FAIL("Unsuported type");
}
}
void BaseTest::setDrawReadBuffer(GLenum draw, GLenum read)
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
GLint drawBuffer;
gl.getIntegerv(GL_DRAW_BUFFER0, &drawBuffer);
m_drawBuffer = static_cast<GLuint>(drawBuffer);
GLint readBuffer;
gl.getIntegerv(GL_READ_BUFFER, &readBuffer);
m_readBuffer = static_cast<GLuint>(readBuffer);
gl.drawBuffers(1, &draw);
gl.readBuffer(read);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer");
}
void BaseTest::restoreDrawReadBuffer()
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.drawBuffers(1, &m_drawBuffer);
gl.readBuffer(m_readBuffer);
GLU_EXPECT_NO_ERROR(gl.getError(), "glReadBuffer");
}
void BaseTest::createTextures()
{
// Creates all the textures and framebuffers
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.genTextures(NUM_TEXTURES, m_textures);
gl.genFramebuffers(NUM_TEXTURES, m_framebuffers);
// packedTexImage
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexImage]);
gl.bindTexture(GL_TEXTURE_2D, m_textures[packedTexImage]);
setupTexture();
std::vector<GLbyte> data;
createGradient(data);
gl.texImage2D(GL_TEXTURE_2D, 0, m_typeFormat.format, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_STENCIL, m_typeFormat.type,
&data[0]);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_textures[packedTexImage], 0);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_textures[packedTexImage], 0);
// packedTexRender
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexRender]);
gl.bindTexture(GL_TEXTURE_2D, m_textures[packedTexRender]);
setupTexture();
gl.texImage2D(GL_TEXTURE_2D, 0, m_typeFormat.format, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_STENCIL, m_typeFormat.type,
NULL);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_textures[packedTexRender], 0);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_textures[packedTexRender], 0);
// packedTexRenderInitStencil
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexRenderInitStencil]);
gl.bindTexture(GL_TEXTURE_2D, m_textures[packedTexRenderInitStencil]);
setupTexture();
createGradient(data);
gl.texImage2D(GL_TEXTURE_2D, 0, m_typeFormat.format, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_STENCIL, m_typeFormat.type,
&data[0]);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_textures[packedTexRenderInitStencil],
0);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
m_textures[packedTexRenderInitStencil], 0);
// packedTexRenderDepthStep
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexRenderDepthStep]);
gl.bindTexture(GL_TEXTURE_2D, m_textures[packedTexRenderDepthStep]);
setupTexture();
gl.texImage2D(GL_TEXTURE_2D, 0, m_typeFormat.format, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_STENCIL, m_typeFormat.type,
NULL);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_textures[packedTexRenderDepthStep],
0);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_textures[packedTexRenderDepthStep],
0);
// packedTexRenderStencilStep
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexRenderStencilStep]);
gl.bindTexture(GL_TEXTURE_2D, m_textures[packedTexRenderStencilStep]);
setupTexture();
gl.texImage2D(GL_TEXTURE_2D, 0, m_typeFormat.format, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_STENCIL, m_typeFormat.type,
NULL);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_textures[packedTexRenderStencilStep],
0);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D,
m_textures[packedTexRenderStencilStep], 0);
gl.bindFramebuffer(GL_FRAMEBUFFER, m_defaultFBO);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
}
void BaseTest::setupTexture()
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
}
// Destroys all the textures and framebuffers
void BaseTest::destroyTextures()
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.deleteFramebuffers(NUM_TEXTURES, m_framebuffers);
gl.deleteTextures(NUM_TEXTURES, m_textures);
}
GLuint BaseTest::createProgram(const char* vsCode, const char* fsCode)
{
glu::RenderContext& renderContext = m_context.getRenderContext();
glu::ContextType contextType = renderContext.getType();
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(contextType);
const char* version = glu::getGLSLVersionDeclaration(glslVersion);
glu::Shader vs(gl, glu::SHADERTYPE_VERTEX);
const char* vSources[] = { version, vsCode };
const int vLengths[] = { int(strlen(version)), int(strlen(vsCode)) };
vs.setSources(2, vSources, vLengths);
vs.compile();
if (!vs.getCompileStatus())
TCU_FAIL("Vertex shader compilation failed");
glu::Shader fs(gl, glu::SHADERTYPE_FRAGMENT);
const char* fSources[] = { version, fsCode };
const int fLengths[] = { int(strlen(version)), int(strlen(fsCode)) };
fs.setSources(2, fSources, fLengths);
fs.compile();
if (!fs.getCompileStatus())
TCU_FAIL("Fragment shader compilation failed");
GLuint p = gl.createProgram();
gl.attachShader(p, vs.getShader());
gl.attachShader(p, fs.getShader());
gl.linkProgram(p);
return p;
}
void BaseTest::setupColorProgram(GLint& uColor)
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
const char* vs = "\n"
"precision highp float;\n"
"in vec4 pos;\n"
"void main() {\n"
" gl_Position = pos;\n"
"}\n";
const char* fs = "\n"
"precision highp float;\n"
"out vec4 color;\n"
"uniform vec4 uColor;\n"
"void main() {\n"
" color = uColor;\n"
"}\n";
// setup shader program
if (!m_colorProgram)
m_colorProgram = createProgram(vs, fs);
if (!m_colorProgram)
TCU_FAIL("Error while loading shader program");
gl.useProgram(m_colorProgram);
// Setup program uniforms
uColor = gl.getUniformLocation(m_colorProgram, "uColor");
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation");
if (uColor == -1)
TCU_FAIL("Error getting uniform uColor");
gl.uniform4f(uColor, 1.0f, 1.0f, 1.0f, 1.0f);
}
// Common code for default and stencil texture rendering shaders
bool BaseTest::setTextureUniform(GLuint programId)
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.useProgram(programId);
GLint uniformTex = gl.getUniformLocation(programId, "tex");
GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation");
if (uniformTex == -1)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Error getting uniform tex" << tcu::TestLog::EndMessage;
return false;
}
gl.uniform1i(uniformTex, 0);
return true;
}
// Loads texture rendering shader
bool BaseTest::setupTextureProgram()
{
const char* vs = "\n"
"precision highp float;\n"
"in vec4 pos;\n"
"in vec2 UV;\n"
"out vec2 vUV;\n"
"void main() {\n"
" gl_Position = pos;\n"
" vUV = UV;\n"
"}\n";
const char* fs = "\n"
"precision highp float;\n"
"in vec2 vUV;\n"
"out vec4 color;\n"
"uniform sampler2D tex;\n"
"void main() {\n"
" color = texture(tex, vUV).rrra;\n"
"}\n";
if (!m_textureProgram)
m_textureProgram = createProgram(vs, fs);
if (!m_textureProgram)
return false;
return setTextureUniform(m_textureProgram);
}
// Loads texture stencil rendering shader
bool BaseTest::setupStencilProgram()
{
const char* vs = "\n"
"precision highp float;\n"
"in vec4 pos;\n"
"in vec2 UV;\n"
"out vec2 vUV;\n"
"void main() {\n"
" gl_Position = pos;\n"
" vUV = UV;\n"
"}\n";
const char* fs = "\n"
"precision highp float;\n"
"in vec2 vUV;\n"
"out vec4 color;\n"
"uniform highp usampler2D tex;\n"
"void main() {\n"
" float s = float(texture(tex, vUV).r);\n"
" s /= 255.0;\n"
" color = vec4(s, s, s, 1);\n"
"}\n";
if (!m_stencilProgram)
m_stencilProgram = createProgram(vs, fs);
if (!m_stencilProgram)
return false;
return setTextureUniform(m_stencilProgram);
}
void BaseTest::drawQuad(DrawMode drawMode, GLuint program)
{
static const GLfloat verticesDefault[] = {
-1.0f, -1.0f, 0.0f, 1.0f, 1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f,
};
static const GLfloat verticesDepthSpan1[] = {
-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
};
static const GLfloat verticesDepthSpan2[] = {
-1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f, 1.0f,
};
static const GLfloat texCoords[] = {
0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f,
};
static const deUint16 quadIndices[] = { 0, 1, 2, 2, 1, 3 };
static PrimitiveList quadPrimitive = glu::pr::TriangleStrip(DE_LENGTH_OF_ARRAY(quadIndices), quadIndices);
static const glu::VertexArrayBinding depthSpanVA1[] = { glu::va::Float("pos", 4, 4, 0, verticesDepthSpan1) };
static const glu::VertexArrayBinding depthSpanVA2[] = { glu::va::Float("pos", 4, 4, 0, verticesDepthSpan2) };
static const glu::VertexArrayBinding defaultVA[] = { glu::va::Float("pos", 4, 4, 0, verticesDefault),
glu::va::Float("UV", 2, 4, 0, texCoords) };
const glu::RenderContext& renderContext = m_context.getRenderContext();
if (drawMode == DEPTH_SPAN1)
glu::draw(renderContext, program, 1, depthSpanVA1, quadPrimitive);
else if (drawMode == DEPTH_SPAN2)
glu::draw(renderContext, program, 1, depthSpanVA2, quadPrimitive);
else
glu::draw(renderContext, program, 2, defaultVA, quadPrimitive);
}
// Renders all non-trivial startup textures
void BaseTest::renderToTextures()
{
const glu::RenderContext& renderContext = m_context.getRenderContext();
const glw::Functions& gl = renderContext.getFunctions();
GLint uColor;
setupColorProgram(uColor);
gl.enable(GL_DEPTH_TEST);
// depth writing must be enabled as it is disabled in places like doReadPixels
gl.depthMask(GL_TRUE);
if (glu::isContextTypeES(renderContext.getType()))
gl.clearDepthf(1.0f);
else
gl.clearDepth(1.0);
gl.depthFunc(GL_LEQUAL);
gl.viewport(0, 0, TEX_SIZE, TEX_SIZE);
drawQuad(DEPTH_SPAN1, m_colorProgram);
// packedTexRender
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexRender]);
setDrawReadBuffer(GL_NONE, GL_NONE);
gl.enable(GL_STENCIL_TEST);
gl.stencilFunc(GL_ALWAYS, 0x0, 0xFF);
gl.stencilOp(GL_ZERO, GL_INCR, GL_INCR);
gl.clear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
drawQuad(DEPTH_SPAN1, m_colorProgram);
gl.disable(GL_STENCIL_TEST);
restoreDrawReadBuffer();
// packedTexRenderInitStencil
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexRenderInitStencil]);
setDrawReadBuffer(GL_NONE, GL_NONE);
gl.clear(GL_DEPTH_BUFFER_BIT);
drawQuad(DEPTH_SPAN1, m_colorProgram);
restoreDrawReadBuffer();
// packedTexRenderDepthStep
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexRenderDepthStep]);
setDrawReadBuffer(GL_NONE, GL_NONE);
gl.clear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
drawQuad(DEPTH_SPAN2, m_colorProgram);
drawQuad(DEPTH_SPAN1, m_colorProgram);
restoreDrawReadBuffer();
// packedTexRenderStencilStep
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexRenderStencilStep]);
setDrawReadBuffer(GL_NONE, GL_NONE);
gl.clear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
gl.enable(GL_SCISSOR_TEST);
gl.scissor(0, 0, TEX_SIZE, TEX_SIZE / 2);
gl.enable(GL_STENCIL_TEST);
gl.stencilFunc(GL_ALWAYS, 0x0, 0xFF);
gl.stencilOp(GL_ZERO, GL_INCR, GL_INCR);
for (int i = 0; i < 256; i++)
drawQuad(DEPTH_SPAN2, m_colorProgram);
gl.disable(GL_SCISSOR_TEST);
gl.stencilFunc(GL_EQUAL, 0xFF, 0xFF);
gl.clear(GL_DEPTH_BUFFER_BIT);
drawQuad(DEPTH_SPAN1, m_colorProgram);
gl.disable(GL_STENCIL_TEST);
GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable");
restoreDrawReadBuffer();
// end
gl.bindFramebuffer(GL_FRAMEBUFFER, m_defaultFBO);
GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer");
}
// Verifies DepthStencil buffer data against reference values
bool BaseTest::verifyDepthStencilGradient(GLvoid* data, unsigned int texIndex, int width, int height)
{
bool result = true;
int index, skip;
int countD, countS;
index = 0;
countD = 0;
countS = 0;
for (int j = 0; j < height; j++)
{
for (int i = 0; i < width; i++)
{
float d, dref = 0.0;
int s, sref = 0;
skip = 0;
switch (m_typeFormat.type)
{
case GL_UNSIGNED_INT_24_8:
{
GLuint v = ((GLuint*)data)[index];
d = ((float)(v >> 8)) / 0xffffff;
s = v & 0xff;
break;
}
case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
{
D32F_S8 v = ((D32F_S8*)data)[index];
d = v.d;
s = v.s & 0xff;
break;
}
default:
d = -1;
s = -1;
break;
}
switch (texIndex)
{
case packedTexImage:
dref = ((float)i) / (width - 1);
sref = (int)(dref * 255);
break;
case packedTexRender:
dref = ((float)j) / (height - 1);
sref = 1;
break;
case packedTexRenderInitStencil:
dref = ((float)j) / (height - 1);
sref = (int)(((float)i) / (width - 1) * 255);
break;
case packedTexRenderDepthStep:
if (j < height * TOLERANCE_LOW)
{
dref = ((float)j) / (height - 1);
sref = 0;
}
else if (j > height * TOLERANCE_HIGH)
{
dref = 1.0f - ((float)j) / (height - 1);
sref = 0;
}
else
{
skip = 1; // give some tolerance to pixels in the middle
}
break;
case packedTexRenderStencilStep:
if (j < height * TOLERANCE_LOW)
{
dref = ((float)j) / (height - 1);
sref = 255;
}
else if (j > height * TOLERANCE_HIGH)
{
dref = 1;
sref = 0;
}
else
{
skip = 1; // give some tolerance to pixels in the middle
}
break;
case verifyCopyTexImage:
if (j < height * TOLERANCE_LOW)
{
dref = ((float)j) / (height - 1);
sref = 1;
}
else if (j > height * TOLERANCE_HIGH)
{
dref = 0.5;
sref = 1;
}
else
{
skip = 1; // give some tolerance to pixels in the middle
}
break;
default:
dref = -2;
sref = -2;
break;
}
if (!skip)
{
if (deFloatAbs(d - dref) > EPSILON)
{
result = false;
countD++;
}
if (s != sref)
{
result = false;
countS++;
}
}
else
{
skip = 0;
}
index++;
}
}
if (countD || countS)
{
m_testCtx.getLog() << tcu::TestLog::Message << "DEPTH_STENCIL comparison failed" << tcu::TestLog::EndMessage;
}
return result;
}
// Verifies Color buffer data against reference values
bool BaseTest::verifyColorGradient(GLvoid* data, unsigned int texIndex, int function, int width, int height)
{
bool result = true;
int index = 0, skip;
int channel = 0;
int count = 0;
for (int j = 0; j < height; j++)
{
for (int i = 0; i < width; i++)
{
skip = 0;
GLuint color = ((GLuint*)data)[index];
GLuint colorref = 0;
// When data back from glReadPixels with arguments GL_RGBA + GL_UNSIGNED_BYTE,
// we should reverse byte order in big-endian platform for (GLuint*) pointer.
#if (DE_ENDIANNESS == DE_BIG_ENDIAN)
color = deReverseBytes32(color);
#endif
switch (texIndex)
{
case packedTexImage:
channel = (int)(((float)i) / (width - 1) * 255);
colorref = 0xff000000 + channel * 0x00010101;
break;
case packedTexRender:
if (function == COLOR_CHECK_DEPTH)
channel = (int)(((float)j) / (height - 1) * 255);
else
channel = 1;
colorref = 0xff000000 + channel * 0x00010101;
break;
case packedTexRenderInitStencil:
if (function == COLOR_CHECK_DEPTH)
channel = (int)(((float)j) / (height - 1) * 255);
else
channel = (int)(((float)i) / (width - 1) * 255);
colorref = 0xff000000 + channel * 0x00010101;
break;
case packedTexRenderDepthStep:
if (function == COLOR_CHECK_DEPTH)
{
if (j < height * TOLERANCE_LOW)
channel = (int)(((float)j) / (height - 1) * 255);
else if (j > height * TOLERANCE_HIGH)
channel = 255 - (int)(((float)j) / (height - 1) * 255);
else
skip = 1; // give some tolerance to pixels in the middle
}
else
channel = 0;
colorref = 0xff000000 + channel * 0x00010101;
break;
case packedTexRenderStencilStep:
if (j < height * TOLERANCE_LOW)
{
if (function == COLOR_CHECK_DEPTH)
channel = (int)(((float)j) / (height - 1) * 255);
else
channel = 255;
}
else if (j > height * TOLERANCE_HIGH)
channel = (function == COLOR_CHECK_DEPTH) ? 255 : 0;
else
skip = 1; // give some tolerance to pixels in the middle
colorref = 0xff000000 + channel * 0x00010101;
break;
case verifyCopyTexImage:
if (j < height * TOLERANCE_LOW)
{
if (function == COLOR_CHECK_DEPTH)
channel = (int)(((float)j) / (height - 1) * 255);
else
channel = 1;
}
else if (j > height * TOLERANCE_HIGH)
{
channel = (function == COLOR_CHECK_DEPTH) ? 127 : 1;
}
else
{
skip = 1; // give some tolerance to pixels in the middle
}
colorref = 0xff000000 + channel * 0x00010101;
break;
case verifyPartialAttachments:
colorref = 0xffffffff;
break;
case verifyMixedAttachments:
if (j > height * TOLERANCE_HIGH)
colorref = 0xffffffff;
else if (j < height * TOLERANCE_LOW)
colorref = 0xcccccccc;
else
skip = 1;
break;
case verifyClearBufferDepth:
if ((i & 0xff) == 0xff)
colorref = 0xffffffff;
else
colorref = 0xcccccccc;
break;
case verifyClearBufferStencil:
if (i > width * TOLERANCE_HIGH)
colorref = 0xffffffff;
else if (i < width * TOLERANCE_LOW)
colorref = 0xcccccccc;
else
skip = 1;
break;
case verifyClearBufferDepthStencil:
colorref = 0xffffffff;
break;
case verifyBlit:
if (j > height * TOLERANCE_HIGH)
colorref = 0xffffffff;
else if (j < height * TOLERANCE_LOW)
colorref = 0xcccccccc;
else
skip = 1;
break;
default:
colorref = 0xdeadbeef;
break;
}
if (skip)
skip = 0;
else if (color != colorref)
{
float d = (float)(color & 0xff) / 0xff;
float dref = (float)(colorref & 0xff) / 0xff;
if (!((function == COLOR_CHECK_DEPTH) && (deFloatAbs(d - dref) < EPSILON)))
{
result = false;
count++;
}
}
index++;
}
}
if (count)
{
m_testCtx.getLog() << tcu::TestLog::Message << "*** Color comparison failed" << tcu::TestLog::EndMessage;
result = false;
}
return result;
}
// Verify DepthStencil texture by replicating it to color channels
// so it can be read using ReadPixels in Halti.
bool BaseTest::doReadPixels(GLuint texture, int function)
{
bool result = true;
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
GLuint fbo;
gl.genFramebuffers(1, &fbo);
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
GLuint texColor;
gl.genTextures(1, &texColor);
gl.bindTexture(GL_TEXTURE_2D, texColor);
setupTexture();
gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 0);
setDrawReadBuffer(GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0);
// Step 1: Verify depth values
GLenum status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer is incomplete: " << status
<< tcu::TestLog::EndMessage;
result = false;
}
else
{
setupTextureProgram();
gl.bindTexture(GL_TEXTURE_2D, texture);
gl.disable(GL_DEPTH_TEST);
gl.depthMask(GL_FALSE);
gl.disable(GL_STENCIL_TEST);
gl.viewport(0, 0, TEX_SIZE, TEX_SIZE);
gl.clearColor(0.8f, 0.8f, 0.8f, 0.8f);
gl.clear(GL_COLOR_BUFFER_BIT);
drawQuad(DEFAULT, m_textureProgram);
std::vector<GLuint> dataColor(TEX_SIZE * TEX_SIZE, 0);
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, &dataColor[0]);
result &= verifyColorGradient(&dataColor[0], function, COLOR_CHECK_DEPTH, TEX_SIZE, TEX_SIZE);
// Step 2: Verify stencil values
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0);
status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer is incomplete: " << status
<< tcu::TestLog::EndMessage;
result = false;
}
else
{
GLint uColor;
setupColorProgram(uColor);
gl.clearColor(0.8f, 0.8f, 0.8f, 0.8f);
gl.clear(GL_COLOR_BUFFER_BIT);
gl.enable(GL_STENCIL_TEST);
for (int i = 0; i < 256; i++)
{
float v = i / 255.0f;
gl.uniform4f(uColor, v, v, v, 1.0f);
gl.stencilFunc(GL_EQUAL, i, 0xFF);
gl.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
drawQuad(DEFAULT, m_colorProgram);
}
gl.disable(GL_STENCIL_TEST);
dataColor.assign(dataColor.size(), 0);
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, &dataColor[0]);
result &= verifyColorGradient(&dataColor[0], function, COLOR_CHECK_STENCIL, TEX_SIZE, TEX_SIZE);
}
}
// clean up
restoreDrawReadBuffer();
gl.deleteFramebuffers(1, &fbo);
gl.deleteTextures(1, &texColor);
return result;
}
class InitialStateTest : public deqp::TestCase
{
public:
InitialStateTest(deqp::Context& context);
virtual ~InitialStateTest();
virtual tcu::TestNode::IterateResult iterate(void);
};
InitialStateTest::InitialStateTest(deqp::Context& context)
: deqp::TestCase(context, "initial_state", "TEXTURE_STENCIL_SIZE for the default texture objects should be 0")
{
}
InitialStateTest::~InitialStateTest()
{
}
tcu::TestNode::IterateResult InitialStateTest::iterate(void)
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
for (int i = 0; i < DE_LENGTH_OF_ARRAY(coreTexTargets); i++)
{
GLenum target = coreTexTargets[i];
GLfloat fp;
gl.getTexLevelParameterfv(target, 0, GL_TEXTURE_STENCIL_SIZE, &fp);
if (deFloatCmpNE(fp, 0.0f))
{
m_testCtx.getLog() << tcu::TestLog::Message << "gl.getTexLevelParameterfv: Parameter is not 0"
<< tcu::TestLog::EndMessage;
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
}
GLint ip;
gl.getTexLevelParameteriv(target, 0, GL_TEXTURE_STENCIL_SIZE, &ip);
if (deFloatCmpNE((float)ip, 0.0f))
{
m_testCtx.getLog() << tcu::TestLog::Message << "gl.getTexLevelParameteriv: Parameter is not 0"
<< tcu::TestLog::EndMessage;
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
}
}
return STOP;
}
class ValidateErrorsTest : public BaseTest
{
public:
ValidateErrorsTest(deqp::Context& context, const TypeFormat& tf);
virtual ~ValidateErrorsTest();
virtual tcu::TestNode::IterateResult iterate(void);
protected:
bool checkErrors();
};
ValidateErrorsTest::ValidateErrorsTest(deqp::Context& context, const TypeFormat& tf) : BaseTest(context, tf)
{
}
ValidateErrorsTest::~ValidateErrorsTest()
{
}
tcu::TestNode::IterateResult ValidateErrorsTest::iterate(void)
{
createTextures();
if (checkErrors())
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
destroyTextures();
return STOP;
}
// Error tests [desktop only]:
// - The error INVALID_ENUM is generated if ReadPixels is
// called where format is DEPTH_STENCIL and type is not
// UNSIGNED_INT_24_8, or FLOAT_32_UNSIGNED_INT_24_8_REV.
// - The error INVALID_OPERATION is generated if ReadPixels
// is called where type is UNSIGNED_INT_24_8 or
// FLOAT_32_UNSIGNED_INT_24_8_REV and format is not DEPTH_STENCIL.
// - The error INVALID_OPERATION is generated if ReadPixels
// is called where format is DEPTH_STENCIL and there is not both a
// depth buffer and a stencil buffer.
// - Calling GetTexImage with a <format> of DEPTH_COMPONENT when the
// base internal format of the texture image is not DEPTH_COMPONENT
// or DEPTH_STENCIL causes the error INVALID_OPERATION.
// - Calling GetTexImage with a <format> of DEPTH_STENCIL when
// the base internal format of the texture image is not
// DEPTH_STENCIL causes the error INVALID_OPERATION.
// Error tests [Halti only]:
// - The error INVALID_ENUM is generated if ReadPixels is
// called where format is DEPTH_STENCIL.
// Error tests [desktop and Halti]:
// - TexImage generates INVALID_OPERATION if one of the base internal format
// and format is DEPTH_COMPONENT or DEPTH_STENCIL, and the other is neither
// of these values.
// - The error INVALID_OPERATION is generated if CopyTexImage
// is called where format is DEPTH_STENCIL and there is not both a
// depth buffer and a stencil buffer.
bool ValidateErrorsTest::checkErrors()
{
bool result = true;
GLuint fbo, fbo2;
GLuint texColor;
std::vector<GLfloat> data(4 * TEX_SIZE * TEX_SIZE, 0.0f);
const glu::RenderContext& renderContext = m_context.getRenderContext();
const glw::Functions& gl = renderContext.getFunctions();
bool isContextES = glu::isContextTypeES(renderContext.getType());
if (isContextES)
{
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexImage]);
setDrawReadBuffer(GL_NONE, GL_NONE);
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_DEPTH_STENCIL, m_typeFormat.type, &data[0]);
GLenum error = gl.getError();
if (((GL_INVALID_OPERATION != error) && (GL_INVALID_ENUM != error)) &&
!((GL_NO_ERROR == error) && m_context.getContextInfo().isExtensionSupported("GL_NV_read_depth_stencil")))
{
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_DEPTH_STENCIL, m_typeFormat.type, &data[0]);
if (gl.getError() != GL_INVALID_OPERATION)
result = false;
}
restoreDrawReadBuffer();
gl.bindFramebuffer(GL_FRAMEBUFFER, m_defaultFBO);
}
else
{
gl.bindTexture(GL_TEXTURE_2D, m_textures[packedTexImage]);
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexImage]);
setDrawReadBuffer(GL_NONE, GL_NONE);
for (unsigned int i = 0; i < m_nonDepthStencilTypesCount; i++)
{
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_DEPTH_STENCIL, m_nonDepthStencilTypes[i], &data[0]);
if (gl.getError() != GL_INVALID_ENUM)
result = false;
}
for (unsigned int i = 0; i < m_nonDepthStencilFormatsCount; i++)
{
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, m_nonDepthStencilFormats[i], m_typeFormat.type, &data[0]);
if (gl.getError() != GL_INVALID_OPERATION)
result = false;
}
for (int i = 0; i < 2; i++)
{
// setup texture/fbo
gl.genTextures(1, &texColor);
gl.genFramebuffers(1, &fbo);
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
GLenum attachmentType = (i == 0) ? GL_DEPTH_ATTACHMENT : GL_STENCIL_ATTACHMENT;
gl.framebufferTexture2D(GL_FRAMEBUFFER, attachmentType, GL_TEXTURE_2D, m_textures[packedTexImage], 0);
gl.bindTexture(GL_TEXTURE_2D, texColor);
setupTexture();
gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 0);
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_DEPTH_STENCIL, m_typeFormat.type, &data[0]);
if (gl.getError() != GL_INVALID_OPERATION)
result = false;
gl.bindFramebuffer(GL_FRAMEBUFFER, m_defaultFBO);
gl.bindTexture(GL_TEXTURE_2D, 0);
gl.deleteFramebuffers(1, &fbo);
gl.deleteTextures(1, &texColor);
}
for (unsigned int i = 0; i < m_otherBaseFormatsCount; i++)
{
GLenum format = m_otherBaseFormats[i];
gl.genTextures(1, &texColor);
gl.bindTexture(GL_TEXTURE_2D, texColor);
setupTexture();
gl.texImage2D(GL_TEXTURE_2D, 0, format, TEX_SIZE, TEX_SIZE, 0, format, GL_UNSIGNED_BYTE, 0);
if (format != GL_DEPTH_COMPONENT)
{
gl.getTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, &data[0]);
if (gl.getError() != GL_INVALID_OPERATION)
result = false;
}
gl.getTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, &data[0]);
if (gl.getError() != GL_INVALID_OPERATION)
result = false;
gl.deleteTextures(1, &texColor);
}
}
bool coreGL = !glu::isContextTypeES(m_context.getRenderContext().getType());
for (int i = 0; i < 4; i++)
{
int limit;
if (i < 2)
limit = m_nonDepthStencilFormatsCount;
else
limit = m_otherBaseFormatsCount;
for (int j = 0; j < limit; j++)
{
GLint internalFormat = 0;
GLint format = 0;
gl.genTextures(1, &texColor);
gl.bindTexture(GL_TEXTURE_2D, texColor);
setupTexture();
switch (i)
{
case 0:
internalFormat = GL_DEPTH_COMPONENT;
format = m_nonDepthStencilFormats[j];
break;
case 1:
internalFormat = GL_DEPTH_STENCIL;
format = m_nonDepthStencilFormats[j];
break;
case 2:
internalFormat = m_otherBaseFormats[j];
format = GL_DEPTH_COMPONENT;
break;
case 3:
internalFormat = m_otherBaseFormats[j];
format = GL_DEPTH_STENCIL;
break;
}
gl.texImage2D(GL_TEXTURE_2D, 0, internalFormat, TEX_SIZE, TEX_SIZE, 0, format,
(format == GL_DEPTH_STENCIL) ? GL_UNSIGNED_INT_24_8 : GL_UNSIGNED_BYTE, 0);
GLenum expectedError = GL_INVALID_OPERATION;
if (coreGL && (format == GL_STENCIL_INDEX))
{
// The OpenGL 4.3 spec is imprecise about what error this should generate
// see Bugzilla 10134: TexImage with a <format> of STENCIL_INDEX
// 4.3 core (Feb 14 2013) p. 174:
// (describing TexImage3D)
// The format STENCIL_INDEX is not allowed.
// The new OpenGL 4.4 feature ARB_texture_stencil8 removes this error. So
// the best we can do for OpenGL is to just allow any error, or no error,
// for this specific case.
gl.getError();
}
else if (gl.getError() != expectedError)
result = false;
gl.bindTexture(GL_TEXTURE_2D, 0);
gl.deleteTextures(1, &texColor);
}
}
gl.genFramebuffers(1, &fbo);
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_textures[packedTexImage], 0);
gl.genFramebuffers(1, &fbo2);
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo2);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, m_textures[packedTexImage], 0);
GLuint tex;
gl.genTextures(1, &tex);
gl.bindTexture(GL_TEXTURE_2D, tex);
setupTexture();
gl.texImage2D(GL_TEXTURE_2D, 0, m_typeFormat.format, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_STENCIL, m_typeFormat.type, 0);
for (int i = 0; i < 2; i++)
{
switch (i)
{
case 0:
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
gl.bindTexture(GL_TEXTURE_2D, tex);
break;
case 1:
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo2);
gl.bindTexture(GL_TEXTURE_2D, tex);
break;
}
setDrawReadBuffer(GL_NONE, GL_NONE);
gl.copyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL, 0, 0, TEX_SIZE, TEX_SIZE, 0);
GLenum error = gl.getError();
if ((GL_INVALID_OPERATION != error) && (GL_INVALID_ENUM != error))
{
gl.copyTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL, 0, 0, TEX_SIZE, TEX_SIZE, 0);
if (gl.getError() != GL_INVALID_OPERATION)
result = false;
}
restoreDrawReadBuffer();
gl.bindFramebuffer(GL_FRAMEBUFFER, m_defaultFBO);
}
gl.bindTexture(GL_TEXTURE_2D, 0);
gl.deleteTextures(1, &tex);
gl.deleteFramebuffers(1, &fbo);
gl.deleteFramebuffers(1, &fbo2);
return result;
}
class VerifyReadPixelsTest : public BaseTest
{
public:
VerifyReadPixelsTest(deqp::Context& context, const TypeFormat& tf);
virtual ~VerifyReadPixelsTest();
virtual tcu::TestNode::IterateResult iterate(void);
};
VerifyReadPixelsTest::VerifyReadPixelsTest(deqp::Context& context, const TypeFormat& tf) : BaseTest(context, tf)
{
}
VerifyReadPixelsTest::~VerifyReadPixelsTest()
{
}
tcu::TestNode::IterateResult VerifyReadPixelsTest::iterate(void)
{
// Use readpixels to verify the results for the 5 textures above are correct.
// Note that in ES you can only use gl.readpixels on color buffers.
// Test method:
// - on desktop: ReadPixel DEPTH_STENCIL value to buffer. Verify gradient.
// - on desktop/Halti: Create FBO with color/depth/stencil attachment.
// Draw a quad with depth texture bound. Verify gradient.
// Draw 256 times using stencil test and gradient color. Verify gradient.
const glu::RenderContext& renderContext = m_context.getRenderContext();
const glw::Functions& gl = renderContext.getFunctions();
std::size_t dataSize = static_cast<std::size_t>(TEX_SIZE * TEX_SIZE * m_typeFormat.size);
std::vector<GLubyte> data(dataSize);
createTextures();
renderToTextures();
bool result = true;
for (int i = 0; i < NUM_TEXTURES; i++)
{
// Read DEPTH_STENCIL value, applies only to desktop
if (!glu::isContextTypeES(renderContext.getType()))
{
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[i]);
setDrawReadBuffer(GL_NONE, GL_NONE);
data.assign(TEX_SIZE * TEX_SIZE * m_typeFormat.size, 0);
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_DEPTH_STENCIL, m_typeFormat.type, &data[0]);
result &= verifyDepthStencilGradient(&data[0], i, TEX_SIZE, TEX_SIZE);
restoreDrawReadBuffer();
}
// On ES3.2 we have to render to color buffer to verify.
// We can run this also on desktop.
result &= doReadPixels(m_textures[i], i);
}
gl.bindFramebuffer(GL_FRAMEBUFFER, m_defaultFBO);
destroyTextures();
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
class VerifyGetTexImageTest : public BaseTest
{
public:
VerifyGetTexImageTest(deqp::Context& context, const TypeFormat& tf);
virtual ~VerifyGetTexImageTest();
virtual tcu::TestNode::IterateResult iterate(void);
};
VerifyGetTexImageTest::VerifyGetTexImageTest(deqp::Context& context, const TypeFormat& tf) : BaseTest(context, tf)
{
}
VerifyGetTexImageTest::~VerifyGetTexImageTest()
{
}
tcu::TestNode::IterateResult VerifyGetTexImageTest::iterate(void)
{
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
std::vector<GLubyte> data(TEX_SIZE * TEX_SIZE * m_typeFormat.size);
createTextures();
renderToTextures();
bool result = true;
for (int i = 0; i < NUM_TEXTURES; i++)
{
data.assign(TEX_SIZE * TEX_SIZE * m_typeFormat.size, 0);
gl.bindTexture(GL_TEXTURE_2D, m_textures[i]);
gl.getTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL, m_typeFormat.type, &data[0]);
result &= verifyDepthStencilGradient(&data[0], i, TEX_SIZE, TEX_SIZE);
}
destroyTextures();
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
class VerifyCopyTexImageTest : public BaseTest
{
public:
VerifyCopyTexImageTest(deqp::Context& context, const TypeFormat& tf);
virtual ~VerifyCopyTexImageTest();
virtual tcu::TestNode::IterateResult iterate(void);
};
VerifyCopyTexImageTest::VerifyCopyTexImageTest(deqp::Context& context, const TypeFormat& tf) : BaseTest(context, tf)
{
}
VerifyCopyTexImageTest::~VerifyCopyTexImageTest()
{
}
tcu::TestNode::IterateResult VerifyCopyTexImageTest::iterate(void)
{
// After rendering to depth and stencil, CopyTexImage the results to a new
// DEPTH_STENCIL texture. Attach this texture to a new FBO. Verify that
// depth and stencil tests work with the copied data.
createTextures();
renderToTextures();
bool result = true;
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
// setup shader
GLint uColor;
setupColorProgram(uColor);
// setup and copy texture/fbo
GLuint tex;
gl.genTextures(1, &tex);
GLuint fbo;
gl.genFramebuffers(1, &fbo);
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexRender]);
gl.bindTexture(GL_TEXTURE_2D, tex);
setupTexture();
setDrawReadBuffer(GL_NONE, GL_NONE);
gl.texImage2D(GL_TEXTURE_2D, 0, m_typeFormat.format, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_STENCIL, m_typeFormat.type,
NULL);
gl.copyTexImage2D(GL_TEXTURE_2D, 0, m_typeFormat.format, 0, 0, TEX_SIZE, TEX_SIZE, 0);
restoreDrawReadBuffer();
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, tex, 0);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, tex, 0);
setDrawReadBuffer(GL_NONE, GL_NONE);
int status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer is incomplete: " << status
<< tcu::TestLog::EndMessage;
result = false;
restoreDrawReadBuffer();
}
else
{
// render
gl.enable(GL_DEPTH_TEST);
gl.depthFunc(GL_LEQUAL);
gl.viewport(0, 0, TEX_SIZE, TEX_SIZE);
gl.enable(GL_STENCIL_TEST);
gl.stencilFunc(GL_EQUAL, 0x1, 0xFF);
gl.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
drawQuad(DEFAULT, m_colorProgram);
gl.disable(GL_STENCIL_TEST);
// verify
std::vector<GLubyte> data(TEX_SIZE * TEX_SIZE * m_typeFormat.size, 0);
gl.getTexImage(GL_TEXTURE_2D, 0, GL_DEPTH_STENCIL, m_typeFormat.type, &data[0]);
result &= verifyDepthStencilGradient(&data[0], verifyCopyTexImage, TEX_SIZE, TEX_SIZE);
restoreDrawReadBuffer();
result &= doReadPixels(tex, verifyCopyTexImage);
}
// clean up
gl.deleteFramebuffers(1, &fbo);
gl.deleteTextures(1, &tex);
destroyTextures();
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
class VerifyPartialAttachmentsTest : public BaseTest
{
public:
VerifyPartialAttachmentsTest(deqp::Context& context, const TypeFormat& tf);
virtual ~VerifyPartialAttachmentsTest();
virtual tcu::TestNode::IterateResult iterate(void);
};
VerifyPartialAttachmentsTest::VerifyPartialAttachmentsTest(deqp::Context& context, const TypeFormat& tf)
: BaseTest(context, tf)
{
}
VerifyPartialAttachmentsTest::~VerifyPartialAttachmentsTest()
{
}
tcu::TestNode::IterateResult VerifyPartialAttachmentsTest::iterate(void)
{
createTextures();
renderToTextures();
bool result = true;
// - Create an FBO with a packed depth stencil renderbuffer attached to
// DEPTH_ATTACHMENT only. If this FBO is complete, stencil test must act as
// if there is no stencil buffer (always pass.)
// - Create an FBO with a packed depth stencil renderbuffer attached to
// STENCIL_ATTACHMENT only. If this FBO is complete, depth test must act as
// if there is no depth buffer (always pass.)
// - Create an FBO with a packed depth stencil renderbuffer attached to
// STENCIL_ATTACHMENT only. If this FBO is complete, occlusion query must
// act as if there is no depth buffer (always pass.)
const glu::RenderContext& renderContext = m_context.getRenderContext();
const glw::Functions& gl = renderContext.getFunctions();
bool isContextES = glu::isContextTypeES(renderContext.getType());
// setup shader
GLint uColor;
setupColorProgram(uColor);
GLuint occ;
gl.genQueries(1, &occ);
for (int i = 0; i < 3; i++)
{
// setup fbo
GLuint fbo;
gl.genFramebuffers(1, &fbo);
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
GLuint rbo[2]; // color, D/S
gl.genRenderbuffers(2, rbo);
gl.bindRenderbuffer(GL_RENDERBUFFER, rbo[0]);
gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, TEX_SIZE, TEX_SIZE);
gl.bindRenderbuffer(GL_RENDERBUFFER, rbo[1]);
gl.renderbufferStorage(GL_RENDERBUFFER, m_typeFormat.format, TEX_SIZE, TEX_SIZE);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo[0]);
setDrawReadBuffer(GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0);
switch (i)
{
case 0:
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo[1]);
break;
case 1:
case 2:
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo[1]);
break;
default:
result = false;
}
if (!result)
break;
int status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer is incomplete: " << status
<< tcu::TestLog::EndMessage;
result = false;
}
else
{
// render
gl.viewport(0, 0, TEX_SIZE, TEX_SIZE);
if (isContextES)
gl.clearDepthf(1.0f);
else
gl.clearDepth(1.0);
gl.clearStencil(0);
gl.clearColor(0.8f, 0.8f, 0.8f, 0.8f);
gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
switch (i)
{
case 0:
gl.disable(GL_DEPTH_TEST);
gl.enable(GL_STENCIL_TEST);
gl.stencilFunc(GL_NEVER, 0xFF, 0xFF);
gl.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
break;
case 1:
gl.enable(GL_DEPTH_TEST);
gl.depthFunc(GL_NEVER);
gl.disable(GL_STENCIL_TEST);
break;
case 2:
gl.enable(GL_DEPTH_TEST);
gl.depthFunc(GL_NEVER);
gl.disable(GL_STENCIL_TEST);
gl.beginQuery(GL_ANY_SAMPLES_PASSED, occ);
break;
default:
break;
}
drawQuad(DEFAULT, m_colorProgram);
if (i == 2)
{
GLuint n;
gl.endQuery(GL_ANY_SAMPLES_PASSED);
gl.getQueryObjectuiv(occ, GL_QUERY_RESULT, &n);
if (n > 0)
{
drawQuad(DEFAULT, m_colorProgram);
}
}
std::vector<GLuint> data(TEX_SIZE * TEX_SIZE, 0);
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
result &= verifyColorGradient(&data[0], verifyPartialAttachments, COLOR_CHECK_DEFAULT, TEX_SIZE, TEX_SIZE);
}
restoreDrawReadBuffer();
gl.bindFramebuffer(GL_FRAMEBUFFER, m_defaultFBO);
// clean up
gl.deleteFramebuffers(1, &fbo);
gl.deleteRenderbuffers(2, rbo);
}
gl.deleteQueries(1, &occ);
destroyTextures();
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
class VerifyMixedAttachmentsTest : public BaseTest
{
public:
VerifyMixedAttachmentsTest(deqp::Context& context, const TypeFormat& tf);
virtual ~VerifyMixedAttachmentsTest();
virtual tcu::TestNode::IterateResult iterate(void);
};
VerifyMixedAttachmentsTest::VerifyMixedAttachmentsTest(deqp::Context& context, const TypeFormat& tf)
: BaseTest(context, tf)
{
}
VerifyMixedAttachmentsTest::~VerifyMixedAttachmentsTest()
{
}
tcu::TestNode::IterateResult VerifyMixedAttachmentsTest::iterate(void)
{
// Create FBOs that mix DEPTH_STENCIL renderbuffers with DEPTH or STENCIL
// renderbuffers. If these FBOs are complete, depth and stencil test
// must work properly.
// Create an FBO with two different packed depth stencil renderbuffers, one
// attached to DEPTH_ATTACHMENT and the other attached to STENCIL_ATTACHMENT.
// Querying DEPTH_STENCIL_ATTACHMENT must fail with INVALID_OPERATION. If
// this FBO is complete, depth and stencil tests must work properly.
createTextures();
renderToTextures();
bool result = true;
const glu::RenderContext& renderContext = m_context.getRenderContext();
const glw::Functions& gl = renderContext.getFunctions();
bool isContextES = glu::isContextTypeES(renderContext.getType());
GLint uColor;
setupColorProgram(uColor);
for (int i = 0; i < 3; i++)
{
// set up FBO/RBOs
GLuint fbo;
gl.genFramebuffers(1, &fbo);
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
GLuint rbo[3]; // color, DEPTH_STENCIL, DEPTH/STENCIL
gl.genRenderbuffers(3, rbo);
gl.bindRenderbuffer(GL_RENDERBUFFER, rbo[0]);
gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, TEX_SIZE, TEX_SIZE);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo[0]);
gl.bindRenderbuffer(GL_RENDERBUFFER, rbo[1]);
gl.renderbufferStorage(GL_RENDERBUFFER, m_typeFormat.format, TEX_SIZE, TEX_SIZE);
gl.bindRenderbuffer(GL_RENDERBUFFER, rbo[2]);
switch (i)
{
case 0:
gl.renderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, TEX_SIZE, TEX_SIZE);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo[1]);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo[2]);
break;
case 1:
gl.renderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, TEX_SIZE, TEX_SIZE);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo[1]);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo[2]);
break;
case 2:
gl.renderbufferStorage(GL_RENDERBUFFER, m_typeFormat.format, TEX_SIZE, TEX_SIZE);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rbo[1]);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo[2]);
GLint param;
gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &param);
if (gl.getError() != GL_INVALID_OPERATION)
{
m_testCtx.getLog() << tcu::TestLog::Message
<< "Expected INVALID_OPERATION for DEPTH_STENCIL_ATTACHMENT query"
<< tcu::TestLog::EndMessage;
result = false;
}
break;
}
GLenum status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
if (status == GL_FRAMEBUFFER_UNSUPPORTED)
{
/* The spec only requires
"when both depth and stencil attachments are present, implementations are only
required to support framebuffer objects where both attachments refer to the same image."
Thus, it is accepatable for an implementation returning GL_FRAMEBUFFER_UNSUPPORTED. And the
test can NOT be marked as fail.
*/
}
else
{
m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer is incomplete" << tcu::TestLog::EndMessage;
result = false;
}
}
else
{
// render
// step 1
gl.viewport(0, 0, TEX_SIZE, TEX_SIZE);
gl.enable(GL_DEPTH_TEST);
gl.depthFunc(GL_LEQUAL);
if (isContextES)
gl.clearDepthf(1.0f);
else
gl.clearDepth(1.0);
gl.enable(GL_STENCIL_TEST);
gl.stencilFunc(GL_ALWAYS, 0x1, 0xFF);
gl.stencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
gl.clearStencil(0);
gl.clearColor(0.8f, 0.8f, 0.8f, 0.8f);
gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
drawQuad(DEPTH_SPAN1, m_colorProgram);
// step 2
gl.stencilFunc(GL_EQUAL, 0x1, 0xFF);
gl.stencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
gl.clearColor(0.8f, 0.8f, 0.8f, 0.8f);
gl.clear(GL_COLOR_BUFFER_BIT);
drawQuad(DEFAULT, m_colorProgram);
std::vector<GLuint> data(TEX_SIZE * TEX_SIZE, 0);
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
result &= verifyColorGradient(&data[0], verifyMixedAttachments, COLOR_CHECK_DEFAULT, TEX_SIZE, TEX_SIZE);
}
// clean up
gl.deleteRenderbuffers(3, rbo);
gl.deleteFramebuffers(1, &fbo);
}
destroyTextures();
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
class VerifyParametersTest : public BaseTest
{
public:
VerifyParametersTest(deqp::Context& context, const TypeFormat& tf);
virtual ~VerifyParametersTest();
virtual tcu::TestNode::IterateResult iterate(void);
};
VerifyParametersTest::VerifyParametersTest(deqp::Context& context, const TypeFormat& tf) : BaseTest(context, tf)
{
}
VerifyParametersTest::~VerifyParametersTest()
{
}
tcu::TestNode::IterateResult VerifyParametersTest::iterate(void)
{
// Verify GetFramebufferAttachmentParameter queries of each <pname> on
// DEPTH_STENCIL_ATTACHMENT work correctly if both attachments are populated
// with the same object.
createTextures();
renderToTextures();
bool result = true;
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexImage]);
GLint param;
gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &param);
if (param != GL_TEXTURE)
{
m_testCtx.getLog() << tcu::TestLog::Message
<< "Invalid value for GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE: " << param
<< tcu::TestLog::EndMessage;
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
const AttachmentParam* attachmentParams = getAttachmentParams();
for (GLuint i = 0; i < m_attachmentParamsCount; i++)
{
int ref;
GLenum pname = attachmentParams[i].pname;
if (GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE == pname)
{
gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, pname, &param);
if (gl.getError() != GL_INVALID_OPERATION)
result = false;
continue;
}
gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, pname, &param);
ref = attachmentParams[i].value;
if (pname == GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME)
ref = m_textures[packedTexImage];
if (param != ref)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value for pname " << attachmentParams[i].pname
<< ": " << param << " ( expected " << ref << ")" << tcu::TestLog::EndMessage;
result = false;
}
}
destroyTextures();
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
class RenderbuffersTest : public BaseTest
{
public:
RenderbuffersTest(deqp::Context& context, const TypeFormat& tf);
virtual ~RenderbuffersTest();
virtual tcu::TestNode::IterateResult iterate(void);
};
RenderbuffersTest::RenderbuffersTest(deqp::Context& context, const TypeFormat& tf) : BaseTest(context, tf)
{
}
RenderbuffersTest::~RenderbuffersTest()
{
}
tcu::TestNode::IterateResult RenderbuffersTest::iterate(void)
{
createTextures();
renderToTextures();
bool result = true;
// Verify RENDERBUFFER_DEPTH_SIZE and RENDERBUFFER_STENCIL_SIZE report
// appropriate values for for DEPTH_STENCIL renderbuffers.
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffers[packedTexImage]);
GLuint rbo;
gl.genRenderbuffers(1, &rbo);
gl.bindRenderbuffer(GL_RENDERBUFFER, rbo);
gl.renderbufferStorage(GL_RENDERBUFFER, m_typeFormat.format, TEX_SIZE, TEX_SIZE);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo);
GLint param;
gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_DEPTH_SIZE, &param);
if (param != m_typeFormat.d)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Invalid depth: " << param << ", expected: " << m_typeFormat.d
<< tcu::TestLog::EndMessage;
result = false;
}
gl.getRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_STENCIL_SIZE, &param);
if (param != m_typeFormat.s)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Invalid stencil: " << param << ", expected: " << m_typeFormat.s
<< tcu::TestLog::EndMessage;
result = false;
}
gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
gl.deleteRenderbuffers(1, &rbo);
gl.bindFramebuffer(GL_FRAMEBUFFER, m_defaultFBO);
destroyTextures();
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
class StencilSizeTest : public BaseTest
{
public:
StencilSizeTest(deqp::Context& context, const TypeFormat& tf);
virtual ~StencilSizeTest();
virtual tcu::TestNode::IterateResult iterate(void);
};
StencilSizeTest::StencilSizeTest(deqp::Context& context, const TypeFormat& tf) : BaseTest(context, tf)
{
}
StencilSizeTest::~StencilSizeTest()
{
}
tcu::TestNode::IterateResult StencilSizeTest::iterate(void)
{
// [desktop only] Verify TEXTURE_STENCIL_SIZE reports 8 for DEPTH_STENCIL
// textures, and 0 for RGBA and DEPTH_COMPONENT textures.
createTextures();
renderToTextures();
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
bool result = true;
GLint param;
gl.bindTexture(GL_TEXTURE_2D, m_textures[packedTexImage]);
gl.getTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_STENCIL_SIZE, &param);
if (param != 8)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value for DEPTH_STENCIL stencil size: " << param
<< tcu::TestLog::EndMessage;
result = false;
}
GLuint texRGBA;
gl.genTextures(1, &texRGBA);
gl.bindTexture(GL_TEXTURE_2D, texRGBA);
setupTexture();
gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
gl.getTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_STENCIL_SIZE, &param);
if (param != 0)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value for RGBA stencil size: " << param
<< tcu::TestLog::EndMessage;
result = false;
}
gl.deleteTextures(1, &texRGBA);
GLuint texDepth;
gl.genTextures(1, &texDepth);
gl.bindTexture(GL_TEXTURE_2D, texDepth);
setupTexture();
gl.texImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT16, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT,
0);
gl.getTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_STENCIL_SIZE, &param);
if (param != 0)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value for DEPTH_COMPONENT stencil size: " << param
<< tcu::TestLog::EndMessage;
result = false;
}
gl.deleteTextures(1, &texDepth);
destroyTextures();
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
class ClearBufferTest : public BaseTest
{
public:
ClearBufferTest(deqp::Context& context, const TypeFormat& tf);
virtual ~ClearBufferTest();
virtual tcu::TestNode::IterateResult iterate(void);
};
ClearBufferTest::ClearBufferTest(deqp::Context& context, const TypeFormat& tf) : BaseTest(context, tf)
{
}
ClearBufferTest::~ClearBufferTest()
{
}
tcu::TestNode::IterateResult ClearBufferTest::iterate(void)
{
// Verify ClearBufferfv correctly clears the depth channel of a DEPTH_STENCIL
// FBO attachment (and does not touch the stencil channel.)
// Verify ClearBufferiv correctly clears the stencil channel of a
// DEPTH_STENCIL FBO attachment (and does not touch the depth channel.)
// Verify ClearBufferfi correctly clears the depth and stencil channels of a
// DEPTH_STENCIL FBO attachment.
createTextures();
renderToTextures();
bool result = true;
GLfloat valuef;
GLint valuei;
GLenum status;
const glw::Functions& gl = m_context.getRenderContext().getFunctions();
// setup shader
GLint uColor;
setupColorProgram(uColor);
for (int i = 0; i < 3; i++)
{
// setup texture/fbo
GLuint tex;
GLuint texColor;
GLuint fbo;
gl.genTextures(1, &tex);
gl.genTextures(1, &texColor);
gl.genFramebuffers(1, &fbo);
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
gl.bindTexture(GL_TEXTURE_2D, tex);
setupTexture();
std::vector<GLbyte> data;
createGradient(data);
gl.texImage2D(GL_TEXTURE_2D, 0, m_typeFormat.format, TEX_SIZE, TEX_SIZE, 0, GL_DEPTH_STENCIL, m_typeFormat.type,
&data[0]);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, tex, 0);
gl.bindTexture(GL_TEXTURE_2D, texColor);
setupTexture();
gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 0);
setDrawReadBuffer(GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0);
status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer is incomplete: " << status
<< tcu::TestLog::EndMessage;
result = false;
}
else
{
// clear relevant buffers
switch (i)
{
case 0:
valuef = 1.0f;
gl.clearBufferfv(GL_DEPTH, 0, &valuef);
break;
case 1:
valuei = 0xff;
gl.clearBufferiv(GL_STENCIL, 0, &valuei);
break;
case 2:
valuef = 1.0f;
valuei = 0xff;
gl.clearBufferfi(GL_DEPTH_STENCIL, 0, valuef, valuei);
break;
}
// render reference image
gl.viewport(0, 0, TEX_SIZE, TEX_SIZE);
gl.enable(GL_DEPTH_TEST);
gl.depthFunc(GL_LEQUAL);
gl.enable(GL_STENCIL_TEST);
gl.stencilFunc(GL_EQUAL, 0xFF, 0xFF);
gl.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
gl.clearColor(0.8f, 0.8f, 0.8f, 0.8f);
gl.clear(GL_COLOR_BUFFER_BIT);
drawQuad(DEFAULT, m_colorProgram);
// verify
std::vector<GLubyte> readData(TEX_SIZE * TEX_SIZE * 4, 0);
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, &readData[0]);
result &=
verifyColorGradient(&readData[0], verifyClearBufferDepth + i, COLOR_CHECK_DEFAULT, TEX_SIZE, TEX_SIZE);
}
// destroy texture/fbo
restoreDrawReadBuffer();
gl.bindFramebuffer(GL_FRAMEBUFFER, m_defaultFBO);
gl.bindTexture(GL_TEXTURE_2D, 0);
gl.deleteFramebuffers(1, &fbo);
gl.deleteTextures(1, &tex);
gl.deleteTextures(1, &texColor);
}
destroyTextures();
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
class BlitTest : public BaseTest
{
public:
BlitTest(deqp::Context& context, const TypeFormat& tf);
virtual ~BlitTest();
virtual tcu::TestNode::IterateResult iterate(void);
};
BlitTest::BlitTest(deqp::Context& context, const TypeFormat& tf) : BaseTest(context, tf)
{
}
BlitTest::~BlitTest()
{
}
tcu::TestNode::IterateResult BlitTest::iterate(void)
{
// Verify that NEAREST filtered blits of DEPTH and/or STENCIL between two
// FBOs with the same format packed depth stencil attachment work. Test
// non-multisample [1->1], multisample resolve [N->1], and multisample
// replicate [1->N] blits, for each supported value of N up to MAX_SAMPLES.
createTextures();
renderToTextures();
GLuint fbo[3]; // Framebuffers: source, dest, downsample
GLuint rbo[4]; // Renderbuffers: source D/S, dest D/S, dest color, downsample color
GLint maxSamples;
int srcSamples, destSamples;
bool result = true;
const glu::RenderContext& renderContext = m_context.getRenderContext();
const glw::Functions& gl = renderContext.getFunctions();
bool isContextES = glu::isContextTypeES(renderContext.getType());
std::vector<GLuint> data(TEX_SIZE * TEX_SIZE);
GLint uColor;
setupColorProgram(uColor);
gl.getIntegerv(GL_MAX_SAMPLES, &maxSamples);
// ES does not allow SAMPLE_BUFFERS for the draw frame
// buffer is greater than zero when doing a blit.
int loopCount = isContextES ? 1 : 2;
for (int j = 0; j < loopCount; j++)
{
for (int i = 0; i <= maxSamples; i++)
{
// Create FBO/RBO
gl.genFramebuffers(3, fbo);
gl.genRenderbuffers(4, rbo);
if (j == 0)
{
srcSamples = i;
destSamples = 0;
}
else
{
srcSamples = 0;
destSamples = i;
}
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo[0]);
gl.bindRenderbuffer(GL_RENDERBUFFER, rbo[0]);
gl.renderbufferStorageMultisample(GL_RENDERBUFFER, srcSamples, m_typeFormat.format, TEX_SIZE, TEX_SIZE);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo[0]);
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo[1]);
gl.bindRenderbuffer(GL_RENDERBUFFER, rbo[1]);
gl.renderbufferStorageMultisample(GL_RENDERBUFFER, destSamples, m_typeFormat.format, TEX_SIZE, TEX_SIZE);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rbo[1]);
gl.bindRenderbuffer(GL_RENDERBUFFER, rbo[2]);
gl.renderbufferStorageMultisample(GL_RENDERBUFFER, destSamples, GL_RGBA8, TEX_SIZE, TEX_SIZE);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo[2]);
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo[2]);
gl.bindRenderbuffer(GL_RENDERBUFFER, rbo[3]);
gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 0, GL_RGBA8, TEX_SIZE, TEX_SIZE);
gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo[3]);
// Render
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo[0]);
setDrawReadBuffer(GL_NONE, GL_NONE);
gl.viewport(0, 0, TEX_SIZE, TEX_SIZE);
gl.enable(GL_DEPTH_TEST);
gl.depthFunc(GL_LEQUAL);
if (isContextES)
gl.clearDepthf(1.0f);
else
gl.clearDepth(1.0);
gl.enable(GL_STENCIL_TEST);
gl.stencilFunc(GL_ALWAYS, 0x1, 0xFF);
gl.stencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
gl.clearStencil(0);
gl.clearColor(0.8f, 0.8f, 0.8f, 0.8f);
gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
drawQuad(DEPTH_SPAN1, m_colorProgram);
restoreDrawReadBuffer();
// Blit
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo[0]);
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[1]);
setDrawReadBuffer(GL_NONE, GL_NONE);
gl.blitFramebuffer(0, 0, TEX_SIZE, TEX_SIZE, 0, 0, TEX_SIZE, TEX_SIZE,
GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT, GL_NEAREST);
restoreDrawReadBuffer();
// Verify
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo[1]);
setDrawReadBuffer(GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0);
gl.stencilFunc(GL_EQUAL, 0x1, 0xFF);
gl.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
gl.clear(GL_COLOR_BUFFER_BIT);
drawQuad(DEFAULT, m_colorProgram);
restoreDrawReadBuffer();
// Downsample blit
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo[1]);
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo[2]);
setDrawReadBuffer(GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0);
gl.blitFramebuffer(0, 0, TEX_SIZE, TEX_SIZE, 0, 0, TEX_SIZE, TEX_SIZE, GL_COLOR_BUFFER_BIT, GL_NEAREST);
restoreDrawReadBuffer();
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo[2]);
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
result &= verifyColorGradient(&data[0], verifyBlit, COLOR_CHECK_DEFAULT, TEX_SIZE, TEX_SIZE);
// Clean up
gl.bindFramebuffer(GL_FRAMEBUFFER, m_defaultFBO);
gl.bindRenderbuffer(GL_RENDERBUFFER, 0);
gl.deleteRenderbuffers(4, rbo);
gl.deleteFramebuffers(3, fbo);
}
}
destroyTextures();
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
class StencilTexturingTest : public BaseTest
{
public:
StencilTexturingTest(deqp::Context& context, const TypeFormat& tf);
virtual ~StencilTexturingTest();
virtual tcu::TestNode::IterateResult iterate(void);
};
StencilTexturingTest::StencilTexturingTest(deqp::Context& context, const TypeFormat& tf) : BaseTest(context, tf)
{
}
StencilTexturingTest::~StencilTexturingTest()
{
}
tcu::TestNode::IterateResult StencilTexturingTest::iterate(void)
{
// Verifies that either depth or stencil can be sampled depending on
// GL_DEPTH_STENCIL_TEXTURE_MODE
const glu::RenderContext& renderContext = m_context.getRenderContext();
glu::ContextType contextType = renderContext.getType();
const glw::Functions& gl = renderContext.getFunctions();
bool notSupported = false;
if (glu::isContextTypeES(contextType))
notSupported = !glu::contextSupports(contextType, glu::ApiType::es(3, 1));
else
notSupported = !glu::contextSupports(contextType, glu::ApiType::core(4, 3));
if (notSupported)
{
m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "stencil_texturing extension is not supported");
return STOP;
}
createTextures();
renderToTextures();
bool result = true;
GLuint fbo;
gl.genFramebuffers(1, &fbo);
gl.bindFramebuffer(GL_FRAMEBUFFER, fbo);
GLuint texColor;
gl.genTextures(1, &texColor);
gl.bindTexture(GL_TEXTURE_2D, texColor);
setupTexture();
gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEX_SIZE, TEX_SIZE, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
gl.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texColor, 0);
setDrawReadBuffer(GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0);
// Step 1: Verify depth values
GLenum status = gl.checkFramebufferStatus(GL_FRAMEBUFFER);
if (status != GL_FRAMEBUFFER_COMPLETE)
{
m_testCtx.getLog() << tcu::TestLog::Message << "Framebuffer is incomplete: " << status
<< tcu::TestLog::EndMessage;
result = false;
}
else
{
gl.bindTexture(GL_TEXTURE_2D, m_textures[packedTexImage]);
gl.disable(GL_DEPTH_TEST);
gl.depthMask(GL_FALSE);
gl.disable(GL_STENCIL_TEST);
gl.viewport(0, 0, TEX_SIZE, TEX_SIZE);
gl.clearColor(0.8f, 0.8f, 0.8f, 0.8f);
gl.clear(GL_COLOR_BUFFER_BIT);
gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT);
setupTextureProgram();
drawQuad(DEFAULT, m_textureProgram);
std::vector<GLuint> dataColor(TEX_SIZE * TEX_SIZE, 0);
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, &dataColor[0]);
result &= verifyColorGradient(&dataColor[0], packedTexImage, COLOR_CHECK_DEPTH, TEX_SIZE, TEX_SIZE);
// Step 2: Verify stencil values
gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX);
setupStencilProgram();
drawQuad(DEFAULT, m_stencilProgram);
dataColor.assign(TEX_SIZE * TEX_SIZE, 0);
gl.readPixels(0, 0, TEX_SIZE, TEX_SIZE, GL_RGBA, GL_UNSIGNED_BYTE, &dataColor[0]);
result &= verifyColorGradient(&dataColor[0], packedTexImage, COLOR_CHECK_DEFAULT, TEX_SIZE, TEX_SIZE);
}
restoreDrawReadBuffer();
gl.deleteFramebuffers(1, &fbo);
gl.deleteTextures(1, &texColor);
destroyTextures();
if (result)
m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
else
m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
return STOP;
}
PackedDepthStencilTests::PackedDepthStencilTests(deqp::Context& context)
: TestCaseGroup(context, "packed_depth_stencil", "")
{
}
PackedDepthStencilTests::~PackedDepthStencilTests(void)
{
}
void PackedDepthStencilTests::init(void)
{
TestCaseGroup* validateErrorsGroup = new deqp::TestCaseGroup(m_context, "validate_errors", "");
TestCaseGroup* verifyReadPixelsGroup = new deqp::TestCaseGroup(m_context, "verify_read_pixels", "");
TestCaseGroup* verifyGetTexImageGroup = new deqp::TestCaseGroup(m_context, "verify_get_tex_image", "");
TestCaseGroup* verifyCopyTexImageGroup = new deqp::TestCaseGroup(m_context, "verify_copy_tex_image", "");
TestCaseGroup* verifyPartialAttachmentsGroup = new deqp::TestCaseGroup(m_context, "verify_partial_attachments", "");
TestCaseGroup* verifyMixedAttachmentsGroup = new deqp::TestCaseGroup(m_context, "verify_mixed_attachments", "");
TestCaseGroup* verifyParametersGroup = new deqp::TestCaseGroup(m_context, "verify_parameters", "");
TestCaseGroup* renderbuffersGroup = new deqp::TestCaseGroup(m_context, "renderbuffers", "");
TestCaseGroup* clearBufferGroup = new deqp::TestCaseGroup(m_context, "clear_buffer", "");
TestCaseGroup* blitGroup = new deqp::TestCaseGroup(m_context, "blit", "");
TestCaseGroup* stencilTexturingGroup = new deqp::TestCaseGroup(m_context, "stencil_texturing", "");
TestCaseGroup* stencilSizeGroup = new deqp::TestCaseGroup(m_context, "stencil_size", "");
bool isContextCoreGL = !glu::isContextTypeES(m_context.getRenderContext().getType());
if (isContextCoreGL)
validateErrorsGroup->addChild(new InitialStateTest(m_context));
for (int i = 0; i < NUM_TEXTURE_TYPES; i++)
{
const TypeFormat& typeFormat = TextureTypes[i];
validateErrorsGroup->addChild(new ValidateErrorsTest(m_context, typeFormat));
verifyReadPixelsGroup->addChild(new VerifyReadPixelsTest(m_context, typeFormat));
verifyPartialAttachmentsGroup->addChild(new VerifyPartialAttachmentsTest(m_context, typeFormat));
verifyMixedAttachmentsGroup->addChild(new VerifyMixedAttachmentsTest(m_context, typeFormat));
verifyParametersGroup->addChild(new VerifyParametersTest(m_context, typeFormat));
renderbuffersGroup->addChild(new RenderbuffersTest(m_context, typeFormat));
clearBufferGroup->addChild(new ClearBufferTest(m_context, typeFormat));
blitGroup->addChild(new BlitTest(m_context, typeFormat));
stencilTexturingGroup->addChild(new StencilTexturingTest(m_context, typeFormat));
if (isContextCoreGL)
{
verifyGetTexImageGroup->addChild(new VerifyGetTexImageTest(m_context, typeFormat));
verifyCopyTexImageGroup->addChild(new VerifyCopyTexImageTest(m_context, typeFormat));
stencilSizeGroup->addChild(new StencilSizeTest(m_context, typeFormat));
}
}
addChild(validateErrorsGroup);
addChild(verifyReadPixelsGroup);
addChild(verifyGetTexImageGroup);
addChild(verifyCopyTexImageGroup);
addChild(verifyPartialAttachmentsGroup);
addChild(verifyMixedAttachmentsGroup);
addChild(verifyParametersGroup);
addChild(renderbuffersGroup);
addChild(clearBufferGroup);
addChild(blitGroup);
addChild(stencilTexturingGroup);
addChild(stencilSizeGroup);
}
} /* glcts namespace */