Home | History | Annotate | Download | only in egl
      1 /*-------------------------------------------------------------------------
      2  * drawElements Quality Program EGL 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 Choose config reference implementation.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "teglChooseConfigReference.hpp"
     25 
     26 #include <algorithm>
     27 #include <vector>
     28 #include <map>
     29 
     30 namespace deqp
     31 {
     32 namespace egl
     33 {
     34 
     35 using eglu::ConfigInfo;
     36 
     37 enum Criteria
     38 {
     39 	CRITERIA_AT_LEAST = 0,
     40 	CRITERIA_EXACT,
     41 	CRITERIA_MASK,
     42 	CRITERIA_SPECIAL,
     43 
     44 	CRITERIA_LAST
     45 };
     46 
     47 enum SortOrder
     48 {
     49 	SORTORDER_NONE	= 0,
     50 	SORTORDER_SMALLER,
     51 	SORTORDER_SPECIAL,
     52 
     53 	SORTORDER_LAST
     54 };
     55 
     56 struct AttribRule
     57 {
     58 	EGLenum		name;
     59 	EGLint		value;
     60 	Criteria	criteria;
     61 	SortOrder	sortOrder;
     62 
     63 	AttribRule (void)
     64 		: name			(EGL_NONE)
     65 		, value			(EGL_NONE)
     66 		, criteria		(CRITERIA_LAST)
     67 		, sortOrder		(SORTORDER_LAST)
     68 	{
     69 	}
     70 
     71 	AttribRule (EGLenum name_, EGLint value_, Criteria criteria_, SortOrder sortOrder_)
     72 		: name			(name_)
     73 		, value			(value_)
     74 		, criteria		(criteria_)
     75 		, sortOrder		(sortOrder_)
     76 	{
     77 	}
     78 };
     79 
     80 class SurfaceConfig
     81 {
     82 private:
     83 	static int getCaveatRank (EGLenum caveat)
     84 	{
     85 		switch (caveat)
     86 		{
     87 			case EGL_NONE:					return 0;
     88 			case EGL_SLOW_CONFIG:			return 1;
     89 			case EGL_NON_CONFORMANT_CONFIG:	return 2;
     90 			default: DE_ASSERT(DE_FALSE);	return 3;
     91 		}
     92 	}
     93 
     94 	static int getColorBufferTypeRank (EGLenum type)
     95 	{
     96 		switch (type)
     97 		{
     98 			case EGL_RGB_BUFFER:			return 0;
     99 			case EGL_LUMINANCE_BUFFER:		return 1;
    100 			default: DE_ASSERT(DE_FALSE);	return 2;
    101 		}
    102 	}
    103 
    104 	typedef bool (*CompareFunc) (const SurfaceConfig& a, const SurfaceConfig& b);
    105 
    106 	static bool compareCaveat (const SurfaceConfig& a, const SurfaceConfig& b)
    107 	{
    108 		return getCaveatRank((EGLenum)a.m_info.configCaveat) < getCaveatRank((EGLenum)b.m_info.configCaveat);
    109 	}
    110 
    111 	static bool compareColorBufferType (const SurfaceConfig& a, const SurfaceConfig& b)
    112 	{
    113 		return getColorBufferTypeRank((EGLenum)a.m_info.colorBufferType) < getColorBufferTypeRank((EGLenum)b.m_info.colorBufferType);
    114 	}
    115 
    116 	static bool compareColorBufferBits (const SurfaceConfig& a, const SurfaceConfig& b)
    117 	{
    118 		DE_ASSERT(a.m_info.colorBufferType == b.m_info.colorBufferType);
    119 		switch (a.m_info.colorBufferType)
    120 		{
    121 			case EGL_RGB_BUFFER:
    122 				return (a.m_info.redSize + a.m_info.greenSize + a.m_info.blueSize + a.m_info.alphaSize)
    123 						> (b.m_info.redSize + b.m_info.greenSize + b.m_info.blueSize + b.m_info.alphaSize);
    124 
    125 			case EGL_LUMINANCE_BUFFER:
    126 				return (a.m_info.luminanceSize + a.m_info.alphaSize) > (b.m_info.luminanceSize + b.m_info.alphaSize);
    127 
    128 			default:
    129 				DE_ASSERT(DE_FALSE);
    130 				return true;
    131 		}
    132 	}
    133 
    134 	template <EGLenum Attribute>
    135 	static bool compareAttributeSmaller (const SurfaceConfig& a, const SurfaceConfig& b)
    136 	{
    137 		return a.getAttribute(Attribute) < b.getAttribute(Attribute);
    138 	}
    139 public:
    140 	SurfaceConfig (EGLConfig config, ConfigInfo &info)
    141 		: m_config(config)
    142 		, m_info(info)
    143 	{
    144 	}
    145 
    146 	EGLConfig getEglConfig (void) const
    147 	{
    148 		return m_config;
    149 	}
    150 
    151 	EGLint getAttribute (const EGLenum attribute) const
    152 	{
    153 		return m_info.getAttribute(attribute);
    154 	}
    155 
    156 	friend bool operator== (const SurfaceConfig& a, const SurfaceConfig& b)
    157 	{
    158 		for (std::map<EGLenum, AttribRule>::const_iterator iter = SurfaceConfig::defaultRules.begin(); iter != SurfaceConfig::defaultRules.end(); iter++)
    159 		{
    160 			const EGLenum attribute = iter->first;
    161 
    162 			if (a.getAttribute(attribute) != b.getAttribute(attribute)) return false;
    163 		}
    164 		return true;
    165 	}
    166 
    167 	bool compareTo (const SurfaceConfig& b, bool skipColorBufferBits=false) const
    168 	{
    169 		static const SurfaceConfig::CompareFunc compareFuncs[] =
    170 		{
    171 			SurfaceConfig::compareCaveat,
    172 			SurfaceConfig::compareColorBufferType,
    173 			SurfaceConfig::compareColorBufferBits,
    174 			SurfaceConfig::compareAttributeSmaller<EGL_BUFFER_SIZE>,
    175 			SurfaceConfig::compareAttributeSmaller<EGL_SAMPLE_BUFFERS>,
    176 			SurfaceConfig::compareAttributeSmaller<EGL_SAMPLES>,
    177 			SurfaceConfig::compareAttributeSmaller<EGL_DEPTH_SIZE>,
    178 			SurfaceConfig::compareAttributeSmaller<EGL_STENCIL_SIZE>,
    179 			SurfaceConfig::compareAttributeSmaller<EGL_ALPHA_MASK_SIZE>,
    180 			SurfaceConfig::compareAttributeSmaller<EGL_CONFIG_ID>
    181 		};
    182 
    183 		if (*this == b)
    184 			return false; // std::sort() can compare object to itself.
    185 
    186 		for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(compareFuncs); ndx++)
    187 		{
    188 			if (skipColorBufferBits && (compareFuncs[ndx] == SurfaceConfig::compareColorBufferBits))
    189 				continue;
    190 
    191 			if (compareFuncs[ndx](*this, b))
    192 				return true;
    193 			else if (compareFuncs[ndx](b, *this))
    194 				return false;
    195 		}
    196 
    197 		TCU_FAIL("Unable to compare configs - duplicate ID?");
    198 	}
    199 
    200 	static const std::map<EGLenum, AttribRule> defaultRules;
    201 
    202 	static std::map<EGLenum, AttribRule> initAttribRules (void)
    203 	{
    204 		// \todo [2011-03-24 pyry] From EGL 1.4 spec - check that this is valid for other versions as well
    205 		std::map<EGLenum, AttribRule> rules;
    206 
    207 		//									Attribute									Default				Selection Criteria	Sort Order			Sort Priority
    208 		rules[EGL_BUFFER_SIZE]				= AttribRule(EGL_BUFFER_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	4
    209 		rules[EGL_RED_SIZE]					= AttribRule(EGL_RED_SIZE,					0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
    210 		rules[EGL_GREEN_SIZE]				= AttribRule(EGL_GREEN_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
    211 		rules[EGL_BLUE_SIZE]				= AttribRule(EGL_BLUE_SIZE,					0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
    212 		rules[EGL_LUMINANCE_SIZE]			= AttribRule(EGL_LUMINANCE_SIZE,			0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
    213 		rules[EGL_ALPHA_SIZE]				= AttribRule(EGL_ALPHA_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
    214 		rules[EGL_ALPHA_MASK_SIZE]			= AttribRule(EGL_ALPHA_MASK_SIZE,			0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	9
    215 		rules[EGL_BIND_TO_TEXTURE_RGB]		= AttribRule(EGL_BIND_TO_TEXTURE_RGB,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
    216 		rules[EGL_BIND_TO_TEXTURE_RGBA]		= AttribRule(EGL_BIND_TO_TEXTURE_RGBA,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
    217 		rules[EGL_COLOR_BUFFER_TYPE]		= AttribRule(EGL_COLOR_BUFFER_TYPE,			EGL_RGB_BUFFER,		CRITERIA_EXACT,		SORTORDER_NONE);	//	2
    218 		rules[EGL_CONFIG_CAVEAT]			= AttribRule(EGL_CONFIG_CAVEAT,				EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_SPECIAL);	//	1
    219 		rules[EGL_CONFIG_ID]				= AttribRule(EGL_CONFIG_ID,					EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_SMALLER);	//	11
    220 		rules[EGL_CONFORMANT]				= AttribRule(EGL_CONFORMANT,				0,					CRITERIA_MASK,		SORTORDER_NONE);
    221 		rules[EGL_DEPTH_SIZE]				= AttribRule(EGL_DEPTH_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	7
    222 		rules[EGL_LEVEL]					= AttribRule(EGL_LEVEL,						0,					CRITERIA_EXACT,		SORTORDER_NONE);
    223 		rules[EGL_MATCH_NATIVE_PIXMAP]		= AttribRule(EGL_MATCH_NATIVE_PIXMAP,		EGL_NONE,			CRITERIA_SPECIAL,	SORTORDER_NONE);
    224 		rules[EGL_MAX_SWAP_INTERVAL]		= AttribRule(EGL_MAX_SWAP_INTERVAL,			EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
    225 		rules[EGL_MIN_SWAP_INTERVAL]		= AttribRule(EGL_MIN_SWAP_INTERVAL,			EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
    226 		rules[EGL_NATIVE_RENDERABLE]		= AttribRule(EGL_NATIVE_RENDERABLE,			EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
    227 		rules[EGL_NATIVE_VISUAL_TYPE]		= AttribRule(EGL_NATIVE_VISUAL_TYPE,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_SPECIAL);	//	10
    228 		rules[EGL_RENDERABLE_TYPE]			= AttribRule(EGL_RENDERABLE_TYPE,			EGL_OPENGL_ES_BIT,	CRITERIA_MASK,		SORTORDER_NONE);
    229 		rules[EGL_SAMPLE_BUFFERS]			= AttribRule(EGL_SAMPLE_BUFFERS,			0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	5
    230 		rules[EGL_SAMPLES]					= AttribRule(EGL_SAMPLES,					0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	6
    231 		rules[EGL_STENCIL_SIZE]				= AttribRule(EGL_STENCIL_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	8
    232 		rules[EGL_SURFACE_TYPE]				= AttribRule(EGL_SURFACE_TYPE,				EGL_WINDOW_BIT,		CRITERIA_MASK,		SORTORDER_NONE);
    233 		rules[EGL_TRANSPARENT_TYPE]			= AttribRule(EGL_TRANSPARENT_TYPE,			EGL_NONE,			CRITERIA_EXACT,		SORTORDER_NONE);
    234 		rules[EGL_TRANSPARENT_RED_VALUE]	= AttribRule(EGL_TRANSPARENT_RED_VALUE,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
    235 		rules[EGL_TRANSPARENT_GREEN_VALUE]	= AttribRule(EGL_TRANSPARENT_GREEN_VALUE,	EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
    236 		rules[EGL_TRANSPARENT_BLUE_VALUE]	= AttribRule(EGL_TRANSPARENT_BLUE_VALUE,	EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
    237 
    238 		return rules;
    239 	}
    240 private:
    241 	EGLConfig m_config;
    242 	ConfigInfo m_info;
    243 };
    244 
    245 const std::map<EGLenum, AttribRule> SurfaceConfig::defaultRules = SurfaceConfig::initAttribRules();
    246 
    247 class CompareConfigs
    248 {
    249 public:
    250 	CompareConfigs (bool skipColorBufferBits)
    251 		: m_skipColorBufferBits(skipColorBufferBits)
    252 	{
    253 	}
    254 
    255 	bool operator() (const SurfaceConfig& a, const SurfaceConfig& b)
    256 	{
    257 		return a.compareTo(b, m_skipColorBufferBits);
    258 	}
    259 
    260 private:
    261 	bool m_skipColorBufferBits;
    262 };
    263 
    264 class ConfigFilter
    265 {
    266 private:
    267 	std::map<EGLenum, AttribRule> m_rules;
    268 public:
    269 	ConfigFilter ()
    270 		: m_rules(SurfaceConfig::defaultRules)
    271 	{
    272 	}
    273 
    274 	void setValue (EGLenum name, EGLint value)
    275 	{
    276 		DE_ASSERT(SurfaceConfig::defaultRules.find(name) != SurfaceConfig::defaultRules.end());
    277 		m_rules[name].value = value;
    278 	}
    279 
    280 	void setValues (std::vector<std::pair<EGLenum, EGLint> > values)
    281 	{
    282 		for (size_t ndx = 0; ndx < values.size(); ndx++)
    283 		{
    284 			const EGLenum	name	= values[ndx].first;
    285 			const EGLint	value	= values[ndx].second;
    286 
    287 			setValue(name, value);
    288 		}
    289 	}
    290 
    291 	AttribRule getAttribute (EGLenum name)
    292 	{
    293 		DE_ASSERT(SurfaceConfig::defaultRules.find(name) != SurfaceConfig::defaultRules.end());
    294 		return m_rules[name];
    295 	}
    296 
    297 	bool isMatch (const SurfaceConfig& config)
    298 	{
    299 		bool result = true;
    300 		for (std::map<EGLenum, AttribRule>::const_iterator iter = m_rules.begin(); iter != m_rules.end(); iter++)
    301 		{
    302 			const AttribRule rule = iter->second;
    303 
    304 			if (rule.value == EGL_DONT_CARE)
    305 				continue;
    306 			else if (rule.name == EGL_MATCH_NATIVE_PIXMAP)
    307 				TCU_CHECK(rule.value == EGL_NONE); // Not supported
    308 			else if (rule.name == EGL_TRANSPARENT_RED_VALUE || rule.name == EGL_TRANSPARENT_GREEN_VALUE || rule.name == EGL_TRANSPARENT_BLUE_VALUE)
    309 				continue;
    310 			else
    311 			{
    312 				const EGLint cfgValue = config.getAttribute(rule.name);
    313 
    314 				switch (rule.criteria)
    315 				{
    316 					case CRITERIA_EXACT:	result = rule.value == cfgValue;				break;
    317 					case CRITERIA_AT_LEAST:	result = rule.value <= cfgValue;				break;
    318 					case CRITERIA_MASK:		result = (rule.value & cfgValue) == rule.value;	break;
    319 					default:				TCU_FAIL("Unknown criteria");
    320 				}
    321 			}
    322 
    323 			if (result == false) return false;
    324 		}
    325 
    326 		return true;
    327 	}
    328 
    329 	bool isColorBitsUnspecified (void)
    330 	{
    331 		const EGLenum	bitAttribs[]	= { EGL_RED_SIZE, EGL_GREEN_SIZE, EGL_BLUE_SIZE, EGL_LUMINANCE_SIZE };
    332 
    333 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bitAttribs); ndx++)
    334 		{
    335 			const EGLenum	attrib	= bitAttribs[ndx];
    336 			const EGLint	value	= getAttribute(attrib).value;
    337 
    338 			if (value != 0 && value != EGL_DONT_CARE) return false;
    339 		}
    340 
    341 		return true;
    342 	}
    343 
    344 	std::vector<SurfaceConfig> filter (const std::vector<SurfaceConfig>& configs)
    345 	{
    346 		std::vector<SurfaceConfig> out;
    347 
    348 		for (std::vector<SurfaceConfig>::const_iterator iter = configs.begin(); iter != configs.end(); iter++)
    349 		{
    350 			if (isMatch(*iter)) out.push_back(*iter);
    351 		}
    352 
    353 		return out;
    354 	}
    355 };
    356 
    357 void chooseConfigReference (const tcu::egl::Display& display, std::vector<EGLConfig>& dst, const std::vector<std::pair<EGLenum, EGLint> >& attributes)
    358 {
    359 	// Get all configs
    360 	std::vector<EGLConfig> eglConfigs;
    361 	display.getConfigs(eglConfigs);
    362 
    363 	// Config infos
    364 	std::vector<ConfigInfo> configInfos;
    365 	configInfos.resize(eglConfigs.size());
    366 	for (size_t ndx = 0; ndx < eglConfigs.size(); ndx++)
    367 		display.describeConfig(eglConfigs[ndx], configInfos[ndx]);
    368 
    369 	TCU_CHECK_EGL_MSG("Config query failed");
    370 
    371 	// Pair configs with info
    372 	std::vector<SurfaceConfig> configs;
    373 	for (size_t ndx = 0; ndx < eglConfigs.size(); ndx++)
    374 		configs.push_back(SurfaceConfig(eglConfigs[ndx], configInfos[ndx]));
    375 
    376 	// Filter configs
    377 	ConfigFilter configFilter;
    378 	configFilter.setValues(attributes);
    379 
    380 	std::vector<SurfaceConfig> filteredConfigs = configFilter.filter(configs);
    381 
    382 	// Sort configs
    383 	std::sort(filteredConfigs.begin(), filteredConfigs.end(), CompareConfigs(configFilter.isColorBitsUnspecified()));
    384 
    385 	// Write to dst list
    386 	dst.resize(filteredConfigs.size());
    387 	for (size_t ndx = 0; ndx < filteredConfigs.size(); ndx++)
    388 		dst[ndx] = filteredConfigs[ndx].getEglConfig();
    389 }
    390 
    391 } // egl
    392 } // deqp
    393