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