| /*------------------------------------------------------------------------- |
| * drawElements Quality Program OpenGL (ES) 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 completeness tests. |
| *//*--------------------------------------------------------------------*/ |
| |
| #include "es2fFboCompletenessTests.hpp" |
| |
| #include "glsFboCompletenessTests.hpp" |
| #include "gluObjectWrapper.hpp" |
| |
| using namespace glw; |
| using deqp::gls::Range; |
| using namespace deqp::gls::FboUtil; |
| using namespace deqp::gls::FboUtil::config; |
| namespace fboc = deqp::gls::fboc; |
| typedef tcu::TestCase::IterateResult IterateResult; |
| |
| namespace deqp |
| { |
| namespace gles2 |
| { |
| namespace Functional |
| { |
| |
| static const FormatKey s_es2ColorRenderables[] = |
| { |
| GL_RGBA4, GL_RGB5_A1, GL_RGB565, |
| }; |
| |
| // GLES2 does not strictly allow these, but this seems to be a bug in the |
| // specification. For now, let's assume the unsized formats corresponding to |
| // the color-renderable sized formats are allowed. |
| // See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=7333 |
| |
| static const FormatKey s_es2UnsizedColorRenderables[] = |
| { |
| GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4), |
| GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1), |
| GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_SHORT_5_6_5) |
| }; |
| |
| static const FormatKey s_es2DepthRenderables[] = |
| { |
| GL_DEPTH_COMPONENT16, |
| }; |
| |
| static const FormatKey s_es2StencilRenderables[] = |
| { |
| GL_STENCIL_INDEX8, |
| }; |
| |
| static const FormatEntry s_es2Formats[] = |
| { |
| { COLOR_RENDERABLE | TEXTURE_VALID, |
| GLS_ARRAY_RANGE(s_es2UnsizedColorRenderables) }, |
| { REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, |
| GLS_ARRAY_RANGE(s_es2ColorRenderables) }, |
| { REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID, |
| GLS_ARRAY_RANGE(s_es2DepthRenderables) }, |
| { REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID, |
| GLS_ARRAY_RANGE(s_es2StencilRenderables) }, |
| }; |
| |
| // We have here only the extensions that are redundant in vanilla GLES3. Those |
| // that are applicable both to GLES2 and GLES3 are in glsFboCompletenessTests.cpp. |
| |
| // GL_OES_texture_float |
| static const FormatKey s_oesTextureFloatFormats[] = |
| { |
| GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_FLOAT), |
| GLS_UNSIZED_FORMATKEY(GL_RGB, GL_FLOAT), |
| }; |
| |
| // GL_OES_texture_half_float |
| static const FormatKey s_oesTextureHalfFloatFormats[] = |
| { |
| GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_HALF_FLOAT_OES), |
| GLS_UNSIZED_FORMATKEY(GL_RGB, GL_HALF_FLOAT_OES), |
| }; |
| |
| // GL_EXT_sRGB_write_control |
| static const FormatKey s_extSrgbWriteControlFormats[] = |
| { |
| GL_SRGB8_ALPHA8 |
| }; |
| |
| // DEQP_gles3_core_no_extension_features |
| static const FormatKey s_es3NoExtRboFormats[] = |
| { |
| GL_RGB10_A2, |
| GL_SRGB8_ALPHA8, |
| }; |
| static const FormatKey s_es3NoExtTextureFormats[] = |
| { |
| GL_R16F, |
| GL_RG16F, |
| GL_RGB16F, |
| GL_RGBA16F, |
| GL_R11F_G11F_B10F, |
| }; |
| static const FormatKey s_es3NoExtTextureColorRenderableFormats[] = |
| { |
| GL_R8, |
| GL_RG8, |
| GL_RGB8, |
| GL_RGBA4, |
| GL_RGB5_A1, |
| GL_RGBA8, |
| GL_RGB10_A2, |
| GL_RGB565, |
| GL_SRGB8_ALPHA8, |
| }; |
| |
| // with ES3 core and GL_EXT_color_buffer_float |
| static const FormatKey s_es3NoExtExtColorBufferFloatFormats[] = |
| { |
| // \note Only the GLES2+exts subset of formats |
| GL_R11F_G11F_B10F, GL_RGBA16F, GL_RG16F, GL_R16F, |
| }; |
| |
| // with ES3 core with OES_texture_stencil8 |
| static const FormatKey s_es3NoExtOesTextureStencil8Formats[] = |
| { |
| GL_STENCIL_INDEX8, |
| }; |
| |
| // DEQP_gles3_core_changed_features |
| static const FormatKey s_es3NoExtDepthRenderable[] = |
| { |
| GL_DEPTH_COMPONENT16, |
| GL_DEPTH_COMPONENT24, |
| GL_DEPTH24_STENCIL8, |
| }; |
| |
| static const FormatKey s_es3NoExtStencilRenderable[] = |
| { |
| GL_DEPTH24_STENCIL8, |
| }; |
| |
| static const FormatExtEntry s_es2ExtFormats[] = |
| { |
| // The extension does not specify these to be color-renderable. |
| { |
| "GL_OES_texture_float", |
| (deUint32)TEXTURE_VALID, |
| GLS_ARRAY_RANGE(s_oesTextureFloatFormats) |
| }, |
| { |
| "GL_OES_texture_half_float", |
| (deUint32)TEXTURE_VALID, |
| GLS_ARRAY_RANGE(s_oesTextureHalfFloatFormats) |
| }, |
| |
| // GL_EXT_sRGB_write_control makes SRGB8_ALPHA8 color-renderable |
| { |
| "GL_EXT_sRGB_write_control", |
| (deUint32)(REQUIRED_RENDERABLE | TEXTURE_VALID | COLOR_RENDERABLE | RENDERBUFFER_VALID), |
| GLS_ARRAY_RANGE(s_extSrgbWriteControlFormats) |
| }, |
| |
| // Since GLES3 is "backwards compatible" to GLES2, we might actually be running on a GLES3 |
| // context. Since GLES3 added some features to core with no corresponding GLES2 extension, |
| // some tests might produce wrong results (since they are using rules of GLES2 & extensions) |
| // |
| // To avoid this, require new features of GLES3 that have no matching GLES2 extension if |
| // context is GLES3. This can be done with a DEQP_* extensions. |
| // |
| // \note Not all feature changes are listed here but only those that alter GLES2 subset of |
| // the formats |
| { |
| "DEQP_gles3_core_compatible", |
| (deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID), |
| GLS_ARRAY_RANGE(s_es3NoExtRboFormats) |
| }, |
| { |
| "DEQP_gles3_core_compatible", |
| (deUint32)TEXTURE_VALID, |
| GLS_ARRAY_RANGE(s_es3NoExtTextureFormats) |
| }, |
| { |
| "DEQP_gles3_core_compatible", |
| (deUint32)(REQUIRED_RENDERABLE | TEXTURE_VALID | COLOR_RENDERABLE | RENDERBUFFER_VALID), |
| GLS_ARRAY_RANGE(s_es3NoExtTextureColorRenderableFormats) |
| }, |
| { |
| "DEQP_gles3_core_compatible GL_EXT_color_buffer_float", |
| (deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID), |
| GLS_ARRAY_RANGE(s_es3NoExtExtColorBufferFloatFormats) |
| }, |
| { |
| "DEQP_gles3_core_compatible GL_OES_texture_stencil8", |
| (deUint32)(REQUIRED_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID), |
| GLS_ARRAY_RANGE(s_es3NoExtOesTextureStencil8Formats) |
| }, |
| { |
| "DEQP_gles3_core_compatible GL_OES_texture_half_float GL_EXT_color_buffer_half_float", |
| (deUint32)(REQUIRED_RENDERABLE | COLOR_RENDERABLE), |
| GLS_ARRAY_RANGE(s_oesTextureHalfFloatFormats) |
| }, |
| { |
| "DEQP_gles3_core_compatible", |
| (deUint32)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID), |
| GLS_ARRAY_RANGE(s_es3NoExtDepthRenderable) |
| }, |
| { |
| "DEQP_gles3_core_compatible", |
| (deUint32)(REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID), |
| GLS_ARRAY_RANGE(s_es3NoExtStencilRenderable) |
| }, |
| }; |
| |
| class ES2Checker : public Checker |
| { |
| public: |
| ES2Checker (const glu::RenderContext& ctx); |
| void check (GLenum attPoint, const Attachment& att, |
| const Image* image); |
| private: |
| GLsizei m_width; //< The common width of images |
| GLsizei m_height; //< The common height of images |
| }; |
| |
| ES2Checker::ES2Checker (const glu::RenderContext& ctx)\ |
| : Checker (ctx) |
| , m_width (-1) |
| , m_height (-1) |
| { |
| } |
| |
| void ES2Checker::check (GLenum attPoint, const Attachment& att, const Image* image) |
| { |
| DE_UNREF(attPoint); |
| DE_UNREF(att); |
| // GLES2: "All attached images have the same width and height." |
| if (m_width == -1) |
| { |
| m_width = image->width; |
| m_height = image->height; |
| } |
| else if (image->width != m_width || image->height != m_height) |
| { |
| // Since GLES3 is "backwards compatible" to GLES2, we might actually be running |
| // on a GLES3 context. On GLES3, FRAMEBUFFER_INCOMPLETE_DIMENSIONS is not generated |
| // if attachments have different sizes. |
| if (!gls::FboUtil::checkExtensionSupport(m_renderCtx, "DEQP_gles3_core_compatible")) |
| { |
| // running on GLES2 |
| addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS, "Sizes of attachments differ"); |
| } |
| } |
| // GLES2, 4.4.5: "some implementations may not support rendering to |
| // particular combinations of internal formats. If the combination of |
| // formats of the images attached to a framebuffer object are not |
| // supported by the implementation, then the framebuffer is not complete |
| // under the clause labeled FRAMEBUFFER_UNSUPPORTED." |
| // |
| // Hence it is _always_ allowed to report FRAMEBUFFER_UNSUPPORTED. |
| addPotentialFBOStatus(GL_FRAMEBUFFER_UNSUPPORTED, "Particular format combinations need not to be supported"); |
| } |
| |
| struct FormatCombination |
| { |
| GLenum colorKind; |
| ImageFormat colorFmt; |
| GLenum depthKind; |
| ImageFormat depthFmt; |
| GLenum stencilKind; |
| ImageFormat stencilFmt; |
| }; |
| |
| class SupportedCombinationTest : public fboc::TestBase |
| { |
| public: |
| SupportedCombinationTest (fboc::Context& ctx, |
| const char* name, const char* desc) |
| : TestBase (ctx, name, desc) {} |
| |
| IterateResult iterate (void); |
| bool tryCombination (const FormatCombination& comb); |
| GLenum formatKind (ImageFormat fmt); |
| }; |
| |
| bool SupportedCombinationTest::tryCombination (const FormatCombination& comb) |
| { |
| glu::Framebuffer fbo(m_ctx.getRenderContext()); |
| FboBuilder builder(*fbo, GL_FRAMEBUFFER, fboc::gl(*this)); |
| |
| attachTargetToNew(GL_COLOR_ATTACHMENT0, comb.colorKind, comb.colorFmt, |
| 64, 64, builder); |
| attachTargetToNew(GL_DEPTH_ATTACHMENT, comb.depthKind, comb.depthFmt, |
| 64, 64, builder); |
| attachTargetToNew(GL_STENCIL_ATTACHMENT, comb.stencilKind, comb.stencilFmt, |
| 64, 64, builder); |
| |
| const GLenum glStatus = fboc::gl(*this).checkFramebufferStatus(GL_FRAMEBUFFER); |
| |
| return (glStatus == GL_FRAMEBUFFER_COMPLETE); |
| } |
| |
| GLenum SupportedCombinationTest::formatKind (ImageFormat fmt) |
| { |
| if (fmt.format == GL_NONE) |
| return GL_NONE; |
| |
| const FormatFlags flags = m_ctx.getCoreFormats().getFormatInfo(fmt); |
| const bool rbo = (flags & RENDERBUFFER_VALID) != 0; |
| // exactly one of renderbuffer and texture is supported by vanilla GLES2 formats |
| DE_ASSERT(rbo != ((flags & TEXTURE_VALID) != 0)); |
| |
| return rbo ? GL_RENDERBUFFER : GL_TEXTURE; |
| } |
| |
| IterateResult SupportedCombinationTest::iterate (void) |
| { |
| const FormatDB& db = m_ctx.getCoreFormats(); |
| const ImageFormat none = ImageFormat::none(); |
| Formats colorFmts = db.getFormats(COLOR_RENDERABLE); |
| Formats depthFmts = db.getFormats(DEPTH_RENDERABLE); |
| Formats stencilFmts = db.getFormats(STENCIL_RENDERABLE); |
| FormatCombination comb; |
| bool succ = false; |
| |
| colorFmts.insert(none); |
| depthFmts.insert(none); |
| stencilFmts.insert(none); |
| |
| for (Formats::const_iterator col = colorFmts.begin(); col != colorFmts.end(); col++) |
| { |
| comb.colorFmt = *col; |
| comb.colorKind = formatKind(*col); |
| for (Formats::const_iterator dep = depthFmts.begin(); dep != depthFmts.end(); dep++) |
| { |
| comb.depthFmt = *dep; |
| comb.depthKind = formatKind(*dep); |
| for (Formats::const_iterator stc = stencilFmts.begin(); |
| stc != stencilFmts.end(); stc++) |
| { |
| comb.stencilFmt = *stc; |
| comb.stencilKind = formatKind(*stc); |
| succ = tryCombination(comb); |
| if (succ) |
| break; |
| } |
| } |
| } |
| |
| if (succ) |
| pass(); |
| else |
| fail("No supported format combination found"); |
| |
| return STOP; |
| } |
| |
| class ES2CheckerFactory : public CheckerFactory |
| { |
| public: |
| Checker* createChecker (const glu::RenderContext& ctx) { return new ES2Checker(ctx); } |
| }; |
| |
| class TestGroup : public TestCaseGroup |
| { |
| public: |
| TestGroup (Context& ctx); |
| void init (void); |
| private: |
| ES2CheckerFactory m_checkerFactory; |
| fboc::Context m_fboc; |
| }; |
| |
| TestGroup::TestGroup (Context& ctx) |
| : TestCaseGroup (ctx, "completeness", "Completeness tests") |
| , m_checkerFactory () |
| , m_fboc (ctx.getTestContext(), ctx.getRenderContext(), m_checkerFactory) |
| { |
| const FormatEntries stdRange = GLS_ARRAY_RANGE(s_es2Formats); |
| const FormatExtEntries extRange = GLS_ARRAY_RANGE(s_es2ExtFormats); |
| |
| m_fboc.addFormats(stdRange); |
| m_fboc.addExtFormats(extRange); |
| m_fboc.setHaveMulticolorAtts( |
| ctx.getContextInfo().isExtensionSupported("GL_NV_fbo_color_attachments")); |
| } |
| |
| void TestGroup::init (void) |
| { |
| tcu::TestCaseGroup* attCombTests = m_fboc.createAttachmentTests(); |
| addChild(m_fboc.createRenderableTests()); |
| attCombTests->addChild(new SupportedCombinationTest( |
| m_fboc, |
| "exists_supported", |
| "Test for existence of a supported combination of formats")); |
| addChild(attCombTests); |
| addChild(m_fboc.createSizeTests()); |
| } |
| |
| tcu::TestCaseGroup* createFboCompletenessTests (Context& context) |
| { |
| return new TestGroup(context); |
| } |
| |
| } // Functional |
| } // gles2 |
| } // deqp |