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