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