1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
7 // http://www.apache.org/licenses/LICENSE-2.0
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 // Config.cpp: Implements the egl::Config class, describing the format, type
16 // and size for an egl::Surface. Implements EGLConfig and related functionality.
17 // [EGL 1.4] section 3.4 page 15.
21 #include "common/debug.h"
23 #include <EGL/eglext.h>
25 #include <system/graphics.h>
38 Config::Config(sw::Format displayFormat, EGLint minInterval, EGLint maxInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
39 : mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
41 mBindToTextureRGB = EGL_FALSE;
42 mBindToTextureRGBA = EGL_FALSE;
44 // Initialize to a high value to lower the preference of formats for which there's no native support
45 mNativeVisualID = 0x7FFFFFFF;
47 switch(renderTargetFormat)
49 case sw::FORMAT_A1R5G5B5:
55 case sw::FORMAT_A2R10G10B10:
61 case sw::FORMAT_A8R8G8B8:
66 mBindToTextureRGBA = EGL_TRUE;
68 mNativeVisualID = HAL_PIXEL_FORMAT_BGRA_8888;
70 mNativeVisualID = 2; // Arbitrary; prefer over ABGR
73 case sw::FORMAT_A8B8G8R8:
78 mBindToTextureRGBA = EGL_TRUE;
80 mNativeVisualID = HAL_PIXEL_FORMAT_RGBA_8888;
83 case sw::FORMAT_R5G6B5:
89 mNativeVisualID = HAL_PIXEL_FORMAT_RGB_565;
92 case sw::FORMAT_X8R8G8B8:
97 mBindToTextureRGB = EGL_TRUE;
99 mNativeVisualID = 0x1FF; // HAL_PIXEL_FORMAT_BGRX_8888
101 mNativeVisualID = 1; // Arbitrary; prefer over XBGR
104 case sw::FORMAT_X8B8G8R8:
109 mBindToTextureRGB = EGL_TRUE;
111 mNativeVisualID = HAL_PIXEL_FORMAT_RGBX_8888;
115 UNREACHABLE(renderTargetFormat);
119 mBufferSize = mRedSize + mGreenSize + mBlueSize + mLuminanceSize + mAlphaSize;
121 mColorBufferType = EGL_RGB_BUFFER;
122 mConfigCaveat = EGL_NONE;
124 mConformant = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
126 switch(depthStencilFormat)
128 case sw::FORMAT_NULL:
132 // case sw::FORMAT_D16_LOCKABLE:
140 // case sw::FORMAT_D15S1:
144 case sw::FORMAT_D24S8:
148 case sw::FORMAT_D24X8:
152 // case sw::FORMAT_D24X4S4:
160 // case sw::FORMAT_D32F_LOCKABLE:
164 // case sw::FORMAT_D24FS8:
169 UNREACHABLE(depthStencilFormat);
173 mMatchNativePixmap = EGL_NONE;
174 mMaxPBufferWidth = 4096;
175 mMaxPBufferHeight = 4096;
176 mMaxPBufferPixels = mMaxPBufferWidth * mMaxPBufferHeight;
177 mMaxSwapInterval = maxInterval;
178 mMinSwapInterval = minInterval;
179 mNativeRenderable = EGL_FALSE;
180 mNativeVisualType = 0;
181 mRenderableType = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
182 mSampleBuffers = (multiSample > 0) ? 1 : 0;
183 mSamples = multiSample;
184 mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT | EGL_MULTISAMPLE_RESOLVE_BOX_BIT;
185 mTransparentType = EGL_NONE;
186 mTransparentRedValue = 0;
187 mTransparentGreenValue = 0;
188 mTransparentBlueValue = 0;
190 // Although we could support any format as an Android HWComposer compatible config by converting when necessary,
191 // the intent of EGL_ANDROID_framebuffer_target is to prevent any copies or conversions.
192 mFramebufferTargetAndroid = (displayFormat == renderTargetFormat) ? EGL_TRUE : EGL_FALSE;
193 mRecordableAndroid = EGL_TRUE;
196 EGLConfig Config::getHandle() const
198 return (EGLConfig)(size_t)mConfigID;
201 // This ordering determines the config ID
202 bool CompareConfig::operator()(const Config &x, const Config &y) const
204 #define SORT_SMALLER(attribute) \
205 if(x.attribute != y.attribute) \
207 return x.attribute < y.attribute; \
210 static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
211 SORT_SMALLER(mConfigCaveat);
213 static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
214 SORT_SMALLER(mColorBufferType);
216 SORT_SMALLER(mRedSize);
217 SORT_SMALLER(mGreenSize);
218 SORT_SMALLER(mBlueSize);
219 SORT_SMALLER(mAlphaSize);
221 SORT_SMALLER(mBufferSize);
222 SORT_SMALLER(mSampleBuffers);
223 SORT_SMALLER(mSamples);
224 SORT_SMALLER(mDepthSize);
225 SORT_SMALLER(mStencilSize);
226 SORT_SMALLER(mAlphaMaskSize);
227 SORT_SMALLER(mNativeVisualType);
228 SORT_SMALLER(mNativeVisualID);
232 // Strict ordering requires sorting all non-equal fields above
233 assert(memcmp(&x, &y, sizeof(Config)) == 0);
238 // Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24.
242 explicit SortConfig(const EGLint *attribList);
244 bool operator()(const Config *x, const Config *y) const;
247 EGLint wantedComponentsSize(const Config *config) const;
256 SortConfig::SortConfig(const EGLint *attribList)
257 : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
259 // [EGL] section 3.4.1 page 24
260 // Sorting rule #3: by larger total number of color bits,
261 // not considering components that are 0 or don't-care.
262 for(const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
264 if(attr[1] != 0 && attr[1] != EGL_DONT_CARE)
268 case EGL_RED_SIZE: mWantRed = true; break;
269 case EGL_GREEN_SIZE: mWantGreen = true; break;
270 case EGL_BLUE_SIZE: mWantBlue = true; break;
271 case EGL_ALPHA_SIZE: mWantAlpha = true; break;
272 case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
278 EGLint SortConfig::wantedComponentsSize(const Config *config) const
282 if(mWantRed) total += config->mRedSize;
283 if(mWantGreen) total += config->mGreenSize;
284 if(mWantBlue) total += config->mBlueSize;
285 if(mWantAlpha) total += config->mAlphaSize;
286 if(mWantLuminance) total += config->mLuminanceSize;
291 bool SortConfig::operator()(const Config *x, const Config *y) const
293 #define SORT_SMALLER(attribute) \
294 if(x->attribute != y->attribute) \
296 return x->attribute < y->attribute; \
299 static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
300 SORT_SMALLER(mConfigCaveat);
302 static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
303 SORT_SMALLER(mColorBufferType);
305 // By larger total number of color bits, only considering those that are requested to be > 0.
306 EGLint xComponentsSize = wantedComponentsSize(x);
307 EGLint yComponentsSize = wantedComponentsSize(y);
308 if(xComponentsSize != yComponentsSize)
310 return xComponentsSize > yComponentsSize;
313 SORT_SMALLER(mBufferSize);
314 SORT_SMALLER(mSampleBuffers);
315 SORT_SMALLER(mSamples);
316 SORT_SMALLER(mDepthSize);
317 SORT_SMALLER(mStencilSize);
318 SORT_SMALLER(mAlphaMaskSize);
319 SORT_SMALLER(mNativeVisualType);
320 SORT_SMALLER(mConfigID);
327 ConfigSet::ConfigSet()
331 void ConfigSet::add(sw::Format displayFormat, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
333 Config conformantConfig(displayFormat, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample);
334 mSet.insert(conformantConfig);
337 size_t ConfigSet::size() const
342 bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
344 vector<const Config*> passed;
345 passed.reserve(mSet.size());
347 for(Iterator config = mSet.begin(); config != mSet.end(); config++)
350 bool caveatMatch = (config->mConfigCaveat == EGL_NONE);
351 const EGLint *attribute = attribList;
353 while(attribute[0] != EGL_NONE)
355 if(attribute[1] != EGL_DONT_CARE)
359 case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
360 case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
361 case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
362 case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
363 case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
364 case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
365 case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
366 case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum)attribute[1]; break;
367 case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
368 case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
369 case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean)attribute[1]; break;
370 case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
371 case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
372 case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
373 case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
374 case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum)attribute[1]; break;
375 case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
376 case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
377 case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
378 case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean)attribute[1]; break;
379 case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean)attribute[1]; break;
380 case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
381 case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
382 case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
383 case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
384 case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum)attribute[1]; break;
385 case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
386 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
387 case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
388 case EGL_RECORDABLE_ANDROID: match = config->mRecordableAndroid == (EGLBoolean)attribute[1]; break;
389 case EGL_FRAMEBUFFER_TARGET_ANDROID: match = config->mFramebufferTargetAndroid == (EGLBoolean)attribute[1]; break;
391 // Ignored attributes
392 case EGL_MAX_PBUFFER_WIDTH:
393 case EGL_MAX_PBUFFER_HEIGHT:
394 case EGL_MAX_PBUFFER_PIXELS:
395 case EGL_NATIVE_VISUAL_ID:
409 if(attribute[0] == EGL_CONFIG_CAVEAT)
417 if(match && caveatMatch) // We require the caveats to be NONE or the requested flags
419 passed.push_back(&*config);
425 sort(passed.begin(), passed.end(), SortConfig(attribList));
428 for(index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
430 configs[index] = passed[index]->getHandle();
437 *numConfig = static_cast<EGLint>(passed.size());
443 const egl::Config *ConfigSet::get(EGLConfig configHandle)
445 for(Iterator config = mSet.begin(); config != mSet.end(); config++)
447 if(config->getHandle() == configHandle)