OSDN Git Service

Treat all X8R8G8B8 and A8R8G8B8 formats as fast 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 #define EGLAPI
21 #include <EGL/eglext.h>
22
23 #include <algorithm>
24 #include <vector>
25
26 using namespace std;
27
28 namespace egl
29 {
30 Config::Config(const DisplayMode &displayMode, EGLint minInterval, EGLint maxInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
31     : mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
32 {
33     mBindToTextureRGB = EGL_FALSE;
34     mBindToTextureRGBA = EGL_FALSE;
35
36     switch (renderTargetFormat)
37     {
38       case sw::FORMAT_A1R5G5B5:
39         mBufferSize = 16;
40         mRedSize = 5;
41         mGreenSize = 5;
42         mBlueSize = 5;
43         mAlphaSize = 1;
44         break;
45       case sw::FORMAT_A2R10G10B10:
46         mBufferSize = 32;
47         mRedSize = 10;
48         mGreenSize = 10;
49         mBlueSize = 10;
50         mAlphaSize = 2;
51         break;
52       case sw::FORMAT_A8R8G8B8:
53         mBufferSize = 32;
54         mRedSize = 8;
55         mGreenSize = 8;
56         mBlueSize = 8;
57         mAlphaSize = 8;
58         mBindToTextureRGBA = true;
59         break;
60       case sw::FORMAT_R5G6B5:
61         mBufferSize = 16;
62         mRedSize = 5;
63         mGreenSize = 6;
64         mBlueSize = 5;
65         mAlphaSize = 0;
66         break;
67       case sw::FORMAT_X8R8G8B8:
68         mBufferSize = 32;
69         mRedSize = 8;
70         mGreenSize = 8;
71         mBlueSize = 8;
72         mAlphaSize = 0;
73         mBindToTextureRGB = true;
74         break;
75       default:
76         UNREACHABLE();   // Other formats should not be valid
77     }
78
79     mLuminanceSize = 0;
80     mAlphaMaskSize = 0;
81     mColorBufferType = EGL_RGB_BUFFER;
82     mConfigCaveat = isSlowConfig() ? EGL_SLOW_CONFIG : EGL_NONE;
83     mConfigID = 0;
84     mConformant = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
85
86         switch (depthStencilFormat)
87         {
88         case sw::FORMAT_NULL:
89                 mDepthSize = 0;
90                 mStencilSize = 0;
91                 break;
92 //  case sw::FORMAT_D16_LOCKABLE:
93 //      mDepthSize = 16;
94 //      mStencilSize = 0;
95 //      break;
96         case sw::FORMAT_D32:
97                 mDepthSize = 32;
98                 mStencilSize = 0;
99                 break;
100 //      case sw::FORMAT_D15S1:
101 //              mDepthSize = 15;
102 //              mStencilSize = 1;
103 //              break;
104         case sw::FORMAT_D24S8:
105                 mDepthSize = 24;
106                 mStencilSize = 8;
107                 break;
108         case sw::FORMAT_D24X8:
109                 mDepthSize = 24;
110                 mStencilSize = 0;
111                 break;
112 //      case sw::FORMAT_D24X4S4:
113 //              mDepthSize = 24;
114 //              mStencilSize = 4;
115 //              break;
116         case sw::FORMAT_D16:
117                 mDepthSize = 16;
118                 mStencilSize = 0;
119                 break;
120 //  case sw::FORMAT_D32F_LOCKABLE:
121 //      mDepthSize = 32;
122 //      mStencilSize = 0;
123 //      break;
124 //  case sw::FORMAT_D24FS8:
125 //      mDepthSize = 24;
126 //      mStencilSize = 8;
127 //      break;
128           default:
129                 UNREACHABLE();
130         }
131
132     mLevel = 0;
133     mMatchNativePixmap = EGL_NONE;
134     mMaxPBufferWidth = 4096;
135     mMaxPBufferHeight = 4096;
136     mMaxPBufferPixels = mMaxPBufferWidth * mMaxPBufferHeight;
137     mMaxSwapInterval = maxInterval;
138     mMinSwapInterval = minInterval;
139     mNativeRenderable = EGL_FALSE;
140     mNativeVisualID = 0;
141     mNativeVisualType = 0;
142     mRenderableType = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT;
143     mSampleBuffers = multiSample ? 1 : 0;
144     mSamples = multiSample;
145     mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
146     mTransparentType = EGL_NONE;
147     mTransparentRedValue = 0;
148     mTransparentGreenValue = 0;
149     mTransparentBlueValue = 0;
150 }
151
152 EGLConfig Config::getHandle() const
153 {
154     return (EGLConfig)(size_t)mConfigID;
155 }
156
157 bool Config::isSlowConfig() const
158 {
159         return mRenderTargetFormat != sw::FORMAT_X8R8G8B8 && mRenderTargetFormat != sw::FORMAT_A8R8G8B8;
160 }
161
162 SortConfig::SortConfig(const EGLint *attribList)
163     : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
164 {
165     scanForWantedComponents(attribList);
166 }
167
168 void SortConfig::scanForWantedComponents(const EGLint *attribList)
169 {
170     // [EGL] section 3.4.1 page 24
171     // Sorting rule #3: by larger total number of color bits, not considering
172     // components that are 0 or don't-care.
173     for(const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
174     {
175         if(attr[1] != 0 && attr[1] != EGL_DONT_CARE)
176         {
177             switch (attr[0])
178             {
179               case EGL_RED_SIZE:       mWantRed = true; break;
180               case EGL_GREEN_SIZE:     mWantGreen = true; break;
181               case EGL_BLUE_SIZE:      mWantBlue = true; break;
182               case EGL_ALPHA_SIZE:     mWantAlpha = true; break;
183               case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
184             }
185         }
186     }
187 }
188
189 EGLint SortConfig::wantedComponentsSize(const Config &config) const
190 {
191     EGLint total = 0;
192
193     if(mWantRed)       total += config.mRedSize;
194     if(mWantGreen)     total += config.mGreenSize;
195     if(mWantBlue)      total += config.mBlueSize;
196     if(mWantAlpha)     total += config.mAlphaSize;
197     if(mWantLuminance) total += config.mLuminanceSize;
198
199     return total;
200 }
201
202 bool SortConfig::operator()(const Config *x, const Config *y) const
203 {
204     return (*this)(*x, *y);
205 }
206
207 bool SortConfig::operator()(const Config &x, const Config &y) const
208 {
209     #define SORT(attribute)                        \
210         if(x.attribute != y.attribute)             \
211         {                                          \
212             return x.attribute < y.attribute;      \
213         }
214
215     META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
216     SORT(mConfigCaveat);
217
218     META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
219     SORT(mColorBufferType);
220
221     // By larger total number of color bits, only considering those that are requested to be > 0.
222     EGLint xComponentsSize = wantedComponentsSize(x);
223     EGLint yComponentsSize = wantedComponentsSize(y);
224     if(xComponentsSize != yComponentsSize)
225     {
226         return xComponentsSize > yComponentsSize;
227     }
228
229     SORT(mBufferSize);
230     SORT(mSampleBuffers);
231     SORT(mSamples);
232     SORT(mDepthSize);
233     SORT(mStencilSize);
234     SORT(mAlphaMaskSize);
235     SORT(mNativeVisualType);
236     SORT(mConfigID);
237
238     #undef SORT
239
240     return false;
241 }
242
243 // We'd like to use SortConfig to also eliminate duplicate configs.
244 // This works as long as we never have two configs with different per-RGB-component layouts,
245 // but the same total.
246 // 5551 and 565 are different because R+G+B is different.
247 // 5551 and 555 are different because bufferSize is different.
248 const EGLint ConfigSet::mSortAttribs[] =
249 {
250     EGL_RED_SIZE, 1,
251     EGL_GREEN_SIZE, 1,
252     EGL_BLUE_SIZE, 1,
253     EGL_LUMINANCE_SIZE, 1,
254     // BUT NOT ALPHA
255     EGL_NONE
256 };
257
258 ConfigSet::ConfigSet()
259     : mSet(SortConfig(mSortAttribs))
260 {
261 }
262
263 void ConfigSet::add(const DisplayMode &displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
264 {
265     Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample);
266
267     mSet.insert(config);
268 }
269
270 size_t ConfigSet::size() const
271 {
272     return mSet.size();
273 }
274
275 bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
276 {
277     vector<const Config*> passed;
278     passed.reserve(mSet.size());
279
280     for(Iterator config = mSet.begin(); config != mSet.end(); config++)
281     {
282         bool match = true;
283         const EGLint *attribute = attribList;
284
285         while(attribute[0] != EGL_NONE)
286         {
287             switch(attribute[0])
288             {
289             case EGL_BUFFER_SIZE:                match = config->mBufferSize >= attribute[1];                      break;
290             case EGL_ALPHA_SIZE:                 match = config->mAlphaSize >= attribute[1];                       break;
291             case EGL_BLUE_SIZE:                  match = config->mBlueSize >= attribute[1];                        break;
292             case EGL_GREEN_SIZE:                 match = config->mGreenSize >= attribute[1];                       break;
293             case EGL_RED_SIZE:                   match = config->mRedSize >= attribute[1];                         break;
294             case EGL_DEPTH_SIZE:                 match = config->mDepthSize >= attribute[1];                       break;
295             case EGL_STENCIL_SIZE:               match = config->mStencilSize >= attribute[1];                     break;
296             case EGL_CONFIG_CAVEAT:              match = config->mConfigCaveat == attribute[1];                    break;
297             case EGL_CONFIG_ID:                  match = config->mConfigID == attribute[1];                        break;
298             case EGL_LEVEL:                      match = config->mLevel >= attribute[1];                           break;
299             case EGL_NATIVE_RENDERABLE:          match = config->mNativeRenderable == attribute[1];                break;
300             case EGL_NATIVE_VISUAL_ID:           match = config->mNativeVisualID == attribute[1];                  break;
301             case EGL_NATIVE_VISUAL_TYPE:         match = config->mNativeVisualType == attribute[1];                break;
302             case EGL_SAMPLES:                    match = config->mSamples >= attribute[1];                         break;
303             case EGL_SAMPLE_BUFFERS:             match = config->mSampleBuffers >= attribute[1];                   break;
304             case EGL_SURFACE_TYPE:               match = (config->mSurfaceType & attribute[1]) == attribute[1];    break;
305             case EGL_TRANSPARENT_TYPE:           match = config->mTransparentType == attribute[1];                 break;
306             case EGL_TRANSPARENT_BLUE_VALUE:     match = config->mTransparentBlueValue == attribute[1];            break;
307             case EGL_TRANSPARENT_GREEN_VALUE:    match = config->mTransparentGreenValue == attribute[1];           break;
308             case EGL_TRANSPARENT_RED_VALUE:      match = config->mTransparentRedValue == attribute[1];             break;
309             case EGL_BIND_TO_TEXTURE_RGB:        match = config->mBindToTextureRGB == attribute[1];                break;
310             case EGL_BIND_TO_TEXTURE_RGBA:       match = config->mBindToTextureRGBA == attribute[1];               break;
311             case EGL_MIN_SWAP_INTERVAL:          match = config->mMinSwapInterval == attribute[1];                 break;
312             case EGL_MAX_SWAP_INTERVAL:          match = config->mMaxSwapInterval == attribute[1];                 break;
313             case EGL_LUMINANCE_SIZE:             match = config->mLuminanceSize >= attribute[1];                   break;
314             case EGL_ALPHA_MASK_SIZE:            match = config->mAlphaMaskSize >= attribute[1];                   break;
315             case EGL_COLOR_BUFFER_TYPE:          match = config->mColorBufferType == attribute[1];                 break;
316             case EGL_RENDERABLE_TYPE:            match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
317             case EGL_MATCH_NATIVE_PIXMAP:        match = false; UNIMPLEMENTED();                                   break;
318             case EGL_CONFORMANT:                 match = (config->mConformant & attribute[1]) == attribute[1];     break;
319             case EGL_MAX_PBUFFER_WIDTH:          match = config->mMaxPBufferWidth >= attribute[1];                 break;
320             case EGL_MAX_PBUFFER_HEIGHT:         match = config->mMaxPBufferHeight >= attribute[1];                break;
321             case EGL_MAX_PBUFFER_PIXELS:         match = config->mMaxPBufferPixels >= attribute[1];                break;
322                         case EGL_RECORDABLE_ANDROID:         match = false; /* UNIMPLEMENTED(); */                             break;
323                         case EGL_FRAMEBUFFER_TARGET_ANDROID: match = false; /* UNIMPLEMENTED(); */                             break;
324                         default:
325                                 UNIMPLEMENTED();
326                                 match = false;
327             }
328
329             if(!match)
330             {
331                 break;
332             }
333
334             attribute += 2;
335         }
336
337         if(match)
338         {
339             passed.push_back(&*config);
340         }
341     }
342
343     if(configs)
344     {
345         sort(passed.begin(), passed.end(), SortConfig(attribList));
346
347         EGLint index;
348         for(index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
349         {
350             configs[index] = passed[index]->getHandle();
351         }
352
353         *numConfig = index;
354     }
355     else
356     {
357         *numConfig = static_cast<EGLint>(passed.size());
358     }
359
360     return true;
361 }
362
363 const egl::Config *ConfigSet::get(EGLConfig configHandle)
364 {
365     for(Iterator config = mSet.begin(); config != mSet.end(); config++)
366     {
367         if(config->getHandle() == configHandle)
368         {
369             return &(*config);
370         }
371     }
372
373     return NULL;
374 }
375 }