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