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