xref: /aosp_15_r20/external/deqp/modules/glshared/glsFboCompletenessTests.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 "glsFboCompletenessTests.hpp"
25 
26 #include "gluStrUtil.hpp"
27 #include "gluObjectWrapper.hpp"
28 #include "deStringUtil.hpp"
29 
30 #include <cctype>
31 #include <iterator>
32 #include <algorithm>
33 
34 using namespace glw;
35 using de::toLower;
36 using de::toString;
37 using glu::Framebuffer;
38 using glu::getErrorName;
39 using glu::getFramebufferStatusName;
40 using glu::getTextureFormatName;
41 using glu::getTypeName;
42 using glu::RenderContext;
43 using std::string;
44 using tcu::MessageBuilder;
45 using tcu::TestCase;
46 using tcu::TestCaseGroup;
47 using tcu::TestLog;
48 using tcu::TestNode;
49 using namespace deqp::gls::FboUtil;
50 using namespace deqp::gls::FboUtil::config;
51 typedef TestCase::IterateResult IterateResult;
52 
53 namespace deqp
54 {
55 namespace gls
56 {
57 namespace fboc
58 {
59 
60 namespace details
61 {
62 
63 // The following extensions are applicable both to ES2 and ES3.
64 
65 // GL_OES_depth_texture
66 static const FormatKey s_oesDepthTextureFormats[] = {
67     GLS_UNSIZED_FORMATKEY(GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT),
68     GLS_UNSIZED_FORMATKEY(GL_DEPTH_COMPONENT, GL_UNSIGNED_INT),
69 };
70 
71 // GL_OES_packed_depth_stencil
72 static const FormatKey s_oesPackedDepthStencilSizedFormats[] = {
73     GL_DEPTH24_STENCIL8,
74 };
75 
76 static const FormatKey s_oesPackedDepthStencilTexFormats[] = {
77     GLS_UNSIZED_FORMATKEY(GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8),
78 };
79 
80 // GL_OES_required_internalformat
81 static const FormatKey s_oesRequiredInternalFormatColorFormats[] = {
82     // Same as ES2 RBO formats, plus RGBA8 (even without OES_rgb8_rgba8)
83     GL_RGB5_A1, GL_RGBA8, GL_RGBA4, GL_RGB565};
84 
85 static const FormatKey s_oesRequiredInternalFormatDepthFormats[] = {
86     GL_DEPTH_COMPONENT16,
87 };
88 
89 // GL_EXT_color_buffer_half_float
90 static const FormatKey s_extColorBufferHalfFloatFormats[] = {
91     GL_RGBA16F,
92     GL_RGB16F,
93     GL_RG16F,
94     GL_R16F,
95 };
96 
97 static const FormatKey s_oesDepth24SizedFormats[] = {GL_DEPTH_COMPONENT24};
98 
99 static const FormatKey s_oesDepth32SizedFormats[] = {GL_DEPTH_COMPONENT32};
100 
101 static const FormatKey s_oesRgb8Rgba8RboFormats[] = {
102     GL_RGB8,
103     GL_RGBA8,
104 };
105 
106 static const FormatKey s_oesRequiredInternalFormatRgb8ColorFormat[] = {
107     GL_RGB8,
108 };
109 
110 static const FormatKey s_extTextureType2101010RevFormats[] = {
111     GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV),
112     GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_INT_2_10_10_10_REV),
113 };
114 
115 static const FormatKey s_oesRequiredInternalFormat10bitColorFormats[] = {
116     GL_RGB10_A2,
117     GL_RGB10,
118 };
119 
120 static const FormatKey s_extTextureRgRboFormats[] = {
121     GL_R8,
122     GL_RG8,
123 };
124 
125 static const FormatKey s_extTextureRgTexFormats[] = {
126     GLS_UNSIZED_FORMATKEY(GL_RED, GL_UNSIGNED_BYTE),
127     GLS_UNSIZED_FORMATKEY(GL_RG, GL_UNSIGNED_BYTE),
128 };
129 
130 static const FormatKey s_extTextureRgFloatTexFormats[] = {
131     GLS_UNSIZED_FORMATKEY(GL_RED, GL_FLOAT),
132     GLS_UNSIZED_FORMATKEY(GL_RG, GL_FLOAT),
133 };
134 
135 static const FormatKey s_extTextureRgHalfFloatTexFormats[] = {
136     GLS_UNSIZED_FORMATKEY(GL_RED, GL_HALF_FLOAT_OES),
137     GLS_UNSIZED_FORMATKEY(GL_RG, GL_HALF_FLOAT_OES),
138 };
139 
140 static const FormatKey s_nvPackedFloatRboFormats[] = {
141     GL_R11F_G11F_B10F,
142 };
143 
144 static const FormatKey s_nvPackedFloatTexFormats[] = {
145     GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV),
146 };
147 
148 static const FormatKey s_extSrgbRboFormats[] = {
149     GL_SRGB8_ALPHA8,
150 };
151 
152 static const FormatKey s_extSrgbRenderableTexFormats[] = {
153     GLS_UNSIZED_FORMATKEY(GL_SRGB_ALPHA, GL_UNSIGNED_BYTE),
154 };
155 
156 static const FormatKey s_extSrgbNonRenderableTexFormats[] = {
157     GLS_UNSIZED_FORMATKEY(GL_SRGB, GL_UNSIGNED_BYTE),
158 };
159 
160 static const FormatKey s_nvSrgbFormatsRboFormats[] = {
161     GL_SRGB8,
162 };
163 
164 static const FormatKey s_nvSrgbFormatsTextureFormats[] = {
165     GL_SRGB8,
166 
167     // The extension does not actually require any unsized format
168     // to be renderable. However, the renderablility of unsized
169     // SRGB,UBYTE internalformat-type pair is implied.
170     GLS_UNSIZED_FORMATKEY(GL_SRGB, GL_UNSIGNED_BYTE),
171 };
172 
173 static const FormatKey s_oesRgb8Rgba8TexFormats[] = {
174     GLS_UNSIZED_FORMATKEY(GL_RGB, GL_UNSIGNED_BYTE),
175     GLS_UNSIZED_FORMATKEY(GL_RGBA, GL_UNSIGNED_BYTE),
176 };
177 
178 static const FormatKey s_extTextureSRGBR8Formats[] = {
179     GL_SR8_EXT,
180 };
181 
182 static const FormatKey s_extTextureSRGBRG8Formats[] = {
183     GL_SRG8_EXT,
184 };
185 
186 static const FormatKey s_qcomRenderSRGBR8RG8Formats[] = {
187     GL_SR8_EXT,
188     GL_SRG8_EXT,
189 };
190 
191 static const FormatExtEntry s_esExtFormats[] = {
192     {
193         "GL_OES_depth_texture",
194         (uint32_t)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | TEXTURE_VALID),
195         GLS_ARRAY_RANGE(s_oesDepthTextureFormats),
196     },
197     {"GL_OES_packed_depth_stencil",
198      (uint32_t)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | STENCIL_RENDERABLE | RENDERBUFFER_VALID),
199      GLS_ARRAY_RANGE(s_oesPackedDepthStencilSizedFormats)},
200     {"GL_OES_packed_depth_stencil GL_OES_required_internalformat", (uint32_t)TEXTURE_VALID,
201      GLS_ARRAY_RANGE(s_oesPackedDepthStencilSizedFormats)},
202     {"GL_OES_packed_depth_stencil GL_OES_depth_texture",
203      (uint32_t)(DEPTH_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID),
204      GLS_ARRAY_RANGE(s_oesPackedDepthStencilTexFormats)},
205     // The ANGLE extension incorporates GL_OES_depth_texture/GL_OES_packed_depth_stencil.
206     {
207         "GL_ANGLE_depth_texture",
208         (uint32_t)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | TEXTURE_VALID),
209         GLS_ARRAY_RANGE(s_oesDepthTextureFormats),
210     },
211     {
212         "GL_OES_packed_depth_stencil GL_ANGLE_depth_texture",
213         (uint32_t)(DEPTH_RENDERABLE | STENCIL_RENDERABLE | TEXTURE_VALID),
214         GLS_ARRAY_RANGE(s_oesPackedDepthStencilTexFormats),
215     },
216     // \todo [2013-12-10 lauri] Find out if OES_texture_half_float is really a
217     // requirement on ES3 also. Or is color_buffer_half_float applicatble at
218     // all on ES3, since there's also EXT_color_buffer_float?
219     {"GL_OES_texture_half_float GL_EXT_color_buffer_half_float",
220      (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
221      GLS_ARRAY_RANGE(s_extColorBufferHalfFloatFormats)},
222 
223     // OES_required_internalformat doesn't actually specify that these are renderable,
224     // since it was written against ES 1.1.
225     {"GL_OES_required_internalformat",
226      // Allow but don't require RGBA8 to be color-renderable if
227      // OES_rgb8_rgba8 is not present.
228      (uint32_t)(COLOR_RENDERABLE | TEXTURE_VALID), GLS_ARRAY_RANGE(s_oesRequiredInternalFormatColorFormats)},
229     {"GL_OES_required_internalformat", (uint32_t)(DEPTH_RENDERABLE | TEXTURE_VALID),
230      GLS_ARRAY_RANGE(s_oesRequiredInternalFormatDepthFormats)},
231     {"GL_EXT_texture_rg", (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID),
232      GLS_ARRAY_RANGE(s_extTextureRgRboFormats)},
233     // These are not specified to be color-renderable, but the wording is
234     // exactly as ambiguous as the wording in the ES2 spec.
235     {"GL_EXT_texture_rg", (uint32_t)(COLOR_RENDERABLE | TEXTURE_VALID), GLS_ARRAY_RANGE(s_extTextureRgTexFormats)},
236     {"GL_EXT_texture_rg GL_OES_texture_float", (uint32_t)(COLOR_RENDERABLE | TEXTURE_VALID),
237      GLS_ARRAY_RANGE(s_extTextureRgFloatTexFormats)},
238     {"GL_EXT_texture_rg GL_OES_texture_half_float", (uint32_t)(COLOR_RENDERABLE | TEXTURE_VALID),
239      GLS_ARRAY_RANGE(s_extTextureRgHalfFloatTexFormats)},
240 
241     {"GL_NV_packed_float", (uint32_t)(COLOR_RENDERABLE | TEXTURE_VALID), GLS_ARRAY_RANGE(s_nvPackedFloatTexFormats)},
242     {"GL_NV_packed_float GL_EXT_color_buffer_half_float",
243      (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
244      GLS_ARRAY_RANGE(s_nvPackedFloatRboFormats)},
245 
246     {"GL_EXT_sRGB", (uint32_t)(COLOR_RENDERABLE | TEXTURE_VALID), GLS_ARRAY_RANGE(s_extSrgbRenderableTexFormats)},
247     {"GL_EXT_sRGB", (uint32_t)TEXTURE_VALID, GLS_ARRAY_RANGE(s_extSrgbNonRenderableTexFormats)},
248     {"GL_EXT_sRGB", (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
249      GLS_ARRAY_RANGE(s_extSrgbRboFormats)},
250     {"GL_NV_sRGB_formats", (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
251      GLS_ARRAY_RANGE(s_nvSrgbFormatsRboFormats)},
252     {"GL_NV_sRGB_formats", (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | TEXTURE_VALID),
253      GLS_ARRAY_RANGE(s_nvSrgbFormatsTextureFormats)},
254 
255     // In Khronos bug 7333 discussion, the consensus is that these texture
256     // formats, at least, should be color-renderable. Still, that cannot be
257     // found in any extension specs, so only allow it, not require it.
258     {"GL_OES_rgb8_rgba8", (uint32_t)(COLOR_RENDERABLE | TEXTURE_VALID), GLS_ARRAY_RANGE(s_oesRgb8Rgba8TexFormats)},
259     {"GL_OES_rgb8_rgba8", (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID),
260      GLS_ARRAY_RANGE(s_oesRgb8Rgba8RboFormats)},
261     {"GL_OES_rgb8_rgba8 GL_OES_required_internalformat", (uint32_t)TEXTURE_VALID,
262      GLS_ARRAY_RANGE(s_oesRequiredInternalFormatRgb8ColorFormat)},
263 
264     // The depth-renderability of the depth RBO formats is not explicitly
265     // spelled out, but all renderbuffer formats are meant to be renderable.
266     {"GL_OES_depth24", (uint32_t)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID),
267      GLS_ARRAY_RANGE(s_oesDepth24SizedFormats)},
268     {"GL_OES_depth24 GL_OES_required_internalformat GL_OES_depth_texture", (uint32_t)TEXTURE_VALID,
269      GLS_ARRAY_RANGE(s_oesDepth24SizedFormats)},
270 
271     {"GL_OES_depth32", (uint32_t)(REQUIRED_RENDERABLE | DEPTH_RENDERABLE | RENDERBUFFER_VALID),
272      GLS_ARRAY_RANGE(s_oesDepth32SizedFormats)},
273     {"GL_OES_depth32 GL_OES_required_internalformat GL_OES_depth_texture", (uint32_t)TEXTURE_VALID,
274      GLS_ARRAY_RANGE(s_oesDepth32SizedFormats)},
275 
276     {"GL_EXT_texture_type_2_10_10_10_REV",
277      (uint32_t)TEXTURE_VALID, // explicitly unrenderable
278      GLS_ARRAY_RANGE(s_extTextureType2101010RevFormats)},
279     {"GL_EXT_texture_type_2_10_10_10_REV GL_OES_required_internalformat",
280      (uint32_t)TEXTURE_VALID, // explicitly unrenderable
281      GLS_ARRAY_RANGE(s_oesRequiredInternalFormat10bitColorFormats)},
282 
283     {"GL_EXT_texture_sRGB_R8", (uint32_t)TEXTURE_VALID, GLS_ARRAY_RANGE(s_extTextureSRGBR8Formats)},
284     {"GL_EXT_texture_sRGB_RG8", (uint32_t)TEXTURE_VALID, GLS_ARRAY_RANGE(s_extTextureSRGBRG8Formats)},
285 
286     {"GL_QCOM_render_sRGB_R8_RG8",
287      (uint32_t)(REQUIRED_RENDERABLE | COLOR_RENDERABLE | RENDERBUFFER_VALID | TEXTURE_VALID),
288      GLS_ARRAY_RANGE(s_qcomRenderSRGBR8RG8Formats)},
289 };
290 
Context(TestContext & testCtx,RenderContext & renderCtx,CheckerFactory & factory)291 Context::Context(TestContext &testCtx, RenderContext &renderCtx, CheckerFactory &factory)
292     : m_testCtx(testCtx)
293     , m_renderCtx(renderCtx)
294     , m_verifier(m_ctxFormats, factory, renderCtx)
295     , m_haveMultiColorAtts(false)
296 {
297     FormatExtEntries extRange = GLS_ARRAY_RANGE(s_esExtFormats);
298     addExtFormats(extRange);
299 }
300 
addFormats(FormatEntries fmtRange)301 void Context::addFormats(FormatEntries fmtRange)
302 {
303     FboUtil::addFormats(m_coreFormats, fmtRange);
304     FboUtil::addFormats(m_ctxFormats, fmtRange);
305     FboUtil::addFormats(m_allFormats, fmtRange);
306 }
307 
addExtFormats(FormatExtEntries extRange)308 void Context::addExtFormats(FormatExtEntries extRange)
309 {
310     FboUtil::addExtFormats(m_ctxFormats, extRange, &m_renderCtx);
311     FboUtil::addExtFormats(m_allFormats, extRange, DE_NULL);
312 }
313 
pass(void)314 void TestBase::pass(void)
315 {
316     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
317 }
318 
qualityWarning(const char * msg)319 void TestBase::qualityWarning(const char *msg)
320 {
321     m_testCtx.setTestResult(QP_TEST_RESULT_QUALITY_WARNING, msg);
322 }
323 
fail(const char * msg)324 void TestBase::fail(const char *msg)
325 {
326     m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, msg);
327 }
328 
gl(const TestBase & test)329 const glw::Functions &gl(const TestBase &test)
330 {
331     return test.getContext().getRenderContext().getFunctions();
332 }
333 
isFormatFeatureSupported(const FormatDB & db,const ImageFormat & format,FormatFlags feature)334 static bool isFormatFeatureSupported(const FormatDB &db, const ImageFormat &format, FormatFlags feature)
335 {
336     return db.isKnownFormat(format) && ((db.getFormatInfo(format) & feature) == feature);
337 }
338 
logAffectingExtensions(const char * prefix,const FormatDB & db,const ImageFormat & format,FormatFlags feature,tcu::MessageBuilder & msg)339 static void logAffectingExtensions(const char *prefix, const FormatDB &db, const ImageFormat &format,
340                                    FormatFlags feature, tcu::MessageBuilder &msg)
341 {
342     const std::set<std::set<std::string>> rows = db.getFormatFeatureExtensions(format, feature);
343 
344     for (std::set<std::set<std::string>>::const_iterator rowIt = rows.begin(); rowIt != rows.end(); ++rowIt)
345     {
346         const std::set<std::string> &requiredExtensions = *rowIt;
347         std::set<std::string>::const_iterator it        = requiredExtensions.begin();
348         std::string extName;
349 
350         msg << prefix;
351 
352         extName = *it++;
353         while (it != requiredExtensions.end())
354         {
355             msg << getExtensionDescription(extName);
356             extName = *it++;
357             msg << (it == requiredExtensions.end() ? " and " : ", ");
358         }
359 
360         msg << getExtensionDescription(extName) << '\n';
361     }
362 }
363 
logFormatInfo(const config::Framebuffer & fbo,const FormatDB & ctxFormats,const FormatDB & coreFormats,const FormatDB & allFormats,tcu::TestLog & log)364 static void logFormatInfo(const config::Framebuffer &fbo, const FormatDB &ctxFormats, const FormatDB &coreFormats,
365                           const FormatDB &allFormats, tcu::TestLog &log)
366 {
367     static const struct
368     {
369         const char *name;
370         const FormatFlags flag;
371     } s_renderability[] = {
372         {"color-renderable", COLOR_RENDERABLE},
373         {"depth-renderable", DEPTH_RENDERABLE},
374         {"stencil-renderable", STENCIL_RENDERABLE},
375     };
376 
377     std::set<ImageFormat> formats;
378 
379     for (config::TextureMap::const_iterator it = fbo.textures.begin(); it != fbo.textures.end(); ++it)
380         formats.insert(it->second->internalFormat);
381     for (config::RboMap::const_iterator it = fbo.rbos.begin(); it != fbo.rbos.end(); ++it)
382         formats.insert(it->second->internalFormat);
383 
384     if (!formats.empty())
385     {
386         const tcu::ScopedLogSection supersection(log, "Format", "Format info");
387 
388         for (std::set<ImageFormat>::const_iterator it = formats.begin(); it != formats.end(); ++it)
389         {
390             const tcu::ScopedLogSection section(log, "FormatInfo", de::toString(*it));
391 
392             // texture validity
393             if (isFormatFeatureSupported(ctxFormats, *it, TEXTURE_VALID))
394             {
395                 tcu::MessageBuilder msg(&log);
396                 msg << "* Valid texture format\n";
397 
398                 if (isFormatFeatureSupported(coreFormats, *it, TEXTURE_VALID))
399                     msg << "\t* core feature";
400                 else
401                 {
402                     msg << "\t* defined in supported extension(s):\n";
403                     logAffectingExtensions("\t\t- ", ctxFormats, *it, TEXTURE_VALID, msg);
404                 }
405 
406                 msg << tcu::TestLog::EndMessage;
407             }
408             else
409             {
410                 tcu::MessageBuilder msg(&log);
411                 msg << "* Unsupported texture format\n";
412 
413                 if (isFormatFeatureSupported(allFormats, *it, TEXTURE_VALID))
414                 {
415                     msg << "\t* requires any of the extensions or combinations:\n";
416                     logAffectingExtensions("\t\t- ", allFormats, *it, TEXTURE_VALID, msg);
417                 }
418                 else
419                     msg << "\t* no extension can make this format valid";
420 
421                 msg << tcu::TestLog::EndMessage;
422             }
423 
424             // RBO validity
425             if (isFormatFeatureSupported(ctxFormats, *it, RENDERBUFFER_VALID))
426             {
427                 tcu::MessageBuilder msg(&log);
428                 msg << "* Valid renderbuffer format\n";
429 
430                 if (isFormatFeatureSupported(coreFormats, *it, RENDERBUFFER_VALID))
431                     msg << "\t* core feature";
432                 else
433                 {
434                     msg << "\t* defined in supported extension(s):\n";
435                     logAffectingExtensions("\t\t- ", ctxFormats, *it, RENDERBUFFER_VALID, msg);
436                 }
437 
438                 msg << tcu::TestLog::EndMessage;
439             }
440             else
441             {
442                 tcu::MessageBuilder msg(&log);
443                 msg << "* Unsupported renderbuffer format\n";
444 
445                 if (isFormatFeatureSupported(allFormats, *it, RENDERBUFFER_VALID))
446                 {
447                     msg << "\t* requires any of the extensions or combinations:\n";
448                     logAffectingExtensions("\t\t- ", allFormats, *it, RENDERBUFFER_VALID, msg);
449                 }
450                 else
451                     msg << "\t* no extension can make this format valid";
452 
453                 msg << tcu::TestLog::EndMessage;
454             }
455 
456             // renderability
457             for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_renderability); ++ndx)
458             {
459                 if (isFormatFeatureSupported(ctxFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE))
460                 {
461                     tcu::MessageBuilder msg(&log);
462                     msg << "* Format is " << s_renderability[ndx].name << "\n";
463 
464                     if (isFormatFeatureSupported(coreFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE))
465                         msg << "\t* core feature";
466                     else
467                     {
468                         msg << "\t* defined in supported extension(s):\n";
469                         logAffectingExtensions("\t\t- ", ctxFormats, *it,
470                                                s_renderability[ndx].flag | REQUIRED_RENDERABLE, msg);
471                     }
472 
473                     msg << tcu::TestLog::EndMessage;
474                 }
475                 else if (isFormatFeatureSupported(ctxFormats, *it, s_renderability[ndx].flag))
476                 {
477                     tcu::MessageBuilder msg(&log);
478                     msg << "* Format is allowed to be " << s_renderability[ndx].name << " but not required\n";
479 
480                     if (isFormatFeatureSupported(coreFormats, *it, s_renderability[ndx].flag))
481                         msg << "\t* core feature";
482                     else if (isFormatFeatureSupported(allFormats, *it, s_renderability[ndx].flag))
483                     {
484                         msg << "\t* extensions that would make format " << s_renderability[ndx].name << ":\n";
485                         logAffectingExtensions("\t\t- ", allFormats, *it, s_renderability[ndx].flag, msg);
486                     }
487                     else
488                         msg << "\t* no extension can make this format " << s_renderability[ndx].name;
489 
490                     msg << tcu::TestLog::EndMessage;
491                 }
492                 else
493                 {
494                     tcu::MessageBuilder msg(&log);
495                     msg << "* Format is NOT " << s_renderability[ndx].name << "\n";
496 
497                     if (isFormatFeatureSupported(allFormats, *it, s_renderability[ndx].flag))
498                     {
499                         if (isFormatFeatureSupported(allFormats, *it, s_renderability[ndx].flag | REQUIRED_RENDERABLE))
500                         {
501                             msg << "\t* extensions that would make format " << s_renderability[ndx].name << ":\n";
502                             logAffectingExtensions("\t\t- ", allFormats, *it,
503                                                    s_renderability[ndx].flag | REQUIRED_RENDERABLE, msg);
504                         }
505                         else
506                         {
507                             msg << "\t* extensions that are allowed to make format " << s_renderability[ndx].name
508                                 << ":\n";
509                             logAffectingExtensions("\t\t- ", allFormats, *it, s_renderability[ndx].flag, msg);
510                         }
511                     }
512                     else
513                         msg << "\t* no extension can make this format " << s_renderability[ndx].name;
514 
515                     msg << tcu::TestLog::EndMessage;
516                 }
517             }
518         }
519     }
520 }
521 
iterate(void)522 IterateResult TestBase::iterate(void)
523 {
524     glu::Framebuffer fbo(m_ctx.getRenderContext());
525     FboBuilder builder(*fbo, GL_FRAMEBUFFER, gl(*this));
526     const IterateResult ret          = build(builder);
527     const ValidStatusCodes reference = m_ctx.getVerifier().validStatusCodes(builder);
528     const GLenum errorCode           = builder.getError();
529 
530     logFramebufferConfig(builder, m_testCtx.getLog());
531     logFormatInfo(builder, m_ctx.getCtxFormats(), m_ctx.getCoreFormats(), m_ctx.getAllFormats(), m_testCtx.getLog());
532     reference.logRules(m_testCtx.getLog());
533     reference.logLegalResults(m_testCtx.getLog());
534 
535     // \todo [2013-12-04 lauri] Check if drawing operations succeed.
536 
537     if (errorCode != GL_NO_ERROR)
538     {
539         m_testCtx.getLog() << TestLog::Message << "Received " << glu::getErrorStr(errorCode)
540                            << " (during FBO initialization)." << TestLog::EndMessage;
541 
542         if (reference.isErrorCodeValid(errorCode))
543             pass();
544         else if (reference.isErrorCodeRequired(GL_NO_ERROR))
545             fail(("Expected no error but got " + de::toString(glu::getErrorStr(errorCode))).c_str());
546         else
547             fail("Got wrong error code");
548     }
549     else
550     {
551         const GLenum fboStatus = gl(*this).checkFramebufferStatus(GL_FRAMEBUFFER);
552         const bool validStatus = reference.isFBOStatusValid(fboStatus);
553 
554         m_testCtx.getLog() << TestLog::Message << "Received " << glu::getFramebufferStatusStr(fboStatus) << "."
555                            << TestLog::EndMessage;
556 
557         if (!validStatus)
558         {
559             if (fboStatus == GL_FRAMEBUFFER_COMPLETE)
560                 fail("Framebuffer checked as complete, expected incomplete");
561             else if (reference.isFBOStatusRequired(GL_FRAMEBUFFER_COMPLETE))
562                 fail("Framebuffer checked is incomplete, expected complete");
563             else
564                 // An incomplete status is allowed, but not _this_ incomplete status.
565                 fail("Framebuffer checked as incomplete, but with wrong status");
566         }
567         else if (fboStatus == GL_FRAMEBUFFER_UNSUPPORTED)
568         {
569             // The spec requires
570             //     "when both depth and stencil attachments are present,implementations are only required
571             //      to support framebuffer objects where both attachments refer to the same image."
572             //
573             // Thus, it is acceptable for an implementation returning GL_FRAMEBUFFER_UNSUPPORTED,
574             // and the test cannot be marked as failed.
575             pass();
576         }
577         else if (fboStatus != GL_FRAMEBUFFER_COMPLETE && reference.isFBOStatusValid(GL_FRAMEBUFFER_COMPLETE))
578             qualityWarning("Framebuffer object could have checked as complete but did not.");
579         else
580             pass();
581     }
582 
583     return ret;
584 }
585 
build(FboBuilder & builder)586 IterateResult TestBase::build(FboBuilder &builder)
587 {
588     DE_UNREF(builder);
589     return STOP;
590 }
591 
getDefaultFormat(GLenum attPoint,GLenum bufType) const592 ImageFormat TestBase::getDefaultFormat(GLenum attPoint, GLenum bufType) const
593 {
594     if (bufType == GL_NONE)
595     {
596         return ImageFormat::none();
597     }
598 
599     // Prefer a standard format, if there is one, but if not, use a format
600     // provided by an extension.
601     Formats formats            = m_ctx.getCoreFormats().getFormats(formatFlag(attPoint) | formatFlag(bufType));
602     Formats::const_iterator it = formats.begin();
603     if (it == formats.end())
604     {
605         formats = m_ctx.getCtxFormats().getFormats(formatFlag(attPoint) | formatFlag(bufType));
606         it      = formats.begin();
607     }
608     if (it == formats.end())
609         throw tcu::NotSupportedError("Unsupported attachment kind for attachment point", "", __FILE__, __LINE__);
610     return *it;
611 }
612 
makeImage(GLenum bufType,ImageFormat format,GLsizei width,GLsizei height,FboBuilder & builder)613 Image *makeImage(GLenum bufType, ImageFormat format, GLsizei width, GLsizei height, FboBuilder &builder)
614 {
615     Image *image = DE_NULL;
616     switch (bufType)
617     {
618     case GL_NONE:
619         return DE_NULL;
620     case GL_RENDERBUFFER:
621         image = &builder.makeConfig<Renderbuffer>();
622         break;
623     case GL_TEXTURE:
624         image = &builder.makeConfig<Texture2D>();
625         break;
626     default:
627         DE_FATAL("Impossible case");
628     }
629     image->internalFormat = format;
630     image->width          = width;
631     image->height         = height;
632     return image;
633 }
634 
makeAttachment(GLenum bufType,ImageFormat format,GLsizei width,GLsizei height,FboBuilder & builder)635 Attachment *makeAttachment(GLenum bufType, ImageFormat format, GLsizei width, GLsizei height, FboBuilder &builder)
636 {
637     Image *const imgCfg = makeImage(bufType, format, width, height, builder);
638     Attachment *att     = DE_NULL;
639     GLuint img          = 0;
640 
641     if (Renderbuffer *rboCfg = dynamic_cast<Renderbuffer *>(imgCfg))
642     {
643         img = builder.glCreateRbo(*rboCfg);
644         att = &builder.makeConfig<RenderbufferAttachment>();
645     }
646     else if (Texture2D *texCfg = dynamic_cast<Texture2D *>(imgCfg))
647     {
648         img                           = builder.glCreateTexture(*texCfg);
649         TextureFlatAttachment &texAtt = builder.makeConfig<TextureFlatAttachment>();
650         texAtt.texTarget              = GL_TEXTURE_2D;
651         att                           = &texAtt;
652     }
653     else
654     {
655         DE_ASSERT(imgCfg == DE_NULL);
656         return DE_NULL;
657     }
658     att->imageName = img;
659     return att;
660 }
661 
attachTargetToNew(GLenum target,GLenum bufType,ImageFormat format,GLsizei width,GLsizei height,FboBuilder & builder)662 void TestBase::attachTargetToNew(GLenum target, GLenum bufType, ImageFormat format, GLsizei width, GLsizei height,
663                                  FboBuilder &builder)
664 {
665     ImageFormat imgFmt = format;
666     if (imgFmt.format == GL_NONE)
667         imgFmt = getDefaultFormat(target, bufType);
668 
669     const Attachment *const att = makeAttachment(bufType, imgFmt, width, height, builder);
670     builder.glAttach(target, att);
671 }
672 
formatName(ImageFormat format)673 static string formatName(ImageFormat format)
674 {
675     const string s      = getTextureFormatName(format.format);
676     const string fmtStr = toLower(s.substr(3));
677 
678     if (format.unsizedType != GL_NONE)
679     {
680         const string typeStr = getTypeName(format.unsizedType);
681         return fmtStr + "_" + toLower(typeStr.substr(3));
682     }
683 
684     return fmtStr;
685 }
686 
formatDesc(ImageFormat format)687 static string formatDesc(ImageFormat format)
688 {
689     const string fmtStr = getTextureFormatName(format.format);
690 
691     if (format.unsizedType != GL_NONE)
692     {
693         const string typeStr = getTypeName(format.unsizedType);
694         return fmtStr + " with type " + typeStr;
695     }
696 
697     return fmtStr;
698 }
699 
700 struct RenderableParams
701 {
702     GLenum attPoint;
703     GLenum bufType;
704     ImageFormat format;
getNamedeqp::gls::fboc::details::RenderableParams705     static string getName(const RenderableParams &params)
706     {
707         return formatName(params.format);
708     }
getDescriptiondeqp::gls::fboc::details::RenderableParams709     static string getDescription(const RenderableParams &params)
710     {
711         return formatDesc(params.format);
712     }
713 };
714 
715 class RenderableTest : public ParamTest<RenderableParams>
716 {
717 public:
RenderableTest(Context & group,const Params & params)718     RenderableTest(Context &group, const Params &params) : ParamTest<RenderableParams>(group, params)
719     {
720     }
721     IterateResult build(FboBuilder &builder);
722 };
723 
build(FboBuilder & builder)724 IterateResult RenderableTest::build(FboBuilder &builder)
725 {
726     attachTargetToNew(m_params.attPoint, m_params.bufType, m_params.format, 64, 64, builder);
727     return STOP;
728 }
729 
attTypeName(GLenum bufType)730 string attTypeName(GLenum bufType)
731 {
732     switch (bufType)
733     {
734     case GL_NONE:
735         return "none";
736     case GL_RENDERBUFFER:
737         return "rbo";
738     case GL_TEXTURE:
739         return "tex";
740     default:
741         DE_FATAL("Impossible case");
742     }
743     return ""; // Shut up compiler
744 }
745 
746 struct AttachmentParams
747 {
748     GLenum color0Kind;
749     GLenum colornKind;
750     GLenum depthKind;
751     GLenum stencilKind;
752 
753     static string getName(const AttachmentParams &params);
getDescriptiondeqp::gls::fboc::details::AttachmentParams754     static string getDescription(const AttachmentParams &params)
755     {
756         return getName(params);
757     }
758 };
759 
getName(const AttachmentParams & params)760 string AttachmentParams::getName(const AttachmentParams &params)
761 {
762     return (attTypeName(params.color0Kind) + "_" + attTypeName(params.colornKind) + "_" +
763             attTypeName(params.depthKind) + "_" + attTypeName(params.stencilKind));
764 }
765 
766 //! Test for combinations of different kinds of attachments
767 class AttachmentTest : public ParamTest<AttachmentParams>
768 {
769 public:
AttachmentTest(Context & group,Params & params)770     AttachmentTest(Context &group, Params &params) : ParamTest<AttachmentParams>(group, params)
771     {
772     }
773 
774 protected:
775     IterateResult build(FboBuilder &builder);
776     void makeDepthAndStencil(FboBuilder &builder);
777 };
778 
makeDepthAndStencil(FboBuilder & builder)779 void AttachmentTest::makeDepthAndStencil(FboBuilder &builder)
780 {
781     if (m_params.stencilKind == m_params.depthKind)
782     {
783         // If there is a common stencil+depth -format, try to use a common
784         // image for both attachments.
785         const FormatFlags flags    = DEPTH_RENDERABLE | STENCIL_RENDERABLE | formatFlag(m_params.stencilKind);
786         const Formats &formats     = m_ctx.getCoreFormats().getFormats(flags);
787         Formats::const_iterator it = formats.begin();
788         if (it != formats.end())
789         {
790             const ImageFormat format = *it;
791             Attachment *att          = makeAttachment(m_params.depthKind, format, 64, 64, builder);
792             builder.glAttach(GL_DEPTH_ATTACHMENT, att);
793             builder.glAttach(GL_STENCIL_ATTACHMENT, att);
794             return;
795         }
796     }
797     // Either the kinds were separate, or a suitable format was not found.
798     // Create separate images.
799     attachTargetToNew(GL_STENCIL_ATTACHMENT, m_params.stencilKind, ImageFormat::none(), 64, 64, builder);
800     attachTargetToNew(GL_DEPTH_ATTACHMENT, m_params.depthKind, ImageFormat::none(), 64, 64, builder);
801 }
802 
build(FboBuilder & builder)803 IterateResult AttachmentTest::build(FboBuilder &builder)
804 {
805     attachTargetToNew(GL_COLOR_ATTACHMENT0, m_params.color0Kind, ImageFormat::none(), 64, 64, builder);
806 
807     if (m_params.colornKind != GL_NONE)
808     {
809         TCU_CHECK_AND_THROW(NotSupportedError, m_ctx.haveMultiColorAtts(), "Multiple attachments not supported");
810         GLint maxAttachments = 1;
811         gl(*this).getIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxAttachments);
812         GLU_EXPECT_NO_ERROR(gl(*this).getError(), "Couldn't read GL_MAX_COLOR_ATTACHMENTS");
813 
814         for (int i = 1; i < maxAttachments; i++)
815         {
816             attachTargetToNew(GL_COLOR_ATTACHMENT0 + i, m_params.colornKind, ImageFormat::none(), 64, 64, builder);
817         }
818     }
819 
820     makeDepthAndStencil(builder);
821 
822     return STOP;
823 }
824 
825 class EmptyImageTest : public TestBase
826 {
827 public:
EmptyImageTest(Context & group,const char * name,const char * desc)828     EmptyImageTest(Context &group, const char *name, const char *desc) : TestBase(group, name, desc)
829     {
830     }
831 
832     IterateResult build(FboBuilder &builder);
833 };
834 
build(FboBuilder & builder)835 IterateResult EmptyImageTest::build(FboBuilder &builder)
836 {
837     attachTargetToNew(GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ImageFormat::none(), 0, 0, builder);
838     return STOP;
839 }
840 
841 class DistinctSizeTest : public TestBase
842 {
843 public:
DistinctSizeTest(Context & group,const char * name,const char * desc)844     DistinctSizeTest(Context &group, const char *name, const char *desc) : TestBase(group, name, desc)
845     {
846     }
847 
848     IterateResult build(FboBuilder &builder);
849 };
850 
build(FboBuilder & builder)851 IterateResult DistinctSizeTest::build(FboBuilder &builder)
852 {
853     attachTargetToNew(GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, ImageFormat::none(), 64, 64, builder);
854     attachTargetToNew(GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, ImageFormat::none(), 128, 128, builder);
855     return STOP;
856 }
857 
createRenderableTests(void)858 TestCaseGroup *Context::createRenderableTests(void)
859 {
860     TestCaseGroup *const renderableTests =
861         new TestCaseGroup(m_testCtx, "renderable", "Tests for support of renderable image formats");
862 
863     TestCaseGroup *const rbRenderableTests =
864         new TestCaseGroup(m_testCtx, "renderbuffer", "Tests for renderbuffer formats");
865 
866     TestCaseGroup *const texRenderableTests = new TestCaseGroup(m_testCtx, "texture", "Tests for texture formats");
867 
868     static const struct AttPoint
869     {
870         GLenum attPoint;
871         const char *name;
872         const char *desc;
873     } attPoints[] = {
874         {GL_COLOR_ATTACHMENT0, "color0", "Tests for color attachments"},
875         {GL_STENCIL_ATTACHMENT, "stencil", "Tests for stencil attachments"},
876         {GL_DEPTH_ATTACHMENT, "depth", "Tests for depth attachments"},
877     };
878 
879     // At each attachment point, iterate through all the possible formats to
880     // detect both false positives and false negatives.
881     const Formats rboFmts = m_allFormats.getFormats(ANY_FORMAT);
882     const Formats texFmts = m_allFormats.getFormats(ANY_FORMAT);
883 
884     for (const AttPoint *it = DE_ARRAY_BEGIN(attPoints); it != DE_ARRAY_END(attPoints); it++)
885     {
886         TestCaseGroup *const rbAttTests  = new TestCaseGroup(m_testCtx, it->name, it->desc);
887         TestCaseGroup *const texAttTests = new TestCaseGroup(m_testCtx, it->name, it->desc);
888 
889         for (Formats::const_iterator it2 = rboFmts.begin(); it2 != rboFmts.end(); it2++)
890         {
891             const RenderableParams params = {it->attPoint, GL_RENDERBUFFER, *it2};
892             rbAttTests->addChild(new RenderableTest(*this, params));
893         }
894         rbRenderableTests->addChild(rbAttTests);
895 
896         for (Formats::const_iterator it2 = texFmts.begin(); it2 != texFmts.end(); it2++)
897         {
898             const RenderableParams params = {it->attPoint, GL_TEXTURE, *it2};
899             texAttTests->addChild(new RenderableTest(*this, params));
900         }
901         texRenderableTests->addChild(texAttTests);
902     }
903     renderableTests->addChild(rbRenderableTests);
904     renderableTests->addChild(texRenderableTests);
905 
906     return renderableTests;
907 }
908 
createAttachmentTests(void)909 TestCaseGroup *Context::createAttachmentTests(void)
910 {
911     TestCaseGroup *const attCombTests =
912         new TestCaseGroup(m_testCtx, "attachment_combinations", "Tests for attachment combinations");
913 
914     static const GLenum s_bufTypes[]   = {GL_NONE, GL_RENDERBUFFER, GL_TEXTURE};
915     static const Range<GLenum> s_kinds = GLS_ARRAY_RANGE(s_bufTypes);
916 
917     for (const GLenum *col0 = s_kinds.begin(); col0 != s_kinds.end(); ++col0)
918         for (const GLenum *coln = s_kinds.begin(); coln != s_kinds.end(); ++coln)
919             for (const GLenum *dep = s_kinds.begin(); dep != s_kinds.end(); ++dep)
920                 for (const GLenum *stc = s_kinds.begin(); stc != s_kinds.end(); ++stc)
921                 {
922                     AttachmentParams params = {*col0, *coln, *dep, *stc};
923                     attCombTests->addChild(new AttachmentTest(*this, params));
924                 }
925 
926     return attCombTests;
927 }
928 
createSizeTests(void)929 TestCaseGroup *Context::createSizeTests(void)
930 {
931     TestCaseGroup *const sizeTests = new TestCaseGroup(m_testCtx, "size", "Tests for attachment sizes");
932     sizeTests->addChild(new EmptyImageTest(*this, "zero", "Test for zero-sized image attachment"));
933     sizeTests->addChild(new DistinctSizeTest(*this, "distinct", "Test for attachments with different sizes"));
934 
935     return sizeTests;
936 }
937 
938 } // namespace details
939 
940 } // namespace fboc
941 } // namespace gls
942 } // namespace deqp
943