| /*------------------------------------------------------------------------- |
| * 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 colorbuffer tests. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "es3fFboColorbufferTests.hpp" |
| #include "es3fFboTestCase.hpp" |
| #include "es3fFboTestUtil.hpp" |
| #include "gluTextureUtil.hpp" |
| #include "gluContextInfo.hpp" |
| #include "tcuImageCompare.hpp" |
| #include "tcuRGBA.hpp" |
| #include "tcuTestLog.hpp" |
| #include "tcuTextureUtil.hpp" |
| #include "sglrContextUtil.hpp" |
| #include "deRandom.hpp" |
| #include "deString.h" |
| #include "glwEnums.hpp" |
| |
| namespace deqp |
| { |
| namespace gles3 |
| { |
| namespace Functional |
| { |
| |
| using std::string; |
| using tcu::Vec2; |
| using tcu::Vec3; |
| using tcu::Vec4; |
| using tcu::IVec2; |
| using tcu::IVec3; |
| using tcu::IVec4; |
| using tcu::UVec4; |
| using tcu::TestLog; |
| using namespace FboTestUtil; |
| |
| const tcu::RGBA MIN_THRESHOLD(12, 12, 12, 12); |
| |
| template <int Size> |
| static tcu::Vector<float, Size> randomVector (de::Random& rnd, const tcu::Vector<float, Size>& minVal = tcu::Vector<float, Size>(0.0f), const tcu::Vector<float, Size>& maxVal = tcu::Vector<float, Size>(1.0f)) |
| { |
| tcu::Vector<float, Size> res; |
| for (int ndx = 0; ndx < Size; ndx++) |
| res[ndx] = rnd.getFloat(minVal[ndx], maxVal[ndx]); |
| return res; |
| } |
| |
| static tcu::Vec4 generateRandomColor (de::Random& random) |
| { |
| tcu::Vec4 retVal; |
| |
| for (int i = 0; i < 3; ++i) |
| retVal[i] = random.getFloat(); |
| retVal[3] = 1.0f; |
| |
| return retVal; |
| } |
| |
| class FboColorbufferCase : public FboTestCase |
| { |
| public: |
| FboColorbufferCase (Context& context, const char* name, const char* desc, const deUint32 format) |
| : FboTestCase (context, name, desc) |
| , m_format (format) |
| { |
| } |
| |
| bool compare (const tcu::Surface& reference, const tcu::Surface& result) |
| { |
| const tcu::RGBA threshold (tcu::max(getFormatThreshold(m_format), MIN_THRESHOLD)); |
| |
| m_testCtx.getLog() << TestLog::Message << "Comparing images, threshold: " << threshold << TestLog::EndMessage; |
| |
| return tcu::bilinearCompare(m_testCtx.getLog(), "Result", "Image comparison result", reference.getAccess(), result.getAccess(), threshold, tcu::COMPARE_LOG_RESULT); |
| } |
| |
| protected: |
| const deUint32 m_format; |
| }; |
| |
| class FboColorClearCase : public FboColorbufferCase |
| { |
| public: |
| FboColorClearCase (Context& context, const char* name, const char* desc, deUint32 format, int width, int height) |
| : FboColorbufferCase (context, name, desc, format) |
| , m_width (width) |
| , m_height (height) |
| { |
| } |
| |
| protected: |
| void preCheck (void) |
| { |
| checkFormatSupport(m_format); |
| } |
| |
| void render (tcu::Surface& dst) |
| { |
| tcu::TextureFormat fboFormat = glu::mapGLInternalFormat(m_format); |
| tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(fboFormat.type); |
| tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat); |
| de::Random rnd (17); |
| const int numClears = 16; |
| deUint32 fbo = 0; |
| deUint32 rbo = 0; |
| |
| glGenFramebuffers(1, &fbo); |
| glGenRenderbuffers(1, &rbo); |
| |
| glBindRenderbuffer(GL_RENDERBUFFER, rbo); |
| glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_width, m_height); |
| checkError(); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); |
| checkError(); |
| checkFramebufferStatus(GL_FRAMEBUFFER); |
| |
| glViewport(0, 0, m_width, m_height); |
| |
| // Initialize to transparent black. |
| switch (fmtClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| glClearBufferfv(GL_COLOR, 0, Vec4(0.0f).getPtr()); |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| glClearBufferuiv(GL_COLOR, 0, UVec4(0).getPtr()); |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| glClearBufferiv(GL_COLOR, 0, IVec4(0).getPtr()); |
| break; |
| |
| default: |
| DE_ASSERT(DE_FALSE); |
| } |
| |
| // Do random scissored clears. |
| glEnable(GL_SCISSOR_TEST); |
| for (int ndx = 0; ndx < numClears; ndx++) |
| { |
| int x = rnd.getInt(0, m_width - 1); |
| int y = rnd.getInt(0, m_height - 1); |
| int w = rnd.getInt(1, m_width - x); |
| int h = rnd.getInt(1, m_height - y); |
| Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax); |
| |
| glScissor(x, y, w, h); |
| |
| switch (fmtClass) |
| { |
| case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: |
| case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: |
| glClearBufferfv(GL_COLOR, 0, color.getPtr()); |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: |
| glClearBufferuiv(GL_COLOR, 0, color.cast<deUint32>().getPtr()); |
| break; |
| |
| case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: |
| glClearBufferiv(GL_COLOR, 0, color.cast<int>().getPtr()); |
| break; |
| |
| default: |
| DE_ASSERT(DE_FALSE); |
| } |
| } |
| |
| // Read results from renderbuffer. |
| readPixels(dst, 0, 0, m_width, m_height, fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias); |
| checkError(); |
| } |
| |
| private: |
| const int m_width; |
| const int m_height; |
| }; |
| |
| class FboColorMultiTex2DCase : public FboColorbufferCase |
| { |
| public: |
| FboColorMultiTex2DCase (Context& context, const char* name, const char* description, deUint32 tex0Fmt, const IVec2& tex0Size, deUint32 tex1Fmt, const IVec2& tex1Size) |
| : FboColorbufferCase (context, name, description, tex0Fmt) |
| , m_tex0Fmt (tex0Fmt) |
| , m_tex1Fmt (tex1Fmt) |
| , m_tex0Size (tex0Size) |
| , m_tex1Size (tex1Size) |
| { |
| } |
| |
| protected: |
| void preCheck (void) |
| { |
| checkFormatSupport(m_tex0Fmt); |
| checkFormatSupport(m_tex1Fmt); |
| } |
| |
| void render (tcu::Surface& dst) |
| { |
| tcu::TextureFormat texFmt0 = glu::mapGLInternalFormat(m_tex0Fmt); |
| tcu::TextureFormat texFmt1 = glu::mapGLInternalFormat(m_tex1Fmt); |
| tcu::TextureFormatInfo fmtInfo0 = tcu::getTextureFormatInfo(texFmt0); |
| tcu::TextureFormatInfo fmtInfo1 = tcu::getTextureFormatInfo(texFmt1); |
| |
| Texture2DShader texToFbo0Shader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt0), fmtInfo0.valueMax-fmtInfo0.valueMin, fmtInfo0.valueMin); |
| Texture2DShader texToFbo1Shader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt1), fmtInfo1.valueMax-fmtInfo1.valueMin, fmtInfo1.valueMin); |
| Texture2DShader multiTexShader (DataTypes() << glu::getSampler2DType(texFmt0) << glu::getSampler2DType(texFmt1), glu::TYPE_FLOAT_VEC4); |
| |
| deUint32 texToFbo0ShaderID = getCurrentContext()->createProgram(&texToFbo0Shader); |
| deUint32 texToFbo1ShaderID = getCurrentContext()->createProgram(&texToFbo1Shader); |
| deUint32 multiTexShaderID = getCurrentContext()->createProgram(&multiTexShader); |
| |
| // Setup shaders |
| multiTexShader.setTexScaleBias(0, fmtInfo0.lookupScale * 0.5f, fmtInfo0.lookupBias * 0.5f); |
| multiTexShader.setTexScaleBias(1, fmtInfo1.lookupScale * 0.5f, fmtInfo1.lookupBias * 0.5f); |
| texToFbo0Shader.setUniforms(*getCurrentContext(), texToFbo0ShaderID); |
| texToFbo1Shader.setUniforms(*getCurrentContext(), texToFbo1ShaderID); |
| multiTexShader.setUniforms (*getCurrentContext(), multiTexShaderID); |
| |
| // Framebuffers. |
| deUint32 fbo0, fbo1; |
| deUint32 tex0, tex1; |
| |
| for (int ndx = 0; ndx < 2; ndx++) |
| { |
| glu::TransferFormat transferFmt = glu::getTransferFormat(ndx ? texFmt1 : texFmt0); |
| deUint32 format = ndx ? m_tex1Fmt : m_tex0Fmt; |
| bool isFilterable = glu::isGLInternalColorFormatFilterable(format); |
| const IVec2& size = ndx ? m_tex1Size : m_tex0Size; |
| deUint32& fbo = ndx ? fbo1 : fbo0; |
| deUint32& tex = ndx ? tex1 : tex0; |
| |
| glGenFramebuffers(1, &fbo); |
| glGenTextures(1, &tex); |
| |
| glBindTexture(GL_TEXTURE_2D, tex); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST); |
| glTexImage2D(GL_TEXTURE_2D, 0, format, size.x(), size.y(), 0, transferFmt.format, transferFmt.dataType, DE_NULL); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0); |
| checkError(); |
| checkFramebufferStatus(GL_FRAMEBUFFER); |
| } |
| |
| // Render textures to both framebuffers. |
| for (int ndx = 0; ndx < 2; ndx++) |
| { |
| const deUint32 format = GL_RGBA; |
| const deUint32 dataType = GL_UNSIGNED_BYTE; |
| const int texW = 128; |
| const int texH = 128; |
| deUint32 tmpTex = 0; |
| deUint32 fbo = ndx ? fbo1 : fbo0; |
| const IVec2& viewport = ndx ? m_tex1Size : m_tex0Size; |
| tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1); |
| |
| if (ndx == 0) |
| tcu::fillWithComponentGradients(data.getAccess(), Vec4(0.0f), Vec4(1.0f)); |
| else |
| tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f)); |
| |
| glGenTextures(1, &tmpTex); |
| glBindTexture(GL_TEXTURE_2D, tmpTex); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr()); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| glViewport(0, 0, viewport.x(), viewport.y()); |
| sglr::drawQuad(*getCurrentContext(), ndx ? texToFbo1ShaderID : texToFbo0ShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| } |
| |
| // Render to framebuffer. |
| glBindFramebuffer(GL_FRAMEBUFFER, 0); |
| glViewport(0, 0, getWidth(), getHeight()); |
| glActiveTexture(GL_TEXTURE0); |
| glBindTexture(GL_TEXTURE_2D, tex0); |
| glActiveTexture(GL_TEXTURE1); |
| glBindTexture(GL_TEXTURE_2D, tex1); |
| sglr::drawQuad(*getCurrentContext(), multiTexShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| |
| readPixels(dst, 0, 0, getWidth(), getHeight()); |
| } |
| |
| private: |
| deUint32 m_tex0Fmt; |
| deUint32 m_tex1Fmt; |
| IVec2 m_tex0Size; |
| IVec2 m_tex1Size; |
| }; |
| |
| class FboColorTexCubeCase : public FboColorbufferCase |
| { |
| public: |
| FboColorTexCubeCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec2& texSize) |
| : FboColorbufferCase (context, name, description, texFmt) |
| , m_texSize (texSize) |
| { |
| } |
| |
| protected: |
| void preCheck (void) |
| { |
| checkFormatSupport(m_format); |
| } |
| |
| void render (tcu::Surface& dst) |
| { |
| static const deUint32 cubeGLFaces[] = |
| { |
| GL_TEXTURE_CUBE_MAP_POSITIVE_X, |
| GL_TEXTURE_CUBE_MAP_POSITIVE_Y, |
| GL_TEXTURE_CUBE_MAP_POSITIVE_Z, |
| GL_TEXTURE_CUBE_MAP_NEGATIVE_X, |
| GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, |
| GL_TEXTURE_CUBE_MAP_NEGATIVE_Z |
| }; |
| |
| static const tcu::CubeFace cubeTexFaces[] = |
| { |
| tcu::CUBEFACE_POSITIVE_X, |
| tcu::CUBEFACE_POSITIVE_Y, |
| tcu::CUBEFACE_POSITIVE_Z, |
| tcu::CUBEFACE_NEGATIVE_X, |
| tcu::CUBEFACE_NEGATIVE_Y, |
| tcu::CUBEFACE_NEGATIVE_Z |
| }; |
| |
| de::Random rnd (deStringHash(getName()) ^ 0x9eef603d); |
| tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_format); |
| tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); |
| |
| Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin); |
| TextureCubeShader cubeTexShader (glu::getSamplerCubeType(texFmt), glu::TYPE_FLOAT_VEC4); |
| |
| deUint32 texToFboShaderID = getCurrentContext()->createProgram(&texToFboShader); |
| deUint32 cubeTexShaderID = getCurrentContext()->createProgram(&cubeTexShader); |
| |
| // Setup shaders |
| texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID); |
| cubeTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias); |
| |
| // Framebuffers. |
| std::vector<deUint32> fbos; |
| deUint32 tex; |
| |
| { |
| glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt); |
| bool isFilterable = glu::isGLInternalColorFormatFilterable(m_format); |
| const IVec2& size = m_texSize; |
| |
| |
| glGenTextures(1, &tex); |
| |
| glBindTexture(GL_TEXTURE_CUBE_MAP, tex); |
| glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST); |
| |
| // Generate an image and FBO for each cube face |
| for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeGLFaces); ndx++) |
| glTexImage2D(cubeGLFaces[ndx], 0, m_format, size.x(), size.y(), 0, transferFmt.format, transferFmt.dataType, DE_NULL); |
| checkError(); |
| |
| for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(cubeGLFaces); ndx++) |
| { |
| deUint32 layerFbo; |
| |
| glGenFramebuffers(1, &layerFbo); |
| glBindFramebuffer(GL_FRAMEBUFFER, layerFbo); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, cubeGLFaces[ndx], tex, 0); |
| checkError(); |
| checkFramebufferStatus(GL_FRAMEBUFFER); |
| |
| fbos.push_back(layerFbo); |
| } |
| } |
| |
| // Render test images to random cube faces |
| std::vector<int> order; |
| |
| for (size_t n = 0; n < fbos.size(); n++) |
| order.push_back((int)n); |
| rnd.shuffle(order.begin(), order.end()); |
| |
| DE_ASSERT(order.size() >= 4); |
| for (int ndx = 0; ndx < 4; ndx++) |
| { |
| const int face = order[ndx]; |
| const deUint32 format = GL_RGBA; |
| const deUint32 dataType = GL_UNSIGNED_BYTE; |
| const int texW = 128; |
| const int texH = 128; |
| deUint32 tmpTex = 0; |
| const deUint32 fbo = fbos[face]; |
| const IVec2& viewport = m_texSize; |
| tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1); |
| |
| tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f)); |
| |
| glGenTextures(1, &tmpTex); |
| glBindTexture(GL_TEXTURE_2D, tmpTex); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr()); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| glViewport(0, 0, viewport.x(), viewport.y()); |
| sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| checkError(); |
| |
| // Render to framebuffer |
| { |
| const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f); |
| const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, 0); |
| glViewport(0, 0, getWidth(), getHeight()); |
| |
| glActiveTexture(GL_TEXTURE0); |
| glBindTexture(GL_TEXTURE_CUBE_MAP, tex); |
| |
| cubeTexShader.setFace(cubeTexFaces[face]); |
| cubeTexShader.setUniforms(*getCurrentContext(), cubeTexShaderID); |
| |
| sglr::drawQuad(*getCurrentContext(), cubeTexShaderID, p0, p1); |
| checkError(); |
| } |
| } |
| |
| readPixels(dst, 0, 0, getWidth(), getHeight()); |
| } |
| |
| private: |
| IVec2 m_texSize; |
| }; |
| |
| class FboColorTex2DArrayCase : public FboColorbufferCase |
| { |
| public: |
| FboColorTex2DArrayCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize) |
| : FboColorbufferCase (context, name, description, texFmt) |
| , m_texSize (texSize) |
| { |
| } |
| |
| protected: |
| void preCheck (void) |
| { |
| checkFormatSupport(m_format); |
| } |
| |
| void render (tcu::Surface& dst) |
| { |
| de::Random rnd (deStringHash(getName()) ^ 0xed607a89); |
| tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_format); |
| tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); |
| |
| Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin); |
| Texture2DArrayShader arrayTexShader (glu::getSampler2DArrayType(texFmt), glu::TYPE_FLOAT_VEC4); |
| |
| deUint32 texToFboShaderID = getCurrentContext()->createProgram(&texToFboShader); |
| deUint32 arrayTexShaderID = getCurrentContext()->createProgram(&arrayTexShader); |
| |
| // Setup textures |
| texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID); |
| arrayTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias); |
| |
| // Framebuffers. |
| std::vector<deUint32> fbos; |
| deUint32 tex; |
| |
| { |
| glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt); |
| bool isFilterable = glu::isGLInternalColorFormatFilterable(m_format); |
| const IVec3& size = m_texSize; |
| |
| |
| glGenTextures(1, &tex); |
| |
| glBindTexture(GL_TEXTURE_2D_ARRAY, tex); |
| glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, isFilterable ? GL_LINEAR : GL_NEAREST); |
| glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL); |
| |
| // Generate an FBO for each layer |
| for (int ndx = 0; ndx < m_texSize.z(); ndx++) |
| { |
| deUint32 layerFbo; |
| |
| glGenFramebuffers(1, &layerFbo); |
| glBindFramebuffer(GL_FRAMEBUFFER, layerFbo); |
| glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx); |
| checkError(); |
| checkFramebufferStatus(GL_FRAMEBUFFER); |
| |
| fbos.push_back(layerFbo); |
| } |
| } |
| |
| // Render test images to random texture layers |
| std::vector<int> order; |
| |
| for (size_t n = 0; n < fbos.size(); n++) |
| order.push_back((int)n); |
| rnd.shuffle(order.begin(), order.end()); |
| |
| for (size_t ndx = 0; ndx < order.size(); ndx++) |
| { |
| const int layer = order[ndx]; |
| const deUint32 format = GL_RGBA; |
| const deUint32 dataType = GL_UNSIGNED_BYTE; |
| const int texW = 128; |
| const int texH = 128; |
| deUint32 tmpTex = 0; |
| const deUint32 fbo = fbos[layer]; |
| const IVec3& viewport = m_texSize; |
| tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1); |
| |
| tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f)); |
| |
| glGenTextures(1, &tmpTex); |
| glBindTexture(GL_TEXTURE_2D, tmpTex); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr()); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| glViewport(0, 0, viewport.x(), viewport.y()); |
| sglr::drawQuad(*getCurrentContext(), texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| checkError(); |
| |
| // Render to framebuffer |
| { |
| const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f); |
| const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, 0); |
| glViewport(0, 0, getWidth(), getHeight()); |
| |
| glActiveTexture(GL_TEXTURE0); |
| glBindTexture(GL_TEXTURE_2D_ARRAY, tex); |
| |
| arrayTexShader.setLayer(layer); |
| arrayTexShader.setUniforms(*getCurrentContext(), arrayTexShaderID); |
| |
| sglr::drawQuad(*getCurrentContext(), arrayTexShaderID, p0, p1); |
| checkError(); |
| } |
| } |
| |
| readPixels(dst, 0, 0, getWidth(), getHeight()); |
| } |
| |
| private: |
| IVec3 m_texSize; |
| }; |
| |
| class FboColorTex3DCase : public FboColorbufferCase |
| { |
| public: |
| FboColorTex3DCase (Context& context, const char* name, const char* description, deUint32 texFmt, const IVec3& texSize) |
| : FboColorbufferCase (context, name, description, texFmt) |
| , m_texSize (texSize) |
| { |
| } |
| |
| protected: |
| void preCheck (void) |
| { |
| checkFormatSupport(m_format); |
| } |
| |
| void render (tcu::Surface& dst) |
| { |
| de::Random rnd (deStringHash(getName()) ^ 0x74d947b2); |
| tcu::TextureFormat texFmt = glu::mapGLInternalFormat(m_format); |
| tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(texFmt); |
| |
| Texture2DShader texToFboShader (DataTypes() << glu::TYPE_SAMPLER_2D, getFragmentOutputType(texFmt), fmtInfo.valueMax-fmtInfo.valueMin, fmtInfo.valueMin); |
| Texture3DShader tdTexShader (glu::getSampler3DType(texFmt), glu::TYPE_FLOAT_VEC4); |
| |
| deUint32 texToFboShaderID= getCurrentContext()->createProgram(&texToFboShader); |
| deUint32 tdTexShaderID = getCurrentContext()->createProgram(&tdTexShader); |
| |
| // Setup shaders |
| texToFboShader.setUniforms(*getCurrentContext(), texToFboShaderID); |
| tdTexShader.setTexScaleBias(fmtInfo.lookupScale, fmtInfo.lookupBias); |
| |
| // Framebuffers. |
| std::vector<deUint32> fbos; |
| deUint32 tex; |
| |
| { |
| glu::TransferFormat transferFmt = glu::getTransferFormat(texFmt); |
| const IVec3& size = m_texSize; |
| |
| glGenTextures(1, &tex); |
| |
| glBindTexture(GL_TEXTURE_3D, tex); |
| glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| glTexImage3D(GL_TEXTURE_3D, 0, m_format, size.x(), size.y(), size.z(), 0, transferFmt.format, transferFmt.dataType, DE_NULL); |
| |
| // Generate an FBO for each layer |
| for (int ndx = 0; ndx < m_texSize.z(); ndx++) |
| { |
| deUint32 layerFbo; |
| |
| glGenFramebuffers(1, &layerFbo); |
| glBindFramebuffer(GL_FRAMEBUFFER, layerFbo); |
| glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, tex, 0, ndx); |
| checkError(); |
| checkFramebufferStatus(GL_FRAMEBUFFER); |
| |
| fbos.push_back(layerFbo); |
| } |
| } |
| |
| // Render test images to random texture layers |
| std::vector<int> order; |
| |
| for (size_t n = 0; n < fbos.size(); n++) |
| order.push_back((int)n); |
| rnd.shuffle(order.begin(), order.end()); |
| |
| for (size_t ndx = 0; ndx < order.size(); ndx++) |
| { |
| const int layer = order[ndx]; |
| const deUint32 format = GL_RGBA; |
| const deUint32 dataType = GL_UNSIGNED_BYTE; |
| const int texW = 128; |
| const int texH = 128; |
| deUint32 tmpTex = 0; |
| const deUint32 fbo = fbos[layer]; |
| const IVec3& viewport = m_texSize; |
| tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1); |
| |
| tcu::fillWithGrid(data.getAccess(), 8, generateRandomColor(rnd), Vec4(0.0f)); |
| |
| glGenTextures(1, &tmpTex); |
| glBindTexture(GL_TEXTURE_2D, tmpTex); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr()); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| glViewport(0, 0, viewport.x(), viewport.y()); |
| sglr::drawQuad(*getCurrentContext() , texToFboShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| checkError(); |
| |
| // Render to framebuffer |
| { |
| const Vec3 p0 = Vec3(float(ndx % 2) - 1.0f, float(ndx / 2) - 1.0f, 0.0f); |
| const Vec3 p1 = p0 + Vec3(1.0f, 1.0f, 0.0f); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, 0); |
| glViewport(0, 0, getWidth(), getHeight()); |
| |
| glActiveTexture(GL_TEXTURE0); |
| glBindTexture(GL_TEXTURE_3D, tex); |
| |
| tdTexShader.setDepth(float(layer) / float(m_texSize.z()-1)); |
| tdTexShader.setUniforms(*getCurrentContext(), tdTexShaderID); |
| |
| sglr::drawQuad(*getCurrentContext(), tdTexShaderID, p0, p1); |
| checkError(); |
| } |
| } |
| |
| readPixels(dst, 0, 0, getWidth(), getHeight()); |
| } |
| |
| private: |
| IVec3 m_texSize; |
| }; |
| |
| class FboBlendCase : public FboColorbufferCase |
| { |
| public: |
| FboBlendCase (Context& context, const char* name, const char* desc, deUint32 format, IVec2 size, deUint32 funcRGB, deUint32 funcAlpha, deUint32 srcRGB, deUint32 dstRGB, deUint32 srcAlpha, deUint32 dstAlpha) |
| : FboColorbufferCase (context, name, desc, format) |
| , m_size (size) |
| , m_funcRGB (funcRGB) |
| , m_funcAlpha (funcAlpha) |
| , m_srcRGB (srcRGB) |
| , m_dstRGB (dstRGB) |
| , m_srcAlpha (srcAlpha) |
| , m_dstAlpha (dstAlpha) |
| { |
| } |
| |
| protected: |
| void preCheck (void) |
| { |
| checkFormatSupport(m_format); |
| } |
| |
| void render (tcu::Surface& dst) |
| { |
| // \note Assumes floating-point or fixed-point format. |
| tcu::TextureFormat fboFmt = glu::mapGLInternalFormat(m_format); |
| Texture2DShader texShader (DataTypes() << glu::TYPE_SAMPLER_2D, glu::TYPE_FLOAT_VEC4); |
| GradientShader gradShader (glu::TYPE_FLOAT_VEC4); |
| deUint32 texShaderID = getCurrentContext()->createProgram(&texShader); |
| deUint32 gradShaderID = getCurrentContext()->createProgram(&gradShader); |
| deUint32 fbo = 0; |
| deUint32 rbo = 0; |
| |
| // Setup shaders |
| texShader.setUniforms (*getCurrentContext(), texShaderID); |
| gradShader.setGradient(*getCurrentContext(), gradShaderID, tcu::Vec4(0.0f), tcu::Vec4(1.0f)); |
| |
| glGenFramebuffers(1, &fbo); |
| glGenRenderbuffers(1, &rbo); |
| |
| glBindRenderbuffer(GL_RENDERBUFFER, rbo); |
| glRenderbufferStorage(GL_RENDERBUFFER, m_format, m_size.x(), m_size.y()); |
| checkError(); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbo); |
| checkError(); |
| checkFramebufferStatus(GL_FRAMEBUFFER); |
| |
| glViewport(0, 0, m_size.x(), m_size.y()); |
| |
| // Fill framebuffer with grid pattern. |
| { |
| const deUint32 format = GL_RGBA; |
| const deUint32 dataType = GL_UNSIGNED_BYTE; |
| const int texW = 128; |
| const int texH = 128; |
| deUint32 gridTex = 0; |
| tcu::TextureLevel data (glu::mapGLTransferFormat(format, dataType), texW, texH, 1); |
| |
| tcu::fillWithGrid(data.getAccess(), 8, Vec4(0.2f, 0.7f, 0.1f, 1.0f), Vec4(0.7f, 0.1f, 0.5f, 0.8f)); |
| |
| glGenTextures(1, &gridTex); |
| glBindTexture(GL_TEXTURE_2D, gridTex); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); |
| glTexImage2D(GL_TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr()); |
| |
| sglr::drawQuad(*getCurrentContext(), texShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| } |
| |
| // Setup blend. |
| glEnable(GL_BLEND); |
| glBlendEquationSeparate(m_funcRGB, m_funcAlpha); |
| glBlendFuncSeparate(m_srcRGB, m_dstRGB, m_srcAlpha, m_dstAlpha); |
| |
| // Render gradient with blend. |
| sglr::drawQuad(*getCurrentContext(), gradShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| |
| readPixels(dst, 0, 0, m_size.x(), m_size.y(), fboFmt, Vec4(1.0f), Vec4(0.0f)); |
| } |
| |
| private: |
| IVec2 m_size; |
| deUint32 m_funcRGB; |
| deUint32 m_funcAlpha; |
| deUint32 m_srcRGB; |
| deUint32 m_dstRGB; |
| deUint32 m_srcAlpha; |
| deUint32 m_dstAlpha; |
| }; |
| |
| class FboRepeatedClearSampleTex2DCase : public FboColorbufferCase |
| { |
| public: |
| FboRepeatedClearSampleTex2DCase (Context& context, const char* name, const char* desc, deUint32 format) |
| : FboColorbufferCase(context, name, desc, format) |
| { |
| } |
| |
| protected: |
| void preCheck (void) |
| { |
| checkFormatSupport(m_format); |
| } |
| |
| void render (tcu::Surface& dst) |
| { |
| const tcu::TextureFormat fboFormat = glu::mapGLInternalFormat(m_format); |
| const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat); |
| const int numRowsCols = 4; |
| const int cellSize = 16; |
| const int fboSizes[] = { cellSize, cellSize*numRowsCols }; |
| |
| Texture2DShader fboBlitShader (DataTypes() << glu::getSampler2DType(fboFormat), getFragmentOutputType(fboFormat), Vec4(1.0f), Vec4(0.0f)); |
| const deUint32 fboBlitShaderID = getCurrentContext()->createProgram(&fboBlitShader); |
| |
| de::Random rnd (18169662); |
| deUint32 fbos[] = { 0, 0 }; |
| deUint32 textures[] = { 0, 0 }; |
| |
| glGenFramebuffers(2, &fbos[0]); |
| glGenTextures(2, &textures[0]); |
| |
| for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++) |
| { |
| glBindTexture(GL_TEXTURE_2D, textures[fboNdx]); |
| glTexStorage2D(GL_TEXTURE_2D, 1, m_format, fboSizes[fboNdx], fboSizes[fboNdx]); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| checkError(); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0); |
| checkError(); |
| checkFramebufferStatus(GL_FRAMEBUFFER); |
| } |
| |
| // larger fbo bound -- clear to transparent black |
| clearColorBuffer(fboFormat, Vec4(0.0f)); |
| |
| fboBlitShader.setUniforms(*getCurrentContext(), fboBlitShaderID); |
| glBindTexture(GL_TEXTURE_2D, textures[0]); |
| |
| for (int cellY = 0; cellY < numRowsCols; cellY++) |
| for (int cellX = 0; cellX < numRowsCols; cellX++) |
| { |
| const Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); |
| clearColorBuffer(fboFormat, color); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); |
| glViewport(cellX*cellSize, cellY*cellSize, cellSize, cellSize); |
| sglr::drawQuad(*getCurrentContext(), fboBlitShaderID, Vec3(-1.0f, -1.0f, 0.0f), Vec3(1.0f, 1.0f, 0.0f)); |
| } |
| |
| readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias); |
| checkError(); |
| } |
| }; |
| |
| class FboRepeatedClearBlitTex2DCase : public FboColorbufferCase |
| { |
| public: |
| FboRepeatedClearBlitTex2DCase (Context& context, const char* name, const char* desc, deUint32 format) |
| : FboColorbufferCase(context, name, desc, format) |
| { |
| } |
| |
| protected: |
| void preCheck (void) |
| { |
| checkFormatSupport(m_format); |
| } |
| |
| void render (tcu::Surface& dst) |
| { |
| const tcu::TextureFormat fboFormat = glu::mapGLInternalFormat(m_format); |
| const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat); |
| const int numRowsCols = 4; |
| const int cellSize = 16; |
| const int fboSizes[] = { cellSize, cellSize*numRowsCols }; |
| |
| de::Random rnd (18169662); |
| deUint32 fbos[] = { 0, 0 }; |
| deUint32 textures[] = { 0, 0 }; |
| |
| glGenFramebuffers(2, &fbos[0]); |
| glGenTextures(2, &textures[0]); |
| |
| for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++) |
| { |
| glBindTexture(GL_TEXTURE_2D, textures[fboNdx]); |
| glTexStorage2D(GL_TEXTURE_2D, 1, m_format, fboSizes[fboNdx], fboSizes[fboNdx]); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| checkError(); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]); |
| glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textures[fboNdx], 0); |
| checkError(); |
| checkFramebufferStatus(GL_FRAMEBUFFER); |
| } |
| |
| // larger fbo bound -- clear to transparent black |
| clearColorBuffer(fboFormat, Vec4(0.0f)); |
| |
| for (int cellY = 0; cellY < numRowsCols; cellY++) |
| for (int cellX = 0; cellX < numRowsCols; cellX++) |
| { |
| const Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); |
| clearColorBuffer(fboFormat, color); |
| |
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); |
| glBlitFramebuffer(0, 0, cellSize, cellSize, cellX*cellSize, cellY*cellSize, (cellX+1)*cellSize, (cellY+1)*cellSize, GL_COLOR_BUFFER_BIT, GL_NEAREST); |
| } |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); |
| readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias); |
| checkError(); |
| } |
| }; |
| |
| class FboRepeatedClearBlitRboCase : public FboColorbufferCase |
| { |
| public: |
| FboRepeatedClearBlitRboCase (Context& context, const char* name, const char* desc, deUint32 format) |
| : FboColorbufferCase(context, name, desc, format) |
| { |
| } |
| |
| protected: |
| void preCheck (void) |
| { |
| checkFormatSupport(m_format); |
| } |
| |
| void render (tcu::Surface& dst) |
| { |
| const tcu::TextureFormat fboFormat = glu::mapGLInternalFormat(m_format); |
| const tcu::TextureFormatInfo fmtInfo = tcu::getTextureFormatInfo(fboFormat); |
| const int numRowsCols = 4; |
| const int cellSize = 16; |
| const int fboSizes[] = { cellSize, cellSize*numRowsCols }; |
| |
| de::Random rnd (18169662); |
| deUint32 fbos[] = { 0, 0 }; |
| deUint32 rbos[] = { 0, 0 }; |
| |
| glGenFramebuffers(2, &fbos[0]); |
| glGenRenderbuffers(2, &rbos[0]); |
| |
| for (int fboNdx = 0; fboNdx < DE_LENGTH_OF_ARRAY(fbos); fboNdx++) |
| { |
| glBindRenderbuffer(GL_RENDERBUFFER, rbos[fboNdx]); |
| glRenderbufferStorage(GL_RENDERBUFFER, m_format, fboSizes[fboNdx], fboSizes[fboNdx]); |
| checkError(); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbos[fboNdx]); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rbos[fboNdx]); |
| checkError(); |
| checkFramebufferStatus(GL_FRAMEBUFFER); |
| } |
| |
| // larger fbo bound -- clear to transparent black |
| clearColorBuffer(fboFormat, Vec4(0.0f)); |
| |
| for (int cellY = 0; cellY < numRowsCols; cellY++) |
| for (int cellX = 0; cellX < numRowsCols; cellX++) |
| { |
| const Vec4 color = randomVector<4>(rnd, fmtInfo.valueMin, fmtInfo.valueMax); |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbos[0]); |
| clearColorBuffer(fboFormat, color); |
| |
| glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbos[1]); |
| glBlitFramebuffer(0, 0, cellSize, cellSize, cellX*cellSize, cellY*cellSize, (cellX+1)*cellSize, (cellY+1)*cellSize, GL_COLOR_BUFFER_BIT, GL_NEAREST); |
| } |
| |
| glBindFramebuffer(GL_FRAMEBUFFER, fbos[1]); |
| readPixels(dst, 0, 0, fboSizes[1], fboSizes[1], fboFormat, fmtInfo.lookupScale, fmtInfo.lookupBias); |
| checkError(); |
| } |
| }; |
| |
| FboColorTests::FboColorTests (Context& context) |
| : TestCaseGroup(context, "color", "Colorbuffer tests") |
| { |
| } |
| |
| FboColorTests::~FboColorTests (void) |
| { |
| } |
| |
| void FboColorTests::init (void) |
| { |
| static const deUint32 colorFormats[] = |
| { |
| // RGBA formats |
| GL_RGBA32I, |
| GL_RGBA32UI, |
| GL_RGBA16I, |
| GL_RGBA16UI, |
| GL_RGBA8, |
| GL_RGBA8I, |
| GL_RGBA8UI, |
| GL_SRGB8_ALPHA8, |
| GL_RGB10_A2, |
| GL_RGB10_A2UI, |
| GL_RGBA4, |
| GL_RGB5_A1, |
| |
| // RGB formats |
| GL_RGB8, |
| GL_RGB565, |
| |
| // RG formats |
| GL_RG32I, |
| GL_RG32UI, |
| GL_RG16I, |
| GL_RG16UI, |
| GL_RG8, |
| GL_RG8I, |
| GL_RG8UI, |
| |
| // R formats |
| GL_R32I, |
| GL_R32UI, |
| GL_R16I, |
| GL_R16UI, |
| GL_R8, |
| GL_R8I, |
| GL_R8UI, |
| |
| // GL_EXT_color_buffer_float |
| GL_RGBA32F, |
| GL_RGBA16F, |
| GL_R11F_G11F_B10F, |
| GL_RG32F, |
| GL_RG16F, |
| GL_R32F, |
| GL_R16F, |
| |
| // GL_EXT_color_buffer_half_float |
| GL_RGB16F |
| }; |
| |
| // .clear |
| { |
| tcu::TestCaseGroup* clearGroup = new tcu::TestCaseGroup(m_testCtx, "clear", "Color clears"); |
| addChild(clearGroup); |
| |
| for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(colorFormats); ndx++) |
| clearGroup->addChild(new FboColorClearCase(m_context, getFormatName(colorFormats[ndx]), "", colorFormats[ndx], 129, 117)); |
| } |
| |
| // .tex2d |
| { |
| tcu::TestCaseGroup* tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "Texture 2D tests"); |
| addChild(tex2DGroup); |
| |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++) |
| tex2DGroup->addChild(new FboColorMultiTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]), "", |
| colorFormats[fmtNdx], IVec2(129, 117), |
| colorFormats[fmtNdx], IVec2(99, 128))); |
| } |
| |
| // .texcube |
| { |
| tcu::TestCaseGroup* texCubeGroup = new tcu::TestCaseGroup(m_testCtx, "texcube", "Texture cube map tests"); |
| addChild(texCubeGroup); |
| |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++) |
| texCubeGroup->addChild(new FboColorTexCubeCase(m_context, getFormatName(colorFormats[fmtNdx]), "", |
| colorFormats[fmtNdx], IVec2(128, 128))); |
| } |
| |
| // .tex2darray |
| { |
| tcu::TestCaseGroup* tex2DArrayGroup = new tcu::TestCaseGroup(m_testCtx, "tex2darray", "Texture 2D array tests"); |
| addChild(tex2DArrayGroup); |
| |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++) |
| tex2DArrayGroup->addChild(new FboColorTex2DArrayCase(m_context, getFormatName(colorFormats[fmtNdx]), "", |
| colorFormats[fmtNdx], IVec3(128, 128, 5))); |
| } |
| |
| // .tex3d |
| { |
| tcu::TestCaseGroup* tex3DGroup = new tcu::TestCaseGroup(m_testCtx, "tex3d", "Texture 3D tests"); |
| addChild(tex3DGroup); |
| |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++) |
| tex3DGroup->addChild(new FboColorTex3DCase(m_context, getFormatName(colorFormats[fmtNdx]), "", |
| colorFormats[fmtNdx], IVec3(128, 128, 5))); |
| } |
| |
| // .blend |
| { |
| tcu::TestCaseGroup* blendGroup = new tcu::TestCaseGroup(m_testCtx, "blend", "Blending tests"); |
| addChild(blendGroup); |
| |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++) |
| { |
| deUint32 format = colorFormats[fmtNdx]; |
| tcu::TextureFormat texFmt = glu::mapGLInternalFormat(format); |
| tcu::TextureChannelClass fmtClass = tcu::getTextureChannelClass(texFmt.type); |
| string fmtName = getFormatName(format); |
| |
| if (texFmt.type == tcu::TextureFormat::FLOAT || |
| fmtClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || |
| fmtClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) |
| continue; // Blending is not supported. |
| |
| blendGroup->addChild(new FboBlendCase(m_context, (fmtName + "_src_over").c_str(), "", format, IVec2(127, 111), GL_FUNC_ADD, GL_FUNC_ADD, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE)); |
| } |
| } |
| |
| // .repeated_clear |
| { |
| tcu::TestCaseGroup* const repeatedClearGroup = new tcu::TestCaseGroup(m_testCtx, "repeated_clear", "Repeated clears and blits"); |
| addChild(repeatedClearGroup); |
| |
| // .sample.tex2d |
| { |
| tcu::TestCaseGroup* const sampleGroup = new tcu::TestCaseGroup(m_testCtx, "sample", "Read by sampling"); |
| repeatedClearGroup->addChild(sampleGroup); |
| |
| tcu::TestCaseGroup* const tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "2D Texture"); |
| sampleGroup->addChild(tex2DGroup); |
| |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++) |
| tex2DGroup->addChild(new FboRepeatedClearSampleTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]), |
| "", colorFormats[fmtNdx])); |
| } |
| |
| // .blit |
| { |
| tcu::TestCaseGroup* const blitGroup = new tcu::TestCaseGroup(m_testCtx, "blit", "Blitted"); |
| repeatedClearGroup->addChild(blitGroup); |
| |
| // .tex2d |
| { |
| tcu::TestCaseGroup* const tex2DGroup = new tcu::TestCaseGroup(m_testCtx, "tex2d", "2D Texture"); |
| blitGroup->addChild(tex2DGroup); |
| |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++) |
| tex2DGroup->addChild(new FboRepeatedClearBlitTex2DCase(m_context, getFormatName(colorFormats[fmtNdx]), |
| "", colorFormats[fmtNdx])); |
| } |
| |
| // .rbo |
| { |
| tcu::TestCaseGroup* const rboGroup = new tcu::TestCaseGroup(m_testCtx, "rbo", "Renderbuffer"); |
| blitGroup->addChild(rboGroup); |
| |
| for (int fmtNdx = 0; fmtNdx < DE_LENGTH_OF_ARRAY(colorFormats); fmtNdx++) |
| rboGroup->addChild(new FboRepeatedClearBlitRboCase(m_context, getFormatName(colorFormats[fmtNdx]), |
| "", colorFormats[fmtNdx])); |
| } |
| } |
| } |
| } |
| |
| } // Functional |
| } // gles3 |
| } // deqp |