/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES 3.0 Module * ------------------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Fbo state query tests. *//*--------------------------------------------------------------------*/ #include "es3fFboStateQueryTests.hpp" #include "glsStateQueryUtil.hpp" #include "es3fApiCase.hpp" #include "gluRenderContext.hpp" #include "glwEnums.hpp" #include "glwFunctions.hpp" #include "tcuRenderTarget.hpp" #include "deMath.h" using namespace glw; // GLint and other GL types using deqp::gls::StateQueryUtil::StateQueryMemoryWriteGuard; namespace deqp { namespace gles3 { namespace Functional { namespace { void checkAttachmentComponentSizeAtLeast (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLenum target, GLenum attachment, int r, int g, int b, int a, int d, int s) { using tcu::TestLog; const int referenceSizes[] = {r, g, b, a, d, s}; const GLenum paramNames[] = { GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE }; DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(referenceSizes) == DE_LENGTH_OF_ARRAY(paramNames)); for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(referenceSizes); ++ndx) { if (referenceSizes[ndx] == -1) continue; StateQueryMemoryWriteGuard state; gl.glGetFramebufferAttachmentParameteriv(target, attachment, paramNames[ndx], &state); if (!state.verifyValidity(testCtx)) { gl.glGetError(); // just log the error continue; } if (state < referenceSizes[ndx]) { testCtx.getLog() << TestLog::Message << "// ERROR: Expected greater or equal to " << referenceSizes[ndx] << "; got " << state << TestLog::EndMessage; if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value"); } } } void checkAttachmentComponentSizeExactly (tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLenum target, GLenum attachment, int r, int g, int b, int a, int d, int s) { using tcu::TestLog; const int referenceSizes[] = {r, g, b, a, d, s}; const GLenum paramNames[] = { GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE, GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE, GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE, GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE }; DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(referenceSizes) == DE_LENGTH_OF_ARRAY(paramNames)); for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(referenceSizes); ++ndx) { if (referenceSizes[ndx] == -1) continue; StateQueryMemoryWriteGuard state; gl.glGetFramebufferAttachmentParameteriv(target, attachment, paramNames[ndx], &state); if (!state.verifyValidity(testCtx)) { gl.glGetError(); // just log the error continue; } if (state != referenceSizes[ndx]) { testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << referenceSizes[ndx] << "; got " << state << TestLog::EndMessage; if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value"); } } } void checkIntEquals (tcu::TestContext& testCtx, GLint got, GLint expected) { using tcu::TestLog; if (got != expected) { testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected << "; got " << got << TestLog::EndMessage; if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value"); } } void checkIntEqualsAny (tcu::TestContext& testCtx, GLint got, GLint expected0, GLint expected1) { using tcu::TestLog; if (got != expected0 && got != expected1) { testCtx.getLog() << TestLog::Message << "// ERROR: Expected " << expected0 << " or " << expected1 << "; got " << got << TestLog::EndMessage; if (testCtx.getTestResult() == QP_TEST_RESULT_PASS) testCtx.setTestResult(QP_TEST_RESULT_FAIL, "got invalid value"); } } void checkAttachmentParam(tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLenum target, GLenum attachment, GLenum pname, GLenum reference) { StateQueryMemoryWriteGuard state; gl.glGetFramebufferAttachmentParameteriv(target, attachment, pname, &state); if (state.verifyValidity(testCtx)) checkIntEquals(testCtx, state, reference); } void checkColorAttachmentParam(tcu::TestContext& testCtx, glu::CallLogWrapper& gl, GLenum target, GLenum pname, GLenum reference) { checkAttachmentParam(testCtx, gl, target, GL_COLOR_ATTACHMENT0, pname, reference); } class DefaultFramebufferCase : public ApiCase { public: DefaultFramebufferCase (Context& context, const char* name, const char* description, GLenum framebufferTarget) : ApiCase (context, name, description) , m_framebufferTarget (framebufferTarget) { } void test (void) { const bool hasColorBuffer = m_context.getRenderTarget().getPixelFormat().redBits > 0 || m_context.getRenderTarget().getPixelFormat().greenBits > 0 || m_context.getRenderTarget().getPixelFormat().blueBits > 0 || m_context.getRenderTarget().getPixelFormat().alphaBits > 0; const GLenum attachments[] = { GL_BACK, GL_DEPTH, GL_STENCIL }; const bool attachmentExists[] = { hasColorBuffer, m_context.getRenderTarget().getDepthBits() > 0, m_context.getRenderTarget().getStencilBits() > 0 }; for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(attachments); ++ndx) { StateQueryMemoryWriteGuard state; glGetFramebufferAttachmentParameteriv(m_framebufferTarget, attachments[ndx], GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &state); expectError(GL_NO_ERROR); if (state.verifyValidity(m_testCtx)) { if (attachmentExists[ndx]) { checkIntEquals(m_testCtx, state, GL_FRAMEBUFFER_DEFAULT); } else { // \note [jarkko] FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE "identifes the type of object which contains the attached image". However, it // is unclear if an object of type FRAMEBUFFER_DEFAULT can contain a null image (or a 0-bits-per-pixel image). Accept both // FRAMEBUFFER_DEFAULT and NONE as valid results in these cases. checkIntEqualsAny(m_testCtx, state, GL_FRAMEBUFFER_DEFAULT, GL_NONE); } } } } private: GLenum m_framebufferTarget; }; class AttachmentObjectCase : public ApiCase { public: AttachmentObjectCase (Context& context, const char* name, const char* description) : ApiCase(context, name, description) { } void test (void) { GLuint framebufferID = 0; glGenFramebuffers(1, &framebufferID); glBindFramebuffer(GL_FRAMEBUFFER, framebufferID); expectError(GL_NO_ERROR); // initial { checkAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_NONE); checkAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, 0); expectError(GL_NO_ERROR); } // texture { GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 128, 128, 0, GL_RGBA, GL_UNSIGNED_BYTE, DE_NULL); expectError(GL_NO_ERROR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0); expectError(GL_NO_ERROR); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_TEXTURE); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, textureID); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glDeleteTextures(1, &textureID); } // rb { GLuint renderbufferID = 0; glGenRenderbuffers(1, &renderbufferID); glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, 128, 128); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, GL_RENDERBUFFER); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, renderbufferID); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); glDeleteRenderbuffers(1, &renderbufferID); } glDeleteFramebuffers(1, &framebufferID); expectError(GL_NO_ERROR); } }; class AttachmentTextureLevelCase : public ApiCase { public: AttachmentTextureLevelCase (Context& context, const char* name, const char* description) : ApiCase(context, name, description) { } void test (void) { GLuint framebufferID = 0; glGenFramebuffers(1, &framebufferID); glBindFramebuffer(GL_FRAMEBUFFER, framebufferID); expectError(GL_NO_ERROR); for (int mipmapLevel = 0; mipmapLevel < 7; ++mipmapLevel) { GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); glTexStorage2D(GL_TEXTURE_2D, 7, GL_RGB8, 128, 128); expectError(GL_NO_ERROR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, mipmapLevel); expectError(GL_NO_ERROR); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL, mipmapLevel); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glDeleteTextures(1, &textureID); } glDeleteFramebuffers(1, &framebufferID); expectError(GL_NO_ERROR); } }; class AttachmentTextureCubeMapFaceCase : public ApiCase { public: AttachmentTextureCubeMapFaceCase (Context& context, const char* name, const char* description) : ApiCase(context, name, description) { } void test (void) { GLuint framebufferID = 0; glGenFramebuffers(1, &framebufferID); glBindFramebuffer(GL_FRAMEBUFFER, framebufferID); expectError(GL_NO_ERROR); { GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_CUBE_MAP, textureID); expectError(GL_NO_ERROR); glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, GL_RGB8, 128, 128); expectError(GL_NO_ERROR); const GLenum faces[] = { 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 }; for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(faces); ++ndx) { glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, faces[ndx], textureID, 0); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE, faces[ndx]); } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glDeleteTextures(1, &textureID); } glDeleteFramebuffers(1, &framebufferID); expectError(GL_NO_ERROR); } }; class AttachmentTextureLayerCase : public ApiCase { public: AttachmentTextureLayerCase (Context& context, const char* name, const char* description) : ApiCase(context, name, description) { } void test (void) { GLuint framebufferID = 0; glGenFramebuffers(1, &framebufferID); glBindFramebuffer(GL_FRAMEBUFFER, framebufferID); expectError(GL_NO_ERROR); // tex3d { GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_3D, textureID); glTexStorage3D(GL_TEXTURE_3D, 1, GL_RGBA8, 16, 16, 16); for (int layer = 0; layer < 16; ++layer) { glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0, layer); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, layer); } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glDeleteTextures(1, &textureID); } // tex2d array { GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D_ARRAY, textureID); glTexStorage3D(GL_TEXTURE_2D_ARRAY, 1, GL_RGBA8, 16, 16, 16); for (int layer = 0; layer < 16; ++layer) { glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0, layer); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER, layer); } glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glDeleteTextures(1, &textureID); } glDeleteFramebuffers(1, &framebufferID); expectError(GL_NO_ERROR); } }; class AttachmentTextureColorCodingCase : public ApiCase { public: AttachmentTextureColorCodingCase (Context& context, const char* name, const char* description) : ApiCase(context, name, description) { } void test (void) { GLuint framebufferID = 0; glGenFramebuffers(1, &framebufferID); glBindFramebuffer(GL_FRAMEBUFFER, framebufferID); expectError(GL_NO_ERROR); // rgb8 color { GLuint renderbufferID = 0; glGenRenderbuffers(1, &renderbufferID); glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID); glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8, 128, 128); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_LINEAR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); glDeleteRenderbuffers(1, &renderbufferID); } // srgb8_alpha8 color { GLuint renderbufferID = 0; glGenRenderbuffers(1, &renderbufferID); glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID); glRenderbufferStorage(GL_RENDERBUFFER, GL_SRGB8_ALPHA8, 128, 128); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_SRGB); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); glDeleteRenderbuffers(1, &renderbufferID); } // depth { GLuint renderbufferID = 0; glGenRenderbuffers(1, &renderbufferID); glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID); glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 128, 128); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); checkAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_LINEAR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); glDeleteRenderbuffers(1, &renderbufferID); } glDeleteFramebuffers(1, &framebufferID); expectError(GL_NO_ERROR); } }; class AttachmentTextureComponentTypeCase : public ApiCase { public: AttachmentTextureComponentTypeCase (Context& context, const char* name, const char* description) : ApiCase(context, name, description) { } void test (void) { GLuint framebufferID = 0; glGenFramebuffers(1, &framebufferID); glBindFramebuffer(GL_FRAMEBUFFER, framebufferID); expectError(GL_NO_ERROR); // color-renderable required texture formats const struct RequiredColorFormat { GLenum internalFormat; GLenum componentType; } requiredColorformats[] = { { GL_R8, GL_UNSIGNED_NORMALIZED }, { GL_RG8, GL_UNSIGNED_NORMALIZED }, { GL_RGB8, GL_UNSIGNED_NORMALIZED }, { GL_RGB565, GL_UNSIGNED_NORMALIZED }, { GL_RGBA4, GL_UNSIGNED_NORMALIZED }, { GL_RGB5_A1, GL_UNSIGNED_NORMALIZED }, { GL_RGBA8, GL_UNSIGNED_NORMALIZED }, { GL_RGB10_A2, GL_UNSIGNED_NORMALIZED }, { GL_RGB10_A2UI, GL_UNSIGNED_INT }, { GL_SRGB8_ALPHA8, GL_UNSIGNED_NORMALIZED }, { GL_R8I, GL_INT }, { GL_R8UI, GL_UNSIGNED_INT }, { GL_R16I, GL_INT }, { GL_R16UI, GL_UNSIGNED_INT }, { GL_R32I, GL_INT }, { GL_R32UI, GL_UNSIGNED_INT }, { GL_RG8I, GL_INT }, { GL_RG8UI, GL_UNSIGNED_INT }, { GL_RG16I, GL_INT }, { GL_RG16UI, GL_UNSIGNED_INT }, { GL_RG32I, GL_INT }, { GL_RG32UI, GL_UNSIGNED_INT }, { GL_RGBA8I, GL_INT }, { GL_RGBA8UI, GL_UNSIGNED_INT }, { GL_RGBA16I, GL_INT }, { GL_RGBA16UI, GL_UNSIGNED_INT }, { GL_RGBA32I, GL_INT }, { GL_RGBA32UI, GL_UNSIGNED_INT } }; for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(requiredColorformats); ++ndx) { const GLenum colorFormat = requiredColorformats[ndx].internalFormat; GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); glTexStorage2D(GL_TEXTURE_2D, 1, colorFormat, 128, 128); expectError(GL_NO_ERROR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0); expectError(GL_NO_ERROR); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, requiredColorformats[ndx].componentType); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glDeleteTextures(1, &textureID); } glDeleteFramebuffers(1, &framebufferID); expectError(GL_NO_ERROR); } }; class AttachmentSizeInitialCase : public ApiCase { public: AttachmentSizeInitialCase (Context& context, const char* name, const char* description) : ApiCase(context, name, description) { } void test (void) { // check default if (attachmentExists(GL_BACK)) { checkAttachmentComponentSizeAtLeast( m_testCtx, *this, GL_FRAMEBUFFER, GL_BACK, m_context.getRenderTarget().getPixelFormat().redBits, m_context.getRenderTarget().getPixelFormat().greenBits, m_context.getRenderTarget().getPixelFormat().blueBits, m_context.getRenderTarget().getPixelFormat().alphaBits, -1, -1); expectError(GL_NO_ERROR); } if (attachmentExists(GL_DEPTH)) { checkAttachmentComponentSizeAtLeast( m_testCtx, *this, GL_FRAMEBUFFER, GL_DEPTH, -1, -1, -1, -1, m_context.getRenderTarget().getDepthBits(), -1); expectError(GL_NO_ERROR); } if (attachmentExists(GL_STENCIL)) { checkAttachmentComponentSizeAtLeast( m_testCtx, *this, GL_FRAMEBUFFER, GL_STENCIL, -1, -1, -1, -1, -1, m_context.getRenderTarget().getStencilBits()); expectError(GL_NO_ERROR); } } bool attachmentExists (GLenum attachment) { StateQueryMemoryWriteGuard state; glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER, attachment, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &state); expectError(GL_NO_ERROR); return !state.isUndefined() && state != GL_NONE; } }; class AttachmentSizeCase : public ApiCase { public: AttachmentSizeCase (Context& context, const char* name, const char* description) : ApiCase(context, name, description) { } virtual void testColorAttachment (GLenum internalFormat, GLenum attachment, GLint bitsR, GLint bitsG, GLint bitsB, GLint bitsA) = DE_NULL; virtual void testDepthAttachment (GLenum internalFormat, GLenum attachment, GLint bitsD, GLint bitsS) = DE_NULL; void test (void) { GLuint framebufferID = 0; glGenFramebuffers(1, &framebufferID); glBindFramebuffer(GL_FRAMEBUFFER, framebufferID); expectError(GL_NO_ERROR); // check some color targets const struct ColorAttachment { GLenum internalFormat; int bitsR, bitsG, bitsB, bitsA; } colorAttachments[] = { { GL_RGBA8, 8, 8, 8, 8 }, { GL_RGB565, 5, 6, 5, 0 }, { GL_RGBA4, 4, 4, 4, 4 }, { GL_RGB5_A1, 5, 5, 5, 1 }, { GL_RGBA8I, 8, 8, 8, 8 }, { GL_RG32UI, 32, 32, 0, 0 } }; for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorAttachments); ++ndx) testColorAttachment(colorAttachments[ndx].internalFormat, GL_COLOR_ATTACHMENT0, colorAttachments[ndx].bitsR, colorAttachments[ndx].bitsG, colorAttachments[ndx].bitsB, colorAttachments[ndx].bitsA); // check some depth targets const struct DepthAttachment { GLenum internalFormat; GLenum attachment; int dbits; int sbits; } depthAttachments[] = { { GL_DEPTH_COMPONENT16, GL_DEPTH_ATTACHMENT, 16, 0 }, { GL_DEPTH_COMPONENT24, GL_DEPTH_ATTACHMENT, 24, 0 }, { GL_DEPTH_COMPONENT32F, GL_DEPTH_ATTACHMENT, 32, 0 }, { GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, 24, 8 }, { GL_DEPTH32F_STENCIL8, GL_DEPTH_STENCIL_ATTACHMENT, 32, 8 }, }; for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(depthAttachments); ++ndx) testDepthAttachment(depthAttachments[ndx].internalFormat, depthAttachments[ndx].attachment, depthAttachments[ndx].dbits, depthAttachments[ndx].sbits); glDeleteFramebuffers(1, &framebufferID); expectError(GL_NO_ERROR); } }; class AttachmentSizeRboCase : public AttachmentSizeCase { public: AttachmentSizeRboCase (Context& context, const char* name, const char* description) : AttachmentSizeCase(context, name, description) { } void testColorAttachment (GLenum internalFormat, GLenum attachment, GLint bitsR, GLint bitsG, GLint bitsB, GLint bitsA) { GLuint renderbufferID = 0; glGenRenderbuffers(1, &renderbufferID); glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID); glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, 128, 128); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); checkAttachmentComponentSizeAtLeast (m_testCtx, *this, GL_FRAMEBUFFER, attachment, bitsR, bitsG, bitsB, bitsA, -1, -1); checkAttachmentComponentSizeExactly (m_testCtx, *this, GL_FRAMEBUFFER, attachment, -1, -1, -1, -1, 0, 0); glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, 0); glDeleteRenderbuffers(1, &renderbufferID); } void testDepthAttachment (GLenum internalFormat, GLenum attachment, GLint bitsD, GLint bitsS) { GLuint renderbufferID = 0; glGenRenderbuffers(1, &renderbufferID); glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID); glRenderbufferStorage(GL_RENDERBUFFER, internalFormat, 128, 128); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); checkAttachmentComponentSizeAtLeast (m_testCtx, *this, GL_FRAMEBUFFER, attachment, -1, -1, -1, -1, bitsD, bitsS); checkAttachmentComponentSizeExactly (m_testCtx, *this, GL_FRAMEBUFFER, attachment, 0, 0, 0, 0, -1, -1); glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, 0); glDeleteRenderbuffers(1, &renderbufferID); } }; class AttachmentSizeTextureCase : public AttachmentSizeCase { public: AttachmentSizeTextureCase (Context& context, const char* name, const char* description) : AttachmentSizeCase(context, name, description) { } void testColorAttachment (GLenum internalFormat, GLenum attachment, GLint bitsR, GLint bitsG, GLint bitsB, GLint bitsA) { GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 128, 128); expectError(GL_NO_ERROR); glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, textureID, 0); expectError(GL_NO_ERROR); checkAttachmentComponentSizeAtLeast (m_testCtx, *this, GL_FRAMEBUFFER, attachment, bitsR, bitsG, bitsB, bitsA, -1, -1); checkAttachmentComponentSizeExactly (m_testCtx, *this, GL_FRAMEBUFFER, attachment, -1, -1, -1, -1, 0, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, 0, 0); glDeleteTextures(1, &textureID); } void testDepthAttachment (GLenum internalFormat, GLenum attachment, GLint bitsD, GLint bitsS) { // don't test stencil formats with textures if (attachment == GL_DEPTH_STENCIL_ATTACHMENT) return; GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 128, 128); expectError(GL_NO_ERROR); glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, textureID, 0); expectError(GL_NO_ERROR); checkAttachmentComponentSizeAtLeast (m_testCtx, *this, GL_FRAMEBUFFER, attachment, -1, -1, -1, -1, bitsD, bitsS); checkAttachmentComponentSizeExactly (m_testCtx, *this, GL_FRAMEBUFFER, attachment, 0, 0, 0, 0, -1, -1); glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, 0, 0); glDeleteTextures(1, &textureID); } }; class UnspecifiedAttachmentTextureColorCodingCase : public ApiCase { public: UnspecifiedAttachmentTextureColorCodingCase (Context& context, const char* name, const char* description) : ApiCase(context, name, description) { } void test (void) { GLuint framebufferID = 0; glGenFramebuffers(1, &framebufferID); glBindFramebuffer(GL_FRAMEBUFFER, framebufferID); expectError(GL_NO_ERROR); // color { GLuint renderbufferID = 0; glGenRenderbuffers(1, &renderbufferID); glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_LINEAR); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); glDeleteRenderbuffers(1, &renderbufferID); } // depth { GLuint renderbufferID = 0; glGenRenderbuffers(1, &renderbufferID); glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); checkAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING, GL_LINEAR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); glDeleteRenderbuffers(1, &renderbufferID); } glDeleteFramebuffers(1, &framebufferID); expectError(GL_NO_ERROR); } }; class UnspecifiedAttachmentTextureComponentTypeCase : public ApiCase { public: UnspecifiedAttachmentTextureComponentTypeCase (Context& context, const char* name, const char* description) : ApiCase(context, name, description) { } void test (void) { GLuint framebufferID = 0; glGenFramebuffers(1, &framebufferID); glBindFramebuffer(GL_FRAMEBUFFER, framebufferID); expectError(GL_NO_ERROR); { GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); expectError(GL_NO_ERROR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0); expectError(GL_NO_ERROR); checkColorAttachmentParam(m_testCtx, *this, GL_FRAMEBUFFER, GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE, GL_NONE); expectError(GL_NO_ERROR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glDeleteTextures(1, &textureID); } glDeleteFramebuffers(1, &framebufferID); expectError(GL_NO_ERROR); } }; class UnspecifiedAttachmentSizeCase : public ApiCase { public: UnspecifiedAttachmentSizeCase (Context& context, const char* name, const char* description) : ApiCase(context, name, description) { } virtual void testColorAttachment (void) = DE_NULL; virtual void testDepthAttachment (void) = DE_NULL; void test (void) { GLuint framebufferID = 0; glGenFramebuffers(1, &framebufferID); glBindFramebuffer(GL_FRAMEBUFFER, framebufferID); expectError(GL_NO_ERROR); // check color target testColorAttachment(); // check depth target testDepthAttachment(); glDeleteFramebuffers(1, &framebufferID); expectError(GL_NO_ERROR); } }; class UnspecifiedAttachmentSizeRboCase : public UnspecifiedAttachmentSizeCase { public: UnspecifiedAttachmentSizeRboCase (Context& context, const char* name, const char* description) : UnspecifiedAttachmentSizeCase(context, name, description) { } void testColorAttachment (void) { GLuint renderbufferID = 0; glGenRenderbuffers(1, &renderbufferID); glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); checkAttachmentComponentSizeExactly (m_testCtx, *this, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0, 0, 0); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0); glDeleteRenderbuffers(1, &renderbufferID); } void testDepthAttachment (void) { GLuint renderbufferID = 0; glGenRenderbuffers(1, &renderbufferID); glBindRenderbuffer(GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbufferID); expectError(GL_NO_ERROR); checkAttachmentComponentSizeExactly (m_testCtx, *this, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0, 0, 0, 0, 0, 0); expectError(GL_NO_ERROR); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0); glDeleteRenderbuffers(1, &renderbufferID); } }; class UnspecifiedAttachmentSizeTextureCase : public UnspecifiedAttachmentSizeCase { public: UnspecifiedAttachmentSizeTextureCase (Context& context, const char* name, const char* description) : UnspecifiedAttachmentSizeCase(context, name, description) { } void testColorAttachment (void) { GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); expectError(GL_NO_ERROR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureID, 0); expectError(GL_NO_ERROR); checkAttachmentComponentSizeExactly (m_testCtx, *this, GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 0, 0, 0, 0, 0, 0); expectError(GL_NO_ERROR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); glDeleteTextures(1, &textureID); } void testDepthAttachment (void) { GLuint textureID = 0; glGenTextures(1, &textureID); glBindTexture(GL_TEXTURE_2D, textureID); expectError(GL_NO_ERROR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, textureID, 0); expectError(GL_NO_ERROR); checkAttachmentComponentSizeExactly (m_testCtx, *this, GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, 0, 0, 0, 0, 0, 0); expectError(GL_NO_ERROR); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0); glDeleteTextures(1, &textureID); } }; } // anonymous FboStateQueryTests::FboStateQueryTests (Context& context) : TestCaseGroup(context, "fbo", "Fbo State Query tests") { } void FboStateQueryTests::init (void) { const struct FramebufferTarget { const char* name; GLenum target; } fboTargets[] = { { "draw_framebuffer_", GL_DRAW_FRAMEBUFFER }, { "read_framebuffer_", GL_READ_FRAMEBUFFER } }; for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(fboTargets); ++ndx) addChild(new DefaultFramebufferCase(m_context, (std::string(fboTargets[ndx].name) + "default_framebuffer").c_str(), "default framebuffer", fboTargets[ndx].target)); addChild(new AttachmentObjectCase (m_context, "framebuffer_attachment_object", "FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE and FRAMEBUFFER_ATTACHMENT_OBJECT_NAME")); addChild(new AttachmentTextureLevelCase (m_context, "framebuffer_attachment_texture_level", "FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL")); addChild(new AttachmentTextureCubeMapFaceCase (m_context, "framebuffer_attachment_texture_cube_map_face", "FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE")); addChild(new AttachmentTextureLayerCase (m_context, "framebuffer_attachment_texture_layer", "FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER")); addChild(new AttachmentTextureColorCodingCase (m_context, "framebuffer_attachment_color_encoding", "FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING")); addChild(new AttachmentTextureComponentTypeCase (m_context, "framebuffer_attachment_component_type", "FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE")); addChild(new AttachmentSizeInitialCase (m_context, "framebuffer_attachment_x_size_initial", "FRAMEBUFFER_ATTACHMENT_x_SIZE")); addChild(new AttachmentSizeRboCase (m_context, "framebuffer_attachment_x_size_rbo", "FRAMEBUFFER_ATTACHMENT_x_SIZE")); addChild(new AttachmentSizeTextureCase (m_context, "framebuffer_attachment_x_size_texture", "FRAMEBUFFER_ATTACHMENT_x_SIZE")); addChild(new UnspecifiedAttachmentTextureColorCodingCase (m_context, "framebuffer_unspecified_attachment_color_encoding", "FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING")); addChild(new UnspecifiedAttachmentTextureComponentTypeCase (m_context, "framebuffer_unspecified_attachment_component_type", "FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE")); addChild(new UnspecifiedAttachmentSizeRboCase (m_context, "framebuffer_unspecified_attachment_x_size_rbo", "FRAMEBUFFER_ATTACHMENT_x_SIZE")); addChild(new UnspecifiedAttachmentSizeTextureCase (m_context, "framebuffer_unspecified_attachment_x_size_texture", "FRAMEBUFFER_ATTACHMENT_x_SIZE")); } } // Functional } // gles3 } // deqp