blob: 511b8aeba65b08dc1a9a1d1aa4cfdc65551c48c8 [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
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000011#include "libEGL/Config.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000012
13#include <algorithm>
14#include <vector>
15
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000016#include "common/debug.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000017
18using namespace std;
19
20namespace egl
21{
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +000022Config::Config(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000023 : mDisplayMode(displayMode), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
24{
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +000025 set(displayMode, minInterval, maxInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000026}
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
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +000065void Config::set(D3DDISPLAYMODE displayMode, EGLint minInterval, EGLint maxInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000066{
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;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000097 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;
daniel@transgaming.com73248ec2010-05-12 03:40:40 +0000113 mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114 mConfigID = 0;
115 mConformant = EGL_OPENGL_ES2_BIT;
116
117 switch (depthStencilFormat)
118 {
daniel@transgaming.comd091b192010-05-07 19:01:47 +0000119// case D3DFMT_D16_LOCKABLE:
120// mDepthSize = 16;
121// mStencilSize = 0;
122// break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123 case D3DFMT_D32:
124 mDepthSize = 32;
125 mStencilSize = 0;
126 break;
127 case D3DFMT_D15S1:
daniel@transgaming.comc28e76b2010-05-05 18:47:16 +0000128 mDepthSize = 15;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000129 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:
daniel@transgaming.comd091b192010-05-07 19:01:47 +0000148// mDepthSize = 32;
149// mStencilSize = 0;
150// break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000151// case D3DFMT_D24FS8:
daniel@transgaming.comd091b192010-05-07 19:01:47 +0000152// mDepthSize = 24;
153// mStencilSize = 8;
154// break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000155 default:
156 UNREACHABLE();
157 }
158
159 mLevel = 0;
160 mMatchNativePixmap = EGL_NONE;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000161 mMaxPBufferWidth = texWidth;
162 mMaxPBufferHeight = texHeight;
163 mMaxPBufferPixels = texWidth*texHeight;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164 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
179EGLConfig Config::getHandle() const
180{
181 return (EGLConfig)(size_t)mConfigID;
182}
183
184SortConfig::SortConfig(const EGLint *attribList)
185 : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
186{
187 scanForWantedComponents(attribList);
188}
189
190void 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
211EGLint 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
224bool SortConfig::operator()(const Config *x, const Config *y) const
225{
226 return (*this)(*x, *y);
227}
228
229bool 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.
270const 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
280ConfigSet::ConfigSet()
281 : mSet(SortConfig(mSortAttribs))
282{
283}
284
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000285void ConfigSet::add(D3DDISPLAYMODE displayMode, EGLint minSwapInterval, EGLint maxSwapInterval, D3DFORMAT renderTargetFormat, D3DFORMAT depthStencilFormat, EGLint multiSample, EGLint texWidth, EGLint texHeight)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286{
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000287 Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288
289 mSet.insert(config);
290}
291
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292size_t ConfigSet::size() const
293{
294 return mSet.size();
295}
296
297bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
298{
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000299 vector<const Config*> passed;
300 passed.reserve(mSet.size());
301
302 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000304 bool match = true;
305 const EGLint *attribute = attribList;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000306
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000307 while (attribute[0] != EGL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000309 switch (attribute[0])
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310 {
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000311 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;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000340 case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
341 case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
342 case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000343 default:
344 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000345 }
346
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000347 if (!match)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000348 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000349 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350 }
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000351
352 attribute += 2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000353 }
354
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000355 if (match)
356 {
357 passed.push_back(&*config);
358 }
359 }
360
361 if (configs)
362 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363 sort(passed.begin(), passed.end(), SortConfig(attribList));
364
365 EGLint index;
366 for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
367 {
368 configs[index] = passed[index]->getHandle();
369 }
370
371 *numConfig = index;
372 }
373 else
374 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000375 *numConfig = passed.size();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000376 }
377
378 return true;
379}
380
381const egl::Config *ConfigSet::get(EGLConfig configHandle)
382{
383 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
384 {
385 if (config->getHandle() == configHandle)
386 {
387 return &(*config);
388 }
389 }
390
391 return NULL;
392}
393}