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