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