• Home
  • 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 "egluUtil.hpp"
27 #include "egluConfigInfo.hpp"
28 #include "egluStrUtil.hpp"
29 #include "eglwLibrary.hpp"
30 #include "eglwEnums.hpp"
31 
32 #include <algorithm>
33 #include <vector>
34 #include <map>
35 
36 namespace deqp
37 {
38 namespace egl
39 {
40 
41 using namespace eglw;
42 using eglu::ConfigInfo;
43 
44 enum Criteria
45 {
46 	CRITERIA_AT_LEAST = 0,
47 	CRITERIA_EXACT,
48 	CRITERIA_MASK,
49 	CRITERIA_SPECIAL,
50 
51 	CRITERIA_LAST
52 };
53 
54 enum SortOrder
55 {
56 	SORTORDER_NONE	= 0,
57 	SORTORDER_SMALLER,
58 	SORTORDER_SPECIAL,
59 
60 	SORTORDER_LAST
61 };
62 
63 struct AttribRule
64 {
65 	EGLenum		name;
66 	EGLint		value;
67 	Criteria	criteria;
68 	SortOrder	sortOrder;
69 
AttribRuledeqp::egl::AttribRule70 	AttribRule (void)
71 		: name			(EGL_NONE)
72 		, value			(EGL_NONE)
73 		, criteria		(CRITERIA_LAST)
74 		, sortOrder		(SORTORDER_LAST)
75 	{
76 	}
77 
AttribRuledeqp::egl::AttribRule78 	AttribRule (EGLenum name_, EGLint value_, Criteria criteria_, SortOrder sortOrder_)
79 		: name			(name_)
80 		, value			(value_)
81 		, criteria		(criteria_)
82 		, sortOrder		(sortOrder_)
83 	{
84 	}
85 };
86 
87 class SurfaceConfig
88 {
89 private:
getCaveatRank(EGLenum caveat)90 	static int getCaveatRank (EGLenum caveat)
91 	{
92 		switch (caveat)
93 		{
94 			case EGL_NONE:					return 0;
95 			case EGL_SLOW_CONFIG:			return 1;
96 			case EGL_NON_CONFORMANT_CONFIG:	return 2;
97 			default:
98 				TCU_THROW(TestError, (std::string("Unknown config caveat: ") + eglu::getConfigCaveatStr(caveat).toString()).c_str());
99 		}
100 	}
101 
getColorBufferTypeRank(EGLenum type)102 	static int getColorBufferTypeRank (EGLenum type)
103 	{
104 		switch (type)
105 		{
106 			case EGL_RGB_BUFFER:			return 0;
107 			case EGL_LUMINANCE_BUFFER:		return 1;
108 			case EGL_YUV_BUFFER_EXT:		return 2;
109 			default:
110 				TCU_THROW(TestError, (std::string("Unknown color buffer type: ") + eglu::getColorBufferTypeStr(type).toString()).c_str());
111 		}
112 	}
113 
114 	typedef bool (*CompareFunc) (const SurfaceConfig& a, const SurfaceConfig& b);
115 
compareCaveat(const SurfaceConfig & a,const SurfaceConfig & b)116 	static bool compareCaveat (const SurfaceConfig& a, const SurfaceConfig& b)
117 	{
118 		return getCaveatRank((EGLenum)a.m_info.configCaveat) < getCaveatRank((EGLenum)b.m_info.configCaveat);
119 	}
120 
compareColorBufferType(const SurfaceConfig & a,const SurfaceConfig & b)121 	static bool compareColorBufferType (const SurfaceConfig& a, const SurfaceConfig& b)
122 	{
123 		return getColorBufferTypeRank((EGLenum)a.m_info.colorBufferType) < getColorBufferTypeRank((EGLenum)b.m_info.colorBufferType);
124 	}
125 
compareColorBufferBits(const SurfaceConfig & a,const SurfaceConfig & b,const tcu::BVec4 & specifiedRGBColors,const tcu::BVec2 & specifiedLuminanceColors)126 	static bool compareColorBufferBits (const SurfaceConfig& a, const SurfaceConfig& b, const tcu::BVec4& specifiedRGBColors, const tcu::BVec2& specifiedLuminanceColors)
127 	{
128 		DE_ASSERT(a.m_info.colorBufferType == b.m_info.colorBufferType);
129 		switch (a.m_info.colorBufferType)
130 		{
131 			case EGL_RGB_BUFFER:
132 			{
133 				const tcu::IVec4	mask	(specifiedRGBColors.cast<deInt32>());
134 
135 				return (a.m_info.redSize * mask[0] + a.m_info.greenSize * mask[1] + a.m_info.blueSize * mask[2] + a.m_info.alphaSize * mask[3])
136 						> (b.m_info.redSize * mask[0] + b.m_info.greenSize * mask[1] + b.m_info.blueSize * mask[2] + b.m_info.alphaSize * mask[3]);
137 			}
138 
139 			case EGL_LUMINANCE_BUFFER:
140 			{
141 				const tcu::IVec2	mask	(specifiedLuminanceColors.cast<deInt32>());
142 
143 				return (a.m_info.luminanceSize * mask[0] + a.m_info.alphaSize * mask[1]) > (b.m_info.luminanceSize * mask[0] + b.m_info.alphaSize * mask[1]);
144 			}
145 
146 			case EGL_YUV_BUFFER_EXT:
147 				// \todo [mika 2015-05-05] Sort YUV configs correctly. Currently all YUV configs are non-conformant and ordering can be relaxed.
148 				return true;
149 
150 			default:
151 				DE_ASSERT(DE_FALSE);
152 				return true;
153 		}
154 	}
155 
156 	template <EGLenum Attribute>
compareAttributeSmaller(const SurfaceConfig & a,const SurfaceConfig & b)157 	static bool compareAttributeSmaller (const SurfaceConfig& a, const SurfaceConfig& b)
158 	{
159 		return a.getAttribute(Attribute) < b.getAttribute(Attribute);
160 	}
161 public:
SurfaceConfig(EGLConfig config,ConfigInfo & info)162 	SurfaceConfig (EGLConfig config, ConfigInfo &info)
163 		: m_config(config)
164 		, m_info(info)
165 	{
166 	}
167 
getEglConfig(void) const168 	EGLConfig getEglConfig (void) const
169 	{
170 		return m_config;
171 	}
172 
getAttribute(const EGLenum attribute) const173 	EGLint getAttribute (const EGLenum attribute) const
174 	{
175 		return m_info.getAttribute(attribute);
176 	}
177 
operator ==(const SurfaceConfig & a,const SurfaceConfig & b)178 	friend bool operator== (const SurfaceConfig& a, const SurfaceConfig& b)
179 	{
180 		for (std::map<EGLenum, AttribRule>::const_iterator iter = SurfaceConfig::defaultRules.begin(); iter != SurfaceConfig::defaultRules.end(); iter++)
181 		{
182 			const EGLenum attribute = iter->first;
183 
184 			if (a.getAttribute(attribute) != b.getAttribute(attribute)) return false;
185 		}
186 		return true;
187 	}
188 
compareTo(const SurfaceConfig & b,const tcu::BVec4 & specifiedRGBColors,const tcu::BVec2 & specifiedLuminanceColors) const189 	bool compareTo (const SurfaceConfig& b, const tcu::BVec4& specifiedRGBColors, const tcu::BVec2& specifiedLuminanceColors) const
190 	{
191 		static const SurfaceConfig::CompareFunc compareFuncs[] =
192 		{
193 			SurfaceConfig::compareCaveat,
194 			SurfaceConfig::compareColorBufferType,
195 			DE_NULL, // SurfaceConfig::compareColorBufferBits,
196 			SurfaceConfig::compareAttributeSmaller<EGL_BUFFER_SIZE>,
197 			SurfaceConfig::compareAttributeSmaller<EGL_SAMPLE_BUFFERS>,
198 			SurfaceConfig::compareAttributeSmaller<EGL_SAMPLES>,
199 			SurfaceConfig::compareAttributeSmaller<EGL_DEPTH_SIZE>,
200 			SurfaceConfig::compareAttributeSmaller<EGL_STENCIL_SIZE>,
201 			SurfaceConfig::compareAttributeSmaller<EGL_ALPHA_MASK_SIZE>,
202 			SurfaceConfig::compareAttributeSmaller<EGL_CONFIG_ID>
203 		};
204 
205 		if (*this == b)
206 			return false; // std::sort() can compare object to itself.
207 
208 		for (int ndx = 0; ndx < (int)DE_LENGTH_OF_ARRAY(compareFuncs); ndx++)
209 		{
210 			if (!compareFuncs[ndx])
211 			{
212 				if (compareColorBufferBits(*this, b, specifiedRGBColors, specifiedLuminanceColors))
213 					return true;
214 				else if (compareColorBufferBits(b, *this, specifiedRGBColors, specifiedLuminanceColors))
215 					return false;
216 
217 				continue;
218 			}
219 
220 			if (compareFuncs[ndx](*this, b))
221 				return true;
222 			else if (compareFuncs[ndx](b, *this))
223 				return false;
224 		}
225 
226 		TCU_FAIL("Unable to compare configs - duplicate ID?");
227 	}
228 
229 	static const std::map<EGLenum, AttribRule> defaultRules;
230 
initAttribRules(void)231 	static std::map<EGLenum, AttribRule> initAttribRules (void)
232 	{
233 		// \todo [2011-03-24 pyry] From EGL 1.4 spec - check that this is valid for other versions as well
234 		std::map<EGLenum, AttribRule> rules;
235 
236 		//									Attribute									Default				Selection Criteria	Sort Order			Sort Priority
237 		rules[EGL_BUFFER_SIZE]				= AttribRule(EGL_BUFFER_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	4
238 		rules[EGL_RED_SIZE]					= AttribRule(EGL_RED_SIZE,					0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
239 		rules[EGL_GREEN_SIZE]				= AttribRule(EGL_GREEN_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
240 		rules[EGL_BLUE_SIZE]				= AttribRule(EGL_BLUE_SIZE,					0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
241 		rules[EGL_LUMINANCE_SIZE]			= AttribRule(EGL_LUMINANCE_SIZE,			0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
242 		rules[EGL_ALPHA_SIZE]				= AttribRule(EGL_ALPHA_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SPECIAL);	//	3
243 		rules[EGL_ALPHA_MASK_SIZE]			= AttribRule(EGL_ALPHA_MASK_SIZE,			0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	9
244 		rules[EGL_BIND_TO_TEXTURE_RGB]		= AttribRule(EGL_BIND_TO_TEXTURE_RGB,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
245 		rules[EGL_BIND_TO_TEXTURE_RGBA]		= AttribRule(EGL_BIND_TO_TEXTURE_RGBA,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
246 		rules[EGL_COLOR_BUFFER_TYPE]		= AttribRule(EGL_COLOR_BUFFER_TYPE,			EGL_RGB_BUFFER,		CRITERIA_EXACT,		SORTORDER_NONE);	//	2
247 		rules[EGL_CONFIG_CAVEAT]			= AttribRule(EGL_CONFIG_CAVEAT,				EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_SPECIAL);	//	1
248 		rules[EGL_CONFIG_ID]				= AttribRule(EGL_CONFIG_ID,					EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_SMALLER);	//	11
249 		rules[EGL_CONFORMANT]				= AttribRule(EGL_CONFORMANT,				0,					CRITERIA_MASK,		SORTORDER_NONE);
250 		rules[EGL_DEPTH_SIZE]				= AttribRule(EGL_DEPTH_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	7
251 		rules[EGL_LEVEL]					= AttribRule(EGL_LEVEL,						0,					CRITERIA_EXACT,		SORTORDER_NONE);
252 		rules[EGL_MATCH_NATIVE_PIXMAP]		= AttribRule(EGL_MATCH_NATIVE_PIXMAP,		EGL_NONE,			CRITERIA_SPECIAL,	SORTORDER_NONE);
253 		rules[EGL_MAX_SWAP_INTERVAL]		= AttribRule(EGL_MAX_SWAP_INTERVAL,			EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
254 		rules[EGL_MIN_SWAP_INTERVAL]		= AttribRule(EGL_MIN_SWAP_INTERVAL,			EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
255 		rules[EGL_NATIVE_RENDERABLE]		= AttribRule(EGL_NATIVE_RENDERABLE,			EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
256 		rules[EGL_NATIVE_VISUAL_TYPE]		= AttribRule(EGL_NATIVE_VISUAL_TYPE,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_SPECIAL);	//	10
257 		rules[EGL_RENDERABLE_TYPE]			= AttribRule(EGL_RENDERABLE_TYPE,			EGL_OPENGL_ES_BIT,	CRITERIA_MASK,		SORTORDER_NONE);
258 		rules[EGL_SAMPLE_BUFFERS]			= AttribRule(EGL_SAMPLE_BUFFERS,			0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	5
259 		rules[EGL_SAMPLES]					= AttribRule(EGL_SAMPLES,					0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	6
260 		rules[EGL_STENCIL_SIZE]				= AttribRule(EGL_STENCIL_SIZE,				0,					CRITERIA_AT_LEAST,	SORTORDER_SMALLER);	//	8
261 		rules[EGL_SURFACE_TYPE]				= AttribRule(EGL_SURFACE_TYPE,				EGL_WINDOW_BIT,		CRITERIA_MASK,		SORTORDER_NONE);
262 		rules[EGL_TRANSPARENT_TYPE]			= AttribRule(EGL_TRANSPARENT_TYPE,			EGL_NONE,			CRITERIA_EXACT,		SORTORDER_NONE);
263 		rules[EGL_TRANSPARENT_RED_VALUE]	= AttribRule(EGL_TRANSPARENT_RED_VALUE,		EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
264 		rules[EGL_TRANSPARENT_GREEN_VALUE]	= AttribRule(EGL_TRANSPARENT_GREEN_VALUE,	EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
265 		rules[EGL_TRANSPARENT_BLUE_VALUE]	= AttribRule(EGL_TRANSPARENT_BLUE_VALUE,	EGL_DONT_CARE,		CRITERIA_EXACT,		SORTORDER_NONE);
266 
267 		return rules;
268 	}
269 private:
270 	EGLConfig m_config;
271 	ConfigInfo m_info;
272 };
273 
274 const std::map<EGLenum, AttribRule> SurfaceConfig::defaultRules = SurfaceConfig::initAttribRules();
275 
276 class CompareConfigs
277 {
278 public:
CompareConfigs(const tcu::BVec4 & specifiedRGBColors,const tcu::BVec2 & specifiedLuminanceColors)279 	CompareConfigs (const tcu::BVec4& specifiedRGBColors, const tcu::BVec2& specifiedLuminanceColors)
280 		: m_specifiedRGBColors			(specifiedRGBColors)
281 		, m_specifiedLuminanceColors	(specifiedLuminanceColors)
282 	{
283 	}
284 
operator ()(const SurfaceConfig & a,const SurfaceConfig & b)285 	bool operator() (const SurfaceConfig& a, const SurfaceConfig& b)
286 	{
287 		return a.compareTo(b, m_specifiedRGBColors, m_specifiedLuminanceColors);
288 	}
289 
290 private:
291 	const tcu::BVec4	m_specifiedRGBColors;
292 	const tcu::BVec2	m_specifiedLuminanceColors;
293 };
294 
295 class ConfigFilter
296 {
297 private:
298 	std::map<EGLenum, AttribRule> m_rules;
299 public:
ConfigFilter()300 	ConfigFilter ()
301 		: m_rules(SurfaceConfig::defaultRules)
302 	{
303 	}
304 
setValue(EGLenum name,EGLint value)305 	void setValue (EGLenum name, EGLint value)
306 	{
307 		DE_ASSERT(SurfaceConfig::defaultRules.find(name) != SurfaceConfig::defaultRules.end());
308 		m_rules[name].value = value;
309 	}
310 
setValues(std::vector<std::pair<EGLenum,EGLint>> values)311 	void setValues (std::vector<std::pair<EGLenum, EGLint> > values)
312 	{
313 		for (size_t ndx = 0; ndx < values.size(); ndx++)
314 		{
315 			const EGLenum	name	= values[ndx].first;
316 			const EGLint	value	= values[ndx].second;
317 
318 			setValue(name, value);
319 		}
320 	}
321 
getAttribute(EGLenum name)322 	AttribRule getAttribute (EGLenum name)
323 	{
324 		DE_ASSERT(SurfaceConfig::defaultRules.find(name) != SurfaceConfig::defaultRules.end());
325 		return m_rules[name];
326 	}
327 
isMatch(const SurfaceConfig & config)328 	bool isMatch (const SurfaceConfig& config)
329 	{
330 		for (std::map<EGLenum, AttribRule>::const_iterator iter = m_rules.begin(); iter != m_rules.end(); iter++)
331 		{
332 			const AttribRule rule = iter->second;
333 
334 			if (rule.value == EGL_DONT_CARE)
335 				continue;
336 			else if (rule.name == EGL_MATCH_NATIVE_PIXMAP)
337 				TCU_CHECK(rule.value == EGL_NONE); // Not supported
338 			else if (rule.name == EGL_TRANSPARENT_RED_VALUE || rule.name == EGL_TRANSPARENT_GREEN_VALUE || rule.name == EGL_TRANSPARENT_BLUE_VALUE)
339 				continue;
340 			else
341 			{
342 				const EGLint cfgValue = config.getAttribute(rule.name);
343 
344 				switch (rule.criteria)
345 				{
346 					case CRITERIA_EXACT:
347 						if (rule.value != cfgValue)
348 							return false;
349 						break;
350 
351 					case CRITERIA_AT_LEAST:
352 						if (rule.value > cfgValue)
353 							return false;
354 						break;
355 
356 					case CRITERIA_MASK:
357 						if ((rule.value & cfgValue) != rule.value)
358 							return false;
359 						break;
360 
361 					default:
362 						TCU_FAIL("Unknown criteria");
363 				}
364 			}
365 		}
366 
367 		return true;
368 	}
369 
getSpecifiedRGBColors(void)370 	tcu::BVec4 getSpecifiedRGBColors (void)
371 	{
372 		const EGLenum bitAttribs[] =
373 		{
374 			EGL_RED_SIZE,
375 			EGL_GREEN_SIZE,
376 			EGL_BLUE_SIZE,
377 			EGL_ALPHA_SIZE
378 		};
379 
380 		tcu::BVec4 result;
381 
382 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bitAttribs); ndx++)
383 		{
384 			const EGLenum	attrib	= bitAttribs[ndx];
385 			const EGLint	value	= getAttribute(attrib).value;
386 
387 			if (value != 0 && value != EGL_DONT_CARE)
388 				result[ndx] = true;
389 			else
390 				result[ndx] = false;
391 		}
392 
393 		return result;
394 	}
395 
getSpecifiedLuminanceColors(void)396 	tcu::BVec2 getSpecifiedLuminanceColors (void)
397 	{
398 		const EGLenum bitAttribs[] =
399 		{
400 			EGL_LUMINANCE_SIZE,
401 			EGL_ALPHA_SIZE
402 		};
403 
404 		tcu::BVec2 result;
405 
406 		for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(bitAttribs); ndx++)
407 		{
408 			const EGLenum	attrib	= bitAttribs[ndx];
409 			const EGLint	value	= getAttribute(attrib).value;
410 
411 			if (value != 0 && value != EGL_DONT_CARE)
412 				result[ndx] = true;
413 			else
414 				result[ndx] = false;
415 		}
416 
417 		return result;
418 	}
419 
filter(const std::vector<SurfaceConfig> & configs)420 	std::vector<SurfaceConfig> filter (const std::vector<SurfaceConfig>& configs)
421 	{
422 		std::vector<SurfaceConfig> out;
423 
424 		for (std::vector<SurfaceConfig>::const_iterator iter = configs.begin(); iter != configs.end(); iter++)
425 		{
426 			if (isMatch(*iter)) out.push_back(*iter);
427 		}
428 
429 		return out;
430 	}
431 };
432 
chooseConfigReference(const Library & egl,EGLDisplay display,std::vector<EGLConfig> & dst,const std::vector<std::pair<EGLenum,EGLint>> & attributes)433 void chooseConfigReference (const Library& egl, EGLDisplay display, std::vector<EGLConfig>& dst, const std::vector<std::pair<EGLenum, EGLint> >& attributes)
434 {
435 	// Get all configs
436 	std::vector<EGLConfig> eglConfigs = eglu::getConfigs(egl, display);
437 
438 	// Config infos
439 	std::vector<ConfigInfo> configInfos;
440 	configInfos.resize(eglConfigs.size());
441 	for (size_t ndx = 0; ndx < eglConfigs.size(); ndx++)
442 		eglu::queryConfigInfo(egl, display, eglConfigs[ndx], &configInfos[ndx]);
443 
444 	// Pair configs with info
445 	std::vector<SurfaceConfig> configs;
446 	for (size_t ndx = 0; ndx < eglConfigs.size(); ndx++)
447 		configs.push_back(SurfaceConfig(eglConfigs[ndx], configInfos[ndx]));
448 
449 	// Filter configs
450 	ConfigFilter configFilter;
451 	configFilter.setValues(attributes);
452 
453 	std::vector<SurfaceConfig> filteredConfigs = configFilter.filter(configs);
454 
455 	// Sort configs
456 	std::sort(filteredConfigs.begin(), filteredConfigs.end(), CompareConfigs(configFilter.getSpecifiedRGBColors(), configFilter.getSpecifiedLuminanceColors()));
457 
458 	// Write to dst list
459 	dst.resize(filteredConfigs.size());
460 	for (size_t ndx = 0; ndx < filteredConfigs.size(); ndx++)
461 		dst[ndx] = filteredConfigs[ndx].getEglConfig();
462 }
463 
464 } // egl
465 } // deqp
466