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 ¶ms)
715 {
716 return formatName(params.format);
717 }
getDescriptiondeqp::gls::fboc::details::RenderableParams718 static string getDescription(const RenderableParams ¶ms)
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 ¶ms) : 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 ¶ms);
getDescriptiondeqp::gls::fboc::details::AttachmentParams763 static string getDescription(const AttachmentParams ¶ms)
764 {
765 return getName(params);
766 }
767 };
768
getName(const AttachmentParams & params)769 string AttachmentParams::getName(const AttachmentParams ¶ms)
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 ¶ms) : 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