Config.cpp (13895B)
1 // 2 // Copyright 2002 The ANGLE Project Authors. All rights reserved. 3 // Use of this source code is governed by a BSD-style license that can be 4 // found in the LICENSE file. 5 // 6 7 // Config.cpp: Implements the egl::Config class, describing the format, type 8 // and size for an egl::Surface. Implements EGLConfig and related functionality. 9 // [EGL 1.5] section 3.4 page 19. 10 11 #include "libANGLE/Config.h" 12 #include "libANGLE/AttributeMap.h" 13 14 #include <algorithm> 15 #include <vector> 16 17 #include <EGL/eglext.h> 18 #include "angle_gl.h" 19 20 #include "common/debug.h" 21 22 namespace egl 23 { 24 25 Config::Config() 26 : renderTargetFormat(GL_NONE), 27 depthStencilFormat(GL_NONE), 28 bufferSize(0), 29 redSize(0), 30 greenSize(0), 31 blueSize(0), 32 luminanceSize(0), 33 alphaSize(0), 34 alphaMaskSize(0), 35 bindToTextureRGB(EGL_FALSE), 36 bindToTextureRGBA(EGL_FALSE), 37 bindToTextureTarget(EGL_TEXTURE_2D), 38 colorBufferType(EGL_RGB_BUFFER), 39 configCaveat(EGL_NONE), 40 configID(0), 41 conformant(0), 42 depthSize(0), 43 level(0), 44 matchNativePixmap(EGL_FALSE), 45 maxPBufferWidth(0), 46 maxPBufferHeight(0), 47 maxPBufferPixels(0), 48 maxSwapInterval(0), 49 minSwapInterval(0), 50 nativeRenderable(EGL_FALSE), 51 nativeVisualID(0), 52 nativeVisualType(0), 53 renderableType(0), 54 sampleBuffers(0), 55 samples(0), 56 stencilSize(0), 57 surfaceType(0), 58 transparentType(EGL_NONE), 59 transparentRedValue(0), 60 transparentGreenValue(0), 61 transparentBlueValue(0), 62 optimalOrientation(0), 63 colorComponentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT), 64 recordable(EGL_FALSE), 65 framebufferTarget(EGL_FALSE), // TODO: http://anglebug.com/4208 66 yInverted(EGL_FALSE) 67 {} 68 69 Config::~Config() {} 70 71 Config::Config(const Config &other) = default; 72 73 Config &Config::operator=(const Config &other) = default; 74 75 ConfigSet::ConfigSet() = default; 76 77 ConfigSet::ConfigSet(const ConfigSet &other) = default; 78 79 ConfigSet &ConfigSet::operator=(const ConfigSet &other) = default; 80 81 ConfigSet::~ConfigSet() = default; 82 83 EGLint ConfigSet::add(const Config &config) 84 { 85 // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4) 86 EGLint id = static_cast<EGLint>(mConfigs.size()) + 1; 87 88 Config copyConfig(config); 89 copyConfig.configID = id; 90 mConfigs.insert(std::make_pair(id, copyConfig)); 91 92 return id; 93 } 94 95 const Config &ConfigSet::get(EGLint id) const 96 { 97 ASSERT(mConfigs.find(id) != mConfigs.end()); 98 return mConfigs.find(id)->second; 99 } 100 101 void ConfigSet::clear() 102 { 103 mConfigs.clear(); 104 } 105 106 size_t ConfigSet::size() const 107 { 108 return mConfigs.size(); 109 } 110 111 bool ConfigSet::contains(const Config *config) const 112 { 113 for (auto i = mConfigs.begin(); i != mConfigs.end(); i++) 114 { 115 const Config &item = i->second; 116 if (config == &item) 117 { 118 return true; 119 } 120 } 121 122 return false; 123 } 124 125 // Function object used by STL sorting routines for ordering Configs according to [EGL 1.5] 126 // section 3.4.1.2 page 28. 127 class ConfigSorter 128 { 129 public: 130 explicit ConfigSorter(const AttributeMap &attributeMap) 131 : mWantRed(false), 132 mWantGreen(false), 133 mWantBlue(false), 134 mWantAlpha(false), 135 mWantLuminance(false) 136 { 137 scanForWantedComponents(attributeMap); 138 } 139 140 bool operator()(const Config *x, const Config *y) const { return (*this)(*x, *y); } 141 142 bool operator()(const Config &x, const Config &y) const 143 { 144 #define SORT(attribute) \ 145 do \ 146 { \ 147 if (x.attribute != y.attribute) \ 148 return x.attribute < y.attribute; \ 149 } while (0) 150 151 static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, 152 "Unexpected EGL enum value."); 153 SORT(configCaveat); 154 155 static_assert(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT < EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT, 156 "Unexpected order of EGL enums."); 157 SORT(colorComponentType); 158 159 static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "Unexpected EGL enum value."); 160 SORT(colorBufferType); 161 162 // By larger total number of color bits, only considering those that are requested to be > 163 // 0. 164 EGLint xComponentsSize = wantedComponentsSize(x); 165 EGLint yComponentsSize = wantedComponentsSize(y); 166 if (xComponentsSize != yComponentsSize) 167 { 168 return xComponentsSize > yComponentsSize; 169 } 170 171 SORT(bufferSize); 172 SORT(sampleBuffers); 173 SORT(samples); 174 SORT(depthSize); 175 SORT(stencilSize); 176 SORT(alphaMaskSize); 177 SORT(nativeVisualType); 178 SORT(configID); 179 180 #undef SORT 181 182 return false; 183 } 184 185 private: 186 static bool wantsComponent(const AttributeMap &attributeMap, EGLAttrib component) 187 { 188 // [EGL 1.5] section 3.4.1.2 page 30 189 // Sorting rule #3: by larger total number of color bits, not considering 190 // components that are 0 or don't-care. 191 EGLAttrib value = attributeMap.get(component, 0); 192 return value != 0 && value != EGL_DONT_CARE; 193 } 194 195 void scanForWantedComponents(const AttributeMap &attributeMap) 196 { 197 mWantRed = wantsComponent(attributeMap, EGL_RED_SIZE); 198 mWantGreen = wantsComponent(attributeMap, EGL_GREEN_SIZE); 199 mWantBlue = wantsComponent(attributeMap, EGL_BLUE_SIZE); 200 mWantAlpha = wantsComponent(attributeMap, EGL_ALPHA_SIZE); 201 mWantLuminance = wantsComponent(attributeMap, EGL_LUMINANCE_SIZE); 202 } 203 204 EGLint wantedComponentsSize(const Config &config) const 205 { 206 EGLint total = 0; 207 208 if (mWantRed) 209 total += config.redSize; 210 if (mWantGreen) 211 total += config.greenSize; 212 if (mWantBlue) 213 total += config.blueSize; 214 if (mWantAlpha) 215 total += config.alphaSize; 216 if (mWantLuminance) 217 total += config.luminanceSize; 218 219 return total; 220 } 221 222 bool mWantRed; 223 bool mWantGreen; 224 bool mWantBlue; 225 bool mWantAlpha; 226 bool mWantLuminance; 227 }; 228 229 std::vector<const Config *> ConfigSet::filter(const AttributeMap &attributeMap) const 230 { 231 std::vector<const Config *> result; 232 result.reserve(mConfigs.size()); 233 234 for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++) 235 { 236 const Config &config = configIter->second; 237 bool match = true; 238 239 for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++) 240 { 241 EGLAttrib attributeKey = attribIter->first; 242 EGLAttrib attributeValue = attribIter->second; 243 244 if (attributeValue == EGL_DONT_CARE) 245 { 246 continue; 247 } 248 249 switch (attributeKey) 250 { 251 case EGL_BUFFER_SIZE: 252 match = config.bufferSize >= attributeValue; 253 break; 254 case EGL_ALPHA_SIZE: 255 match = config.alphaSize >= attributeValue; 256 break; 257 case EGL_BLUE_SIZE: 258 match = config.blueSize >= attributeValue; 259 break; 260 case EGL_GREEN_SIZE: 261 match = config.greenSize >= attributeValue; 262 break; 263 case EGL_RED_SIZE: 264 match = config.redSize >= attributeValue; 265 break; 266 case EGL_DEPTH_SIZE: 267 match = config.depthSize >= attributeValue; 268 break; 269 case EGL_STENCIL_SIZE: 270 match = config.stencilSize >= attributeValue; 271 break; 272 case EGL_CONFIG_CAVEAT: 273 match = config.configCaveat == static_cast<EGLenum>(attributeValue); 274 break; 275 case EGL_CONFIG_ID: 276 match = config.configID == attributeValue; 277 break; 278 case EGL_LEVEL: 279 match = config.level == attributeValue; 280 break; 281 case EGL_NATIVE_RENDERABLE: 282 match = config.nativeRenderable == static_cast<EGLBoolean>(attributeValue); 283 break; 284 case EGL_NATIVE_VISUAL_TYPE: 285 match = config.nativeVisualType == attributeValue; 286 break; 287 case EGL_SAMPLES: 288 match = config.samples >= attributeValue; 289 break; 290 case EGL_SAMPLE_BUFFERS: 291 match = config.sampleBuffers >= attributeValue; 292 break; 293 case EGL_SURFACE_TYPE: 294 match = (config.surfaceType & attributeValue) == attributeValue; 295 break; 296 case EGL_TRANSPARENT_TYPE: 297 match = config.transparentType == static_cast<EGLenum>(attributeValue); 298 break; 299 case EGL_TRANSPARENT_BLUE_VALUE: 300 if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE) 301 { 302 match = config.transparentBlueValue == attributeValue; 303 } 304 break; 305 case EGL_TRANSPARENT_GREEN_VALUE: 306 if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE) 307 { 308 match = config.transparentGreenValue == attributeValue; 309 } 310 break; 311 case EGL_TRANSPARENT_RED_VALUE: 312 if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE) 313 { 314 match = config.transparentRedValue == attributeValue; 315 } 316 break; 317 case EGL_BIND_TO_TEXTURE_RGB: 318 match = config.bindToTextureRGB == static_cast<EGLBoolean>(attributeValue); 319 break; 320 case EGL_BIND_TO_TEXTURE_RGBA: 321 match = config.bindToTextureRGBA == static_cast<EGLBoolean>(attributeValue); 322 break; 323 case EGL_BIND_TO_TEXTURE_TARGET_ANGLE: 324 match = config.bindToTextureTarget == static_cast<EGLenum>(attributeValue); 325 break; 326 case EGL_MIN_SWAP_INTERVAL: 327 match = config.minSwapInterval == attributeValue; 328 break; 329 case EGL_MAX_SWAP_INTERVAL: 330 match = config.maxSwapInterval == attributeValue; 331 break; 332 case EGL_LUMINANCE_SIZE: 333 match = config.luminanceSize >= attributeValue; 334 break; 335 case EGL_ALPHA_MASK_SIZE: 336 match = config.alphaMaskSize >= attributeValue; 337 break; 338 case EGL_COLOR_BUFFER_TYPE: 339 match = config.colorBufferType == static_cast<EGLenum>(attributeValue); 340 break; 341 case EGL_RENDERABLE_TYPE: 342 match = (config.renderableType & attributeValue) == attributeValue; 343 break; 344 case EGL_MATCH_NATIVE_PIXMAP: 345 match = false; 346 UNIMPLEMENTED(); 347 break; 348 case EGL_CONFORMANT: 349 match = (config.conformant & attributeValue) == attributeValue; 350 break; 351 case EGL_MAX_PBUFFER_WIDTH: 352 match = config.maxPBufferWidth >= attributeValue; 353 break; 354 case EGL_MAX_PBUFFER_HEIGHT: 355 match = config.maxPBufferHeight >= attributeValue; 356 break; 357 case EGL_MAX_PBUFFER_PIXELS: 358 match = config.maxPBufferPixels >= attributeValue; 359 break; 360 case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE: 361 match = config.optimalOrientation == attributeValue; 362 break; 363 case EGL_COLOR_COMPONENT_TYPE_EXT: 364 match = config.colorComponentType == static_cast<EGLenum>(attributeValue); 365 break; 366 case EGL_RECORDABLE_ANDROID: 367 match = config.recordable == static_cast<EGLBoolean>(attributeValue); 368 break; 369 case EGL_FRAMEBUFFER_TARGET_ANDROID: 370 match = config.framebufferTarget == static_cast<EGLBoolean>(attributeValue); 371 break; 372 case EGL_Y_INVERTED_NOK: 373 match = config.yInverted == static_cast<EGLBoolean>(attributeValue); 374 break; 375 case EGL_MATCH_FORMAT_KHR: 376 if (attributeValue == EGL_NONE) 377 { 378 match = (config.surfaceType & EGL_LOCK_SURFACE_BIT_KHR) == 0; 379 } 380 else 381 { 382 match = config.matchFormat == attributeValue; 383 } 384 break; 385 default: 386 UNREACHABLE(); 387 } 388 389 if (!match) 390 { 391 break; 392 } 393 } 394 395 if (match) 396 { 397 result.push_back(&config); 398 } 399 } 400 401 // Sort the result 402 std::sort(result.begin(), result.end(), ConfigSorter(attributeMap)); 403 404 return result; 405 } 406 407 ConfigSet::ConfigMap::iterator ConfigSet::begin() 408 { 409 return mConfigs.begin(); 410 } 411 412 ConfigSet::ConfigMap::iterator ConfigSet::end() 413 { 414 return mConfigs.end(); 415 } 416 } // namespace egl