OSDN Git Service

43ca44d125d2daff183f48e6955dbc76a905faf8
[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 // 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;
42 #else
43 const bool strictConformance = false;
44 #endif
45
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)
48 {
49         mBindToTextureRGB = EGL_FALSE;
50         mBindToTextureRGBA = EGL_FALSE;
51
52         // Initialize to a high value to lower the preference of formats for which there's no native support
53         mNativeVisualID = 0x7FFFFFFF;
54
55         switch(renderTargetFormat)
56         {
57         case sw::FORMAT_A1R5G5B5:
58                 mRedSize = 5;
59                 mGreenSize = 5;
60                 mBlueSize = 5;
61                 mAlphaSize = 1;
62                 break;
63         case sw::FORMAT_A2R10G10B10:
64                 mRedSize = 10;
65                 mGreenSize = 10;
66                 mBlueSize = 10;
67                 mAlphaSize = 2;
68                 break;
69         case sw::FORMAT_A8R8G8B8:
70                 mRedSize = 8;
71                 mGreenSize = 8;
72                 mBlueSize = 8;
73                 mAlphaSize = 8;
74                 mBindToTextureRGBA = EGL_TRUE;
75                 #ifdef __ANDROID__
76                         mNativeVisualID = HAL_PIXEL_FORMAT_BGRA_8888;
77                 #else
78                         mNativeVisualID = 2;   // Arbitrary; prefer over ABGR
79                 #endif
80                 break;
81         case sw::FORMAT_A8B8G8R8:
82                 mRedSize = 8;
83                 mGreenSize = 8;
84                 mBlueSize = 8;
85                 mAlphaSize = 8;
86                 mBindToTextureRGBA = EGL_TRUE;
87                 #ifdef __ANDROID__
88                         mNativeVisualID = HAL_PIXEL_FORMAT_RGBA_8888;
89                 #endif
90                 break;
91         case sw::FORMAT_R5G6B5:
92                 mRedSize = 5;
93                 mGreenSize = 6;
94                 mBlueSize = 5;
95                 mAlphaSize = 0;
96                 #ifdef __ANDROID__
97                         mNativeVisualID = HAL_PIXEL_FORMAT_RGB_565;
98                 #endif
99                 break;
100         case sw::FORMAT_X8R8G8B8:
101                 mRedSize = 8;
102                 mGreenSize = 8;
103                 mBlueSize = 8;
104                 mAlphaSize = 0;
105                 mBindToTextureRGB = EGL_TRUE;
106                 #ifdef __ANDROID__
107                         mNativeVisualID = 0x1FF;   // HAL_PIXEL_FORMAT_BGRX_8888
108                 #else
109                         mNativeVisualID = 1;   // Arbitrary; prefer over XBGR
110                 #endif
111                 break;
112         case sw::FORMAT_X8B8G8R8:
113                 mRedSize = 8;
114                 mGreenSize = 8;
115                 mBlueSize = 8;
116                 mAlphaSize = 0;
117                 mBindToTextureRGB = EGL_TRUE;
118                 #ifdef __ANDROID__
119                         mNativeVisualID = HAL_PIXEL_FORMAT_RGBX_8888;
120                 #endif
121                 break;
122         default:
123                 UNREACHABLE(renderTargetFormat);
124         }
125
126         mLuminanceSize = 0;
127         mBufferSize = mRedSize + mGreenSize + mBlueSize + mLuminanceSize + mAlphaSize;
128         mAlphaMaskSize = 0;
129         mColorBufferType = EGL_RGB_BUFFER;
130         mConfigCaveat = (conformant || !strictConformance) ? EGL_NONE : EGL_NON_CONFORMANT_CONFIG;
131         mConfigID = 0;
132         mConformant = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | (strictConformance ? 0 : EGL_OPENGL_ES3_BIT);
133
134         switch(depthStencilFormat)
135         {
136         case sw::FORMAT_NULL:
137                 mDepthSize = 0;
138                 mStencilSize = 0;
139                 break;
140 //      case sw::FORMAT_D16_LOCKABLE:
141 //              mDepthSize = 16;
142 //              mStencilSize = 0;
143 //              break;
144         case sw::FORMAT_D32:
145                 mDepthSize = 32;
146                 mStencilSize = 0;
147                 break;
148 //      case sw::FORMAT_D15S1:
149 //              mDepthSize = 15;
150 //              mStencilSize = 1;
151 //              break;
152         case sw::FORMAT_D24S8:
153                 mDepthSize = 24;
154                 mStencilSize = 8;
155                 break;
156         case sw::FORMAT_D24X8:
157                 mDepthSize = 24;
158                 mStencilSize = 0;
159                 break;
160 //      case sw::FORMAT_D24X4S4:
161 //              mDepthSize = 24;
162 //              mStencilSize = 4;
163 //              break;
164         case sw::FORMAT_D16:
165                 mDepthSize = 16;
166                 mStencilSize = 0;
167                 break;
168 //      case sw::FORMAT_D32F_LOCKABLE:
169 //              mDepthSize = 32;
170 //              mStencilSize = 0;
171 //              break;
172 //      case sw::FORMAT_D24FS8:
173 //              mDepthSize = 24;
174 //              mStencilSize = 8;
175 //              break;
176         default:
177                 UNREACHABLE(depthStencilFormat);
178         }
179
180         mLevel = 0;
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;
197
198         mRecordableAndroid = EGL_TRUE;
199         mFramebufferTargetAndroid = (displayFormat == renderTargetFormat) ? EGL_TRUE : EGL_FALSE;
200 }
201
202 EGLConfig Config::getHandle() const
203 {
204         return (EGLConfig)(size_t)mConfigID;
205 }
206
207 // This ordering determines the config ID
208 bool CompareConfig::operator()(const Config &x, const Config &y) const
209 {
210         #define SORT_SMALLER(attribute)                \
211                 if(x.attribute != y.attribute)             \
212                 {                                          \
213                         return x.attribute < y.attribute;      \
214                 }
215
216         static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
217         SORT_SMALLER(mConfigCaveat);
218
219         static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
220         SORT_SMALLER(mColorBufferType);
221
222         SORT_SMALLER(mRedSize);
223         SORT_SMALLER(mGreenSize);
224         SORT_SMALLER(mBlueSize);
225         SORT_SMALLER(mAlphaSize);
226
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);
235
236         #undef SORT_SMALLER
237
238         // Strict ordering requires sorting all non-equal fields above
239         assert(memcmp(&x, &y, sizeof(Config)) == 0);
240
241         return false;
242 }
243
244 // Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24.
245 class SortConfig
246 {
247 public:
248         explicit SortConfig(const EGLint *attribList);
249
250         bool operator()(const Config *x, const Config *y) const;
251
252 private:
253         EGLint wantedComponentsSize(const Config *config) const;
254
255         bool mWantRed;
256         bool mWantGreen;
257         bool mWantBlue;
258         bool mWantAlpha;
259         bool mWantLuminance;
260 };
261
262 SortConfig::SortConfig(const EGLint *attribList)
263         : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
264 {
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)
269         {
270                 if(attr[1] != 0 && attr[1] != EGL_DONT_CARE)
271                 {
272                         switch(attr[0])
273                         {
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;
279                         }
280                 }
281         }
282 }
283
284 EGLint SortConfig::wantedComponentsSize(const Config *config) const
285 {
286         EGLint total = 0;
287
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;
293
294         return total;
295 }
296
297 bool SortConfig::operator()(const Config *x, const Config *y) const
298 {
299         #define SORT_SMALLER(attribute)                \
300                 if(x->attribute != y->attribute)           \
301                 {                                          \
302                         return x->attribute < y->attribute;    \
303                 }
304
305         static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
306         SORT_SMALLER(mConfigCaveat);
307
308         static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
309         SORT_SMALLER(mColorBufferType);
310
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)
315         {
316                 return xComponentsSize > yComponentsSize;
317         }
318
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);
327
328         #undef SORT_SMALLER
329
330         return false;
331 }
332
333 ConfigSet::ConfigSet()
334 {
335 }
336
337 void ConfigSet::add(sw::Format displayFormat, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
338 {
339         Config conformantConfig(displayFormat, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, true);
340         mSet.insert(conformantConfig);
341
342         if(strictConformance)   // When strict conformance is required, add non-conformant configs explicitly as such.
343         {
344                 Config nonConformantConfig(displayFormat, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, false);
345                 mSet.insert(nonConformantConfig);
346         }
347 }
348
349 size_t ConfigSet::size() const
350 {
351         return mSet.size();
352 }
353
354 bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
355 {
356         vector<const Config*> passed;
357         passed.reserve(mSet.size());
358
359         for(Iterator config = mSet.begin(); config != mSet.end(); config++)
360         {
361                 bool match = true;
362                 bool caveatMatch = (config->mConfigCaveat == EGL_NONE);
363                 const EGLint *attribute = attribList;
364
365                 while(attribute[0] != EGL_NONE)
366                 {
367                         if(attribute[1] != EGL_DONT_CARE)
368                         {
369                                 switch(attribute[0])
370                                 {
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;
406                                 default:
407                                         *numConfig = 0;
408                                         return false;
409                                 }
410
411                                 if(!match)
412                                 {
413                                         break;
414                                 }
415                         }
416
417                         if(attribute[0] == EGL_CONFIG_CAVEAT)
418                         {
419                                 caveatMatch = match;
420                         }
421
422                         attribute += 2;
423                 }
424
425                 if(match && caveatMatch)   // We require the caveats to be NONE or the requested flags
426                 {
427                         passed.push_back(&*config);
428                 }
429         }
430
431         if(configs)
432         {
433                 sort(passed.begin(), passed.end(), SortConfig(attribList));
434
435                 EGLint index;
436                 for(index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
437                 {
438                         configs[index] = passed[index]->getHandle();
439                 }
440
441                 *numConfig = index;
442         }
443         else
444         {
445                 *numConfig = static_cast<EGLint>(passed.size());
446         }
447
448         return true;
449 }
450
451 const egl::Config *ConfigSet::get(EGLConfig configHandle)
452 {
453         for(Iterator config = mSet.begin(); config != mSet.end(); config++)
454         {
455                 if(config->getHandle() == configHandle)
456                 {
457                         return &(*config);
458                 }
459         }
460
461         return nullptr;
462 }
463 }