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