| /*------------------------------------------------------------------------- |
| * 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 Framebuffer Object Tests. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "es3fFboRenderTest.hpp" |
| #include "sglrContextUtil.hpp" |
| #include "sglrGLContext.hpp" |
| #include "sglrReferenceContext.hpp" |
| #include "es3fFboTestUtil.hpp" |
| #include "tcuSurface.hpp" |
| #include "tcuImageCompare.hpp" |
| #include "tcuTextureUtil.hpp" |
| #include "tcuVectorUtil.hpp" |
| #include "tcuRenderTarget.hpp" |
| #include "gluPixelTransfer.hpp" |
| #include "gluTextureUtil.hpp" |
| #include "gluStrUtil.hpp" |
| #include "deRandom.h" |
| #include "deString.h" |
| #include "glwDefs.hpp" |
| #include "glwEnums.hpp" |
| |
| #include <sstream> |
| |
| using std::vector; |
| using std::string; |
| using tcu::TestLog; |
| using tcu::Vec2; |
| using tcu::Vec3; |
| using tcu::Vec4; |
| using tcu::IVec2; |
| using tcu::IVec3; |
| using tcu::IVec4; |
| using tcu::RGBA; |
| using tcu::Surface; |
| |
| namespace deqp |
| { |
| namespace gles3 |
| { |
| namespace Functional |
| { |
| |
| using glw::GLenum; |
| using namespace FboTestUtil; |
| |
| class FboConfig |
| { |
| public: |
| FboConfig (deUint32 buffers_, deUint32 colorType_, deUint32 colorFormat_, deUint32 depthStencilType_, deUint32 depthStencilFormat_, int width_ = 0, int height_ = 0, int samples_ = 0) |
| : buffers (buffers_) |
| , colorType (colorType_) |
| , colorFormat (colorFormat_) |
| , depthStencilType (depthStencilType_) |
| , depthStencilFormat (depthStencilFormat_) |
| , width (width_) |
| , height (height_) |
| , samples (samples_) |
| { |
| } |
| |
| FboConfig (void) |
| : buffers (0) |
| , colorType (GL_NONE) |
| , colorFormat (GL_NONE) |
| , depthStencilType (GL_NONE) |
| , depthStencilFormat (GL_NONE) |
| , width (0) |
| , height (0) |
| , samples (0) |
| { |
| } |
| |
| std::string getName (void) const; |
| |
| deUint32 buffers; //!< Buffer bit mask (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|...) |
| |
| GLenum colorType; //!< GL_TEXTURE_2D, GL_TEXTURE_CUBE_MAP, GL_RENDERBUFFER |
| GLenum colorFormat; //!< Internal format for color buffer texture or renderbuffer |
| |
| GLenum depthStencilType; |
| GLenum depthStencilFormat; |
| |
| int width; |
| int height; |
| int samples; |
| }; |
| |
| static const char* getTypeName (GLenum type) |
| { |
| switch (type) |
| { |
| case GL_TEXTURE_2D: return "tex2d"; |
| case GL_RENDERBUFFER: return "rbo"; |
| default: |
| TCU_FAIL("Unknown type"); |
| } |
| } |
| |
| std::string FboConfig::getName (void) const |
| { |
| std::ostringstream name; |
| |
| DE_ASSERT(buffers & GL_COLOR_BUFFER_BIT); |
| name << getTypeName(colorType) << "_" << getFormatName(colorFormat); |
| |
| if (buffers & GL_DEPTH_BUFFER_BIT) |
| name << "_depth"; |
| if (buffers & GL_STENCIL_BUFFER_BIT) |
| name << "_stencil"; |
| |
| if (buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) |
| name << "_" << getTypeName(depthStencilType) << "_" << getFormatName(depthStencilFormat); |
| |
| return name.str(); |
| } |
| |
| class Framebuffer |
| { |
| public: |
| Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo = 0, deUint32 colorBuffer = 0, deUint32 depthStencilBuffer = 0); |
| ~Framebuffer (void); |
| |
| const FboConfig& getConfig (void) const { return m_config; } |
| deUint32 getFramebuffer (void) const { return m_framebuffer; } |
| deUint32 getColorBuffer (void) const { return m_colorBuffer; } |
| deUint32 getDepthStencilBuffer (void) const { return m_depthStencilBuffer; } |
| |
| void checkCompleteness (void); |
| |
| private: |
| deUint32 createTex2D (deUint32 name, GLenum format, int width, int height); |
| deUint32 createRbo (deUint32 name, GLenum format, int width, int height); |
| void destroyBuffer (deUint32 name, GLenum type); |
| |
| FboConfig m_config; |
| sglr::Context& m_context; |
| deUint32 m_framebuffer; |
| deUint32 m_colorBuffer; |
| deUint32 m_depthStencilBuffer; |
| }; |
| |
| static std::vector<std::string> getEnablingExtensions (deUint32 format) |
| { |
| std::vector<std::string> out; |
| |
| switch (format) |
| { |
| case GL_RGB16F: |
| out.push_back("GL_EXT_color_buffer_half_float"); |
| break; |
| |
| case GL_RGBA16F: |
| case GL_RG16F: |
| case GL_R16F: |
| out.push_back("GL_EXT_color_buffer_half_float"); |
| // Fallthrough |
| |
| case GL_RGBA32F: |
| case GL_RGB32F: |
| case GL_R11F_G11F_B10F: |
| case GL_RG32F: |
| case GL_R32F: |
| out.push_back("GL_EXT_color_buffer_float"); |
| break; |
| |
| default: |
| break; |
| } |
| |
| return out; |
| } |
| |
| static bool isExtensionSupported (sglr::Context& context, const char* name) |
| { |
| std::istringstream extensions(context.getString(GL_EXTENSIONS)); |
| std::string extension; |
| |
| while (std::getline(extensions, extension, ' ')) |
| { |
| if (extension == name) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| static bool isAnyExtensionSupported (sglr::Context& context, const std::vector<std::string>& requiredExts) |
| { |
| if (requiredExts.empty()) |
| return true; |
| |
| for (std::vector<std::string>::const_iterator iter = requiredExts.begin(); iter != requiredExts.end(); iter++) |
| { |
| const std::string& extension = *iter; |
| |
| if (isExtensionSupported(context, extension.c_str())) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| template<typename T> |
| static std::string join (const std::vector<T>& list, const std::string& sep) |
| { |
| std::ostringstream out; |
| |
| for (typename std::vector<T>::const_iterator iter = list.begin(); iter != list.end(); iter++) |
| { |
| if (iter != list.begin()) |
| out << sep; |
| out << *iter; |
| } |
| |
| return out.str(); |
| } |
| |
| static void checkColorFormatSupport (sglr::Context& context, deUint32 sizedFormat) |
| { |
| const std::vector<std::string> requiredExts = getEnablingExtensions(sizedFormat); |
| |
| if (!isAnyExtensionSupported(context, requiredExts)) |
| { |
| std::string errMsg = "Format not supported, requires " |
| + ((requiredExts.size() == 1) ? requiredExts[0] : " one of the following: " + join(requiredExts, ", ")); |
| |
| throw tcu::NotSupportedError(errMsg); |
| } |
| } |
| |
| Framebuffer::Framebuffer (sglr::Context& context, const FboConfig& config, int width, int height, deUint32 fbo, deUint32 colorBufferName, deUint32 depthStencilBufferName) |
| : m_config (config) |
| , m_context (context) |
| , m_framebuffer (fbo) |
| , m_colorBuffer (0) |
| , m_depthStencilBuffer (0) |
| { |
| // Verify that color format is supported |
| checkColorFormatSupport(context, config.colorFormat); |
| |
| if (m_framebuffer == 0) |
| context.genFramebuffers(1, &m_framebuffer); |
| context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); |
| |
| if (m_config.buffers & (GL_COLOR_BUFFER_BIT)) |
| { |
| switch (m_config.colorType) |
| { |
| case GL_TEXTURE_2D: |
| m_colorBuffer = createTex2D(colorBufferName, m_config.colorFormat, width, height); |
| context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffer, 0); |
| break; |
| |
| case GL_RENDERBUFFER: |
| m_colorBuffer = createRbo(colorBufferName, m_config.colorFormat, width, height); |
| context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_colorBuffer); |
| break; |
| |
| default: |
| TCU_FAIL("Unsupported type"); |
| } |
| } |
| |
| if (m_config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) |
| { |
| switch (m_config.depthStencilType) |
| { |
| case GL_TEXTURE_2D: m_depthStencilBuffer = createTex2D(depthStencilBufferName, m_config.depthStencilFormat, width, height); break; |
| case GL_RENDERBUFFER: m_depthStencilBuffer = createRbo(depthStencilBufferName, m_config.depthStencilFormat, width, height); break; |
| default: |
| TCU_FAIL("Unsupported type"); |
| } |
| } |
| |
| for (int ndx = 0; ndx < 2; ndx++) |
| { |
| deUint32 bit = ndx ? GL_STENCIL_BUFFER_BIT : GL_DEPTH_BUFFER_BIT; |
| deUint32 point = ndx ? GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; |
| |
| if ((m_config.buffers & bit) == 0) |
| continue; /* Not used. */ |
| |
| switch (m_config.depthStencilType) |
| { |
| case GL_TEXTURE_2D: context.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, m_depthStencilBuffer, 0); break; |
| case GL_RENDERBUFFER: context.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, m_depthStencilBuffer); break; |
| default: |
| DE_ASSERT(false); |
| } |
| } |
| |
| GLenum err = m_context.getError(); |
| if (err != GL_NO_ERROR) |
| throw glu::Error(err, glu::getErrorStr(err).toString().c_str(), "", __FILE__, __LINE__); |
| |
| context.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| } |
| |
| Framebuffer::~Framebuffer (void) |
| { |
| m_context.deleteFramebuffers(1, &m_framebuffer); |
| destroyBuffer(m_colorBuffer, m_config.colorType); |
| destroyBuffer(m_depthStencilBuffer, m_config.depthStencilType); |
| } |
| |
| void Framebuffer::checkCompleteness (void) |
| { |
| m_context.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer); |
| GLenum status = m_context.checkFramebufferStatus(GL_FRAMEBUFFER); |
| m_context.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| if (status != GL_FRAMEBUFFER_COMPLETE) |
| throw FboIncompleteException(status, __FILE__, __LINE__); |
| } |
| |
| deUint32 Framebuffer::createTex2D (deUint32 name, GLenum format, int width, int height) |
| { |
| if (name == 0) |
| m_context.genTextures(1, &name); |
| |
| m_context.bindTexture(GL_TEXTURE_2D, name); |
| m_context.texImage2D(GL_TEXTURE_2D, 0, format, width, height); |
| |
| if (!deIsPowerOfTwo32(width) || !deIsPowerOfTwo32(height)) |
| { |
| // Set wrap mode to clamp for NPOT FBOs |
| m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| } |
| |
| m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| m_context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| |
| return name; |
| } |
| |
| deUint32 Framebuffer::createRbo (deUint32 name, GLenum format, int width, int height) |
| { |
| if (name == 0) |
| m_context.genRenderbuffers(1, &name); |
| |
| m_context.bindRenderbuffer(GL_RENDERBUFFER, name); |
| m_context.renderbufferStorage(GL_RENDERBUFFER, format, width, height); |
| |
| return name; |
| } |
| |
| void Framebuffer::destroyBuffer (deUint32 name, GLenum type) |
| { |
| if (type == GL_TEXTURE_2D || type == GL_TEXTURE_CUBE_MAP) |
| m_context.deleteTextures(1, &name); |
| else if (type == GL_RENDERBUFFER) |
| m_context.deleteRenderbuffers(1, &name); |
| else |
| DE_ASSERT(type == GL_NONE); |
| } |
| |
| static void createMetaballsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height) |
| { |
| tcu::TextureFormat texFormat = glu::mapGLTransferFormat(format, dataType); |
| tcu::TextureLevel level (texFormat, width, height); |
| |
| tcu::fillWithMetaballs(level.getAccess(), 5, name ^ width ^ height); |
| |
| context.bindTexture(GL_TEXTURE_2D, name); |
| context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr()); |
| context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| } |
| |
| static void createQuadsTex2D (sglr::Context& context, deUint32 name, GLenum format, GLenum dataType, int width, int height) |
| { |
| tcu::TextureFormat texFormat = glu::mapGLTransferFormat(format, dataType); |
| tcu::TextureLevel level (texFormat, width, height); |
| |
| tcu::fillWithRGBAQuads(level.getAccess()); |
| |
| context.bindTexture(GL_TEXTURE_2D, name); |
| context.texImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr()); |
| context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| } |
| |
| class FboRenderCase : public TestCase |
| { |
| public: |
| FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config); |
| virtual ~FboRenderCase (void) {} |
| |
| virtual IterateResult iterate (void); |
| virtual void render (sglr::Context& fboContext, Surface& dst) = DE_NULL; |
| |
| bool compare (const tcu::Surface& reference, const tcu::Surface& result); |
| |
| protected: |
| const FboConfig m_config; |
| }; |
| |
| FboRenderCase::FboRenderCase (Context& context, const char* name, const char* description, const FboConfig& config) |
| : TestCase (context, name, description) |
| , m_config (config) |
| { |
| } |
| |
| TestCase::IterateResult FboRenderCase::iterate (void) |
| { |
| tcu::Vec4 clearColor = tcu::Vec4(0.125f, 0.25f, 0.5f, 1.0f); |
| glu::RenderContext& renderCtx = m_context.getRenderContext(); |
| const tcu::RenderTarget& renderTarget = renderCtx.getRenderTarget(); |
| tcu::TestLog& log = m_testCtx.getLog(); |
| const char* failReason = DE_NULL; |
| |
| // Position & size for context |
| deRandom rnd; |
| deRandom_init(&rnd, deStringHash(getName())); |
| |
| int width = deMin32(renderTarget.getWidth(), 128); |
| int height = deMin32(renderTarget.getHeight(), 128); |
| int xMax = renderTarget.getWidth()-width+1; |
| int yMax = renderTarget.getHeight()-height+1; |
| int x = deRandom_getUint32(&rnd) % xMax; |
| int y = deRandom_getUint32(&rnd) % yMax; |
| |
| tcu::Surface gles3Frame (width, height); |
| tcu::Surface refFrame (width, height); |
| GLenum gles3Error; |
| GLenum refError; |
| |
| // Render using GLES3 |
| try |
| { |
| sglr::GLContext context(renderCtx, log, sglr::GLCONTEXT_LOG_CALLS, tcu::IVec4(x, y, width, height)); |
| |
| context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w()); |
| context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| |
| render(context, gles3Frame); // Call actual render func |
| gles3Error = context.getError(); |
| } |
| catch (const FboIncompleteException& e) |
| { |
| if (e.getReason() == GL_FRAMEBUFFER_UNSUPPORTED) |
| { |
| // Mark test case as unsupported |
| log << e; |
| m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not supported"); |
| return STOP; |
| } |
| else |
| throw; // Propagate error |
| } |
| |
| // Render reference image |
| { |
| sglr::ReferenceContextBuffers buffers (tcu::PixelFormat(8,8,8,renderTarget.getPixelFormat().alphaBits?8:0), renderTarget.getDepthBits(), renderTarget.getStencilBits(), width, height); |
| sglr::ReferenceContext context (sglr::ReferenceContextLimits(renderCtx), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer()); |
| |
| context.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w()); |
| context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| |
| render(context, refFrame); |
| refError = context.getError(); |
| } |
| |
| // Compare error codes |
| bool errorCodesOk = (gles3Error == refError); |
| |
| if (!errorCodesOk) |
| { |
| log << tcu::TestLog::Message << "Error code mismatch: got " << glu::getErrorStr(gles3Error) << ", expected " << glu::getErrorStr(refError) << tcu::TestLog::EndMessage; |
| failReason = "Got unexpected error"; |
| } |
| |
| // Compare images |
| bool imagesOk = compare(refFrame, gles3Frame); |
| |
| if (!imagesOk && !failReason) |
| failReason = "Image comparison failed"; |
| |
| // Store test result |
| bool isOk = errorCodesOk && imagesOk; |
| m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, |
| isOk ? "Pass" : failReason); |
| |
| return STOP; |
| } |
| |
| bool FboRenderCase::compare (const tcu::Surface& reference, const tcu::Surface& result) |
| { |
| const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_config.colorFormat), tcu::RGBA(12, 12, 12, 12))); |
| |
| return tcu::bilinearCompare(m_testCtx.getLog(), "ComparisonResult", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT); |
| } |
| |
| namespace FboCases |
| { |
| |
| class StencilClearsTest : public FboRenderCase |
| { |
| public: |
| StencilClearsTest (Context& context, const FboConfig& config); |
| virtual ~StencilClearsTest (void) {}; |
| |
| void render (sglr::Context& context, Surface& dst); |
| }; |
| |
| StencilClearsTest::StencilClearsTest (Context& context, const FboConfig& config) |
| : FboRenderCase (context, config.getName().c_str(), "Stencil clears", config) |
| { |
| } |
| |
| void StencilClearsTest::render (sglr::Context& context, Surface& dst) |
| { |
| tcu::TextureFormat colorFormat = glu::mapGLInternalFormat(m_config.colorFormat); |
| glu::DataType fboSamplerType = glu::getSampler2DType(colorFormat); |
| glu::DataType fboOutputType = getFragmentOutputType(colorFormat); |
| tcu::TextureFormatInfo fboRangeInfo = tcu::getTextureFormatInfo(colorFormat); |
| Vec4 fboOutScale = fboRangeInfo.valueMax - fboRangeInfo.valueMin; |
| Vec4 fboOutBias = fboRangeInfo.valueMin; |
| |
| Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType); |
| Texture2DShader texFromFboShader (DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4); |
| |
| deUint32 texToFboShaderID = context.createProgram(&texToFboShader); |
| deUint32 texFromFboShaderID = context.createProgram(&texFromFboShader); |
| |
| deUint32 metaballsTex = 1; |
| deUint32 quadsTex = 2; |
| int width = 128; |
| int height = 128; |
| |
| texToFboShader.setOutScaleBias(fboOutScale, fboOutBias); |
| texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias); |
| |
| createQuadsTex2D(context, quadsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height); |
| createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, width, height); |
| |
| Framebuffer fbo(context, m_config, width, height); |
| fbo.checkCompleteness(); |
| |
| // Bind framebuffer and clear |
| context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); |
| context.viewport(0, 0, width, height); |
| context.clearColor(0.0f, 0.0f, 0.0f, 1.0f); |
| context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| |
| // Do stencil clears |
| context.enable(GL_SCISSOR_TEST); |
| context.scissor(10, 16, 32, 120); |
| context.clearStencil(1); |
| context.clear(GL_STENCIL_BUFFER_BIT); |
| context.scissor(16, 32, 100, 64); |
| context.clearStencil(2); |
| context.clear(GL_STENCIL_BUFFER_BIT); |
| context.disable(GL_SCISSOR_TEST); |
| |
| // Draw 2 textures with stecil tests |
| context.enable(GL_STENCIL_TEST); |
| |
| context.bindTexture(GL_TEXTURE_2D, quadsTex); |
| context.stencilFunc(GL_EQUAL, 1, 0xffu); |
| |
| texToFboShader.setUniforms(context, texToFboShaderID); |
| sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); |
| |
| context.bindTexture(GL_TEXTURE_2D, metaballsTex); |
| context.stencilFunc(GL_EQUAL, 2, 0xffu); |
| |
| texToFboShader.setUniforms(context, texToFboShaderID); |
| sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); |
| |
| context.disable(GL_STENCIL_TEST); |
| |
| if (fbo.getConfig().colorType == GL_TEXTURE_2D) |
| { |
| context.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer()); |
| context.viewport(0, 0, context.getWidth(), context.getHeight()); |
| |
| texFromFboShader.setUniforms(context, texFromFboShaderID); |
| sglr::drawQuad(context, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| |
| context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); |
| } |
| else |
| readPixels(context, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias); |
| } |
| |
| class SharedColorbufferTest : public FboRenderCase |
| { |
| public: |
| SharedColorbufferTest (Context& context, const FboConfig& config); |
| virtual ~SharedColorbufferTest (void) {}; |
| |
| void render (sglr::Context& context, Surface& dst); |
| }; |
| |
| SharedColorbufferTest::SharedColorbufferTest (Context& context, const FboConfig& config) |
| : FboRenderCase (context, config.getName().c_str(), "Shared colorbuffer", config) |
| { |
| } |
| |
| void SharedColorbufferTest::render (sglr::Context& context, Surface& dst) |
| { |
| Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4); |
| FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); |
| deUint32 texShaderID = context.createProgram(&texShader); |
| deUint32 flatShaderID = context.createProgram(&flatShader); |
| |
| int width = 128; |
| int height = 128; |
| deUint32 quadsTex = 1; |
| deUint32 metaballsTex = 2; |
| bool stencil = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0; |
| |
| context.disable(GL_DITHER); |
| |
| // Textures |
| createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); |
| createMetaballsTex2D(context, metaballsTex, GL_RGBA, GL_UNSIGNED_BYTE, 64, 64); |
| |
| context.viewport(0, 0, width, height); |
| |
| // Fbo A |
| Framebuffer fboA(context, m_config, width, height); |
| fboA.checkCompleteness(); |
| |
| // Fbo B - don't create colorbuffer |
| FboConfig cfg = m_config; |
| cfg.buffers &= ~GL_COLOR_BUFFER_BIT; |
| cfg.colorType = GL_NONE; |
| cfg.colorFormat = GL_NONE; |
| Framebuffer fboB(context, cfg, width, height); |
| |
| // Attach color buffer from fbo A |
| context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer()); |
| switch (m_config.colorType) |
| { |
| case GL_TEXTURE_2D: |
| context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboA.getColorBuffer(), 0); |
| break; |
| |
| case GL_RENDERBUFFER: |
| context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fboA.getColorBuffer()); |
| break; |
| |
| default: |
| DE_ASSERT(DE_FALSE); |
| } |
| |
| // Clear depth and stencil in fbo B |
| context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| |
| // Render quads to fbo 1, with depth 0.0 |
| context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer()); |
| context.bindTexture(GL_TEXTURE_2D, quadsTex); |
| context.clearColor(0.0f, 0.0f, 0.0f, 1.0f); |
| context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| |
| if (stencil) |
| { |
| // Stencil to 1 in fbo A |
| context.clearStencil(1); |
| context.clear(GL_STENCIL_BUFFER_BIT); |
| } |
| |
| texShader.setUniforms(context, texShaderID); |
| |
| context.enable(GL_DEPTH_TEST); |
| sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| context.disable(GL_DEPTH_TEST); |
| |
| // Blend metaballs to fbo 2 |
| context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer()); |
| context.bindTexture(GL_TEXTURE_2D, metaballsTex); |
| context.enable(GL_BLEND); |
| context.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE); |
| sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| |
| // Render small quad that is only visible if depth buffer is not shared with fbo A - or there is no depth bits |
| context.bindTexture(GL_TEXTURE_2D, quadsTex); |
| context.enable(GL_DEPTH_TEST); |
| sglr::drawQuad(context, texShaderID, Vec3(0.5f, 0.5f, 0.5f), Vec3(1.0f, 1.0f, 0.5f)); |
| context.disable(GL_DEPTH_TEST); |
| |
| if (stencil) |
| { |
| flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)); |
| |
| // Clear subset of stencil buffer to 1 |
| context.enable(GL_SCISSOR_TEST); |
| context.scissor(10, 10, 12, 25); |
| context.clearStencil(1); |
| context.clear(GL_STENCIL_BUFFER_BIT); |
| context.disable(GL_SCISSOR_TEST); |
| |
| // Render quad with stencil mask == 1 |
| context.enable(GL_STENCIL_TEST); |
| context.stencilFunc(GL_EQUAL, 1, 0xffu); |
| sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| context.disable(GL_STENCIL_TEST); |
| } |
| |
| // Get results |
| if (fboA.getConfig().colorType == GL_TEXTURE_2D) |
| { |
| texShader.setUniforms(context, texShaderID); |
| |
| context.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| context.bindTexture(GL_TEXTURE_2D, fboA.getColorBuffer()); |
| context.viewport(0, 0, context.getWidth(), context.getHeight()); |
| sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); |
| } |
| else |
| readPixels(context, dst, 0, 0, width, height, glu::mapGLInternalFormat(fboA.getConfig().colorFormat), Vec4(1.0f), Vec4(0.0f)); |
| } |
| |
| class SharedColorbufferClearsTest : public FboRenderCase |
| { |
| public: |
| SharedColorbufferClearsTest (Context& context, const FboConfig& config); |
| virtual ~SharedColorbufferClearsTest (void) {} |
| |
| void render (sglr::Context& context, Surface& dst); |
| }; |
| |
| SharedColorbufferClearsTest::SharedColorbufferClearsTest (Context& context, const FboConfig& config) |
| : FboRenderCase (context, config.getName().c_str(), "Shared colorbuffer clears", config) |
| { |
| } |
| |
| void SharedColorbufferClearsTest::render (sglr::Context& context, Surface& dst) |
| { |
| tcu::TextureFormat colorFormat = glu::mapGLInternalFormat(m_config.colorFormat); |
| glu::DataType fboSamplerType = glu::getSampler2DType(colorFormat); |
| int width = 128; |
| int height = 128; |
| deUint32 colorbuffer = 1; |
| |
| // Check for format support. |
| checkColorFormatSupport(context, m_config.colorFormat); |
| |
| // Single colorbuffer |
| if (m_config.colorType == GL_TEXTURE_2D) |
| { |
| context.bindTexture(GL_TEXTURE_2D, colorbuffer); |
| context.texImage2D(GL_TEXTURE_2D, 0, m_config.colorFormat, width, height); |
| context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| } |
| else |
| { |
| DE_ASSERT(m_config.colorType == GL_RENDERBUFFER); |
| context.bindRenderbuffer(GL_RENDERBUFFER, colorbuffer); |
| context.renderbufferStorage(GL_RENDERBUFFER, m_config.colorFormat, width, height); |
| } |
| |
| // Multiple framebuffers sharing the colorbuffer |
| for (int fbo = 1; fbo <= 3; fbo++) |
| { |
| context.bindFramebuffer(GL_FRAMEBUFFER, fbo); |
| |
| if (m_config.colorType == GL_TEXTURE_2D) |
| context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, colorbuffer, 0); |
| else |
| context.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorbuffer); |
| } |
| |
| context.bindFramebuffer(GL_FRAMEBUFFER, 1); |
| |
| // Check completeness |
| { |
| GLenum status = context.checkFramebufferStatus(GL_FRAMEBUFFER); |
| if (status != GL_FRAMEBUFFER_COMPLETE) |
| throw FboIncompleteException(status, __FILE__, __LINE__); |
| } |
| |
| // Render to them |
| context.viewport(0, 0, width, height); |
| context.clearColor(0.0f, 0.0f, 1.0f, 1.0f); |
| context.clear(GL_COLOR_BUFFER_BIT); |
| |
| context.enable(GL_SCISSOR_TEST); |
| |
| context.bindFramebuffer(GL_FRAMEBUFFER, 2); |
| context.clearColor(0.6f, 0.0f, 0.0f, 1.0f); |
| context.scissor(10, 10, 64, 64); |
| context.clear(GL_COLOR_BUFFER_BIT); |
| context.clearColor(0.0f, 0.6f, 0.0f, 1.0f); |
| context.scissor(60, 60, 40, 20); |
| context.clear(GL_COLOR_BUFFER_BIT); |
| |
| context.bindFramebuffer(GL_FRAMEBUFFER, 3); |
| context.clearColor(0.0f, 0.0f, 0.6f, 1.0f); |
| context.scissor(20, 20, 100, 10); |
| context.clear(GL_COLOR_BUFFER_BIT); |
| |
| context.bindFramebuffer(GL_FRAMEBUFFER, 1); |
| context.clearColor(0.6f, 0.0f, 0.6f, 1.0f); |
| context.scissor(20, 20, 5, 100); |
| context.clear(GL_COLOR_BUFFER_BIT); |
| |
| context.disable(GL_SCISSOR_TEST); |
| |
| if (m_config.colorType == GL_TEXTURE_2D) |
| { |
| Texture2DShader shader(DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4); |
| deUint32 shaderID = context.createProgram(&shader); |
| |
| shader.setUniforms(context, shaderID); |
| |
| context.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| context.viewport(0, 0, context.getWidth(), context.getHeight()); |
| sglr::drawQuad(context, shaderID, Vec3(-0.9f, -0.9f, 0.0f), Vec3(0.9f, 0.9f, 0.0f)); |
| context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); |
| } |
| else |
| readPixels(context, dst, 0, 0, width, height, colorFormat, Vec4(1.0f), Vec4(0.0f)); |
| } |
| |
| class SharedDepthStencilTest : public FboRenderCase |
| { |
| public: |
| SharedDepthStencilTest (Context& context, const FboConfig& config); |
| virtual ~SharedDepthStencilTest (void) {}; |
| |
| static bool isConfigSupported (const FboConfig& config); |
| void render (sglr::Context& context, Surface& dst); |
| }; |
| |
| SharedDepthStencilTest::SharedDepthStencilTest (Context& context, const FboConfig& config) |
| : FboRenderCase (context, config.getName().c_str(), "Shared depth/stencilbuffer", config) |
| { |
| } |
| |
| bool SharedDepthStencilTest::isConfigSupported (const FboConfig& config) |
| { |
| return (config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) != 0; |
| } |
| |
| void SharedDepthStencilTest::render (sglr::Context& context, Surface& dst) |
| { |
| Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4); |
| FlatColorShader flatShader (glu::TYPE_FLOAT_VEC4); |
| deUint32 texShaderID = context.createProgram(&texShader); |
| deUint32 flatShaderID = context.createProgram(&flatShader); |
| int width = 128; |
| int height = 128; |
| // bool depth = (m_config.buffers & GL_DEPTH_BUFFER_BIT) != 0; |
| bool stencil = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0; |
| |
| // Textures |
| deUint32 metaballsTex = 5; |
| deUint32 quadsTex = 6; |
| createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); |
| createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); |
| |
| context.viewport(0, 0, width, height); |
| |
| // Fbo A |
| Framebuffer fboA(context, m_config, width, height); |
| fboA.checkCompleteness(); |
| |
| // Fbo B |
| FboConfig cfg = m_config; |
| cfg.buffers &= ~(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| cfg.depthStencilType = GL_NONE; |
| cfg.depthStencilFormat = GL_NONE; |
| Framebuffer fboB(context, cfg, width, height); |
| |
| // Bind depth/stencil buffers from fbo A to fbo B |
| context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer()); |
| for (int ndx = 0; ndx < 2; ndx++) |
| { |
| deUint32 bit = ndx ? GL_STENCIL_BUFFER_BIT : GL_DEPTH_BUFFER_BIT; |
| deUint32 point = ndx ? GL_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT; |
| |
| if ((m_config.buffers & bit) == 0) |
| continue; |
| |
| switch (m_config.depthStencilType) |
| { |
| case GL_TEXTURE_2D: context.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, fboA.getDepthStencilBuffer(), 0); break; |
| case GL_RENDERBUFFER: context.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, fboA.getDepthStencilBuffer()); break; |
| default: |
| TCU_FAIL("Not implemented"); |
| } |
| } |
| |
| // Setup uniforms |
| texShader.setUniforms(context, texShaderID); |
| |
| // Clear color to red and stencil to 1 in fbo B. |
| context.clearColor(1.0f, 0.0f, 0.0f, 1.0f); |
| context.clearStencil(1); |
| context.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| |
| context.enable(GL_DEPTH_TEST); |
| |
| // Render quad to fbo A |
| context.bindFramebuffer(GL_FRAMEBUFFER, fboA.getFramebuffer()); |
| context.bindTexture(GL_TEXTURE_2D, quadsTex); |
| sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| |
| if (stencil) |
| { |
| // Clear subset of stencil buffer to 0 in fbo A |
| context.enable(GL_SCISSOR_TEST); |
| context.scissor(10, 10, 12, 25); |
| context.clearStencil(0); |
| context.clear(GL_STENCIL_BUFFER_BIT); |
| context.disable(GL_SCISSOR_TEST); |
| } |
| |
| // Render metaballs to fbo B |
| context.bindFramebuffer(GL_FRAMEBUFFER, fboB.getFramebuffer()); |
| context.bindTexture(GL_TEXTURE_2D, metaballsTex); |
| sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, -1.0f), Vec3(1.0f, 1.0f, 1.0f)); |
| |
| context.disable(GL_DEPTH_TEST); |
| |
| if (stencil) |
| { |
| // Render quad with stencil mask == 0 |
| context.enable(GL_STENCIL_TEST); |
| context.stencilFunc(GL_EQUAL, 0, 0xffu); |
| context.useProgram(flatShaderID); |
| flatShader.setColor(context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f)); |
| sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); |
| context.disable(GL_STENCIL_TEST); |
| } |
| |
| if (m_config.colorType == GL_TEXTURE_2D) |
| { |
| // Render both to screen |
| context.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| context.viewport(0, 0, context.getWidth(), context.getHeight()); |
| context.bindTexture(GL_TEXTURE_2D, fboA.getColorBuffer()); |
| sglr::drawQuad(context, texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 1.0f, 0.0f)); |
| context.bindTexture(GL_TEXTURE_2D, fboB.getColorBuffer()); |
| sglr::drawQuad(context, texShaderID, Vec3(0.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| |
| context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); |
| } |
| else |
| { |
| // Read results from fbo B |
| readPixels(context, dst, 0, 0, width, height, glu::mapGLInternalFormat(m_config.colorFormat), Vec4(1.0f), Vec4(0.0f)); |
| } |
| } |
| |
| #if 0 |
| class TexSubImageAfterRenderTest : public FboRenderCase |
| { |
| public: |
| TexSubImageAfterRenderTest (Context& context, const FboConfig& config); |
| virtual ~TexSubImageAfterRenderTest (void) {} |
| |
| void render (sglr::Context& context, Surface& dst); |
| }; |
| |
| TexSubImageAfterRenderTest::TexSubImageAfterRenderTest (Context& context, const FboConfig& config) |
| : FboRenderCase(context, (string("after_render_") + config.getName()).c_str(), "TexSubImage after rendering to texture", config) |
| { |
| } |
| |
| void TexSubImageAfterRenderTest::render (sglr::Context& context, Surface& dst) |
| { |
| using sglr::TexturedQuadOp; |
| |
| bool isRGBA = true; |
| |
| Surface fourQuads(Surface::PIXELFORMAT_RGB, 64, 64); |
| tcu::SurfaceUtil::fillWithFourQuads(fourQuads); |
| |
| Surface metaballs(isRGBA ? Surface::PIXELFORMAT_RGBA : Surface::PIXELFORMAT_RGB, 64, 64); |
| tcu::SurfaceUtil::fillWithMetaballs(metaballs, 5, 3); |
| |
| deUint32 fourQuadsTex = 1; |
| context.bindTexture(GL_TEXTURE_2D, fourQuadsTex); |
| context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, fourQuads); |
| |
| context.bindFramebuffer(GL_FRAMEBUFFER, 1); |
| |
| deUint32 fboTex = 2; |
| context.bindTexture(GL_TEXTURE_2D, fboTex); |
| context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128); |
| context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0); |
| |
| // Render to fbo |
| context.viewport(0, 0, 128, 128); |
| context.bindTexture(GL_TEXTURE_2D, fourQuadsTex); |
| context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0)); |
| |
| // Update texture using TexSubImage2D |
| context.bindTexture(GL_TEXTURE_2D, fboTex); |
| context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, metaballs); |
| |
| // Draw to screen |
| context.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| context.viewport(0, 0, context.getWidth(), context.getHeight()); |
| context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0)); |
| context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); |
| } |
| |
| class TexSubImageBetweenRenderTest : public FboRenderCase |
| { |
| public: |
| TexSubImageBetweenRenderTest (Context& context, const FboConfig& config); |
| virtual ~TexSubImageBetweenRenderTest (void) {} |
| |
| void render (sglr::Context& context, Surface& dst); |
| }; |
| |
| TexSubImageBetweenRenderTest::TexSubImageBetweenRenderTest (Context& context, const FboConfig& config) |
| : FboRenderCase(context, (string("between_render_") + config.getName()).c_str(), "TexSubImage between rendering calls", config) |
| { |
| } |
| |
| void TexSubImageBetweenRenderTest::render (sglr::Context& context, Surface& dst) |
| { |
| using sglr::TexturedQuadOp; |
| using sglr::BlendTextureOp; |
| |
| bool isRGBA = true; |
| |
| Surface fourQuads(Surface::PIXELFORMAT_RGB, 64, 64); |
| tcu::SurfaceUtil::fillWithFourQuads(fourQuads); |
| |
| Surface metaballs(isRGBA ? Surface::PIXELFORMAT_RGBA : Surface::PIXELFORMAT_RGB, 64, 64); |
| tcu::SurfaceUtil::fillWithMetaballs(metaballs, 5, 3); |
| |
| Surface metaballs2(Surface::PIXELFORMAT_RGBA, 64, 64); |
| tcu::SurfaceUtil::fillWithMetaballs(metaballs2, 5, 4); |
| |
| deUint32 metaballsTex = 3; |
| context.bindTexture(GL_TEXTURE_2D, metaballsTex); |
| context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| context.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, metaballs2); |
| |
| deUint32 fourQuadsTex = 1; |
| context.bindTexture(GL_TEXTURE_2D, fourQuadsTex); |
| context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| context.texImage2D(GL_TEXTURE_2D, 0, GL_RGB, fourQuads); |
| |
| context.bindFramebuffer(GL_FRAMEBUFFER, 1); |
| |
| deUint32 fboTex = 2; |
| context.bindTexture(GL_TEXTURE_2D, fboTex); |
| context.texImage2D(GL_TEXTURE_2D, 0, isRGBA ? GL_RGBA : GL_RGB, 128, 128); |
| context.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| context.framebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, fboTex, 0); |
| |
| // Render to fbo |
| context.viewport(0, 0, 128, 128); |
| context.bindTexture(GL_TEXTURE_2D, fourQuadsTex); |
| context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0)); |
| |
| // Update texture using TexSubImage2D |
| context.bindTexture(GL_TEXTURE_2D, fboTex); |
| context.texSubImage2D(GL_TEXTURE_2D, 0, 32, 32, metaballs); |
| |
| // Render again to fbo |
| context.bindTexture(GL_TEXTURE_2D, metaballsTex); |
| context.draw(BlendTextureOp(0)); |
| |
| // Draw to screen |
| context.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| context.viewport(0, 0, context.getWidth(), context.getHeight()); |
| context.bindTexture(GL_TEXTURE_2D, fboTex); |
| context.draw(TexturedQuadOp(-1.0f, -1.0f, 1.0f, 1.0f, 0)); |
| |
| context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); |
| } |
| #endif |
| |
| class ResizeTest : public FboRenderCase |
| { |
| public: |
| ResizeTest (Context& context, const FboConfig& config); |
| virtual ~ResizeTest (void) {} |
| |
| void render (sglr::Context& context, Surface& dst); |
| }; |
| |
| ResizeTest::ResizeTest (Context& context, const FboConfig& config) |
| : FboRenderCase (context, config.getName().c_str(), "Resize framebuffer", config) |
| { |
| } |
| |
| void ResizeTest::render (sglr::Context& context, Surface& dst) |
| { |
| tcu::TextureFormat colorFormat = glu::mapGLInternalFormat(m_config.colorFormat); |
| glu::DataType fboSamplerType = glu::getSampler2DType(colorFormat); |
| glu::DataType fboOutputType = getFragmentOutputType(colorFormat); |
| tcu::TextureFormatInfo fboRangeInfo = tcu::getTextureFormatInfo(colorFormat); |
| Vec4 fboOutScale = fboRangeInfo.valueMax - fboRangeInfo.valueMin; |
| Vec4 fboOutBias = fboRangeInfo.valueMin; |
| |
| Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType); |
| Texture2DShader texFromFboShader (DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4); |
| FlatColorShader flatShader (fboOutputType); |
| deUint32 texToFboShaderID = context.createProgram(&texToFboShader); |
| deUint32 texFromFboShaderID = context.createProgram(&texFromFboShader); |
| deUint32 flatShaderID = context.createProgram(&flatShader); |
| |
| deUint32 quadsTex = 1; |
| deUint32 metaballsTex = 2; |
| bool depth = (m_config.buffers & GL_DEPTH_BUFFER_BIT) != 0; |
| bool stencil = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0; |
| int initialWidth = 128; |
| int initialHeight = 128; |
| int newWidth = 64; |
| int newHeight = 32; |
| |
| texToFboShader.setOutScaleBias(fboOutScale, fboOutBias); |
| texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias); |
| |
| createQuadsTex2D(context, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); |
| createMetaballsTex2D(context, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 32, 32); |
| |
| Framebuffer fbo(context, m_config, initialWidth, initialHeight); |
| fbo.checkCompleteness(); |
| |
| // Setup shaders |
| texToFboShader.setUniforms (context, texToFboShaderID); |
| texFromFboShader.setUniforms(context, texFromFboShaderID); |
| flatShader.setColor (context, flatShaderID, Vec4(0.0f, 1.0f, 0.0f, 1.0f) * fboOutScale + fboOutBias); |
| |
| // Render quads |
| context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); |
| context.viewport(0, 0, initialWidth, initialHeight); |
| clearColorBuffer(context, colorFormat, tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f)); |
| context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| context.bindTexture(GL_TEXTURE_2D, quadsTex); |
| sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| |
| if (fbo.getConfig().colorType == GL_TEXTURE_2D) |
| { |
| // Render fbo to screen |
| context.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| context.viewport(0, 0, context.getWidth(), context.getHeight()); |
| context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer()); |
| sglr::drawQuad(context, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| |
| // Restore binding |
| context.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); |
| } |
| |
| // Resize buffers |
| switch (fbo.getConfig().colorType) |
| { |
| case GL_TEXTURE_2D: |
| context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer()); |
| context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().colorFormat, newWidth, newHeight); |
| break; |
| |
| case GL_RENDERBUFFER: |
| context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getColorBuffer()); |
| context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().colorFormat, newWidth, newHeight); |
| break; |
| |
| default: |
| DE_ASSERT(DE_FALSE); |
| } |
| |
| if (depth || stencil) |
| { |
| switch (fbo.getConfig().depthStencilType) |
| { |
| case GL_TEXTURE_2D: |
| context.bindTexture(GL_TEXTURE_2D, fbo.getDepthStencilBuffer()); |
| context.texImage2D(GL_TEXTURE_2D, 0, fbo.getConfig().depthStencilFormat, newWidth, newHeight); |
| break; |
| |
| case GL_RENDERBUFFER: |
| context.bindRenderbuffer(GL_RENDERBUFFER, fbo.getDepthStencilBuffer()); |
| context.renderbufferStorage(GL_RENDERBUFFER, fbo.getConfig().depthStencilFormat, newWidth, newHeight); |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| } |
| } |
| |
| // Render to resized fbo |
| context.viewport(0, 0, newWidth, newHeight); |
| clearColorBuffer(context, colorFormat, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); |
| context.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| |
| context.enable(GL_DEPTH_TEST); |
| |
| context.bindTexture(GL_TEXTURE_2D, metaballsTex); |
| sglr::drawQuad(context, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); |
| |
| context.bindTexture(GL_TEXTURE_2D, quadsTex); |
| sglr::drawQuad(context, texToFboShaderID, Vec3(0.0f, 0.0f, -1.0f), Vec3(+1.0f, +1.0f, 1.0f)); |
| |
| context.disable(GL_DEPTH_TEST); |
| |
| if (stencil) |
| { |
| context.enable(GL_SCISSOR_TEST); |
| context.clearStencil(1); |
| context.scissor(10, 10, 5, 15); |
| context.clear(GL_STENCIL_BUFFER_BIT); |
| context.disable(GL_SCISSOR_TEST); |
| |
| context.enable(GL_STENCIL_TEST); |
| context.stencilFunc(GL_EQUAL, 1, 0xffu); |
| sglr::drawQuad(context, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(+1.0f, +1.0f, 0.0f)); |
| context.disable(GL_STENCIL_TEST); |
| } |
| |
| if (m_config.colorType == GL_TEXTURE_2D) |
| { |
| context.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| context.viewport(0, 0, context.getWidth(), context.getHeight()); |
| context.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer()); |
| sglr::drawQuad(context, texFromFboShaderID, Vec3(-0.5f, -0.5f, 0.0f), Vec3(0.5f, 0.5f, 0.0f)); |
| context.readPixels(dst, 0, 0, context.getWidth(), context.getHeight()); |
| } |
| else |
| readPixels(context, dst, 0, 0, newWidth, newHeight, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias); |
| } |
| |
| class RecreateBuffersTest : public FboRenderCase |
| { |
| public: |
| RecreateBuffersTest (Context& context, const FboConfig& config, deUint32 buffers, bool rebind); |
| virtual ~RecreateBuffersTest (void) {} |
| |
| void render (sglr::Context& context, Surface& dst); |
| |
| private: |
| deUint32 m_buffers; |
| bool m_rebind; |
| }; |
| |
| RecreateBuffersTest::RecreateBuffersTest (Context& context, const FboConfig& config, deUint32 buffers, bool rebind) |
| : FboRenderCase (context, (string(config.getName()) + (rebind ? "" : "_no_rebind")).c_str(), "Recreate buffers", config) |
| , m_buffers (buffers) |
| , m_rebind (rebind) |
| { |
| } |
| |
| void RecreateBuffersTest::render (sglr::Context& ctx, Surface& dst) |
| { |
| tcu::TextureFormat colorFormat = glu::mapGLInternalFormat(m_config.colorFormat); |
| glu::DataType fboSamplerType = glu::getSampler2DType(colorFormat); |
| glu::DataType fboOutputType = getFragmentOutputType(colorFormat); |
| tcu::TextureFormatInfo fboRangeInfo = tcu::getTextureFormatInfo(colorFormat); |
| Vec4 fboOutScale = fboRangeInfo.valueMax - fboRangeInfo.valueMin; |
| Vec4 fboOutBias = fboRangeInfo.valueMin; |
| |
| Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, fboOutputType); |
| Texture2DShader texFromFboShader (DataTypes() << fboSamplerType, glu::TYPE_FLOAT_VEC4); |
| FlatColorShader flatShader (fboOutputType); |
| deUint32 texToFboShaderID = ctx.createProgram(&texToFboShader); |
| deUint32 texFromFboShaderID = ctx.createProgram(&texFromFboShader); |
| deUint32 flatShaderID = ctx.createProgram(&flatShader); |
| |
| int width = 128; |
| int height = 128; |
| deUint32 metaballsTex = 1; |
| deUint32 quadsTex = 2; |
| bool stencil = (m_config.buffers & GL_STENCIL_BUFFER_BIT) != 0; |
| |
| createQuadsTex2D(ctx, quadsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); |
| createMetaballsTex2D(ctx, metaballsTex, GL_RGB, GL_UNSIGNED_BYTE, 64, 64); |
| |
| Framebuffer fbo(ctx, m_config, width, height); |
| fbo.checkCompleteness(); |
| |
| // Setup shaders |
| texToFboShader.setOutScaleBias(fboOutScale, fboOutBias); |
| texFromFboShader.setTexScaleBias(0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias); |
| texToFboShader.setUniforms (ctx, texToFboShaderID); |
| texFromFboShader.setUniforms(ctx, texFromFboShaderID); |
| flatShader.setColor (ctx, flatShaderID, Vec4(0.0f, 0.0f, 1.0f, 1.0f) * fboOutScale + fboOutBias); |
| |
| // Draw scene |
| ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); |
| ctx.viewport(0, 0, width, height); |
| clearColorBuffer(ctx, colorFormat, tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f)); |
| ctx.clear(GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| |
| ctx.enable(GL_DEPTH_TEST); |
| |
| ctx.bindTexture(GL_TEXTURE_2D, quadsTex); |
| sglr::drawQuad(ctx, texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| |
| ctx.disable(GL_DEPTH_TEST); |
| |
| if (stencil) |
| { |
| ctx.enable(GL_SCISSOR_TEST); |
| ctx.scissor(width/4, height/4, width/2, height/2); |
| ctx.clearStencil(1); |
| ctx.clear(GL_STENCIL_BUFFER_BIT); |
| ctx.disable(GL_SCISSOR_TEST); |
| } |
| |
| // Recreate buffers |
| if (!m_rebind) |
| ctx.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| |
| DE_ASSERT((m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) == 0 || |
| (m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)) == (m_config.buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT))); |
| |
| // Recreate. |
| for (int ndx = 0; ndx < 2; ndx++) |
| { |
| deUint32 bit = ndx == 0 ? GL_COLOR_BUFFER_BIT |
| : (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT); |
| deUint32 type = ndx == 0 ? fbo.getConfig().colorType |
| : fbo.getConfig().depthStencilType; |
| deUint32 format = ndx == 0 ? fbo.getConfig().colorFormat |
| : fbo.getConfig().depthStencilFormat; |
| deUint32 buf = ndx == 0 ? fbo.getColorBuffer() |
| : fbo.getDepthStencilBuffer(); |
| |
| if ((m_buffers & bit) == 0) |
| continue; |
| |
| switch (type) |
| { |
| case GL_TEXTURE_2D: |
| ctx.deleteTextures(1, &buf); |
| ctx.bindTexture(GL_TEXTURE_2D, buf); |
| ctx.texImage2D(GL_TEXTURE_2D, 0, format, width, height); |
| ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| ctx.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| break; |
| |
| case GL_RENDERBUFFER: |
| ctx.deleteRenderbuffers(1, &buf); |
| ctx.bindRenderbuffer(GL_RENDERBUFFER, buf); |
| ctx.renderbufferStorage(GL_RENDERBUFFER, format, width, height); |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| } |
| } |
| |
| // Rebind. |
| if (m_rebind) |
| { |
| for (int ndx = 0; ndx < 3; ndx++) |
| { |
| deUint32 bit = ndx == 0 ? GL_COLOR_BUFFER_BIT : |
| ndx == 1 ? GL_DEPTH_BUFFER_BIT : |
| ndx == 2 ? GL_STENCIL_BUFFER_BIT : 0; |
| deUint32 point = ndx == 0 ? GL_COLOR_ATTACHMENT0 : |
| ndx == 1 ? GL_DEPTH_ATTACHMENT : |
| ndx == 2 ? GL_STENCIL_ATTACHMENT : 0; |
| deUint32 type = ndx == 0 ? fbo.getConfig().colorType |
| : fbo.getConfig().depthStencilType; |
| deUint32 buf = ndx == 0 ? fbo.getColorBuffer() |
| : fbo.getDepthStencilBuffer(); |
| |
| if ((m_buffers & bit) == 0) |
| continue; |
| |
| switch (type) |
| { |
| case GL_TEXTURE_2D: |
| ctx.framebufferTexture2D(GL_FRAMEBUFFER, point, GL_TEXTURE_2D, buf, 0); |
| break; |
| |
| case GL_RENDERBUFFER: |
| ctx.framebufferRenderbuffer(GL_FRAMEBUFFER, point, GL_RENDERBUFFER, buf); |
| break; |
| |
| default: |
| DE_ASSERT(false); |
| } |
| } |
| } |
| |
| if (!m_rebind) |
| ctx.bindFramebuffer(GL_FRAMEBUFFER, fbo.getFramebuffer()); |
| |
| ctx.clearStencil(0); |
| ctx.clear(m_buffers & (GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT)); // \note Clear only buffers that were re-created |
| if (m_buffers & GL_COLOR_BUFFER_BIT) |
| { |
| // Clearing of integer buffers is undefined so do clearing by rendering flat color. |
| sglr::drawQuad(ctx, flatShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| } |
| |
| ctx.enable(GL_DEPTH_TEST); |
| |
| if (stencil) |
| { |
| // \note Stencil test enabled only if we have stencil buffer |
| ctx.enable(GL_STENCIL_TEST); |
| ctx.stencilFunc(GL_EQUAL, 0, 0xffu); |
| } |
| ctx.bindTexture(GL_TEXTURE_2D, metaballsTex); |
| sglr::drawQuad(ctx, texToFboShaderID, Vec3(-1.0f, -1.0f, 1.0f), Vec3(1.0f, 1.0f, -1.0f)); |
| if (stencil) |
| ctx.disable(GL_STENCIL_TEST); |
| |
| ctx.disable(GL_DEPTH_TEST); |
| |
| if (fbo.getConfig().colorType == GL_TEXTURE_2D) |
| { |
| // Unbind fbo |
| ctx.bindFramebuffer(GL_FRAMEBUFFER, 0); |
| |
| // Draw to screen |
| ctx.bindTexture(GL_TEXTURE_2D, fbo.getColorBuffer()); |
| ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight()); |
| sglr::drawQuad(ctx, texFromFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| |
| // Read from screen |
| ctx.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight()); |
| } |
| else |
| { |
| // Read from fbo |
| readPixels(ctx, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias); |
| } |
| } |
| |
| } // FboCases |
| |
| FboRenderTestGroup::FboRenderTestGroup (Context& context) |
| : TestCaseGroup(context, "render", "Rendering Tests") |
| { |
| } |
| |
| FboRenderTestGroup::~FboRenderTestGroup (void) |
| { |
| } |
| |
| void FboRenderTestGroup::init (void) |
| { |
| static const deUint32 objectTypes[] = |
| { |
| GL_TEXTURE_2D, |
| GL_RENDERBUFFER |
| }; |
| |
| enum FormatType |
| { |
| FORMATTYPE_FLOAT = 0, |
| FORMATTYPE_FIXED, |
| FORMATTYPE_INT, |
| FORMATTYPE_UINT, |
| |
| FORMATTYPE_LAST |
| }; |
| |
| // Required by specification. |
| static const struct |
| { |
| deUint32 format; |
| FormatType type; |
| } colorFormats[] = |
| { |
| { GL_RGBA32F, FORMATTYPE_FLOAT }, |
| { GL_RGBA32I, FORMATTYPE_INT }, |
| { GL_RGBA32UI, FORMATTYPE_UINT }, |
| { GL_RGBA16F, FORMATTYPE_FLOAT }, |
| { GL_RGBA16I, FORMATTYPE_INT }, |
| { GL_RGBA16UI, FORMATTYPE_UINT }, |
| { GL_RGB16F, FORMATTYPE_FLOAT }, |
| { GL_RGBA8, FORMATTYPE_FIXED }, |
| { GL_RGBA8I, FORMATTYPE_INT }, |
| { GL_RGBA8UI, FORMATTYPE_UINT }, |
| { GL_SRGB8_ALPHA8, FORMATTYPE_FIXED }, |
| { GL_RGB10_A2, FORMATTYPE_FIXED }, |
| { GL_RGB10_A2UI, FORMATTYPE_UINT }, |
| { GL_RGBA4, FORMATTYPE_FIXED }, |
| { GL_RGB5_A1, FORMATTYPE_FIXED }, |
| { GL_RGB8, FORMATTYPE_FIXED }, |
| { GL_RGB565, FORMATTYPE_FIXED }, |
| { GL_R11F_G11F_B10F, FORMATTYPE_FLOAT }, |
| { GL_RG32F, FORMATTYPE_FLOAT }, |
| { GL_RG32I, FORMATTYPE_INT }, |
| { GL_RG32UI, FORMATTYPE_UINT }, |
| { GL_RG16F, FORMATTYPE_FLOAT }, |
| { GL_RG16I, FORMATTYPE_INT }, |
| { GL_RG16UI, FORMATTYPE_UINT }, |
| { GL_RG8, FORMATTYPE_FLOAT }, |
| { GL_RG8I, FORMATTYPE_INT }, |
| { GL_RG8UI, FORMATTYPE_UINT }, |
| { GL_R32F, FORMATTYPE_FLOAT }, |
| { GL_R32I, FORMATTYPE_INT }, |
| { GL_R32UI, FORMATTYPE_UINT }, |
| { GL_R16F, FORMATTYPE_FLOAT }, |
| { GL_R16I, FORMATTYPE_INT }, |
| { GL_R16UI, FORMATTYPE_UINT }, |
| { GL_R8, FORMATTYPE_FLOAT }, |
| { GL_R8I, FORMATTYPE_INT }, |
| { GL_R8UI, FORMATTYPE_UINT } |
| }; |
| |
| static const struct |
| { |
| deUint32 format; |
| bool depth; |
| bool stencil; |
| } depthStencilFormats[] = |
| { |
| { GL_DEPTH_COMPONENT32F, true, false }, |
| { GL_DEPTH_COMPONENT24, true, false }, |
| { GL_DEPTH_COMPONENT16, true, false }, |
| { GL_DEPTH32F_STENCIL8, true, true }, |
| { GL_DEPTH24_STENCIL8, true, true }, |
| { GL_STENCIL_INDEX8, false, true } |
| }; |
| |
| using namespace FboCases; |
| |
| // .stencil_clear |
| tcu::TestCaseGroup* stencilClearGroup = new tcu::TestCaseGroup(m_testCtx, "stencil_clear", "Stencil buffer clears"); |
| addChild(stencilClearGroup); |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++) |
| { |
| deUint32 colorType = GL_TEXTURE_2D; |
| deUint32 stencilType = GL_RENDERBUFFER; |
| deUint32 colorFmt = GL_RGBA8; |
| |
| if (!depthStencilFormats[fmtNdx].stencil) |
| continue; |
| |
| FboConfig config(GL_COLOR_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, colorType, colorFmt, stencilType, depthStencilFormats[fmtNdx].format); |
| stencilClearGroup->addChild(new StencilClearsTest(m_context, config)); |
| } |
| |
| // .shared_colorbuffer_clear |
| tcu::TestCaseGroup* sharedColorbufferClearGroup = new tcu::TestCaseGroup(m_testCtx, "shared_colorbuffer_clear", "Shader colorbuffer clears"); |
| addChild(sharedColorbufferClearGroup); |
| for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++) |
| { |
| // Clearing of integer buffers is undefined. |
| if (colorFormats[colorFmtNdx].type == FORMATTYPE_INT || colorFormats[colorFmtNdx].type == FORMATTYPE_UINT) |
| continue; |
| |
| for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++) |
| { |
| FboConfig config(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, GL_NONE, GL_NONE); |
| sharedColorbufferClearGroup->addChild(new SharedColorbufferClearsTest(m_context, config)); |
| } |
| } |
| |
| // .shared_colorbuffer |
| tcu::TestCaseGroup* sharedColorbufferGroup = new tcu::TestCaseGroup(m_testCtx, "shared_colorbuffer", "Shared colorbuffer tests"); |
| addChild(sharedColorbufferGroup); |
| for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++) |
| { |
| deUint32 depthStencilType = GL_RENDERBUFFER; |
| deUint32 depthStencilFormat = GL_DEPTH24_STENCIL8; |
| |
| // Blending with integer buffers and fp32 targets is not supported. |
| if (colorFormats[colorFmtNdx].type == FORMATTYPE_INT || |
| colorFormats[colorFmtNdx].type == FORMATTYPE_UINT || |
| colorFormats[colorFmtNdx].format == GL_RGBA32F || |
| colorFormats[colorFmtNdx].format == GL_RGB32F || |
| colorFormats[colorFmtNdx].format == GL_RG32F || |
| colorFormats[colorFmtNdx].format == GL_R32F) |
| continue; |
| |
| for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++) |
| { |
| FboConfig colorOnlyConfig (GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, GL_NONE, GL_NONE); |
| FboConfig colorDepthConfig (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat); |
| FboConfig colorDepthStencilConfig (GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat); |
| |
| sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorOnlyConfig)); |
| sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorDepthConfig)); |
| sharedColorbufferGroup->addChild(new SharedColorbufferTest(m_context, colorDepthStencilConfig)); |
| } |
| } |
| |
| // .shared_depth_stencil |
| tcu::TestCaseGroup* sharedDepthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "shared_depth_stencil", "Shared depth and stencil buffers"); |
| addChild(sharedDepthStencilGroup); |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++) |
| { |
| deUint32 colorType = GL_TEXTURE_2D; |
| deUint32 colorFmt = GL_RGBA8; |
| bool depth = depthStencilFormats[fmtNdx].depth; |
| bool stencil = depthStencilFormats[fmtNdx].stencil; |
| |
| if (!depth) |
| continue; // Not verified. |
| |
| // Depth and stencil: both rbo and textures |
| for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++) |
| { |
| FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format); |
| sharedDepthStencilGroup->addChild(new SharedDepthStencilTest(m_context, config)); |
| } |
| } |
| |
| // .resize |
| tcu::TestCaseGroup* resizeGroup = new tcu::TestCaseGroup(m_testCtx, "resize", "FBO resize tests"); |
| addChild(resizeGroup); |
| for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++) |
| { |
| deUint32 colorFormat = colorFormats[colorFmtNdx].format; |
| |
| // Color-only. |
| for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++) |
| { |
| FboConfig config(GL_COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormat, GL_NONE, GL_NONE); |
| resizeGroup->addChild(new ResizeTest(m_context, config)); |
| } |
| |
| // For selected color formats tests depth & stencil variants. |
| if (colorFormat == GL_RGBA8 || colorFormat == GL_RGBA16F) |
| { |
| for (int depthStencilFmtNdx = 0; depthStencilFmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); depthStencilFmtNdx++) |
| { |
| deUint32 colorType = GL_TEXTURE_2D; |
| bool depth = depthStencilFormats[depthStencilFmtNdx].depth; |
| bool stencil = depthStencilFormats[depthStencilFmtNdx].stencil; |
| |
| // Depth and stencil: both rbo and textures |
| for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++) |
| { |
| if (!depth && objectTypes[typeNdx] != GL_RENDERBUFFER) |
| continue; // Not supported. |
| |
| FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), |
| colorType, colorFormat, |
| objectTypes[typeNdx], depthStencilFormats[depthStencilFmtNdx].format); |
| resizeGroup->addChild(new ResizeTest(m_context, config)); |
| } |
| } |
| } |
| } |
| |
| // .recreate_color |
| tcu::TestCaseGroup* recreateColorGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_color", "Recreate colorbuffer tests"); |
| addChild(recreateColorGroup); |
| for (int colorFmtNdx = 0; colorFmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); colorFmtNdx++) |
| { |
| deUint32 colorFormat = colorFormats[colorFmtNdx].format; |
| deUint32 depthStencilFormat = GL_DEPTH24_STENCIL8; |
| deUint32 depthStencilType = GL_RENDERBUFFER; |
| |
| // Color-only. |
| for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++) |
| { |
| FboConfig config(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT, objectTypes[typeNdx], colorFormat, depthStencilType, depthStencilFormat); |
| recreateColorGroup->addChild(new RecreateBuffersTest(m_context, config, GL_COLOR_BUFFER_BIT, true /* rebind */)); |
| } |
| } |
| |
| // .recreate_depth_stencil |
| tcu::TestCaseGroup* recreateDepthStencilGroup = new tcu::TestCaseGroup(m_testCtx, "recreate_depth_stencil", "Recreate depth and stencil buffers"); |
| addChild(recreateDepthStencilGroup); |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(depthStencilFormats); fmtNdx++) |
| { |
| deUint32 colorType = GL_TEXTURE_2D; |
| deUint32 colorFmt = GL_RGBA8; |
| bool depth = depthStencilFormats[fmtNdx].depth; |
| bool stencil = depthStencilFormats[fmtNdx].stencil; |
| |
| // Depth and stencil: both rbo and textures |
| for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(objectTypes); typeNdx++) |
| { |
| if (!depth && objectTypes[typeNdx] != GL_RENDERBUFFER) |
| continue; |
| |
| FboConfig config(GL_COLOR_BUFFER_BIT|(depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format); |
| recreateDepthStencilGroup->addChild(new RecreateBuffersTest(m_context, config, (depth ? GL_DEPTH_BUFFER_BIT : 0)|(stencil ? GL_STENCIL_BUFFER_BIT : 0), true /* rebind */)); |
| } |
| } |
| } |
| |
| } // Functional |
| } // gles3 |
| } // deqp |