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 ¶ms)
706 {
707 return formatName(params.format);
708 }
getDescriptiondeqp::gls::fboc::details::RenderableParams709 static string getDescription(const RenderableParams ¶ms)
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 ¶ms) : 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 ¶ms);
getDescriptiondeqp::gls::fboc::details::AttachmentParams754 static string getDescription(const AttachmentParams ¶ms)
755 {
756 return getName(params);
757 }
758 };
759
getName(const AttachmentParams & params)760 string AttachmentParams::getName(const AttachmentParams ¶ms)
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 ¶ms) : 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