1 // SwiftShader Software Renderer
3 // Copyright(c) 2005-2013 TransGaming Inc.
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,
6 // transcribed, stored in a retrieval system, translated into any human or computer
7 // language by any means, or disclosed to third parties without the explicit written
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9 // or implied, including but not limited to any patent rights, are granted to you.
12 // Config.cpp: Implements the egl::Config class, describing the format, type
13 // and size for an egl::Surface. Implements EGLConfig and related functionality.
14 // [EGL 1.4] section 3.4 page 15.
18 #include "common/debug.h"
21 #include <EGL/eglext.h>
30 Config::Config(const DisplayMode &displayMode, EGLint minInterval, EGLint maxInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
31 : mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
33 mBindToTextureRGB = EGL_FALSE;
34 mBindToTextureRGBA = EGL_FALSE;
36 switch (renderTargetFormat)
38 case sw::FORMAT_A1R5G5B5:
45 case sw::FORMAT_A2R10G10B10:
52 case sw::FORMAT_A8R8G8B8:
58 mBindToTextureRGBA = true;
60 case sw::FORMAT_R5G6B5:
67 case sw::FORMAT_X8R8G8B8:
73 mBindToTextureRGB = true;
76 UNREACHABLE(); // Other formats should not be valid
81 mColorBufferType = EGL_RGB_BUFFER;
82 mConfigCaveat = isSlowConfig() ? EGL_SLOW_CONFIG : EGL_NONE;
84 mConformant = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
86 switch (depthStencilFormat)
92 // case sw::FORMAT_D16_LOCKABLE:
100 // case sw::FORMAT_D15S1:
104 case sw::FORMAT_D24S8:
108 case sw::FORMAT_D24X8:
112 // case sw::FORMAT_D24X4S4:
120 // case sw::FORMAT_D32F_LOCKABLE:
124 // case sw::FORMAT_D24FS8:
133 mMatchNativePixmap = EGL_NONE;
134 mMaxPBufferWidth = 4096;
135 mMaxPBufferHeight = 4096;
136 mMaxPBufferPixels = mMaxPBufferWidth * mMaxPBufferHeight;
137 mMaxSwapInterval = maxInterval;
138 mMinSwapInterval = minInterval;
139 mNativeRenderable = EGL_FALSE;
141 mNativeVisualType = 0;
142 mRenderableType = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
143 mSampleBuffers = multiSample ? 1 : 0;
144 mSamples = multiSample;
145 mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
146 mTransparentType = EGL_NONE;
147 mTransparentRedValue = 0;
148 mTransparentGreenValue = 0;
149 mTransparentBlueValue = 0;
152 EGLConfig Config::getHandle() const
154 return (EGLConfig)(size_t)mConfigID;
157 bool Config::isSlowConfig() const
159 return mRenderTargetFormat != sw::FORMAT_X8R8G8B8 && mRenderTargetFormat != sw::FORMAT_A8R8G8B8;
162 SortConfig::SortConfig(const EGLint *attribList)
163 : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
165 scanForWantedComponents(attribList);
168 void SortConfig::scanForWantedComponents(const EGLint *attribList)
170 // [EGL] section 3.4.1 page 24
171 // Sorting rule #3: by larger total number of color bits, not considering
172 // components that are 0 or don't-care.
173 for(const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
175 if(attr[1] != 0 && attr[1] != EGL_DONT_CARE)
179 case EGL_RED_SIZE: mWantRed = true; break;
180 case EGL_GREEN_SIZE: mWantGreen = true; break;
181 case EGL_BLUE_SIZE: mWantBlue = true; break;
182 case EGL_ALPHA_SIZE: mWantAlpha = true; break;
183 case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
189 EGLint SortConfig::wantedComponentsSize(const Config &config) const
193 if(mWantRed) total += config.mRedSize;
194 if(mWantGreen) total += config.mGreenSize;
195 if(mWantBlue) total += config.mBlueSize;
196 if(mWantAlpha) total += config.mAlphaSize;
197 if(mWantLuminance) total += config.mLuminanceSize;
202 bool SortConfig::operator()(const Config *x, const Config *y) const
204 return (*this)(*x, *y);
207 bool SortConfig::operator()(const Config &x, const Config &y) const
209 #define SORT(attribute) \
210 if(x.attribute != y.attribute) \
212 return x.attribute < y.attribute; \
215 META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
218 META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
219 SORT(mColorBufferType);
221 // By larger total number of color bits, only considering those that are requested to be > 0.
222 EGLint xComponentsSize = wantedComponentsSize(x);
223 EGLint yComponentsSize = wantedComponentsSize(y);
224 if(xComponentsSize != yComponentsSize)
226 return xComponentsSize > yComponentsSize;
230 SORT(mSampleBuffers);
234 SORT(mAlphaMaskSize);
235 SORT(mNativeVisualType);
243 // We'd like to use SortConfig to also eliminate duplicate configs.
244 // This works as long as we never have two configs with different per-RGB-component layouts,
245 // but the same total.
246 // 5551 and 565 are different because R+G+B is different.
247 // 5551 and 555 are different because bufferSize is different.
248 const EGLint ConfigSet::mSortAttribs[] =
253 EGL_LUMINANCE_SIZE, 1,
258 ConfigSet::ConfigSet()
259 : mSet(SortConfig(mSortAttribs))
263 void ConfigSet::add(const DisplayMode &displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
265 Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample);
270 size_t ConfigSet::size() const
275 bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
277 vector<const Config*> passed;
278 passed.reserve(mSet.size());
280 for(Iterator config = mSet.begin(); config != mSet.end(); config++)
283 const EGLint *attribute = attribList;
285 while(attribute[0] != EGL_NONE)
289 case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
290 case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
291 case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
292 case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
293 case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
294 case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
295 case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
296 case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == attribute[1]; break;
297 case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
298 case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
299 case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == attribute[1]; break;
300 case EGL_NATIVE_VISUAL_ID: match = config->mNativeVisualID == attribute[1]; break;
301 case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
302 case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
303 case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
304 case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
305 case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == attribute[1]; break;
306 case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
307 case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
308 case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
309 case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == attribute[1]; break;
310 case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == attribute[1]; break;
311 case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
312 case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
313 case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
314 case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
315 case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == attribute[1]; break;
316 case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
317 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
318 case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
319 case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
320 case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
321 case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
322 case EGL_RECORDABLE_ANDROID: match = false; /* UNIMPLEMENTED(); */ break;
323 case EGL_FRAMEBUFFER_TARGET_ANDROID: match = false; /* UNIMPLEMENTED(); */ break;
339 passed.push_back(&*config);
345 sort(passed.begin(), passed.end(), SortConfig(attribList));
348 for(index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
350 configs[index] = passed[index]->getHandle();
357 *numConfig = static_cast<EGLint>(passed.size());
363 const egl::Config *ConfigSet::get(EGLConfig configHandle)
365 for(Iterator config = mSet.begin(); config != mSet.end(); config++)
367 if(config->getHandle() == configHandle)