OSDN Git Service

Skip ignored EGL config attributes.
[android-x86/external-swiftshader.git] / src / OpenGL / libEGL / Config.cpp
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
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
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
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.
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"
22
23 #include <EGL/eglext.h>
24 #ifdef __ANDROID__
25 #include <system/graphics.h>
26 #endif
27
28 #include <string.h>
29 #include <algorithm>
30 #include <cstring>
31 #include <vector>
32
33 using namespace std;
34
35 namespace egl
36 {
37
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)
40 {
41         mBindToTextureRGB = EGL_FALSE;
42         mBindToTextureRGBA = EGL_FALSE;
43
44         // Initialize to a high value to lower the preference of formats for which there's no native support
45         mNativeVisualID = 0x7FFFFFFF;
46
47         switch(renderTargetFormat)
48         {
49         case sw::FORMAT_A1R5G5B5:
50                 mRedSize = 5;
51                 mGreenSize = 5;
52                 mBlueSize = 5;
53                 mAlphaSize = 1;
54                 break;
55         case sw::FORMAT_A2R10G10B10:
56                 mRedSize = 10;
57                 mGreenSize = 10;
58                 mBlueSize = 10;
59                 mAlphaSize = 2;
60                 break;
61         case sw::FORMAT_A8R8G8B8:
62                 mRedSize = 8;
63                 mGreenSize = 8;
64                 mBlueSize = 8;
65                 mAlphaSize = 8;
66                 mBindToTextureRGBA = EGL_TRUE;
67                 #ifdef __ANDROID__
68                         mNativeVisualID = HAL_PIXEL_FORMAT_BGRA_8888;
69                 #else
70                         mNativeVisualID = 2;   // Arbitrary; prefer over ABGR
71                 #endif
72                 break;
73         case sw::FORMAT_A8B8G8R8:
74                 mRedSize = 8;
75                 mGreenSize = 8;
76                 mBlueSize = 8;
77                 mAlphaSize = 8;
78                 mBindToTextureRGBA = EGL_TRUE;
79                 #ifdef __ANDROID__
80                         mNativeVisualID = HAL_PIXEL_FORMAT_RGBA_8888;
81                 #endif
82                 break;
83         case sw::FORMAT_R5G6B5:
84                 mRedSize = 5;
85                 mGreenSize = 6;
86                 mBlueSize = 5;
87                 mAlphaSize = 0;
88                 #ifdef __ANDROID__
89                         mNativeVisualID = HAL_PIXEL_FORMAT_RGB_565;
90                 #endif
91                 break;
92         case sw::FORMAT_X8R8G8B8:
93                 mRedSize = 8;
94                 mGreenSize = 8;
95                 mBlueSize = 8;
96                 mAlphaSize = 0;
97                 mBindToTextureRGB = EGL_TRUE;
98                 #ifdef __ANDROID__
99                         mNativeVisualID = 0x1FF;   // HAL_PIXEL_FORMAT_BGRX_8888
100                 #else
101                         mNativeVisualID = 1;   // Arbitrary; prefer over XBGR
102                 #endif
103                 break;
104         case sw::FORMAT_X8B8G8R8:
105                 mRedSize = 8;
106                 mGreenSize = 8;
107                 mBlueSize = 8;
108                 mAlphaSize = 0;
109                 mBindToTextureRGB = EGL_TRUE;
110                 #ifdef __ANDROID__
111                         mNativeVisualID = HAL_PIXEL_FORMAT_RGBX_8888;
112                 #endif
113                 break;
114         default:
115                 UNREACHABLE(renderTargetFormat);
116         }
117
118         mLuminanceSize = 0;
119         mBufferSize = mRedSize + mGreenSize + mBlueSize + mLuminanceSize + mAlphaSize;
120         mAlphaMaskSize = 0;
121         mColorBufferType = EGL_RGB_BUFFER;
122         mConfigCaveat = EGL_NONE;
123         mConfigID = 0;
124         mConformant = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
125
126         switch(depthStencilFormat)
127         {
128         case sw::FORMAT_NULL:
129                 mDepthSize = 0;
130                 mStencilSize = 0;
131                 break;
132 //      case sw::FORMAT_D16_LOCKABLE:
133 //              mDepthSize = 16;
134 //              mStencilSize = 0;
135 //              break;
136         case sw::FORMAT_D32:
137                 mDepthSize = 32;
138                 mStencilSize = 0;
139                 break;
140 //      case sw::FORMAT_D15S1:
141 //              mDepthSize = 15;
142 //              mStencilSize = 1;
143 //              break;
144         case sw::FORMAT_D24S8:
145                 mDepthSize = 24;
146                 mStencilSize = 8;
147                 break;
148         case sw::FORMAT_D24X8:
149                 mDepthSize = 24;
150                 mStencilSize = 0;
151                 break;
152 //      case sw::FORMAT_D24X4S4:
153 //              mDepthSize = 24;
154 //              mStencilSize = 4;
155 //              break;
156         case sw::FORMAT_D16:
157                 mDepthSize = 16;
158                 mStencilSize = 0;
159                 break;
160 //      case sw::FORMAT_D32F_LOCKABLE:
161 //              mDepthSize = 32;
162 //              mStencilSize = 0;
163 //              break;
164 //      case sw::FORMAT_D24FS8:
165 //              mDepthSize = 24;
166 //              mStencilSize = 8;
167 //              break;
168         default:
169                 UNREACHABLE(depthStencilFormat);
170         }
171
172         mLevel = 0;
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;
189
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;
194 }
195
196 EGLConfig Config::getHandle() const
197 {
198         return (EGLConfig)(size_t)mConfigID;
199 }
200
201 // This ordering determines the config ID
202 bool CompareConfig::operator()(const Config &x, const Config &y) const
203 {
204         #define SORT_SMALLER(attribute)                \
205                 if(x.attribute != y.attribute)             \
206                 {                                          \
207                         return x.attribute < y.attribute;      \
208                 }
209
210         static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
211         SORT_SMALLER(mConfigCaveat);
212
213         static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
214         SORT_SMALLER(mColorBufferType);
215
216         SORT_SMALLER(mRedSize);
217         SORT_SMALLER(mGreenSize);
218         SORT_SMALLER(mBlueSize);
219         SORT_SMALLER(mAlphaSize);
220
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);
229
230         #undef SORT_SMALLER
231
232         // Strict ordering requires sorting all non-equal fields above
233         assert(memcmp(&x, &y, sizeof(Config)) == 0);
234
235         return false;
236 }
237
238 // Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24.
239 class SortConfig
240 {
241 public:
242         explicit SortConfig(const EGLint *attribList);
243
244         bool operator()(const Config *x, const Config *y) const;
245
246 private:
247         EGLint wantedComponentsSize(const Config *config) const;
248
249         bool mWantRed;
250         bool mWantGreen;
251         bool mWantBlue;
252         bool mWantAlpha;
253         bool mWantLuminance;
254 };
255
256 SortConfig::SortConfig(const EGLint *attribList)
257         : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
258 {
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)
263         {
264                 if(attr[1] != 0 && attr[1] != EGL_DONT_CARE)
265                 {
266                         switch(attr[0])
267                         {
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;
273                         }
274                 }
275         }
276 }
277
278 EGLint SortConfig::wantedComponentsSize(const Config *config) const
279 {
280         EGLint total = 0;
281
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;
287
288         return total;
289 }
290
291 bool SortConfig::operator()(const Config *x, const Config *y) const
292 {
293         #define SORT_SMALLER(attribute)                \
294                 if(x->attribute != y->attribute)           \
295                 {                                          \
296                         return x->attribute < y->attribute;    \
297                 }
298
299         static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
300         SORT_SMALLER(mConfigCaveat);
301
302         static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
303         SORT_SMALLER(mColorBufferType);
304
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         }
312
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);
321
322         #undef SORT_SMALLER
323
324         return false;
325 }
326
327 ConfigSet::ConfigSet()
328 {
329 }
330
331 void ConfigSet::add(sw::Format displayFormat, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
332 {
333         Config conformantConfig(displayFormat, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample);
334         mSet.insert(conformantConfig);
335 }
336
337 size_t ConfigSet::size() const
338 {
339         return mSet.size();
340 }
341
342 bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
343 {
344         vector<const Config*> passed;
345         passed.reserve(mSet.size());
346
347         for(Iterator config = mSet.begin(); config != mSet.end(); config++)
348         {
349                 bool match = true;
350                 bool caveatMatch = (config->mConfigCaveat == EGL_NONE);
351                 const EGLint *attribute = attribList;
352
353                 while(attribute[0] != EGL_NONE)
354                 {
355                         if(attribute[1] != EGL_DONT_CARE)
356                         {
357                                 switch(attribute[0])
358                                 {
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;
390
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:
396                                         break;
397
398                                 default:
399                                         *numConfig = 0;
400                                         return false;
401                                 }
402
403                                 if(!match)
404                                 {
405                                         break;
406                                 }
407                         }
408
409                         if(attribute[0] == EGL_CONFIG_CAVEAT)
410                         {
411                                 caveatMatch = match;
412                         }
413
414                         attribute += 2;
415                 }
416
417                 if(match && caveatMatch)   // We require the caveats to be NONE or the requested flags
418                 {
419                         passed.push_back(&*config);
420                 }
421         }
422
423         if(configs)
424         {
425                 sort(passed.begin(), passed.end(), SortConfig(attribList));
426
427                 EGLint index;
428                 for(index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
429                 {
430                         configs[index] = passed[index]->getHandle();
431                 }
432
433                 *numConfig = index;
434         }
435         else
436         {
437                 *numConfig = static_cast<EGLint>(passed.size());
438         }
439
440         return true;
441 }
442
443 const egl::Config *ConfigSet::get(EGLConfig configHandle)
444 {
445         for(Iterator config = mSet.begin(); config != mSet.end(); config++)
446         {
447                 if(config->getHandle() == configHandle)
448                 {
449                         return &(*config);
450                 }
451         }
452
453         return nullptr;
454 }
455 }