OSDN Git Service

Fix strict ordering of EGL configs.
[android-x86/external-swiftshader.git] / src / OpenGL / libEGL / Config.cpp
1 // SwiftShader Software Renderer
2 //
3 // Copyright(c) 2005-2013 TransGaming Inc.
4 //
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,
6 // transcribed, stored in a retrieval system, translated into any human or computer
7 // language by any means, or disclosed to third parties without the explicit written
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9 // or implied, including but not limited to any patent rights, are granted to you.
10 //
11
12 // Config.cpp: Implements the egl::Config class, describing the format, type
13 // and size for an egl::Surface. Implements EGLConfig and related functionality.
14 // [EGL 1.4] section 3.4 page 15.
15
16 #include "Config.h"
17
18 #include "common/debug.h"
19
20 #include <EGL/eglext.h>
21 #ifdef __ANDROID__
22 #include <system/graphics.h>
23 #endif
24
25 #include <string.h>
26 #include <algorithm>
27 #include <vector>
28
29 using namespace std;
30
31 namespace egl
32 {
33 Config::Config(sw::Format displayFormat, EGLint minInterval, EGLint maxInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
34     : mDisplayFormat(displayFormat), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
35 {
36     mBindToTextureRGB = EGL_FALSE;
37     mBindToTextureRGBA = EGL_FALSE;
38
39         // Initialize to a high value to lower the preference of formats for which there's no native support
40     mNativeVisualID = 0x7FFFFFFF;
41
42     switch(renderTargetFormat)
43     {
44     case sw::FORMAT_A1R5G5B5:
45         mRedSize = 5;
46         mGreenSize = 5;
47         mBlueSize = 5;
48         mAlphaSize = 1;
49         break;
50     case sw::FORMAT_A2R10G10B10:
51         mRedSize = 10;
52         mGreenSize = 10;
53         mBlueSize = 10;
54         mAlphaSize = 2;
55         break;
56     case sw::FORMAT_A8R8G8B8:
57         mRedSize = 8;
58         mGreenSize = 8;
59         mBlueSize = 8;
60         mAlphaSize = 8;
61         mBindToTextureRGBA = EGL_TRUE;
62         #ifdef __ANDROID__
63                         mNativeVisualID = HAL_PIXEL_FORMAT_BGRA_8888;
64                 #else
65                         mNativeVisualID = 2;   // Arbitrary; prefer over ABGR
66                 #endif
67         break;
68         case sw::FORMAT_A8B8G8R8:
69         mRedSize = 8;
70         mGreenSize = 8;
71         mBlueSize = 8;
72         mAlphaSize = 8;
73         mBindToTextureRGBA = EGL_TRUE;
74                 #ifdef __ANDROID__
75                         mNativeVisualID = HAL_PIXEL_FORMAT_RGBA_8888;
76                 #endif
77         break;
78     case sw::FORMAT_R5G6B5:
79         mRedSize = 5;
80         mGreenSize = 6;
81         mBlueSize = 5;
82         mAlphaSize = 0;
83         #ifdef __ANDROID__
84                         mNativeVisualID = HAL_PIXEL_FORMAT_RGB_565;
85                 #endif
86         break;
87     case sw::FORMAT_X8R8G8B8:
88         mRedSize = 8;
89         mGreenSize = 8;
90         mBlueSize = 8;
91         mAlphaSize = 0;
92         mBindToTextureRGB = EGL_TRUE;
93                 #ifdef __ANDROID__
94                         mNativeVisualID = 0x1FF;   // HAL_PIXEL_FORMAT_BGRX_8888
95                 #else
96                         mNativeVisualID = 1;   // Arbitrary; prefer over XBGR
97                 #endif
98         break;
99         case sw::FORMAT_X8B8G8R8:
100         mRedSize = 8;
101         mGreenSize = 8;
102         mBlueSize = 8;
103         mAlphaSize = 0;
104         mBindToTextureRGBA = EGL_TRUE;
105                 #ifdef __ANDROID__
106                         mNativeVisualID = HAL_PIXEL_FORMAT_RGBX_8888;
107                 #endif
108         break;
109     default:
110         UNREACHABLE(renderTargetFormat);
111     }
112
113     mLuminanceSize = 0;
114     mBufferSize = mRedSize + mGreenSize + mBlueSize + mLuminanceSize + mAlphaSize;
115     mAlphaMaskSize = 0;
116     mColorBufferType = EGL_RGB_BUFFER;
117     mConfigCaveat = EGL_NONE;
118     mConfigID = 0;
119     mConformant = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT
120 #ifndef __ANDROID__ // Do not allow GLES 3.0 on Android
121         | EGL_OPENGL_ES3_BIT
122 #endif
123         ;
124
125         switch(depthStencilFormat)
126         {
127         case sw::FORMAT_NULL:
128                 mDepthSize = 0;
129                 mStencilSize = 0;
130                 break;
131 //  case sw::FORMAT_D16_LOCKABLE:
132 //      mDepthSize = 16;
133 //      mStencilSize = 0;
134 //      break;
135         case sw::FORMAT_D32:
136                 mDepthSize = 32;
137                 mStencilSize = 0;
138                 break;
139 //      case sw::FORMAT_D15S1:
140 //              mDepthSize = 15;
141 //              mStencilSize = 1;
142 //              break;
143         case sw::FORMAT_D24S8:
144                 mDepthSize = 24;
145                 mStencilSize = 8;
146                 break;
147         case sw::FORMAT_D24X8:
148                 mDepthSize = 24;
149                 mStencilSize = 0;
150                 break;
151 //      case sw::FORMAT_D24X4S4:
152 //              mDepthSize = 24;
153 //              mStencilSize = 4;
154 //              break;
155         case sw::FORMAT_D16:
156                 mDepthSize = 16;
157                 mStencilSize = 0;
158                 break;
159 //  case sw::FORMAT_D32F_LOCKABLE:
160 //      mDepthSize = 32;
161 //      mStencilSize = 0;
162 //      break;
163 //  case sw::FORMAT_D24FS8:
164 //      mDepthSize = 24;
165 //      mStencilSize = 8;
166 //      break;
167         default:
168                 UNREACHABLE(depthStencilFormat);
169         }
170
171     mLevel = 0;
172     mMatchNativePixmap = EGL_NONE;
173     mMaxPBufferWidth = 4096;
174     mMaxPBufferHeight = 4096;
175     mMaxPBufferPixels = mMaxPBufferWidth * mMaxPBufferHeight;
176     mMaxSwapInterval = maxInterval;
177     mMinSwapInterval = minInterval;
178     mNativeRenderable = EGL_FALSE;
179     mNativeVisualType = 0;
180     mRenderableType = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT
181 #ifndef __ANDROID__ // Do not allow GLES 3.0 on Android
182         | EGL_OPENGL_ES3_BIT
183 #endif
184         ;
185     mSampleBuffers = (multiSample > 0) ? 1 : 0;
186     mSamples = multiSample;
187     mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
188     mTransparentType = EGL_NONE;
189     mTransparentRedValue = 0;
190     mTransparentGreenValue = 0;
191     mTransparentBlueValue = 0;
192
193         mRecordableAndroid = EGL_TRUE;
194         mFramebufferTargetAndroid = (displayFormat == renderTargetFormat) ? EGL_TRUE : EGL_FALSE;
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     META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
212     SORT_SMALLER(mConfigCaveat);
213
214     META_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         if(attr[1] != 0 && attr[1] != EGL_DONT_CARE)
266         {
267             switch (attr[0])
268             {
269             case EGL_RED_SIZE:       mWantRed = true;       break;
270             case EGL_GREEN_SIZE:     mWantGreen = true;     break;
271             case EGL_BLUE_SIZE:      mWantBlue = true;      break;
272             case EGL_ALPHA_SIZE:     mWantAlpha = true;     break;
273             case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
274             }
275         }
276     }
277 }
278
279 EGLint SortConfig::wantedComponentsSize(const Config *config) const
280 {
281     EGLint total = 0;
282
283     if(mWantRed)       total += config->mRedSize;
284     if(mWantGreen)     total += config->mGreenSize;
285     if(mWantBlue)      total += config->mBlueSize;
286     if(mWantAlpha)     total += config->mAlphaSize;
287     if(mWantLuminance) total += config->mLuminanceSize;
288
289     return total;
290 }
291
292 bool SortConfig::operator()(const Config *x, const Config *y) const
293 {
294     #define SORT_SMALLER(attribute)                \
295         if(x->attribute != y->attribute)           \
296         {                                          \
297             return x->attribute < y->attribute;    \
298         }
299
300     META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
301     SORT_SMALLER(mConfigCaveat);
302
303     META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
304     SORT_SMALLER(mColorBufferType);
305
306         // By larger total number of color bits, only considering those that are requested to be > 0.
307         EGLint xComponentsSize = wantedComponentsSize(x);
308         EGLint yComponentsSize = wantedComponentsSize(y);
309         if(xComponentsSize != yComponentsSize)
310         {
311                 return xComponentsSize > yComponentsSize;
312         }
313
314     SORT_SMALLER(mBufferSize);
315     SORT_SMALLER(mSampleBuffers);
316     SORT_SMALLER(mSamples);
317     SORT_SMALLER(mDepthSize);
318     SORT_SMALLER(mStencilSize);
319     SORT_SMALLER(mAlphaMaskSize);
320     SORT_SMALLER(mNativeVisualType);
321     SORT_SMALLER(mConfigID);
322
323     #undef SORT_SMALLER
324
325     return false;
326 }
327
328 ConfigSet::ConfigSet()
329 {
330 }
331
332 void ConfigSet::add(sw::Format displayFormat, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
333 {
334     Config config(displayFormat, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample);
335
336     mSet.insert(config);
337 }
338
339 size_t ConfigSet::size() const
340 {
341     return mSet.size();
342 }
343
344 bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
345 {
346     vector<const Config*> passed;
347     passed.reserve(mSet.size());
348
349     for(Iterator config = mSet.begin(); config != mSet.end(); config++)
350     {
351         bool match = true;
352         const EGLint *attribute = attribList;
353
354         while(attribute[0] != EGL_NONE)
355         {
356                         if(attribute[1] != EGL_DONT_CARE)
357                         {
358                                 switch(attribute[0])
359                                 {
360                                 case EGL_BUFFER_SIZE:                match = config->mBufferSize >= attribute[1];                      break;
361                                 case EGL_ALPHA_SIZE:                 match = config->mAlphaSize >= attribute[1];                       break;
362                                 case EGL_BLUE_SIZE:                  match = config->mBlueSize >= attribute[1];                        break;
363                                 case EGL_GREEN_SIZE:                 match = config->mGreenSize >= attribute[1];                       break;
364                                 case EGL_RED_SIZE:                   match = config->mRedSize >= attribute[1];                         break;
365                                 case EGL_DEPTH_SIZE:                 match = config->mDepthSize >= attribute[1];                       break;
366                                 case EGL_STENCIL_SIZE:               match = config->mStencilSize >= attribute[1];                     break;
367                                 case EGL_CONFIG_CAVEAT:              match = config->mConfigCaveat == attribute[1];                    break;
368                                 case EGL_CONFIG_ID:                  match = config->mConfigID == attribute[1];                        break;
369                                 case EGL_LEVEL:                      match = config->mLevel >= attribute[1];                           break;
370                                 case EGL_NATIVE_RENDERABLE:          match = config->mNativeRenderable == attribute[1];                break;
371                                 case EGL_NATIVE_VISUAL_ID:           match = config->mNativeVisualID == attribute[1];                  break;
372                                 case EGL_NATIVE_VISUAL_TYPE:         match = config->mNativeVisualType == attribute[1];                break;
373                                 case EGL_SAMPLES:                    match = config->mSamples >= attribute[1];                         break;
374                                 case EGL_SAMPLE_BUFFERS:             match = config->mSampleBuffers >= attribute[1];                   break;
375                                 case EGL_SURFACE_TYPE:               match = (config->mSurfaceType & attribute[1]) == attribute[1];    break;
376                                 case EGL_TRANSPARENT_TYPE:           match = config->mTransparentType == attribute[1];                 break;
377                                 case EGL_TRANSPARENT_BLUE_VALUE:     match = config->mTransparentBlueValue == attribute[1];            break;
378                                 case EGL_TRANSPARENT_GREEN_VALUE:    match = config->mTransparentGreenValue == attribute[1];           break;
379                                 case EGL_TRANSPARENT_RED_VALUE:      match = config->mTransparentRedValue == attribute[1];             break;
380                                 case EGL_BIND_TO_TEXTURE_RGB:        match = config->mBindToTextureRGB == attribute[1];                break;
381                                 case EGL_BIND_TO_TEXTURE_RGBA:       match = config->mBindToTextureRGBA == attribute[1];               break;
382                                 case EGL_MIN_SWAP_INTERVAL:          match = config->mMinSwapInterval == attribute[1];                 break;
383                                 case EGL_MAX_SWAP_INTERVAL:          match = config->mMaxSwapInterval == attribute[1];                 break;
384                                 case EGL_LUMINANCE_SIZE:             match = config->mLuminanceSize >= attribute[1];                   break;
385                                 case EGL_ALPHA_MASK_SIZE:            match = config->mAlphaMaskSize >= attribute[1];                   break;
386                                 case EGL_COLOR_BUFFER_TYPE:          match = config->mColorBufferType == attribute[1];                 break;
387                                 case EGL_RENDERABLE_TYPE:            match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
388                                 case EGL_MATCH_NATIVE_PIXMAP:        match = false; UNIMPLEMENTED();                                   break;
389                                 case EGL_CONFORMANT:                 match = (config->mConformant & attribute[1]) == attribute[1];     break;
390                                 case EGL_MAX_PBUFFER_WIDTH:          match = config->mMaxPBufferWidth >= attribute[1];                 break;
391                                 case EGL_MAX_PBUFFER_HEIGHT:         match = config->mMaxPBufferHeight >= attribute[1];                break;
392                                 case EGL_MAX_PBUFFER_PIXELS:         match = config->mMaxPBufferPixels >= attribute[1];                break;
393                                 case EGL_RECORDABLE_ANDROID:         match = config->mRecordableAndroid == attribute[1];               break;
394                                 case EGL_FRAMEBUFFER_TARGET_ANDROID: match = config->mFramebufferTargetAndroid == attribute[1];        break;
395                                 default:
396                                         *numConfig = 0;
397                                         return false;
398                                 }
399
400                                 if(!match)
401                                 {
402                                         break;
403                                 }
404                         }
405
406             attribute += 2;
407         }
408
409         if(match)
410         {
411             passed.push_back(&*config);
412         }
413     }
414
415     if(configs)
416     {
417         sort(passed.begin(), passed.end(), SortConfig(attribList));
418
419         EGLint index;
420         for(index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
421         {
422             configs[index] = passed[index]->getHandle();
423         }
424
425         *numConfig = index;
426     }
427     else
428     {
429         *numConfig = static_cast<EGLint>(passed.size());
430     }
431
432     return true;
433 }
434
435 const egl::Config *ConfigSet::get(EGLConfig configHandle)
436 {
437     for(Iterator config = mSet.begin(); config != mSet.end(); config++)
438     {
439         if(config->getHandle() == configHandle)
440         {
441             return &(*config);
442         }
443     }
444
445     return NULL;
446 }
447 }