blob: 5a67f8d771ed0694bd701daa7993db7c671f7d1c [file] [log] [blame]
/*-------------------------------------------------------------------------
* 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
};
static const FormatExtEntry s_es2ExtFormats[] =
{
// The extension does not specify these to be color-renderable.
{
"GL_OES_texture_float",
TEXTURE_VALID,
GLS_ARRAY_RANGE(s_oesTextureFloatFormats)
},
{
"GL_OES_texture_half_float",
TEXTURE_VALID,
GLS_ARRAY_RANGE(s_oesTextureHalfFloatFormats)
},
// GL_EXT_sRGB_write_control makes SRGB8_ALPHA8 color-renderable
{
"GL_EXT_sRGB_write_control",
REQUIRED_RENDERABLE | TEXTURE_VALID | COLOR_RENDERABLE | RENDERBUFFER_VALID,
GLS_ARRAY_RANGE(s_extSrgbWriteControlFormats)
},
};
class ES2Checker : public Checker
{
public:
ES2Checker (void) : m_width(-1), m_height(-1) {}
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
};
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
{
require(image->width == m_width && image->height == m_height,
GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS);
}
// 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.
canRequire(false, GL_FRAMEBUFFER_UNSUPPORTED);
}
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.getMinFormats().getFormatInfo(fmt, ANY_FORMAT);
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.getMinFormats();
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 (void) { return new ES2Checker(); }
};
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