• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
AttribRuledeqp::egl::AttribRule63 	AttribRule (void)
64 		: name			(EGL_NONE)
65 		, value			(EGL_NONE)
66 		, criteria		(CRITERIA_LAST)
67 		, sortOrder		(SORTORDER_LAST)
68 	{
69 	}
70 
AttribRuledeqp::egl::AttribRule71 	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:
getCaveatRank(EGLenum caveat)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 
getColorBufferTypeRank(EGLenum type)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 
compareCaveat(const SurfaceConfig & a,const SurfaceConfig & b)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 
compareColorBufferType(const SurfaceConfig & a,const SurfaceConfig & b)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 
compareColorBufferBits(const SurfaceConfig & a,const SurfaceConfig & b)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>
compareAttributeSmaller(const SurfaceConfig & a,const SurfaceConfig & b)135 	static bool compareAttributeSmaller (const SurfaceConfig& a, const SurfaceConfig& b)
136 	{
137 		return a.getAttribute(Attribute) < b.getAttribute(Attribute);
138 	}
139 public:
SurfaceConfig(EGLConfig config,ConfigInfo & info)140 	SurfaceConfig (EGLConfig config, ConfigInfo &info)
141 		: m_config(config)
142 		, m_info(info)
143 	{
144 	}
145 
getEglConfig(void) const146 	EGLConfig getEglConfig (void) const
147 	{
148 		return m_config;
149 	}
150 
getAttribute(const EGLenum attribute) const151 	EGLint getAttribute (const EGLenum attribute) const
152 	{
153 		return m_info.getAttribute(attribute);
154 	}
155 
operator ==(const SurfaceConfig & a,const SurfaceConfig & b)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 
compareTo(const SurfaceConfig & b,bool skipColorBufferBits=false) const167 	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 
initAttribRules(void)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:
CompareConfigs(bool skipColorBufferBits)250 	CompareConfigs (bool skipColorBufferBits)
251 		: m_skipColorBufferBits(skipColorBufferBits)
252 	{
253 	}
254 
operator ()(const SurfaceConfig & a,const SurfaceConfig & b)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:
ConfigFilter()269 	ConfigFilter ()
270 		: m_rules(SurfaceConfig::defaultRules)
271 	{
272 	}
273 
setValue(EGLenum name,EGLint value)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 
setValues(std::vector<std::pair<EGLenum,EGLint>> values)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 
getAttribute(EGLenum name)291 	AttribRule getAttribute (EGLenum name)
292 	{
293 		DE_ASSERT(SurfaceConfig::defaultRules.find(name) != SurfaceConfig::defaultRules.end());
294 		return m_rules[name];
295 	}
296 
isMatch(const SurfaceConfig & config)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 
isColorBitsUnspecified(void)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 
filter(const std::vector<SurfaceConfig> & configs)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 
chooseConfigReference(const tcu::egl::Display & display,std::vector<EGLConfig> & dst,const std::vector<std::pair<EGLenum,EGLint>> & attributes)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