1 // 2 // Copyright (c) 2002-2010 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.4] section 3.4 page 15. 10 11 #include "libEGL/Config.h" 12 13 #include <algorithm> 14 #include <vector> 15 16 #include "common/debug.h" 17 18 using namespace std; 19 20 namespace egl 21 { 22 Config::Config(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample) 23 : mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample) 24 { 25 set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample); 26 } 27 28 void Config::setDefaults() 29 { 30 mBufferSize = 0; 31 mRedSize = 0; 32 mGreenSize = 0; 33 mBlueSize = 0; 34 mLuminanceSize = 0; 35 mAlphaSize = 0; 36 mAlphaMaskSize = 0; 37 mBindToTextureRGB = EGL_DONT_CARE; 38 mBindToTextureRGBA = EGL_DONT_CARE; 39 mColorBufferType = EGL_RGB_BUFFER; 40 mConfigCaveat = EGL_DONT_CARE; 41 mConfigID = EGL_DONT_CARE; 42 mConformant = 0; 43 mDepthSize = 0; 44 mLevel = 0; 45 mMatchNativePixmap = EGL_NONE; 46 mMaxPBufferWidth = 0; 47 mMaxPBufferHeight = 0; 48 mMaxPBufferPixels = 0; 49 mMaxSwapInterval = EGL_DONT_CARE; 50 mMinSwapInterval = EGL_DONT_CARE; 51 mNativeRenderable = EGL_DONT_CARE; 52 mNativeVisualID = 0; 53 mNativeVisualType = EGL_DONT_CARE; 54 mRenderableType = EGL_OPENGL_ES_BIT; 55 mSampleBuffers = 0; 56 mSamples = 0; 57 mStencilSize = 0; 58 mSurfaceType = EGL_WINDOW_BIT; 59 mTransparentType = EGL_NONE; 60 mTransparentRedValue = EGL_DONT_CARE; 61 mTransparentGreenValue = EGL_DONT_CARE; 62 mTransparentBlueValue = EGL_DONT_CARE; 63 } 64 65 void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample) 66 { 67 switch (renderTargetFormat) 68 { 69 case D3DFMT_A1R5G5B5: 70 mBufferSize = 16; 71 mRedSize = 5; 72 mGreenSize = 5; 73 mBlueSize = 5; 74 mAlphaSize = 1; 75 break; 76 case D3DFMT_A2R10G10B10: 77 mBufferSize = 32; 78 mRedSize = 10; 79 mGreenSize = 10; 80 mBlueSize = 10; 81 mAlphaSize = 2; 82 break; 83 case D3DFMT_A8R8G8B8: 84 mBufferSize = 32; 85 mRedSize = 8; 86 mGreenSize = 8; 87 mBlueSize = 8; 88 mAlphaSize = 8; 89 break; 90 case D3DFMT_R5G6B5: 91 mBufferSize = 16; 92 mRedSize = 5; 93 mGreenSize = 6; 94 mBlueSize = 5; 95 mAlphaSize = 0; 96 break; 97 case D3DFMT_X8R8G8B8: 98 mBufferSize = 32; 99 mRedSize = 8; 100 mGreenSize = 8; 101 mBlueSize = 8; 102 mAlphaSize = 0; 103 break; 104 default: 105 UNREACHABLE(); // Other formats should not be valid 106 } 107 108 mLuminanceSize = 0; 109 mAlphaMaskSize = 0; 110 mBindToTextureRGB = EGL_FALSE; 111 mBindToTextureRGBA = EGL_FALSE; 112 mColorBufferType = EGL_RGB_BUFFER; 113 mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG; 114 mConfigID = 0; 115 mConformant = EGL_OPENGL_ES2_BIT; 116 117 switch (depthStencilFormat) 118 { 119 // case D3DFMT_D16_LOCKABLE: 120 // mDepthSize = 16; 121 // mStencilSize = 0; 122 // break; 123 case D3DFMT_D32: 124 mDepthSize = 32; 125 mStencilSize = 0; 126 break; 127 case D3DFMT_D15S1: 128 mDepthSize = 15; 129 mStencilSize = 1; 130 break; 131 case D3DFMT_D24S8: 132 mDepthSize = 24; 133 mStencilSize = 8; 134 break; 135 case D3DFMT_D24X8: 136 mDepthSize = 24; 137 mStencilSize = 0; 138 break; 139 case D3DFMT_D24X4S4: 140 mDepthSize = 24; 141 mStencilSize = 4; 142 break; 143 case D3DFMT_D16: 144 mDepthSize = 16; 145 mStencilSize = 0; 146 break; 147 // case D3DFMT_D32F_LOCKABLE: 148 // mDepthSize = 32; 149 // mStencilSize = 0; 150 // break; 151 // case D3DFMT_D24FS8: 152 // mDepthSize = 24; 153 // mStencilSize = 8; 154 // break; 155 default: 156 UNREACHABLE(); 157 } 158 159 mLevel = 0; 160 mMatchNativePixmap = EGL_NONE; 161 mMaxPBufferWidth = 0; 162 mMaxPBufferHeight = 0; 163 mMaxPBufferPixels = 0; 164 mMaxSwapInterval = maxInterval; 165 mMinSwapInterval = minInterval; 166 mNativeRenderable = EGL_FALSE; 167 mNativeVisualID = 0; 168 mNativeVisualType = 0; 169 mRenderableType = EGL_OPENGL_ES2_BIT; 170 mSampleBuffers = multiSample ? 1 : 0; 171 mSamples = multiSample; 172 mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 173 mTransparentType = EGL_NONE; 174 mTransparentRedValue = 0; 175 mTransparentGreenValue = 0; 176 mTransparentBlueValue = 0; 177 } 178 179 EGLConfig Config::getHandle() const 180 { 181 return (EGLConfig)(size_t)mConfigID; 182 } 183 184 SortConfig::SortConfig(const EGLint *attribList) 185 : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false) 186 { 187 scanForWantedComponents(attribList); 188 } 189 190 void SortConfig::scanForWantedComponents(const EGLint *attribList) 191 { 192 // [EGL] section 3.4.1 page 24 193 // Sorting rule #3: by larger total number of color bits, not considering 194 // components that are 0 or don't-care. 195 for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2) 196 { 197 if (attr[1] != 0 && attr[1] != EGL_DONT_CARE) 198 { 199 switch (attr[0]) 200 { 201 case EGL_RED_SIZE: mWantRed = true; break; 202 case EGL_GREEN_SIZE: mWantGreen = true; break; 203 case EGL_BLUE_SIZE: mWantBlue = true; break; 204 case EGL_ALPHA_SIZE: mWantAlpha = true; break; 205 case EGL_LUMINANCE_SIZE: mWantLuminance = true; break; 206 } 207 } 208 } 209 } 210 211 EGLint SortConfig::wantedComponentsSize(const Config &config) const 212 { 213 EGLint total = 0; 214 215 if (mWantRed) total += config.mRedSize; 216 if (mWantGreen) total += config.mGreenSize; 217 if (mWantBlue) total += config.mBlueSize; 218 if (mWantAlpha) total += config.mAlphaSize; 219 if (mWantLuminance) total += config.mLuminanceSize; 220 221 return total; 222 } 223 224 bool SortConfig::operator()(const Config *x, const Config *y) const 225 { 226 return (*this)(*x, *y); 227 } 228 229 bool SortConfig::operator()(const Config &x, const Config &y) const 230 { 231 #define SORT(attribute) \ 232 if (x.attribute != y.attribute) \ 233 { \ 234 return x.attribute < y.attribute; \ 235 } 236 237 META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); 238 SORT(mConfigCaveat); 239 240 META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); 241 SORT(mColorBufferType); 242 243 // By larger total number of color bits, only considering those that are requested to be > 0. 244 EGLint xComponentsSize = wantedComponentsSize(x); 245 EGLint yComponentsSize = wantedComponentsSize(y); 246 if (xComponentsSize != yComponentsSize) 247 { 248 return xComponentsSize > yComponentsSize; 249 } 250 251 SORT(mBufferSize); 252 SORT(mSampleBuffers); 253 SORT(mSamples); 254 SORT(mDepthSize); 255 SORT(mStencilSize); 256 SORT(mAlphaMaskSize); 257 SORT(mNativeVisualType); 258 SORT(mConfigID); 259 260 #undef SORT 261 262 return false; 263 } 264 265 // We'd like to use SortConfig to also eliminate duplicate configs. 266 // This works as long as we never have two configs with different per-RGB-component layouts, 267 // but the same total. 268 // 5551 and 565 are different because R+G+B is different. 269 // 5551 and 555 are different because bufferSize is different. 270 const EGLint ConfigSet::mSortAttribs[] = 271 { 272 EGL_RED_SIZE, 1, 273 EGL_GREEN_SIZE, 1, 274 EGL_BLUE_SIZE, 1, 275 EGL_LUMINANCE_SIZE, 1, 276 // BUT NOT ALPHA 277 EGL_NONE 278 }; 279 280 ConfigSet::ConfigSet() 281 : mSet(SortConfig(mSortAttribs)) 282 { 283 } 284 285 void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample) 286 { 287 Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample); 288 289 mSet.insert(config); 290 } 291 292 size_t ConfigSet::size() const 293 { 294 return mSet.size(); 295 } 296 297 bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) 298 { 299 vector<const Config*> passed; 300 passed.reserve(mSet.size()); 301 302 for (Iterator config = mSet.begin(); config != mSet.end(); config++) 303 { 304 bool match = true; 305 const EGLint *attribute = attribList; 306 307 while (attribute[0] != EGL_NONE) 308 { 309 switch (attribute[0]) 310 { 311 case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break; 312 case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break; 313 case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break; 314 case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break; 315 case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break; 316 case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break; 317 case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break; 318 case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == attribute[1]; break; 319 case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break; 320 case EGL_LEVEL: match = config->mLevel >= attribute[1]; break; 321 case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == attribute[1]; break; 322 case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break; 323 case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break; 324 case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break; 325 case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break; 326 case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == attribute[1]; break; 327 case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break; 328 case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break; 329 case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break; 330 case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == attribute[1]; break; 331 case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == attribute[1]; break; 332 case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break; 333 case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break; 334 case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break; 335 case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break; 336 case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == attribute[1]; break; 337 case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break; 338 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break; 339 case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break; 340 default: 341 return false; 342 } 343 344 if (!match) 345 { 346 break; 347 } 348 349 attribute += 2; 350 } 351 352 if (match) 353 { 354 passed.push_back(&*config); 355 } 356 } 357 358 if (configs) 359 { 360 sort(passed.begin(), passed.end(), SortConfig(attribList)); 361 362 EGLint index; 363 for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++) 364 { 365 configs[index] = passed[index]->getHandle(); 366 } 367 368 *numConfig = index; 369 } 370 else 371 { 372 *numConfig = passed.size(); 373 } 374 375 return true; 376 } 377 378 const egl::Config *ConfigSet::get(EGLConfig configHandle) 379 { 380 for (Iterator config = mSet.begin(); config != mSet.end(); config++) 381 { 382 if (config->getHandle() == configHandle) 383 { 384 return &(*config); 385 } 386 } 387 388 return NULL; 389 } 390 } 391