Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 1 | // Copyright 2016 The SwiftShader Authors. All Rights Reserved. |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 2 | // |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 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 |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 6 | // |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 7 | // http://www.apache.org/licenses/LICENSE-2.0 |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 8 | // |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 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. |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 14 | |
| 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. |
| 18 | |
| 19 | #include "Config.h" |
| 20 | |
| 21 | #include "common/debug.h" |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 22 | |
Nicolas Capens | f4fea7f | 2014-11-25 13:31:46 -0500 | [diff] [blame] | 23 | #include <EGL/eglext.h> |
Stephen White | e6ab01f | 2019-04-04 14:31:25 -0400 | [diff] [blame] | 24 | #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD) |
Nicolas Capens | b3c0c73 | 2015-10-30 14:05:23 -0400 | [diff] [blame] | 25 | #include <system/graphics.h> |
| 26 | #endif |
Nicolas Capens | f4fea7f | 2014-11-25 13:31:46 -0500 | [diff] [blame] | 27 | |
Nicolas Capens | b77b877 | 2015-10-30 13:50:31 -0400 | [diff] [blame] | 28 | #include <string.h> |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 29 | #include <algorithm> |
Anthony Vallee-Dubois | 13241c6 | 2015-08-17 14:12:32 -0400 | [diff] [blame] | 30 | #include <cstring> |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 31 | #include <vector> |
Chris Forbes | 787e3d5 | 2018-08-31 18:26:20 -0700 | [diff] [blame] | 32 | #include <map> |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 33 | |
| 34 | using namespace std; |
| 35 | |
| 36 | namespace egl |
| 37 | { |
Nicolas Capens | 216980a | 2017-01-02 16:21:39 -0500 | [diff] [blame] | 38 | |
Nicolas Capens | c8fcfd8 | 2018-01-11 12:53:57 -0500 | [diff] [blame] | 39 | Config::Config(sw::Format displayFormat, EGLint minInterval, EGLint maxInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample) |
Nicolas Capens | 81c2857 | 2017-03-13 15:08:39 -0400 | [diff] [blame] | 40 | : mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample) |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 41 | { |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 42 | mBindToTextureRGB = EGL_FALSE; |
| 43 | mBindToTextureRGBA = EGL_FALSE; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 44 | |
Nicolas Capens | f59ad06 | 2015-11-13 12:39:21 -0500 | [diff] [blame] | 45 | // Initialize to a high value to lower the preference of formats for which there's no native support |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 46 | mNativeVisualID = 0x7FFFFFFF; |
Nicolas Capens | b3c0c73 | 2015-10-30 14:05:23 -0400 | [diff] [blame] | 47 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 48 | switch(renderTargetFormat) |
| 49 | { |
| 50 | case sw::FORMAT_A1R5G5B5: |
| 51 | mRedSize = 5; |
| 52 | mGreenSize = 5; |
| 53 | mBlueSize = 5; |
| 54 | mAlphaSize = 1; |
| 55 | break; |
| 56 | case sw::FORMAT_A2R10G10B10: |
| 57 | mRedSize = 10; |
| 58 | mGreenSize = 10; |
| 59 | mBlueSize = 10; |
| 60 | mAlphaSize = 2; |
| 61 | break; |
| 62 | case sw::FORMAT_A8R8G8B8: |
| 63 | mRedSize = 8; |
| 64 | mGreenSize = 8; |
| 65 | mBlueSize = 8; |
| 66 | mAlphaSize = 8; |
| 67 | mBindToTextureRGBA = EGL_TRUE; |
Stephen White | e6ab01f | 2019-04-04 14:31:25 -0400 | [diff] [blame] | 68 | #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD) |
Nicolas Capens | b3c0c73 | 2015-10-30 14:05:23 -0400 | [diff] [blame] | 69 | mNativeVisualID = HAL_PIXEL_FORMAT_BGRA_8888; |
Nicolas Capens | f59ad06 | 2015-11-13 12:39:21 -0500 | [diff] [blame] | 70 | #else |
| 71 | mNativeVisualID = 2; // Arbitrary; prefer over ABGR |
Nicolas Capens | b3c0c73 | 2015-10-30 14:05:23 -0400 | [diff] [blame] | 72 | #endif |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 73 | break; |
Nicolas Capens | 5716cf0 | 2015-10-30 13:54:24 -0400 | [diff] [blame] | 74 | case sw::FORMAT_A8B8G8R8: |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 75 | mRedSize = 8; |
| 76 | mGreenSize = 8; |
| 77 | mBlueSize = 8; |
| 78 | mAlphaSize = 8; |
| 79 | mBindToTextureRGBA = EGL_TRUE; |
Stephen White | e6ab01f | 2019-04-04 14:31:25 -0400 | [diff] [blame] | 80 | #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD) |
Nicolas Capens | b3c0c73 | 2015-10-30 14:05:23 -0400 | [diff] [blame] | 81 | mNativeVisualID = HAL_PIXEL_FORMAT_RGBA_8888; |
| 82 | #endif |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 83 | break; |
| 84 | case sw::FORMAT_R5G6B5: |
| 85 | mRedSize = 5; |
| 86 | mGreenSize = 6; |
| 87 | mBlueSize = 5; |
| 88 | mAlphaSize = 0; |
Stephen White | e6ab01f | 2019-04-04 14:31:25 -0400 | [diff] [blame] | 89 | #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD) |
Nicolas Capens | b3c0c73 | 2015-10-30 14:05:23 -0400 | [diff] [blame] | 90 | mNativeVisualID = HAL_PIXEL_FORMAT_RGB_565; |
| 91 | #endif |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 92 | break; |
| 93 | case sw::FORMAT_X8R8G8B8: |
| 94 | mRedSize = 8; |
| 95 | mGreenSize = 8; |
| 96 | mBlueSize = 8; |
| 97 | mAlphaSize = 0; |
| 98 | mBindToTextureRGB = EGL_TRUE; |
Stephen White | e6ab01f | 2019-04-04 14:31:25 -0400 | [diff] [blame] | 99 | #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD) |
Nicolas Capens | f59ad06 | 2015-11-13 12:39:21 -0500 | [diff] [blame] | 100 | mNativeVisualID = 0x1FF; // HAL_PIXEL_FORMAT_BGRX_8888 |
| 101 | #else |
| 102 | mNativeVisualID = 1; // Arbitrary; prefer over XBGR |
Nicolas Capens | b3c0c73 | 2015-10-30 14:05:23 -0400 | [diff] [blame] | 103 | #endif |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 104 | break; |
Nicolas Capens | 5716cf0 | 2015-10-30 13:54:24 -0400 | [diff] [blame] | 105 | case sw::FORMAT_X8B8G8R8: |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 106 | mRedSize = 8; |
| 107 | mGreenSize = 8; |
| 108 | mBlueSize = 8; |
| 109 | mAlphaSize = 0; |
| 110 | mBindToTextureRGB = EGL_TRUE; |
Stephen White | e6ab01f | 2019-04-04 14:31:25 -0400 | [diff] [blame] | 111 | #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD) |
Nicolas Capens | b3c0c73 | 2015-10-30 14:05:23 -0400 | [diff] [blame] | 112 | mNativeVisualID = HAL_PIXEL_FORMAT_RGBX_8888; |
| 113 | #endif |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 114 | break; |
| 115 | default: |
| 116 | UNREACHABLE(renderTargetFormat); |
| 117 | } |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 118 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 119 | mLuminanceSize = 0; |
| 120 | mBufferSize = mRedSize + mGreenSize + mBlueSize + mLuminanceSize + mAlphaSize; |
| 121 | mAlphaMaskSize = 0; |
| 122 | mColorBufferType = EGL_RGB_BUFFER; |
Nicolas Capens | c8fcfd8 | 2018-01-11 12:53:57 -0500 | [diff] [blame] | 123 | mConfigCaveat = EGL_NONE; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 124 | mConfigID = 0; |
Nicolas Capens | c8fcfd8 | 2018-01-11 12:53:57 -0500 | [diff] [blame] | 125 | mConformant = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 126 | |
Nicolas Capens | 5716cf0 | 2015-10-30 13:54:24 -0400 | [diff] [blame] | 127 | switch(depthStencilFormat) |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 128 | { |
| 129 | case sw::FORMAT_NULL: |
| 130 | mDepthSize = 0; |
| 131 | mStencilSize = 0; |
| 132 | break; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 133 | // case sw::FORMAT_D16_LOCKABLE: |
| 134 | // mDepthSize = 16; |
| 135 | // mStencilSize = 0; |
| 136 | // break; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 137 | case sw::FORMAT_D32: |
| 138 | mDepthSize = 32; |
| 139 | mStencilSize = 0; |
| 140 | break; |
| 141 | // case sw::FORMAT_D15S1: |
| 142 | // mDepthSize = 15; |
| 143 | // mStencilSize = 1; |
| 144 | // break; |
| 145 | case sw::FORMAT_D24S8: |
| 146 | mDepthSize = 24; |
| 147 | mStencilSize = 8; |
| 148 | break; |
| 149 | case sw::FORMAT_D24X8: |
| 150 | mDepthSize = 24; |
| 151 | mStencilSize = 0; |
| 152 | break; |
| 153 | // case sw::FORMAT_D24X4S4: |
| 154 | // mDepthSize = 24; |
| 155 | // mStencilSize = 4; |
| 156 | // break; |
| 157 | case sw::FORMAT_D16: |
| 158 | mDepthSize = 16; |
| 159 | mStencilSize = 0; |
| 160 | break; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 161 | // case sw::FORMAT_D32F_LOCKABLE: |
| 162 | // mDepthSize = 32; |
| 163 | // mStencilSize = 0; |
| 164 | // break; |
| 165 | // case sw::FORMAT_D24FS8: |
| 166 | // mDepthSize = 24; |
| 167 | // mStencilSize = 8; |
| 168 | // break; |
Nicolas Capens | 101e4f0 | 2015-06-03 14:54:38 -0400 | [diff] [blame] | 169 | default: |
Nicolas Capens | 3713cd4 | 2015-06-22 10:41:54 -0400 | [diff] [blame] | 170 | UNREACHABLE(depthStencilFormat); |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 171 | } |
| 172 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 173 | mLevel = 0; |
| 174 | mMatchNativePixmap = EGL_NONE; |
| 175 | mMaxPBufferWidth = 4096; |
| 176 | mMaxPBufferHeight = 4096; |
| 177 | mMaxPBufferPixels = mMaxPBufferWidth * mMaxPBufferHeight; |
| 178 | mMaxSwapInterval = maxInterval; |
| 179 | mMinSwapInterval = minInterval; |
| 180 | mNativeRenderable = EGL_FALSE; |
| 181 | mNativeVisualType = 0; |
Nicolas Capens | c8fcfd8 | 2018-01-11 12:53:57 -0500 | [diff] [blame] | 182 | mRenderableType = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 183 | mSampleBuffers = (multiSample > 0) ? 1 : 0; |
| 184 | mSamples = multiSample; |
Nicolas Capens | c8eedeb | 2018-04-12 12:50:21 -0400 | [diff] [blame] | 185 | mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT | EGL_MULTISAMPLE_RESOLVE_BOX_BIT; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 186 | mTransparentType = EGL_NONE; |
| 187 | mTransparentRedValue = 0; |
| 188 | mTransparentGreenValue = 0; |
| 189 | mTransparentBlueValue = 0; |
Nicolas Capens | 9a74a0e | 2015-08-12 16:36:52 -0400 | [diff] [blame] | 190 | |
Nicolas Capens | 81c2857 | 2017-03-13 15:08:39 -0400 | [diff] [blame] | 191 | // Although we could support any format as an Android HWComposer compatible config by converting when necessary, |
| 192 | // the intent of EGL_ANDROID_framebuffer_target is to prevent any copies or conversions. |
Nicolas Capens | b77b877 | 2015-10-30 13:50:31 -0400 | [diff] [blame] | 193 | mFramebufferTargetAndroid = (displayFormat == renderTargetFormat) ? EGL_TRUE : EGL_FALSE; |
Nicolas Capens | 81c2857 | 2017-03-13 15:08:39 -0400 | [diff] [blame] | 194 | mRecordableAndroid = EGL_TRUE; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 195 | } |
| 196 | |
| 197 | EGLConfig Config::getHandle() const |
| 198 | { |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 199 | return (EGLConfig)(size_t)mConfigID; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 200 | } |
| 201 | |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 202 | // This ordering determines the config ID |
| 203 | bool CompareConfig::operator()(const Config &x, const Config &y) const |
| 204 | { |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 205 | #define SORT_SMALLER(attribute) \ |
| 206 | if(x.attribute != y.attribute) \ |
| 207 | { \ |
| 208 | return x.attribute < y.attribute; \ |
| 209 | } |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 210 | |
Nicolas Capens | a26bade | 2016-05-27 13:19:49 -0400 | [diff] [blame] | 211 | static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, ""); |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 212 | SORT_SMALLER(mConfigCaveat); |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 213 | |
Nicolas Capens | a26bade | 2016-05-27 13:19:49 -0400 | [diff] [blame] | 214 | static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, ""); |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 215 | SORT_SMALLER(mColorBufferType); |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 216 | |
Nicolas Capens | 101e4f0 | 2015-06-03 14:54:38 -0400 | [diff] [blame] | 217 | SORT_SMALLER(mRedSize); |
| 218 | SORT_SMALLER(mGreenSize); |
| 219 | SORT_SMALLER(mBlueSize); |
| 220 | SORT_SMALLER(mAlphaSize); |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 221 | |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 222 | SORT_SMALLER(mBufferSize); |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 223 | SORT_SMALLER(mSampleBuffers); |
| 224 | SORT_SMALLER(mSamples); |
| 225 | SORT_SMALLER(mDepthSize); |
| 226 | SORT_SMALLER(mStencilSize); |
| 227 | SORT_SMALLER(mAlphaMaskSize); |
| 228 | SORT_SMALLER(mNativeVisualType); |
Nicolas Capens | f59ad06 | 2015-11-13 12:39:21 -0500 | [diff] [blame] | 229 | SORT_SMALLER(mNativeVisualID); |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 230 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 231 | #undef SORT_SMALLER |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 232 | |
| 233 | // Strict ordering requires sorting all non-equal fields above |
| 234 | assert(memcmp(&x, &y, sizeof(Config)) == 0); |
| 235 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 236 | return false; |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 237 | } |
| 238 | |
Nicolas Capens | 101e4f0 | 2015-06-03 14:54:38 -0400 | [diff] [blame] | 239 | // Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24. |
| 240 | class SortConfig |
| 241 | { |
| 242 | public: |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 243 | explicit SortConfig(const EGLint *attribList); |
Nicolas Capens | 101e4f0 | 2015-06-03 14:54:38 -0400 | [diff] [blame] | 244 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 245 | bool operator()(const Config *x, const Config *y) const; |
Nicolas Capens | 101e4f0 | 2015-06-03 14:54:38 -0400 | [diff] [blame] | 246 | |
| 247 | private: |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 248 | EGLint wantedComponentsSize(const Config *config) const; |
Nicolas Capens | 101e4f0 | 2015-06-03 14:54:38 -0400 | [diff] [blame] | 249 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 250 | bool mWantRed; |
| 251 | bool mWantGreen; |
| 252 | bool mWantBlue; |
| 253 | bool mWantAlpha; |
| 254 | bool mWantLuminance; |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 255 | }; |
| 256 | |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 257 | SortConfig::SortConfig(const EGLint *attribList) |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 258 | : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false) |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 259 | { |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 260 | // [EGL] section 3.4.1 page 24 |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 261 | // Sorting rule #3: by larger total number of color bits, |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 262 | // not considering components that are 0 or don't-care. |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 263 | for(const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2) |
| 264 | { |
Chris Forbes | 787e3d5 | 2018-08-31 18:26:20 -0700 | [diff] [blame] | 265 | // When multiple instances of the same attribute are present, last wins. |
| 266 | bool isSpecified = attr[1] && attr[1] != EGL_DONT_CARE; |
| 267 | switch(attr[0]) |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 268 | { |
Chris Forbes | 787e3d5 | 2018-08-31 18:26:20 -0700 | [diff] [blame] | 269 | case EGL_RED_SIZE: mWantRed = isSpecified; break; |
| 270 | case EGL_GREEN_SIZE: mWantGreen = isSpecified; break; |
| 271 | case EGL_BLUE_SIZE: mWantBlue = isSpecified; break; |
| 272 | case EGL_ALPHA_SIZE: mWantAlpha = isSpecified; break; |
| 273 | case EGL_LUMINANCE_SIZE: mWantLuminance = isSpecified; break; |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 274 | } |
| 275 | } |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 276 | } |
| 277 | |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 278 | EGLint SortConfig::wantedComponentsSize(const Config *config) const |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 279 | { |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 280 | EGLint total = 0; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 281 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 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; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 287 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 288 | return total; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 289 | } |
| 290 | |
| 291 | bool SortConfig::operator()(const Config *x, const Config *y) const |
| 292 | { |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 293 | #define SORT_SMALLER(attribute) \ |
| 294 | if(x->attribute != y->attribute) \ |
| 295 | { \ |
| 296 | return x->attribute < y->attribute; \ |
| 297 | } |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 298 | |
Nicolas Capens | a26bade | 2016-05-27 13:19:49 -0400 | [diff] [blame] | 299 | static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, ""); |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 300 | SORT_SMALLER(mConfigCaveat); |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 301 | |
Nicolas Capens | a26bade | 2016-05-27 13:19:49 -0400 | [diff] [blame] | 302 | static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, ""); |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 303 | SORT_SMALLER(mColorBufferType); |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 304 | |
Nicolas Capens | e2b31f2 | 2015-05-31 01:38:47 -0400 | [diff] [blame] | 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) |
| 309 | { |
| 310 | return xComponentsSize > yComponentsSize; |
| 311 | } |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 312 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 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); |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 321 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 322 | #undef SORT_SMALLER |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 323 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 324 | return false; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 325 | } |
| 326 | |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 327 | ConfigSet::ConfigSet() |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 328 | { |
| 329 | } |
| 330 | |
Nicolas Capens | 8b4ea00 | 2015-10-01 01:09:27 -0400 | [diff] [blame] | 331 | void ConfigSet::add(sw::Format displayFormat, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample) |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 332 | { |
Nicolas Capens | c8fcfd8 | 2018-01-11 12:53:57 -0500 | [diff] [blame] | 333 | Config conformantConfig(displayFormat, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample); |
Nicolas Capens | 216980a | 2017-01-02 16:21:39 -0500 | [diff] [blame] | 334 | mSet.insert(conformantConfig); |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 335 | } |
| 336 | |
| 337 | size_t ConfigSet::size() const |
| 338 | { |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 339 | return mSet.size(); |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 340 | } |
| 341 | |
| 342 | bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig) |
| 343 | { |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 344 | vector<const Config*> passed; |
| 345 | passed.reserve(mSet.size()); |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 346 | |
Chris Forbes | 787e3d5 | 2018-08-31 18:26:20 -0700 | [diff] [blame] | 347 | /* Conformance expects for multiple instances of the same attribute that the |
| 348 | * last instance `wins`. Reduce the attribute list first to comply with |
| 349 | * this. |
| 350 | */ |
| 351 | /* TODO: C++11: unordered_map would be fine here */ |
| 352 | map<EGLint, EGLint> attribs; |
| 353 | const EGLint *attribute = attribList; |
| 354 | while (attribute[0] != EGL_NONE) |
| 355 | { |
| 356 | attribs[attribute[0]] = attribute[1]; |
| 357 | attribute += 2; |
| 358 | } |
| 359 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 360 | for(Iterator config = mSet.begin(); config != mSet.end(); config++) |
| 361 | { |
| 362 | bool match = true; |
Nicolas Capens | 216980a | 2017-01-02 16:21:39 -0500 | [diff] [blame] | 363 | bool caveatMatch = (config->mConfigCaveat == EGL_NONE); |
Chris Forbes | 787e3d5 | 2018-08-31 18:26:20 -0700 | [diff] [blame] | 364 | for (map<EGLint, EGLint>::iterator attribIt = attribs.begin(); attribIt != attribs.end(); attribIt++) |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 365 | { |
Chris Forbes | 787e3d5 | 2018-08-31 18:26:20 -0700 | [diff] [blame] | 366 | if(attribIt->second != EGL_DONT_CARE) |
Nicolas Capens | 101e4f0 | 2015-06-03 14:54:38 -0400 | [diff] [blame] | 367 | { |
Chris Forbes | 787e3d5 | 2018-08-31 18:26:20 -0700 | [diff] [blame] | 368 | switch(attribIt->first) |
Nicolas Capens | fc02cfc | 2015-06-04 08:59:09 -0400 | [diff] [blame] | 369 | { |
Chris Forbes | 787e3d5 | 2018-08-31 18:26:20 -0700 | [diff] [blame] | 370 | case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribIt->second; break; |
| 371 | case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribIt->second; break; |
| 372 | case EGL_BLUE_SIZE: match = config->mBlueSize >= attribIt->second; break; |
| 373 | case EGL_GREEN_SIZE: match = config->mGreenSize >= attribIt->second; break; |
| 374 | case EGL_RED_SIZE: match = config->mRedSize >= attribIt->second; break; |
| 375 | case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribIt->second; break; |
| 376 | case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribIt->second; break; |
| 377 | case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum)attribIt->second; break; |
| 378 | case EGL_CONFIG_ID: match = config->mConfigID == attribIt->second; break; |
| 379 | case EGL_LEVEL: match = config->mLevel >= attribIt->second; break; |
| 380 | case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean)attribIt->second; break; |
| 381 | case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribIt->second; break; |
| 382 | case EGL_SAMPLES: match = config->mSamples >= attribIt->second; break; |
| 383 | case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribIt->second; break; |
| 384 | case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribIt->second) == attribIt->second; break; |
| 385 | case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum)attribIt->second; break; |
| 386 | case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribIt->second; break; |
| 387 | case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribIt->second; break; |
| 388 | case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribIt->second; break; |
| 389 | case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean)attribIt->second; break; |
| 390 | case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean)attribIt->second; break; |
| 391 | case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribIt->second; break; |
| 392 | case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribIt->second; break; |
| 393 | case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribIt->second; break; |
| 394 | case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribIt->second; break; |
| 395 | case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum)attribIt->second; break; |
| 396 | case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribIt->second) == attribIt->second; break; |
| 397 | case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break; |
| 398 | case EGL_CONFORMANT: match = (config->mConformant & attribIt->second) == attribIt->second; break; |
| 399 | case EGL_RECORDABLE_ANDROID: match = config->mRecordableAndroid == (EGLBoolean)attribIt->second; break; |
| 400 | case EGL_FRAMEBUFFER_TARGET_ANDROID: match = config->mFramebufferTargetAndroid == (EGLBoolean)attribIt->second; break; |
Nicolas Capens | e76163e | 2018-04-18 14:46:17 -0400 | [diff] [blame] | 401 | |
| 402 | // Ignored attributes |
| 403 | case EGL_MAX_PBUFFER_WIDTH: |
| 404 | case EGL_MAX_PBUFFER_HEIGHT: |
| 405 | case EGL_MAX_PBUFFER_PIXELS: |
| 406 | case EGL_NATIVE_VISUAL_ID: |
| 407 | break; |
| 408 | |
Nicolas Capens | fc02cfc | 2015-06-04 08:59:09 -0400 | [diff] [blame] | 409 | default: |
Nicolas Capens | 0c19ed8 | 2015-08-12 17:21:06 -0400 | [diff] [blame] | 410 | *numConfig = 0; |
| 411 | return false; |
Nicolas Capens | fc02cfc | 2015-06-04 08:59:09 -0400 | [diff] [blame] | 412 | } |
| 413 | |
| 414 | if(!match) |
| 415 | { |
| 416 | break; |
| 417 | } |
Nicolas Capens | 101e4f0 | 2015-06-03 14:54:38 -0400 | [diff] [blame] | 418 | } |
| 419 | |
Chris Forbes | 787e3d5 | 2018-08-31 18:26:20 -0700 | [diff] [blame] | 420 | if(attribIt->first == EGL_CONFIG_CAVEAT) |
Nicolas Capens | 216980a | 2017-01-02 16:21:39 -0500 | [diff] [blame] | 421 | { |
| 422 | caveatMatch = match; |
| 423 | } |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 424 | } |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 425 | |
Nicolas Capens | 216980a | 2017-01-02 16:21:39 -0500 | [diff] [blame] | 426 | if(match && caveatMatch) // We require the caveats to be NONE or the requested flags |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 427 | { |
| 428 | passed.push_back(&*config); |
| 429 | } |
| 430 | } |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 431 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 432 | if(configs) |
| 433 | { |
| 434 | sort(passed.begin(), passed.end(), SortConfig(attribList)); |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 435 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 436 | EGLint index; |
| 437 | for(index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++) |
| 438 | { |
| 439 | configs[index] = passed[index]->getHandle(); |
| 440 | } |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 441 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 442 | *numConfig = index; |
| 443 | } |
| 444 | else |
| 445 | { |
| 446 | *numConfig = static_cast<EGLint>(passed.size()); |
| 447 | } |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 448 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 449 | return true; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 450 | } |
| 451 | |
| 452 | const egl::Config *ConfigSet::get(EGLConfig configHandle) |
| 453 | { |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 454 | for(Iterator config = mSet.begin(); config != mSet.end(); config++) |
| 455 | { |
| 456 | if(config->getHandle() == configHandle) |
| 457 | { |
| 458 | return &(*config); |
| 459 | } |
| 460 | } |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 461 | |
Nicolas Capens | 0bac285 | 2016-05-07 06:09:58 -0400 | [diff] [blame] | 462 | return nullptr; |
John Bauman | 66b8ab2 | 2014-05-06 15:57:45 -0400 | [diff] [blame] | 463 | } |
| 464 | } |