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