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
namespace Functional { static const FormatKey s_es3ColorRenderables[] = { // GLES3, 4.4.4: "An internal format is color-renderable if it is one of // the formats from table 3.12 noted as color-renderable..." GL_R8, GL_RG8, GL_RGB8, GL_RGB565, GL_RGBA4, GL_RGB5_A1, GL_RGBA8, GL_RGB10_A2, GL_RGB10_A2UI, GL_SRGB8_ALPHA8, GL_R8I, GL_R8UI, GL_R16I, GL_R16UI, GL_R32I, GL_R32UI, GL_RG8I, GL_RG8UI, GL_RG16I, GL_RG16UI, GL_RG32I, GL_RG32UI, GL_RGBA8I, GL_RGBA8UI, GL_RGBA16I, GL_RGBA16UI, GL_RGBA32I, GL_RGBA32UI, }; static const FormatKey s_es3UnsizedColorRenderables[] = { // "...or if it is unsized format RGBA or RGB." // See Table 3.3 in GLES3. GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_BYTE), 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_BYTE), GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_SHORT_5_6_5), }; static const FormatKey s_es3DepthRenderables[] = { // GLES3, 4.4.4: "An internal format is depth-renderable if it is one of // the formats from table 3.13." GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT32F, GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8, }; static const FormatKey s_es3StencilRboRenderables[] = { // GLES3, 4.4.4: "An internal format is stencil-renderable if it is // STENCIL_INDEX8..." GL_STENCIL_INDEX8, }; static const FormatKey s_es3StencilRenderables[] = { // "...or one of the formats from table 3.13 whose base internal format is // DEPTH_STENCIL." GL_DEPTH24_STENCIL8, GL_DEPTH32F_STENCIL8, }; static const FormatKey s_es3TextureFloatFormats[] = { GL_RGBA32F, GL_RGBA16F, GL_R11F_G11F_B10F, GL_RG32F, GL_RG16F, GL_R32F, GL_R16F, GL_RGBA16F, GL_RGB16F, GL_RG16F, GL_R16F, }; static const FormatKey s_es3NotRenderableTextureFormats[] = { GL_R8_SNORM, GL_RG8_SNORM, GL_RGB8_SNORM, GL_RGBA8_SNORM, GL_RGB9_E5, GL_SRGB8, GL_RGB8I, GL_RGB16I, GL_RGB32I, GL_RGB8UI, GL_RGB16UI,GL_RGB32UI, }; static const FormatEntry s_es3Formats[] = { // Renderbuffers don't support unsized formats { REQUIRED_RENDERABLE | COLOR_RENDERABLE | TEXTURE_VALID, GLS_ARRAY_RANGE(s_es3UnsizedColorRenderables) }, { REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID, GLS_ARRAY_RANGE(s_es3ColorRenderables) }, { REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID, GLS_ARRAY_RANGE(s_es3DepthRenderables) }, { REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID, GLS_ARRAY_RANGE(s_es3StencilRboRenderables) }, { REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID, GLS_ARRAY_RANGE(s_es3StencilRenderables) }, { TEXTURE_VALID, GLS_ARRAY_RANGE(s_es3NotRenderableTextureFormats) }, // These are not color-renderable in vanilla ES3, but we need to mark them // as valid for textures, since EXT_color_buffer_(half_)float brings in // color-renderability and only renderbuffer-validity. { TEXTURE_VALID, GLS_ARRAY_RANGE(s_es3TextureFloatFormats) }, }; // GL_EXT_color_buffer_float static const FormatKey s_extColorBufferFloatFormats[] = { GL_RGBA32F, GL_RGBA16F, GL_R11F_G11F_B10F, GL_RG32F, GL_RG16F, GL_R32F, GL_R16F, }; // GL_OES_texture_stencil8 static const FormatKey s_extOESTextureStencil8[] = { GL_STENCIL_INDEX8, }; // GL_EXT_render_snorm static const FormatKey s_extRenderSnorm[] = { GL_R8_SNORM, GL_RG8_SNORM, GL_RGBA8_SNORM, }; static const FormatExtEntry s_es3ExtFormats[] = { { "GL_EXT_color_buffer_float", // These are already texture-valid in ES3, the extension just adds RBO // support and makes them color-renderable. REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, GLS_ARRAY_RANGE(s_extColorBufferFloatFormats) }, { "GL_OES_texture_stencil8", // \note: es3 RBO tests actually cover the first two requirements // - kept here for completeness REQUIRED_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID, GLS_ARRAY_RANGE(s_extOESTextureStencil8) }, // Since GLES31 is backwards compatible to GLES3, we might actually be running on a GLES31. // Add rule changes of GLES31 that have no corresponding GLES3 extension. // // \note Not all feature changes are listed here but only those that alter GLES3 subset of // the formats { "DEQP_gles31_core_compatible GL_EXT_render_snorm", REQUIRED_RENDERABLE | COLOR_RENDERABLE | TEXTURE_VALID | RENDERBUFFER_VALID, GLS_ARRAY_RANGE(s_extRenderSnorm) }, }; class ES3Checker : public Checker { public: ES3Checker (const glu::RenderContext& ctx) : Checker (ctx) , m_numSamples (-1) , m_depthStencilImage (0) , m_depthStencilType (GL_NONE) {} void check (GLenum attPoint, const Attachment& att, const Image* image); private: //! The common number of samples of images. GLsizei m_numSamples; //! The common image for depth and stencil attachments. GLuint m_depthStencilImage; GLenum m_depthStencilType; }; void ES3Checker::check (GLenum attPoint, const Attachment& att, const Image* image) { GLsizei imgSamples = imageNumSamples(*image); if (m_numSamples == -1) { m_numSamples = imgSamples; } else { // GLES3: "The value of RENDERBUFFER_SAMPLES is the same for all attached // renderbuffers and, if the attached images are a mix of renderbuffers // and textures, the value of RENDERBUFFER_SAMPLES is zero." // // On creating a renderbuffer: "If _samples_ is zero, then // RENDERBUFFER_SAMPLES is set to zero. Otherwise [...] the resulting // value for RENDERBUFFER_SAMPLES is guaranteed to be greater than or // equal to _samples_ and no more than the next larger sample count // supported by the implementation." // Either all attachments are zero-sample renderbuffers and/or // textures, or none of them are. if ((m_numSamples == 0) != (imgSamples == 0)) addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, "Mixed multi- and single-sampled attachments"); // If the attachments requested a different number of samples, the // implementation is allowed to report this as incomplete. However, it // is also possible that despite the different requests, the // implementation allocated the same number of samples to both. Hence // reporting the framebuffer as complete is also legal. if (m_numSamples != imgSamples) addPotentialFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE, "Number of samples differ"); } // "Depth and stencil attachments, if present, are the same image." if (attPoint == GL_DEPTH_ATTACHMENT || attPoint == GL_STENCIL_ATTACHMENT) { if (m_depthStencilImage == 0) { m_depthStencilImage = att.imageName; m_depthStencilType = attachmentType(att); } else { if (m_depthStencilImage != att.imageName || m_depthStencilType != attachmentType(att)) addFBOStatus(GL_FRAMEBUFFER_UNSUPPORTED, "Depth and stencil attachments are not the same image"); } } } struct NumLayersParams { GLenum textureKind; //< GL_TEXTURE_3D or GL_TEXTURE_2D_ARRAY GLsizei numLayers; //< Number of layers in texture GLsizei attachmentLayer; //< Layer referenced by attachment static string getName (const NumLayersParams& params); static string getDescription (const NumLayersParams& params); }; string NumLayersParams::getName (const NumLayersParams& params) { ostringstream os; const string kindStr = params.textureKind == GL_TEXTURE_3D ? "3d" : "2darr"; os << kindStr << "_" << params.numLayers << "_" << params.attachmentLayer; return os.str(); } string NumLayersParams::getDescription (const NumLayersParams& params) { ostringstream os; const string kindStr = (params.textureKind == GL_TEXTURE_3D ? "3D Texture" : "2D Array Texture"); os << kindStr + ", " << params.numLayers << " layers, " << "attached layer " << params.attachmentLayer << "."; return os.str(); } class NumLayersTest : public fboc::ParamTest<NumLayersParams> { public: NumLayersTest (fboc::Context& ctx, NumLayersParams param) : fboc::ParamTest<NumLayersParams> (ctx, param) {} IterateResult build (FboBuilder& builder); }; IterateResult NumLayersTest::build (FboBuilder& builder) { TextureLayered* texCfg = DE_NULL; const GLenum target = GL_COLOR_ATTACHMENT0; switch (m_params.textureKind) { case GL_TEXTURE_3D: texCfg = &builder.makeConfig<Texture3D>(); break; case GL_TEXTURE_2D_ARRAY: texCfg = &builder.makeConfig<Texture2DArray>(); break; default: DE_ASSERT(!"Impossible case"); } texCfg->internalFormat = getDefaultFormat(target, GL_TEXTURE); texCfg->width = 64; texCfg->height = 64; texCfg->numLayers = m_params.numLayers; const GLuint tex = builder.glCreateTexture(*texCfg); TextureLayerAttachment* att = &builder.makeConfig<TextureLayerAttachment>(); att->layer = m_params.attachmentLayer; att->imageName = tex; builder.glAttach(target, att); return STOP; } enum { SAMPLES_NONE = -2, SAMPLES_TEXTURE = -1 }; struct NumSamplesParams { // >= 0: renderbuffer with N samples, -1: texture, -2: no attachment GLsizei numSamples[3]; static string getName (const NumSamplesParams& params); static string getDescription (const NumSamplesParams& params); }; string NumSamplesParams::getName (const NumSamplesParams& params) { ostringstream os; bool first = true; for (const GLsizei* ns = DE_ARRAY_BEGIN(params.numSamples); ns != DE_ARRAY_END(params.numSamples); ns++) { if (first) first = false; else os << "_"; if (*ns == SAMPLES_NONE) os << "none"; else if (*ns == SAMPLES_TEXTURE) os << "tex"; else os << "rbo" << *ns; } return os.str(); } string NumSamplesParams::getDescription (const NumSamplesParams& params) { ostringstream os; bool first = true; static const char* const s_names[] = { "color", "depth", "stencil" }; DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_names) == DE_LENGTH_OF_ARRAY(params.numSamples)); for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_names); i++) { GLsizei ns = params.numSamples[i]; if (ns == SAMPLES_NONE) continue; if (first) first = false; else os << ", "; if (ns == SAMPLES_TEXTURE) os << "texture " << s_names[i] << " attachment"; else os << ns << "-sample renderbuffer " << s_names[i] << " attachment"; } return os.str(); } class NumSamplesTest : public fboc::ParamTest<NumSamplesParams> { public: NumSamplesTest (fboc::Context& ctx, NumSamplesParams param) : fboc::ParamTest<NumSamplesParams> (ctx, param) {} IterateResult build (FboBuilder& builder); }; IterateResult NumSamplesTest::build (FboBuilder& builder) { static const GLenum s_targets[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_DEPTH_ATTACHMENT, }; // Non-integer formats for each attachment type. // \todo [2013-12-17 lauri] Add fixed/floating/integer metadata for formats so // we can pick one smartly or maybe try several. static const GLenum s_formats[] = { GL_RGBA8, GL_RGB565, GL_DEPTH_COMPONENT24, }; DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(s_targets) == DE_LENGTH_OF_ARRAY(m_params.numSamples)); for (int i = 0; i < DE_LENGTH_OF_ARRAY(s_targets); i++) { const GLenum target = s_targets[i]; const ImageFormat fmt = { s_formats[i], GL_NONE }; const GLsizei ns = m_params.numSamples[i]; if (ns == -2) continue; if (ns == -1) { attachTargetToNew(target, GL_TEXTURE, fmt, 64, 64, builder); } else { Renderbuffer& rboCfg = builder.makeConfig<Renderbuffer>(); rboCfg.internalFormat = fmt; rboCfg.width = rboCfg.height = 64; rboCfg.numSamples = ns; const GLuint rbo = builder.glCreateRbo(rboCfg); // Implementations do not necessarily support sample sizes greater than 1. TCU_CHECK_AND_THROW(NotSupportedError, builder.getError() != GL_INVALID_OPERATION, "Unsupported number of samples"); RenderbufferAttachment& att = builder.makeConfig<RenderbufferAttachment>(); att.imageName = rbo; builder.glAttach(target, &att); } } return STOP; } class ES3CheckerFactory : public CheckerFactory { public: Checker* createChecker (const glu::RenderContext& ctx) { return new ES3Checker(ctx); } }; class TestGroup : public TestCaseGroup { public: TestGroup (Context& context); void init (void); private: ES3CheckerFactory m_checkerFactory; fboc::Context m_fboc; }; void TestGroup::init (void) { addChild(m_fboc.createRenderableTests()); addChild(m_fboc.createAttachmentTests()); addChild(m_fboc.createSizeTests()); TestCaseGroup* layerTests = new TestCaseGroup( getContext(), "layer", "Tests for layer attachments"); static const NumLayersParams s_layersParams[] = { // textureKind numLayers attachmentKind { GL_TEXTURE_2D_ARRAY, 1, 0 }, { GL_TEXTURE_2D_ARRAY, 1, 3 }, { GL_TEXTURE_2D_ARRAY, 4, 3 }, { GL_TEXTURE_2D_ARRAY, 4, 15 }, { GL_TEXTURE_3D, 1, 0 }, { GL_TEXTURE_3D, 1, 15 }, { GL_TEXTURE_3D, 4, 15 }, { GL_TEXTURE_3D, 64, 15 }, }; for (const NumLayersParams* lp = DE_ARRAY_BEGIN(s_layersParams); lp != DE_ARRAY_END(s_layersParams); ++lp) layerTests->addChild(new NumLayersTest(m_fboc, *lp)); addChild(layerTests); TestCaseGroup* sampleTests = new TestCaseGroup( getContext(), "samples", "Tests for multisample attachments"); static const NumSamplesParams s_samplesParams[] = { { { 0, SAMPLES_NONE, SAMPLES_NONE } }, { { 1, SAMPLES_NONE, SAMPLES_NONE } }, { { 2, SAMPLES_NONE, SAMPLES_NONE } }, { { 0, SAMPLES_TEXTURE, SAMPLES_NONE } }, { { 1, SAMPLES_TEXTURE, SAMPLES_NONE } }, { { 2, SAMPLES_TEXTURE, SAMPLES_NONE } }, { { 2, 1, SAMPLES_NONE } }, { { 2, 2, SAMPLES_NONE } }, { { 0, 0, SAMPLES_TEXTURE } }, { { 1, 2, 0 } }, { { 2, 2, 0 } }, { { 1, 1, 1 } }, { { 1, 2, 4 } }, }; for (const NumSamplesParams* lp = DE_ARRAY_BEGIN(s_samplesParams); lp != DE_ARRAY_END(s_samplesParams); ++lp) sampleTests->addChild(new NumSamplesTest(m_fboc, *lp)); addChild(sampleTests); } 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_es3Formats); const FormatExtEntries extRange = GLS_ARRAY_RANGE(s_es3ExtFormats); m_fboc.addFormats(stdRange); m_fboc.addExtFormats(extRange); m_fboc.setHaveMulticolorAtts(true); // Vanilla ES3 has multiple color attachments } tcu::TestCaseGroup* createFboCompletenessTests (Context& context) { return new TestGroup(context); } } // Functional