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>
37 // OpenGL ES 3.0 support is not conformant yet, but can be used for testing purposes. Expose it as conformant configs
38 // if strict conformance advertisement isn't required. If strict conformance advertisement is required, expose them
39 // as non-conformant configs, but only when EGL_CONFIG_CAVEAT is EGL_NON_CONFORMANT_CONFIG or EGL_DONT_CARE.
40 #if defined(__ANDROID__) || defined(STRICT_CONFORMANCE)
41 const bool strictConformance = true;
43 const bool strictConformance = false;
46 Config::Config(sw::Format displayFormat, EGLint minInterval, EGLint maxInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample, bool conformant)
47 : mDisplayFormat(displayFormat), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
49 mBindToTextureRGB = EGL_FALSE;
50 mBindToTextureRGBA = EGL_FALSE;
52 // Initialize to a high value to lower the preference of formats for which there's no native support
53 mNativeVisualID = 0x7FFFFFFF;
55 switch(renderTargetFormat)
57 case sw::FORMAT_A1R5G5B5:
63 case sw::FORMAT_A2R10G10B10:
69 case sw::FORMAT_A8R8G8B8:
74 mBindToTextureRGBA = EGL_TRUE;
76 mNativeVisualID = HAL_PIXEL_FORMAT_BGRA_8888;
78 mNativeVisualID = 2; // Arbitrary; prefer over ABGR
81 case sw::FORMAT_A8B8G8R8:
86 mBindToTextureRGBA = EGL_TRUE;
88 mNativeVisualID = HAL_PIXEL_FORMAT_RGBA_8888;
91 case sw::FORMAT_R5G6B5:
97 mNativeVisualID = HAL_PIXEL_FORMAT_RGB_565;
100 case sw::FORMAT_X8R8G8B8:
105 mBindToTextureRGB = EGL_TRUE;
107 mNativeVisualID = 0x1FF; // HAL_PIXEL_FORMAT_BGRX_8888
109 mNativeVisualID = 1; // Arbitrary; prefer over XBGR
112 case sw::FORMAT_X8B8G8R8:
117 mBindToTextureRGB = EGL_TRUE;
119 mNativeVisualID = HAL_PIXEL_FORMAT_RGBX_8888;
123 UNREACHABLE(renderTargetFormat);
127 mBufferSize = mRedSize + mGreenSize + mBlueSize + mLuminanceSize + mAlphaSize;
129 mColorBufferType = EGL_RGB_BUFFER;
130 mConfigCaveat = (conformant || !strictConformance) ? EGL_NONE : EGL_NON_CONFORMANT_CONFIG;
132 mConformant = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | (strictConformance ? 0 : EGL_OPENGL_ES3_BIT);
134 switch(depthStencilFormat)
136 case sw::FORMAT_NULL:
140 // case sw::FORMAT_D16_LOCKABLE:
148 // case sw::FORMAT_D15S1:
152 case sw::FORMAT_D24S8:
156 case sw::FORMAT_D24X8:
160 // case sw::FORMAT_D24X4S4:
168 // case sw::FORMAT_D32F_LOCKABLE:
172 // case sw::FORMAT_D24FS8:
177 UNREACHABLE(depthStencilFormat);
181 mMatchNativePixmap = EGL_NONE;
182 mMaxPBufferWidth = 4096;
183 mMaxPBufferHeight = 4096;
184 mMaxPBufferPixels = mMaxPBufferWidth * mMaxPBufferHeight;
185 mMaxSwapInterval = maxInterval;
186 mMinSwapInterval = minInterval;
187 mNativeRenderable = EGL_FALSE;
188 mNativeVisualType = 0;
189 mRenderableType = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | ((conformant && strictConformance) ? 0 : EGL_OPENGL_ES3_BIT);
190 mSampleBuffers = (multiSample > 0) ? 1 : 0;
191 mSamples = multiSample;
192 mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
193 mTransparentType = EGL_NONE;
194 mTransparentRedValue = 0;
195 mTransparentGreenValue = 0;
196 mTransparentBlueValue = 0;
198 mRecordableAndroid = EGL_TRUE;
199 mFramebufferTargetAndroid = (displayFormat == renderTargetFormat) ? EGL_TRUE : EGL_FALSE;
202 EGLConfig Config::getHandle() const
204 return (EGLConfig)(size_t)mConfigID;
207 // This ordering determines the config ID
208 bool CompareConfig::operator()(const Config &x, const Config &y) const
210 #define SORT_SMALLER(attribute) \
211 if(x.attribute != y.attribute) \
213 return x.attribute < y.attribute; \
216 static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
217 SORT_SMALLER(mConfigCaveat);
219 static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
220 SORT_SMALLER(mColorBufferType);
222 SORT_SMALLER(mRedSize);
223 SORT_SMALLER(mGreenSize);
224 SORT_SMALLER(mBlueSize);
225 SORT_SMALLER(mAlphaSize);
227 SORT_SMALLER(mBufferSize);
228 SORT_SMALLER(mSampleBuffers);
229 SORT_SMALLER(mSamples);
230 SORT_SMALLER(mDepthSize);
231 SORT_SMALLER(mStencilSize);
232 SORT_SMALLER(mAlphaMaskSize);
233 SORT_SMALLER(mNativeVisualType);
234 SORT_SMALLER(mNativeVisualID);
238 // Strict ordering requires sorting all non-equal fields above
239 assert(memcmp(&x, &y, sizeof(Config)) == 0);
244 // Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24.
248 explicit SortConfig(const EGLint *attribList);
250 bool operator()(const Config *x, const Config *y) const;
253 EGLint wantedComponentsSize(const Config *config) const;
262 SortConfig::SortConfig(const EGLint *attribList)
263 : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
265 // [EGL] section 3.4.1 page 24
266 // Sorting rule #3: by larger total number of color bits,
267 // not considering components that are 0 or don't-care.
268 for(const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
270 if(attr[1] != 0 && attr[1] != EGL_DONT_CARE)
274 case EGL_RED_SIZE: mWantRed = true; break;
275 case EGL_GREEN_SIZE: mWantGreen = true; break;
276 case EGL_BLUE_SIZE: mWantBlue = true; break;
277 case EGL_ALPHA_SIZE: mWantAlpha = true; break;
278 case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
284 EGLint SortConfig::wantedComponentsSize(const Config *config) const
288 if(mWantRed) total += config->mRedSize;
289 if(mWantGreen) total += config->mGreenSize;
290 if(mWantBlue) total += config->mBlueSize;
291 if(mWantAlpha) total += config->mAlphaSize;
292 if(mWantLuminance) total += config->mLuminanceSize;
297 bool SortConfig::operator()(const Config *x, const Config *y) const
299 #define SORT_SMALLER(attribute) \
300 if(x->attribute != y->attribute) \
302 return x->attribute < y->attribute; \
305 static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
306 SORT_SMALLER(mConfigCaveat);
308 static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
309 SORT_SMALLER(mColorBufferType);
311 // By larger total number of color bits, only considering those that are requested to be > 0.
312 EGLint xComponentsSize = wantedComponentsSize(x);
313 EGLint yComponentsSize = wantedComponentsSize(y);
314 if(xComponentsSize != yComponentsSize)
316 return xComponentsSize > yComponentsSize;
319 SORT_SMALLER(mBufferSize);
320 SORT_SMALLER(mSampleBuffers);
321 SORT_SMALLER(mSamples);
322 SORT_SMALLER(mDepthSize);
323 SORT_SMALLER(mStencilSize);
324 SORT_SMALLER(mAlphaMaskSize);
325 SORT_SMALLER(mNativeVisualType);
326 SORT_SMALLER(mConfigID);
333 ConfigSet::ConfigSet()
337 void ConfigSet::add(sw::Format displayFormat, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
339 Config conformantConfig(displayFormat, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, true);
340 mSet.insert(conformantConfig);
342 if(strictConformance) // When strict conformance is required, add non-conformant configs explicitly as such.
344 Config nonConformantConfig(displayFormat, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, false);
345 mSet.insert(nonConformantConfig);
349 size_t ConfigSet::size() const
354 bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
356 vector<const Config*> passed;
357 passed.reserve(mSet.size());
359 for(Iterator config = mSet.begin(); config != mSet.end(); config++)
362 bool caveatMatch = (config->mConfigCaveat == EGL_NONE);
363 const EGLint *attribute = attribList;
365 while(attribute[0] != EGL_NONE)
367 if(attribute[1] != EGL_DONT_CARE)
371 case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
372 case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
373 case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
374 case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
375 case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
376 case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
377 case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
378 case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum)attribute[1]; break;
379 case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
380 case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
381 case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean)attribute[1]; break;
382 case EGL_NATIVE_VISUAL_ID: match = config->mNativeVisualID == attribute[1]; break;
383 case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
384 case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
385 case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
386 case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
387 case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum)attribute[1]; break;
388 case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
389 case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
390 case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
391 case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean)attribute[1]; break;
392 case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean)attribute[1]; break;
393 case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
394 case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
395 case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
396 case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
397 case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum)attribute[1]; break;
398 case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
399 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
400 case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
401 case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
402 case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
403 case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
404 case EGL_RECORDABLE_ANDROID: match = config->mRecordableAndroid == (EGLBoolean)attribute[1]; break;
405 case EGL_FRAMEBUFFER_TARGET_ANDROID: match = config->mFramebufferTargetAndroid == (EGLBoolean)attribute[1]; break;
417 if(attribute[0] == EGL_CONFIG_CAVEAT)
425 if(match && caveatMatch) // We require the caveats to be NONE or the requested flags
427 passed.push_back(&*config);
433 sort(passed.begin(), passed.end(), SortConfig(attribList));
436 for(index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
438 configs[index] = passed[index]->getHandle();
445 *numConfig = static_cast<EGLint>(passed.size());
451 const egl::Config *ConfigSet::get(EGLConfig configHandle)
453 for(Iterator config = mSet.begin(); config != mSet.end(); config++)
455 if(config->getHandle() == configHandle)