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