OSDN Git Service

Implement an Android NDK build of SwiftShader using the CMake files.
[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 #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
25 #include <system/graphics.h>
26 #endif
27
28 #include <string.h>
29 #include <algorithm>
30 #include <cstring>
31 #include <vector>
32 #include <map>
33
34 using namespace std;
35
36 namespace egl
37 {
38
39 Config::Config(sw::Format displayFormat, EGLint minInterval, EGLint maxInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
40         : mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
41 {
42         mBindToTextureRGB = EGL_FALSE;
43         mBindToTextureRGBA = EGL_FALSE;
44
45         // Initialize to a high value to lower the preference of formats for which there's no native support
46         mNativeVisualID = 0x7FFFFFFF;
47
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;
68                 #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
69                         mNativeVisualID = HAL_PIXEL_FORMAT_BGRA_8888;
70                 #else
71                         mNativeVisualID = 2;   // Arbitrary; prefer over ABGR
72                 #endif
73                 break;
74         case sw::FORMAT_A8B8G8R8:
75                 mRedSize = 8;
76                 mGreenSize = 8;
77                 mBlueSize = 8;
78                 mAlphaSize = 8;
79                 mBindToTextureRGBA = EGL_TRUE;
80                 #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
81                         mNativeVisualID = HAL_PIXEL_FORMAT_RGBA_8888;
82                 #endif
83                 break;
84         case sw::FORMAT_R5G6B5:
85                 mRedSize = 5;
86                 mGreenSize = 6;
87                 mBlueSize = 5;
88                 mAlphaSize = 0;
89                 #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
90                         mNativeVisualID = HAL_PIXEL_FORMAT_RGB_565;
91                 #endif
92                 break;
93         case sw::FORMAT_X8R8G8B8:
94                 mRedSize = 8;
95                 mGreenSize = 8;
96                 mBlueSize = 8;
97                 mAlphaSize = 0;
98                 mBindToTextureRGB = EGL_TRUE;
99                 #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
100                         mNativeVisualID = 0x1FF;   // HAL_PIXEL_FORMAT_BGRX_8888
101                 #else
102                         mNativeVisualID = 1;   // Arbitrary; prefer over XBGR
103                 #endif
104                 break;
105         case sw::FORMAT_X8B8G8R8:
106                 mRedSize = 8;
107                 mGreenSize = 8;
108                 mBlueSize = 8;
109                 mAlphaSize = 0;
110                 mBindToTextureRGB = EGL_TRUE;
111                 #if defined(__ANDROID__) && !defined(ANDROID_NDK_BUILD)
112                         mNativeVisualID = HAL_PIXEL_FORMAT_RGBX_8888;
113                 #endif
114                 break;
115         default:
116                 UNREACHABLE(renderTargetFormat);
117         }
118
119         mLuminanceSize = 0;
120         mBufferSize = mRedSize + mGreenSize + mBlueSize + mLuminanceSize + mAlphaSize;
121         mAlphaMaskSize = 0;
122         mColorBufferType = EGL_RGB_BUFFER;
123         mConfigCaveat = EGL_NONE;
124         mConfigID = 0;
125         mConformant = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
126
127         switch(depthStencilFormat)
128         {
129         case sw::FORMAT_NULL:
130                 mDepthSize = 0;
131                 mStencilSize = 0;
132                 break;
133 //      case sw::FORMAT_D16_LOCKABLE:
134 //              mDepthSize = 16;
135 //              mStencilSize = 0;
136 //              break;
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;
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;
169         default:
170                 UNREACHABLE(depthStencilFormat);
171         }
172
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;
182         mRenderableType = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT;
183         mSampleBuffers = (multiSample > 0) ? 1 : 0;
184         mSamples = multiSample;
185         mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT | EGL_MULTISAMPLE_RESOLVE_BOX_BIT;
186         mTransparentType = EGL_NONE;
187         mTransparentRedValue = 0;
188         mTransparentGreenValue = 0;
189         mTransparentBlueValue = 0;
190
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.
193         mFramebufferTargetAndroid = (displayFormat == renderTargetFormat) ? EGL_TRUE : EGL_FALSE;
194         mRecordableAndroid = EGL_TRUE;
195 }
196
197 EGLConfig Config::getHandle() const
198 {
199         return (EGLConfig)(size_t)mConfigID;
200 }
201
202 // This ordering determines the config ID
203 bool CompareConfig::operator()(const Config &x, const Config &y) const
204 {
205         #define SORT_SMALLER(attribute)                \
206                 if(x.attribute != y.attribute)             \
207                 {                                          \
208                         return x.attribute < y.attribute;      \
209                 }
210
211         static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
212         SORT_SMALLER(mConfigCaveat);
213
214         static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
215         SORT_SMALLER(mColorBufferType);
216
217         SORT_SMALLER(mRedSize);
218         SORT_SMALLER(mGreenSize);
219         SORT_SMALLER(mBlueSize);
220         SORT_SMALLER(mAlphaSize);
221
222         SORT_SMALLER(mBufferSize);
223         SORT_SMALLER(mSampleBuffers);
224         SORT_SMALLER(mSamples);
225         SORT_SMALLER(mDepthSize);
226         SORT_SMALLER(mStencilSize);
227         SORT_SMALLER(mAlphaMaskSize);
228         SORT_SMALLER(mNativeVisualType);
229         SORT_SMALLER(mNativeVisualID);
230
231         #undef SORT_SMALLER
232
233         // Strict ordering requires sorting all non-equal fields above
234         assert(memcmp(&x, &y, sizeof(Config)) == 0);
235
236         return false;
237 }
238
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:
243         explicit SortConfig(const EGLint *attribList);
244
245         bool operator()(const Config *x, const Config *y) const;
246
247 private:
248         EGLint wantedComponentsSize(const Config *config) const;
249
250         bool mWantRed;
251         bool mWantGreen;
252         bool mWantBlue;
253         bool mWantAlpha;
254         bool mWantLuminance;
255 };
256
257 SortConfig::SortConfig(const EGLint *attribList)
258         : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
259 {
260         // [EGL] section 3.4.1 page 24
261         // Sorting rule #3: by larger total number of color bits,
262         // not considering components that are 0 or don't-care.
263         for(const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
264         {
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])
268                 {
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;
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         /* 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
360         for(Iterator config = mSet.begin(); config != mSet.end(); config++)
361         {
362                 bool match = true;
363                 bool caveatMatch = (config->mConfigCaveat == EGL_NONE);
364                 for (map<EGLint, EGLint>::iterator attribIt = attribs.begin(); attribIt != attribs.end(); attribIt++)
365                 {
366                         if(attribIt->second != EGL_DONT_CARE)
367                         {
368                                 switch(attribIt->first)
369                                 {
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;
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
409                                 default:
410                                         *numConfig = 0;
411                                         return false;
412                                 }
413
414                                 if(!match)
415                                 {
416                                         break;
417                                 }
418                         }
419
420                         if(attribIt->first == EGL_CONFIG_CAVEAT)
421                         {
422                                 caveatMatch = match;
423                         }
424                 }
425
426                 if(match && caveatMatch)   // We require the caveats to be NONE or the requested flags
427                 {
428                         passed.push_back(&*config);
429                 }
430         }
431
432         if(configs)
433         {
434                 sort(passed.begin(), passed.end(), SortConfig(attribList));
435
436                 EGLint index;
437                 for(index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
438                 {
439                         configs[index] = passed[index]->getHandle();
440                 }
441
442                 *numConfig = index;
443         }
444         else
445         {
446                 *numConfig = static_cast<EGLint>(passed.size());
447         }
448
449         return true;
450 }
451
452 const egl::Config *ConfigSet::get(EGLConfig configHandle)
453 {
454         for(Iterator config = mSet.begin(); config != mSet.end(); config++)
455         {
456                 if(config->getHandle() == configHandle)
457                 {
458                         return &(*config);
459                 }
460         }
461
462         return nullptr;
463 }
464 }