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 63 AttribRule (void) 64 : name (EGL_NONE) 65 , value (EGL_NONE) 66 , criteria (CRITERIA_LAST) 67 , sortOrder (SORTORDER_LAST) 68 { 69 } 70 71 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: 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 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 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 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 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> 135 static bool compareAttributeSmaller (const SurfaceConfig& a, const SurfaceConfig& b) 136 { 137 return a.getAttribute(Attribute) < b.getAttribute(Attribute); 138 } 139 public: 140 SurfaceConfig (EGLConfig config, ConfigInfo &info) 141 : m_config(config) 142 , m_info(info) 143 { 144 } 145 146 EGLConfig getEglConfig (void) const 147 { 148 return m_config; 149 } 150 151 EGLint getAttribute (const EGLenum attribute) const 152 { 153 return m_info.getAttribute(attribute); 154 } 155 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 167 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 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: 250 CompareConfigs (bool skipColorBufferBits) 251 : m_skipColorBufferBits(skipColorBufferBits) 252 { 253 } 254 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: 269 ConfigFilter () 270 : m_rules(SurfaceConfig::defaultRules) 271 { 272 } 273 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 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 291 AttribRule getAttribute (EGLenum name) 292 { 293 DE_ASSERT(SurfaceConfig::defaultRules.find(name) != SurfaceConfig::defaultRules.end()); 294 return m_rules[name]; 295 } 296 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 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 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 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