blob: 8ad51366a822c9f4c314fff4f5349542a2be03a4 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
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 "Config.h"
12
13#include <algorithm>
14#include <vector>
15
16#include "debug.h"
17
18using namespace std;
19
20namespace egl
21{
22Config::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
28void 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
65void 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_X1R5G5B5:
98 mBufferSize = 16;
99 mRedSize = 5;
100 mGreenSize = 5;
101 mBlueSize = 5;
102 mAlphaSize = 0;
103 break;
104 case D3DFMT_X8R8G8B8:
105 mBufferSize = 32;
106 mRedSize = 8;
107 mGreenSize = 8;
108 mBlueSize = 8;
109 mAlphaSize = 0;
110 break;
111 default:
112 UNREACHABLE(); // Other formats should not be valid
113 }
114
115 mLuminanceSize = 0;
116 mAlphaMaskSize = 0;
117 mBindToTextureRGB = EGL_FALSE;
118 mBindToTextureRGBA = EGL_FALSE;
119 mColorBufferType = EGL_RGB_BUFFER;
120 mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
121 mConfigID = 0;
122 mConformant = EGL_OPENGL_ES2_BIT;
123
124 switch (depthStencilFormat)
125 {
126// case D3DFMT_D16_LOCKABLE:
127// mDepthSize = 16;
128// mStencilSize = 0;
129// break;
130 case D3DFMT_D32:
131 mDepthSize = 32;
132 mStencilSize = 0;
133 break;
134 case D3DFMT_D15S1:
135 mDepthSize = 16;
136 mStencilSize = 1;
137 break;
138 case D3DFMT_D24S8:
139 mDepthSize = 24;
140 mStencilSize = 8;
141 break;
142 case D3DFMT_D24X8:
143 mDepthSize = 24;
144 mStencilSize = 0;
145 break;
146 case D3DFMT_D24X4S4:
147 mDepthSize = 24;
148 mStencilSize = 4;
149 break;
150 case D3DFMT_D16:
151 mDepthSize = 16;
152 mStencilSize = 0;
153 break;
154// case D3DFMT_D32F_LOCKABLE:
155// mDepthSize = 32;
156// mStencilSize = 0;
157// break;
158// case D3DFMT_D24FS8:
159// mDepthSize = 24;
160// mStencilSize = 8;
161// break;
162 default:
163 UNREACHABLE();
164 }
165
166 mLevel = 0;
167 mMatchNativePixmap = EGL_NONE;
168 mMaxPBufferWidth = 0;
169 mMaxPBufferHeight = 0;
170 mMaxPBufferPixels = 0;
171 mMaxSwapInterval = maxInterval;
172 mMinSwapInterval = minInterval;
173 mNativeRenderable = EGL_FALSE;
174 mNativeVisualID = 0;
175 mNativeVisualType = 0;
176 mRenderableType = EGL_OPENGL_ES2_BIT;
177 mSampleBuffers = multiSample ? 1 : 0;
178 mSamples = multiSample;
179 mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
180 mTransparentType = EGL_NONE;
181 mTransparentRedValue = 0;
182 mTransparentGreenValue = 0;
183 mTransparentBlueValue = 0;
184}
185
186EGLConfig Config::getHandle() const
187{
188 return (EGLConfig)(size_t)mConfigID;
189}
190
191SortConfig::SortConfig(const EGLint *attribList)
192 : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
193{
194 scanForWantedComponents(attribList);
195}
196
197void SortConfig::scanForWantedComponents(const EGLint *attribList)
198{
199 // [EGL] section 3.4.1 page 24
200 // Sorting rule #3: by larger total number of color bits, not considering
201 // components that are 0 or don't-care.
202 for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
203 {
204 if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
205 {
206 switch (attr[0])
207 {
208 case EGL_RED_SIZE: mWantRed = true; break;
209 case EGL_GREEN_SIZE: mWantGreen = true; break;
210 case EGL_BLUE_SIZE: mWantBlue = true; break;
211 case EGL_ALPHA_SIZE: mWantAlpha = true; break;
212 case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
213 }
214 }
215 }
216}
217
218EGLint SortConfig::wantedComponentsSize(const Config &config) const
219{
220 EGLint total = 0;
221
222 if (mWantRed) total += config.mRedSize;
223 if (mWantGreen) total += config.mGreenSize;
224 if (mWantBlue) total += config.mBlueSize;
225 if (mWantAlpha) total += config.mAlphaSize;
226 if (mWantLuminance) total += config.mLuminanceSize;
227
228 return total;
229}
230
231bool SortConfig::operator()(const Config *x, const Config *y) const
232{
233 return (*this)(*x, *y);
234}
235
236bool SortConfig::operator()(const Config &x, const Config &y) const
237{
238 #define SORT(attribute) \
239 if (x.attribute != y.attribute) \
240 { \
241 return x.attribute < y.attribute; \
242 }
243
244 META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
245 SORT(mConfigCaveat);
246
247 META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
248 SORT(mColorBufferType);
249
250 // By larger total number of color bits, only considering those that are requested to be > 0.
251 EGLint xComponentsSize = wantedComponentsSize(x);
252 EGLint yComponentsSize = wantedComponentsSize(y);
253 if (xComponentsSize != yComponentsSize)
254 {
255 return xComponentsSize > yComponentsSize;
256 }
257
258 SORT(mBufferSize);
259 SORT(mSampleBuffers);
260 SORT(mSamples);
261 SORT(mDepthSize);
262 SORT(mStencilSize);
263 SORT(mAlphaMaskSize);
264 SORT(mNativeVisualType);
265 SORT(mConfigID);
266
267 #undef SORT
268
269 return false;
270}
271
272// We'd like to use SortConfig to also eliminate duplicate configs.
273// This works as long as we never have two configs with different per-RGB-component layouts,
274// but the same total.
275// 5551 and 565 are different because R+G+B is different.
276// 5551 and 555 are different because bufferSize is different.
277const EGLint ConfigSet::mSortAttribs[] =
278{
279 EGL_RED_SIZE, 1,
280 EGL_GREEN_SIZE, 1,
281 EGL_BLUE_SIZE, 1,
282 EGL_LUMINANCE_SIZE, 1,
283 // BUT NOT ALPHA
284 EGL_NONE
285};
286
287ConfigSet::ConfigSet()
288 : mSet(SortConfig(mSortAttribs))
289{
290}
291
292void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample)
293{
294 Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample);
295
296 mSet.insert(config);
297}
298
299void ConfigSet::enumerate()
300{
301 EGLint index = 1;
302
303 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
304 {
305 config->mConfigID = index;
306 index++;
307 }
308}
309
310size_t ConfigSet::size() const
311{
312 return mSet.size();
313}
314
315bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
316{
317 if (configs)
318 {
319 vector<const Config*> passed;
320 passed.reserve(mSet.size());
321
322 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
323 {
324 bool match = true;
325 const EGLint *attribute = attribList;
326
327 while (attribute[0] != EGL_NONE)
328 {
329 switch (attribute[0])
330 {
331 case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
332 case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
333 case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
334 case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
335 case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
336 case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
337 case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
338 case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == attribute[1]; break;
339 case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
340 case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
341 case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == attribute[1]; break;
342 case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
343 case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
344 case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
345 case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
346 case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == attribute[1]; break;
347 case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
348 case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
349 case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
350 case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == attribute[1]; break;
351 case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == attribute[1]; break;
352 case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
353 case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
354 case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
355 case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
356 case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == attribute[1]; break;
357 case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
358 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
359 case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
360 default:
361 return false;
362 }
363
364 if (!match)
365 {
366 break;
367 }
368
369 attribute += 2;
370 }
371
372 if (match)
373 {
374 passed.push_back(&*config);
375 }
376 }
377
378 sort(passed.begin(), passed.end(), SortConfig(attribList));
379
380 EGLint index;
381 for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
382 {
383 configs[index] = passed[index]->getHandle();
384 }
385
386 *numConfig = index;
387 }
388 else
389 {
390 *numConfig = (EGLint)mSet.size();
391 }
392
393 return true;
394}
395
396const egl::Config *ConfigSet::get(EGLConfig configHandle)
397{
398 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
399 {
400 if (config->getHandle() == configHandle)
401 {
402 return &(*config);
403 }
404 }
405
406 return NULL;
407}
408}