1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/angle/src/libEGL/Config.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,340 @@ 1.4 +// 1.5 +// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved. 1.6 +// Use of this source code is governed by a BSD-style license that can be 1.7 +// found in the LICENSE file. 1.8 +// 1.9 + 1.10 +// Config.cpp: Implements the egl::Config class, describing the format, type 1.11 +// and size for an egl::Surface. Implements EGLConfig and related functionality. 1.12 +// [EGL 1.4] section 3.4 page 15. 1.13 + 1.14 +#include "libEGL/Config.h" 1.15 + 1.16 +#include <algorithm> 1.17 +#include <vector> 1.18 + 1.19 +#include <GLES2/gl2.h> 1.20 +#include <GLES2/gl2ext.h> 1.21 + 1.22 +#include "common/debug.h" 1.23 + 1.24 +using namespace std; 1.25 + 1.26 +namespace egl 1.27 +{ 1.28 +Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight) 1.29 + : mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample) 1.30 +{ 1.31 + mBindToTextureRGB = EGL_FALSE; 1.32 + mBindToTextureRGBA = EGL_FALSE; 1.33 + switch (desc.renderTargetFormat) 1.34 + { 1.35 + case GL_RGB5_A1: 1.36 + mBufferSize = 16; 1.37 + mRedSize = 5; 1.38 + mGreenSize = 5; 1.39 + mBlueSize = 5; 1.40 + mAlphaSize = 1; 1.41 + break; 1.42 + case GL_RGBA8_OES: 1.43 + mBufferSize = 32; 1.44 + mRedSize = 8; 1.45 + mGreenSize = 8; 1.46 + mBlueSize = 8; 1.47 + mAlphaSize = 8; 1.48 + mBindToTextureRGBA = true; 1.49 + break; 1.50 + case GL_RGB565: 1.51 + mBufferSize = 16; 1.52 + mRedSize = 5; 1.53 + mGreenSize = 6; 1.54 + mBlueSize = 5; 1.55 + mAlphaSize = 0; 1.56 + break; 1.57 + case GL_RGB8_OES: 1.58 + mBufferSize = 32; 1.59 + mRedSize = 8; 1.60 + mGreenSize = 8; 1.61 + mBlueSize = 8; 1.62 + mAlphaSize = 0; 1.63 + mBindToTextureRGB = true; 1.64 + break; 1.65 + case GL_BGRA8_EXT: 1.66 + mBufferSize = 32; 1.67 + mRedSize = 8; 1.68 + mGreenSize = 8; 1.69 + mBlueSize = 8; 1.70 + mAlphaSize = 8; 1.71 + mBindToTextureRGBA = true; 1.72 + break; 1.73 + default: 1.74 + UNREACHABLE(); // Other formats should not be valid 1.75 + } 1.76 + 1.77 + mLuminanceSize = 0; 1.78 + mAlphaMaskSize = 0; 1.79 + mColorBufferType = EGL_RGB_BUFFER; 1.80 + mConfigCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG; 1.81 + mConfigID = 0; 1.82 + mConformant = EGL_OPENGL_ES2_BIT; 1.83 + 1.84 + switch (desc.depthStencilFormat) 1.85 + { 1.86 + case GL_NONE: 1.87 + mDepthSize = 0; 1.88 + mStencilSize = 0; 1.89 + break; 1.90 + case GL_DEPTH_COMPONENT32_OES: 1.91 + mDepthSize = 32; 1.92 + mStencilSize = 0; 1.93 + break; 1.94 + case GL_DEPTH24_STENCIL8_OES: 1.95 + mDepthSize = 24; 1.96 + mStencilSize = 8; 1.97 + break; 1.98 + case GL_DEPTH_COMPONENT24_OES: 1.99 + mDepthSize = 24; 1.100 + mStencilSize = 0; 1.101 + break; 1.102 + case GL_DEPTH_COMPONENT16: 1.103 + mDepthSize = 16; 1.104 + mStencilSize = 0; 1.105 + break; 1.106 + default: 1.107 + UNREACHABLE(); 1.108 + } 1.109 + 1.110 + mLevel = 0; 1.111 + mMatchNativePixmap = EGL_NONE; 1.112 + mMaxPBufferWidth = texWidth; 1.113 + mMaxPBufferHeight = texHeight; 1.114 + mMaxPBufferPixels = texWidth*texHeight; 1.115 + mMaxSwapInterval = maxInterval; 1.116 + mMinSwapInterval = minInterval; 1.117 + mNativeRenderable = EGL_FALSE; 1.118 + mNativeVisualID = 0; 1.119 + mNativeVisualType = 0; 1.120 + mRenderableType = EGL_OPENGL_ES2_BIT; 1.121 + mSampleBuffers = desc.multiSample ? 1 : 0; 1.122 + mSamples = desc.multiSample; 1.123 + mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 1.124 + mTransparentType = EGL_NONE; 1.125 + mTransparentRedValue = 0; 1.126 + mTransparentGreenValue = 0; 1.127 + mTransparentBlueValue = 0; 1.128 +} 1.129 + 1.130 +EGLConfig Config::getHandle() const 1.131 +{ 1.132 + return (EGLConfig)(size_t)mConfigID; 1.133 +} 1.134 + 1.135 +SortConfig::SortConfig(const EGLint *attribList) 1.136 + : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false) 1.137 +{ 1.138 + scanForWantedComponents(attribList); 1.139 +} 1.140 + 1.141 +void SortConfig::scanForWantedComponents(const EGLint *attribList) 1.142 +{ 1.143 + // [EGL] section 3.4.1 page 24 1.144 + // Sorting rule #3: by larger total number of color bits, not considering 1.145 + // components that are 0 or don't-care. 1.146 + for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2) 1.147 + { 1.148 + if (attr[1] != 0 && attr[1] != EGL_DONT_CARE) 1.149 + { 1.150 + switch (attr[0]) 1.151 + { 1.152 + case EGL_RED_SIZE: mWantRed = true; break; 1.153 + case EGL_GREEN_SIZE: mWantGreen = true; break; 1.154 + case EGL_BLUE_SIZE: mWantBlue = true; break; 1.155 + case EGL_ALPHA_SIZE: mWantAlpha = true; break; 1.156 + case EGL_LUMINANCE_SIZE: mWantLuminance = true; break; 1.157 + } 1.158 + } 1.159 + } 1.160 +} 1.161 + 1.162 +EGLint SortConfig::wantedComponentsSize(const Config &config) const 1.163 +{ 1.164 + EGLint total = 0; 1.165 + 1.166 + if (mWantRed) total += config.mRedSize; 1.167 + if (mWantGreen) total += config.mGreenSize; 1.168 + if (mWantBlue) total += config.mBlueSize; 1.169 + if (mWantAlpha) total += config.mAlphaSize; 1.170 + if (mWantLuminance) total += config.mLuminanceSize; 1.171 + 1.172 + return total; 1.173 +} 1.174 + 1.175 +bool SortConfig::operator()(const Config *x, const Config *y) const 1.176 +{ 1.177 + return (*this)(*x, *y); 1.178 +} 1.179 + 1.180 +bool SortConfig::operator()(const Config &x, const Config &y) const 1.181 +{ 1.182 + #define SORT(attribute) \ 1.183 + if (x.attribute != y.attribute) \ 1.184 + { \ 1.185 + return x.attribute < y.attribute; \ 1.186 + } 1.187 + 1.188 + META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); 1.189 + SORT(mConfigCaveat); 1.190 + 1.191 + META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); 1.192 + SORT(mColorBufferType); 1.193 + 1.194 + // By larger total number of color bits, only considering those that are requested to be > 0. 1.195 + EGLint xComponentsSize = wantedComponentsSize(x); 1.196 + EGLint yComponentsSize = wantedComponentsSize(y); 1.197 + if (xComponentsSize != yComponentsSize) 1.198 + { 1.199 + return xComponentsSize > yComponentsSize; 1.200 + } 1.201 + 1.202 + SORT(mBufferSize); 1.203 + SORT(mSampleBuffers); 1.204 + SORT(mSamples); 1.205 + SORT(mDepthSize); 1.206 + SORT(mStencilSize); 1.207 + SORT(mAlphaMaskSize); 1.208 + SORT(mNativeVisualType); 1.209 + SORT(mConfigID); 1.210 + 1.211 + #undef SORT 1.212 + 1.213 + return false; 1.214 +} 1.215 + 1.216 +// We'd like to use SortConfig to also eliminate duplicate configs. 1.217 +// This works as long as we never have two configs with different per-RGB-component layouts, 1.218 +// but the same total. 1.219 +// 5551 and 565 are different because R+G+B is different. 1.220 +// 5551 and 555 are different because bufferSize is different. 1.221 +const EGLint ConfigSet::mSortAttribs[] = 1.222 +{ 1.223 + EGL_RED_SIZE, 1, 1.224 + EGL_GREEN_SIZE, 1, 1.225 + EGL_BLUE_SIZE, 1, 1.226 + EGL_LUMINANCE_SIZE, 1, 1.227 + // BUT NOT ALPHA 1.228 + EGL_NONE 1.229 +}; 1.230 + 1.231 +ConfigSet::ConfigSet() 1.232 + : mSet(SortConfig(mSortAttribs)) 1.233 +{ 1.234 +} 1.235 + 1.236 +void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight) 1.237 +{ 1.238 + Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight); 1.239 + mSet.insert(config); 1.240 +} 1.241 + 1.242 +size_t ConfigSet::size() const 1.243 +{ 1.244 + return mSet.size(); 1.245 +} 1.246 + 1.247 +bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) 1.248 +{ 1.249 + vector<const Config*> passed; 1.250 + passed.reserve(mSet.size()); 1.251 + 1.252 + for (Iterator config = mSet.begin(); config != mSet.end(); config++) 1.253 + { 1.254 + bool match = true; 1.255 + const EGLint *attribute = attribList; 1.256 + 1.257 + while (attribute[0] != EGL_NONE) 1.258 + { 1.259 + switch (attribute[0]) 1.260 + { 1.261 + case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break; 1.262 + case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break; 1.263 + case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break; 1.264 + case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break; 1.265 + case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break; 1.266 + case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break; 1.267 + case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break; 1.268 + case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum) attribute[1]; break; 1.269 + case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break; 1.270 + case EGL_LEVEL: match = config->mLevel >= attribute[1]; break; 1.271 + case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean) attribute[1]; break; 1.272 + case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break; 1.273 + case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break; 1.274 + case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break; 1.275 + case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break; 1.276 + case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum) attribute[1]; break; 1.277 + case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break; 1.278 + case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break; 1.279 + case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break; 1.280 + case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean) attribute[1]; break; 1.281 + case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1]; break; 1.282 + case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break; 1.283 + case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break; 1.284 + case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break; 1.285 + case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break; 1.286 + case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum) attribute[1]; break; 1.287 + case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break; 1.288 + case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break; 1.289 + case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break; 1.290 + case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break; 1.291 + case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break; 1.292 + case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break; 1.293 + default: 1.294 + return false; 1.295 + } 1.296 + 1.297 + if (!match) 1.298 + { 1.299 + break; 1.300 + } 1.301 + 1.302 + attribute += 2; 1.303 + } 1.304 + 1.305 + if (match) 1.306 + { 1.307 + passed.push_back(&*config); 1.308 + } 1.309 + } 1.310 + 1.311 + if (configs) 1.312 + { 1.313 + sort(passed.begin(), passed.end(), SortConfig(attribList)); 1.314 + 1.315 + EGLint index; 1.316 + for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++) 1.317 + { 1.318 + configs[index] = passed[index]->getHandle(); 1.319 + } 1.320 + 1.321 + *numConfig = index; 1.322 + } 1.323 + else 1.324 + { 1.325 + *numConfig = passed.size(); 1.326 + } 1.327 + 1.328 + return true; 1.329 +} 1.330 + 1.331 +const egl::Config *ConfigSet::get(EGLConfig configHandle) 1.332 +{ 1.333 + for (Iterator config = mSet.begin(); config != mSet.end(); config++) 1.334 + { 1.335 + if (config->getHandle() == configHandle) 1.336 + { 1.337 + return &(*config); 1.338 + } 1.339 + } 1.340 + 1.341 + return NULL; 1.342 +} 1.343 +}