/*------------------------------------------------------------------------- * 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 #include #include 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& 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& data) { switch (m_typeFormat.type) { case GL_UNSIGNED_INT_24_8: { data.resize(TEX_SIZE * TEX_SIZE * sizeof(GLuint)); GLuint* dataPtr = reinterpret_cast(&data[0]); for (int j = 0; j < TEX_SIZE; j++) { for (int i = 0; i < TEX_SIZE; i++) { GLuint d = static_cast(static_cast(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(&data[0]); for (int j = 0; j < TEX_SIZE; j++) { for (int i = 0; i < TEX_SIZE; i++) { D32F_S8 v = { static_cast(i) / (TEX_SIZE - 1), static_cast(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(drawBuffer); GLint readBuffer; gl.getIntegerv(GL_READ_BUFFER, &readBuffer); m_readBuffer = static_cast(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 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 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 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 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 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 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(TEX_SIZE * TEX_SIZE * m_typeFormat.size); std::vector 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 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 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 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, ¶m); 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 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 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, ¶m); 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, ¶m); if (gl.getError() != GL_INVALID_OPERATION) result = false; continue; } gl.getFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, pname, ¶m); 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, ¶m); 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, ¶m); 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, ¶m); 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, ¶m); 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, ¶m); 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 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 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 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 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 */