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