xref: /aosp_15_r20/external/deqp/modules/gles2/functional/es2fFboCompletenessTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL (ES) Module
3  * -----------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Framebuffer completeness tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es2fFboCompletenessTests.hpp"
25 
26 #include "glsFboCompletenessTests.hpp"
27 #include "gluObjectWrapper.hpp"
28 
29 using namespace glw;
30 using deqp::gls::Range;
31 using namespace deqp::gls::FboUtil;
32 using namespace deqp::gls::FboUtil::config;
33 namespace fboc = deqp::gls::fboc;
34 typedef tcu::TestCase::IterateResult IterateResult;
35 
36 namespace deqp
37 {
38 namespace gles2
39 {
40 namespace Functional
41 {
42 
43 static const FormatKey s_es2ColorRenderables[] = {
44     GL_RGBA4,
45     GL_RGB5_A1,
46     GL_RGB565,
47 };
48 
49 // GLES2 does not strictly allow these, but this seems to be a bug in the
50 // specification. For now, let's assume the unsized formats corresponding to
51 // the color-renderable sized formats are allowed.
52 // See https://cvs.khronos.org/bugzilla/show_bug.cgi?id=7333
53 
54 static const FormatKey s_es2UnsizedColorRenderables[] = {GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4),
55                                                          GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1),
56                                                          GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_SHORT_5_6_5)};
57 
58 static const FormatKey s_es2DepthRenderables[] = {
59     GL_DEPTH_COMPONENT16,
60 };
61 
62 static const FormatKey s_es2StencilRenderables[] = {
63     GL_STENCIL_INDEX8,
64 };
65 
66 static const FormatEntry s_es2Formats[] = {
67     {COLOR_RENDERABLE | TEXTURE_VALID, GLS_ARRAY_RANGE(s_es2UnsizedColorRenderables)},
68     {REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID, GLS_ARRAY_RANGE(s_es2ColorRenderables)},
69     {REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID, GLS_ARRAY_RANGE(s_es2DepthRenderables)},
70     {REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID, GLS_ARRAY_RANGE(s_es2StencilRenderables)},
71 };
72 
73 // We have here only the extensions that are redundant in vanilla GLES3. Those
74 // that are applicable both to GLES2 and GLES3 are in glsFboCompletenessTests.cpp.
75 
76 // GL_OES_texture_float
77 static const FormatKey s_oesTextureFloatFormats[] = {
78     GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_FLOAT),
79     GLS_UNSIZED_FORMATKEY(GL_RGB, GL_FLOAT),
80 };
81 
82 // GL_OES_texture_half_float
83 static const FormatKey s_oesTextureHalfFloatFormats[] = {
84     GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_HALF_FLOAT_OES),
85     GLS_UNSIZED_FORMATKEY(GL_RGB, GL_HALF_FLOAT_OES),
86 };
87 
88 // GL_EXT_color_buffer_half_float
89 static const FormatKey s_extColorBufferHalfFloatUnsized[] = {
90     GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_HALF_FLOAT_OES),
91 };
92 
93 // GL_EXT_sRGB_write_control
94 static const FormatKey s_extSrgbWriteControlFormats[] = {GL_SRGB8_ALPHA8};
95 
96 // DEQP_gles3_core_no_extension_features
97 static const FormatKey s_es3NoExtRboFormats[] = {
98     GL_RGB10_A2,
99     GL_SRGB8_ALPHA8,
100 };
101 static const FormatKey s_es3NoExtTextureFormats[] = {
102     GL_R16F, GL_RG16F, GL_RGB16F, GL_RGBA16F, GL_R11F_G11F_B10F,
103 };
104 static const FormatKey s_es3NoExtTextureColorRenderableFormats[] = {
105     GL_R8, GL_RG8, GL_RGB8, GL_RGBA4, GL_RGB5_A1, GL_RGBA8, GL_RGB10_A2, GL_RGB565, GL_SRGB8_ALPHA8,
106 };
107 
108 // with ES3 core and GL_EXT_color_buffer_float
109 static const FormatKey s_es3NoExtExtColorBufferFloatFormats[] = {
110     // \note Only the GLES2+exts subset of formats
111     GL_R11F_G11F_B10F,
112     GL_RGBA16F,
113     GL_RG16F,
114     GL_R16F,
115 };
116 
117 // with ES3 core with OES_texture_stencil8
118 static const FormatKey s_es3NoExtOesTextureStencil8Formats[] = {
119     GL_STENCIL_INDEX8,
120 };
121 
122 // DEQP_gles3_core_changed_features
123 static const FormatKey s_es3NoExtDepthRenderable[] = {
124     GL_DEPTH_COMPONENT16,
125     GL_DEPTH_COMPONENT24,
126     GL_DEPTH24_STENCIL8,
127 };
128 
129 static const FormatKey s_es3NoExtStencilRenderable[] = {
130     GL_DEPTH24_STENCIL8,
131 };
132 
133 static const FormatExtEntry s_es2ExtFormats[] = {
134     // The extension does not specify these to be color-renderable.
135     {"GL_OES_texture_float", (uint32_t)TEXTURE_VALID, GLS_ARRAY_RANGE(s_oesTextureFloatFormats)},
136     {"GL_OES_texture_half_float", (uint32_t)TEXTURE_VALID, GLS_ARRAY_RANGE(s_oesTextureHalfFloatFormats)},
137     // However GL_EXT_color_buffer_half_float does say explicitly
138     // that the RGBA variant should be renderable.
139     {"GL_OES_texture_half_float GL_EXT_color_buffer_half_float", (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE),
140      GLS_ARRAY_RANGE(s_extColorBufferHalfFloatUnsized)},
141 
142     // GL_EXT_sRGB_write_control makes SRGB8_ALPHA8 color-renderable
143     {"GL_EXT_sRGB_write_control",
144      (uint32_t)(REQUIRED_RENDERABLE | TEXTURE_VALID | COLOR_RENDERABLE | RENDERBUFFER_VALID),
145      GLS_ARRAY_RANGE(s_extSrgbWriteControlFormats)},
146 
147     // Since GLES3 is "backwards compatible" to GLES2, we might actually be running on a GLES3
148     // context. Since GLES3 added some features to core with no corresponding GLES2 extension,
149     // some tests might produce wrong results (since they are using rules of GLES2 & extensions)
150     //
151     // To avoid this, require new features of GLES3 that have no matching GLES2 extension if
152     // context is GLES3. This can be done with a DEQP_* extensions.
153     //
154     // \note Not all feature changes are listed here but only those that alter GLES2 subset of
155     //       the formats
156     {"DEQP_gles3_core_compatible", (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
157      GLS_ARRAY_RANGE(s_es3NoExtRboFormats)},
158     {"DEQP_gles3_core_compatible", (uint32_t)TEXTURE_VALID, GLS_ARRAY_RANGE(s_es3NoExtTextureFormats)},
159     {"DEQP_gles3_core_compatible",
160      (uint32_t)(REQUIRED_RENDERABLE | TEXTURE_VALID | COLOR_RENDERABLE | RENDERBUFFER_VALID),
161      GLS_ARRAY_RANGE(s_es3NoExtTextureColorRenderableFormats)},
162     {"DEQP_gles3_core_compatible GL_EXT_color_buffer_float",
163      (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
164      GLS_ARRAY_RANGE(s_es3NoExtExtColorBufferFloatFormats)},
165     {"DEQP_gles3_core_compatible GL_OES_texture_stencil8",
166      (uint32_t)(REQUIRED_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID),
167      GLS_ARRAY_RANGE(s_es3NoExtOesTextureStencil8Formats)},
168     {"DEQP_gles3_core_compatible GL_OES_texture_half_float GL_EXT_color_buffer_half_float",
169      (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE), GLS_ARRAY_RANGE(s_oesTextureHalfFloatFormats)},
170     {"DEQP_gles3_core_compatible",
171      (uint32_t)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID),
172      GLS_ARRAY_RANGE(s_es3NoExtDepthRenderable)},
173     {"DEQP_gles3_core_compatible",
174      (uint32_t)(REQUIRED_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID),
175      GLS_ARRAY_RANGE(s_es3NoExtStencilRenderable)},
176 };
177 
178 class ES2Checker : public Checker
179 {
180 public:
181     ES2Checker(const glu::RenderContext &ctx, const FormatDB &formats);
182     void check(GLenum attPoint, const Attachment &att, const Image *image);
183 
184 private:
185     GLsizei m_width;  //< The common width of images
186     GLsizei m_height; //< The common height of images
187 };
188 
ES2Checker(const glu::RenderContext & ctx,const FormatDB & formats)189 ES2Checker::ES2Checker(const glu::RenderContext &ctx, const FormatDB &formats)
190     : Checker(ctx, formats)
191     , m_width(-1)
192     , m_height(-1)
193 {
194 }
195 
check(GLenum attPoint,const Attachment & att,const Image * image)196 void ES2Checker::check(GLenum attPoint, const Attachment &att, const Image *image)
197 {
198     DE_UNREF(attPoint);
199     DE_UNREF(att);
200     // GLES2: "All attached images have the same width and height."
201     if (m_width == -1)
202     {
203         m_width  = image->width;
204         m_height = image->height;
205     }
206     else if (image->width != m_width || image->height != m_height)
207     {
208         // Since GLES3 is "backwards compatible" to GLES2, we might actually be running
209         // on a GLES3 context. On GLES3, FRAMEBUFFER_INCOMPLETE_DIMENSIONS is not generated
210         // if attachments have different sizes.
211         if (!gls::FboUtil::checkExtensionSupport(m_renderCtx, "DEQP_gles3_core_compatible"))
212         {
213             // running on GLES2
214             addFBOStatus(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS, "Sizes of attachments differ");
215         }
216     }
217     // GLES2, 4.4.5: "some implementations may not support rendering to
218     // particular combinations of internal formats. If the combination of
219     // formats of the images attached to a framebuffer object are not
220     // supported by the implementation, then the framebuffer is not complete
221     // under the clause labeled FRAMEBUFFER_UNSUPPORTED."
222     //
223     // Hence it is _always_ allowed to report FRAMEBUFFER_UNSUPPORTED.
224     addPotentialFBOStatus(GL_FRAMEBUFFER_UNSUPPORTED, "Particular format combinations need not to be supported");
225 }
226 
227 struct FormatCombination
228 {
229     GLenum colorKind;
230     ImageFormat colorFmt;
231     GLenum depthKind;
232     ImageFormat depthFmt;
233     GLenum stencilKind;
234     ImageFormat stencilFmt;
235 };
236 
237 class SupportedCombinationTest : public fboc::TestBase
238 {
239 public:
SupportedCombinationTest(fboc::Context & ctx,const char * name,const char * desc)240     SupportedCombinationTest(fboc::Context &ctx, const char *name, const char *desc) : TestBase(ctx, name, desc)
241     {
242     }
243 
244     IterateResult iterate(void);
245     bool tryCombination(const FormatCombination &comb);
246     GLenum formatKind(ImageFormat fmt);
247 };
248 
tryCombination(const FormatCombination & comb)249 bool SupportedCombinationTest::tryCombination(const FormatCombination &comb)
250 {
251     glu::Framebuffer fbo(m_ctx.getRenderContext());
252     FboBuilder builder(*fbo, GL_FRAMEBUFFER, fboc::gl(*this));
253 
254     attachTargetToNew(GL_COLOR_ATTACHMENT0, comb.colorKind, comb.colorFmt, 64, 64, builder);
255     attachTargetToNew(GL_DEPTH_ATTACHMENT, comb.depthKind, comb.depthFmt, 64, 64, builder);
256     attachTargetToNew(GL_STENCIL_ATTACHMENT, comb.stencilKind, comb.stencilFmt, 64, 64, builder);
257 
258     const GLenum glStatus = fboc::gl(*this).checkFramebufferStatus(GL_FRAMEBUFFER);
259 
260     return (glStatus == GL_FRAMEBUFFER_COMPLETE);
261 }
262 
formatKind(ImageFormat fmt)263 GLenum SupportedCombinationTest::formatKind(ImageFormat fmt)
264 {
265     if (fmt.format == GL_NONE)
266         return GL_NONE;
267 
268     const FormatFlags flags = m_ctx.getCoreFormats().getFormatInfo(fmt);
269     const bool rbo          = (flags & RENDERBUFFER_VALID) != 0;
270     // exactly one of renderbuffer and texture is supported by vanilla GLES2 formats
271     DE_ASSERT(rbo != ((flags & TEXTURE_VALID) != 0));
272 
273     return rbo ? GL_RENDERBUFFER : GL_TEXTURE;
274 }
275 
iterate(void)276 IterateResult SupportedCombinationTest::iterate(void)
277 {
278     const FormatDB &db     = m_ctx.getCoreFormats();
279     const ImageFormat none = ImageFormat::none();
280     Formats colorFmts      = db.getFormats(COLOR_RENDERABLE);
281     Formats depthFmts      = db.getFormats(DEPTH_RENDERABLE);
282     Formats stencilFmts    = db.getFormats(STENCIL_RENDERABLE);
283     FormatCombination comb;
284     bool succ = false;
285 
286     colorFmts.insert(none);
287     depthFmts.insert(none);
288     stencilFmts.insert(none);
289 
290     for (Formats::const_iterator col = colorFmts.begin(); col != colorFmts.end(); col++)
291     {
292         comb.colorFmt  = *col;
293         comb.colorKind = formatKind(*col);
294         for (Formats::const_iterator dep = depthFmts.begin(); dep != depthFmts.end(); dep++)
295         {
296             comb.depthFmt  = *dep;
297             comb.depthKind = formatKind(*dep);
298             for (Formats::const_iterator stc = stencilFmts.begin(); stc != stencilFmts.end(); stc++)
299             {
300                 comb.stencilFmt  = *stc;
301                 comb.stencilKind = formatKind(*stc);
302                 succ             = tryCombination(comb);
303                 if (succ)
304                     break;
305             }
306         }
307     }
308 
309     if (succ)
310         pass();
311     else
312         fail("No supported format combination found");
313 
314     return STOP;
315 }
316 
317 class ES2CheckerFactory : public CheckerFactory
318 {
319 public:
createChecker(const glu::RenderContext & ctx,const FormatDB & formats)320     Checker *createChecker(const glu::RenderContext &ctx, const FormatDB &formats)
321     {
322         return new ES2Checker(ctx, formats);
323     }
324 };
325 
326 class TestGroup : public TestCaseGroup
327 {
328 public:
329     TestGroup(Context &ctx);
330     void init(void);
331 
332 private:
333     ES2CheckerFactory m_checkerFactory;
334     fboc::Context m_fboc;
335 };
336 
TestGroup(Context & ctx)337 TestGroup::TestGroup(Context &ctx)
338     : TestCaseGroup(ctx, "completeness", "Completeness tests")
339     , m_checkerFactory()
340     , m_fboc(ctx.getTestContext(), ctx.getRenderContext(), m_checkerFactory)
341 {
342     const FormatEntries stdRange    = GLS_ARRAY_RANGE(s_es2Formats);
343     const FormatExtEntries extRange = GLS_ARRAY_RANGE(s_es2ExtFormats);
344 
345     m_fboc.addFormats(stdRange);
346     m_fboc.addExtFormats(extRange);
347     m_fboc.setHaveMulticolorAtts(ctx.getContextInfo().isExtensionSupported("GL_NV_fbo_color_attachments"));
348 }
349 
init(void)350 void TestGroup::init(void)
351 {
352     tcu::TestCaseGroup *attCombTests = m_fboc.createAttachmentTests();
353     addChild(m_fboc.createRenderableTests());
354     attCombTests->addChild(new SupportedCombinationTest(m_fboc, "exists_supported",
355                                                         "Test for existence of a supported combination of formats"));
356     addChild(attCombTests);
357     addChild(m_fboc.createSizeTests());
358 }
359 
createFboCompletenessTests(Context & context)360 tcu::TestCaseGroup *createFboCompletenessTests(Context &context)
361 {
362     return new TestGroup(context);
363 }
364 
365 } // namespace Functional
366 } // namespace gles2
367 } // namespace deqp
368