blob: 4177962de9c0f0060ba5d8859b898251968b2e48 [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{
jbauman@chromium.orgae345802011-03-30 22:04:25 +000067 mBindToTextureRGB = EGL_FALSE;
68 mBindToTextureRGBA = EGL_FALSE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000069 switch (renderTargetFormat)
70 {
71 case D3DFMT_A1R5G5B5:
72 mBufferSize = 16;
73 mRedSize = 5;
74 mGreenSize = 5;
75 mBlueSize = 5;
76 mAlphaSize = 1;
77 break;
78 case D3DFMT_A2R10G10B10:
79 mBufferSize = 32;
80 mRedSize = 10;
81 mGreenSize = 10;
82 mBlueSize = 10;
83 mAlphaSize = 2;
84 break;
85 case D3DFMT_A8R8G8B8:
86 mBufferSize = 32;
87 mRedSize = 8;
88 mGreenSize = 8;
89 mBlueSize = 8;
90 mAlphaSize = 8;
jbauman@chromium.orgae345802011-03-30 22:04:25 +000091 mBindToTextureRGBA = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092 break;
93 case D3DFMT_R5G6B5:
94 mBufferSize = 16;
95 mRedSize = 5;
96 mGreenSize = 6;
97 mBlueSize = 5;
98 mAlphaSize = 0;
99 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100 case D3DFMT_X8R8G8B8:
101 mBufferSize = 32;
102 mRedSize = 8;
103 mGreenSize = 8;
104 mBlueSize = 8;
105 mAlphaSize = 0;
jbauman@chromium.orgae345802011-03-30 22:04:25 +0000106 mBindToTextureRGB = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107 break;
108 default:
109 UNREACHABLE(); // Other formats should not be valid
110 }
111
112 mLuminanceSize = 0;
113 mAlphaMaskSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114 mColorBufferType = EGL_RGB_BUFFER;
daniel@transgaming.com73248ec2010-05-12 03:40:40 +0000115 mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000116 mConfigID = 0;
117 mConformant = EGL_OPENGL_ES2_BIT;
118
119 switch (depthStencilFormat)
120 {
daniel@transgaming.comd091b192010-05-07 19:01:47 +0000121// case D3DFMT_D16_LOCKABLE:
122// mDepthSize = 16;
123// mStencilSize = 0;
124// break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000125 case D3DFMT_D32:
126 mDepthSize = 32;
127 mStencilSize = 0;
128 break;
129 case D3DFMT_D15S1:
daniel@transgaming.comc28e76b2010-05-05 18:47:16 +0000130 mDepthSize = 15;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131 mStencilSize = 1;
132 break;
133 case D3DFMT_D24S8:
134 mDepthSize = 24;
135 mStencilSize = 8;
136 break;
137 case D3DFMT_D24X8:
138 mDepthSize = 24;
139 mStencilSize = 0;
140 break;
141 case D3DFMT_D24X4S4:
142 mDepthSize = 24;
143 mStencilSize = 4;
144 break;
145 case D3DFMT_D16:
146 mDepthSize = 16;
147 mStencilSize = 0;
148 break;
149// case D3DFMT_D32F_LOCKABLE:
daniel@transgaming.comd091b192010-05-07 19:01:47 +0000150// mDepthSize = 32;
151// mStencilSize = 0;
152// break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000153// case D3DFMT_D24FS8:
daniel@transgaming.comd091b192010-05-07 19:01:47 +0000154// mDepthSize = 24;
155// mStencilSize = 8;
156// break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000157 default:
158 UNREACHABLE();
159 }
160
161 mLevel = 0;
162 mMatchNativePixmap = EGL_NONE;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000163 mMaxPBufferWidth = texWidth;
164 mMaxPBufferHeight = texHeight;
165 mMaxPBufferPixels = texWidth*texHeight;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166 mMaxSwapInterval = maxInterval;
167 mMinSwapInterval = minInterval;
168 mNativeRenderable = EGL_FALSE;
169 mNativeVisualID = 0;
170 mNativeVisualType = 0;
171 mRenderableType = EGL_OPENGL_ES2_BIT;
172 mSampleBuffers = multiSample ? 1 : 0;
173 mSamples = multiSample;
174 mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
175 mTransparentType = EGL_NONE;
176 mTransparentRedValue = 0;
177 mTransparentGreenValue = 0;
178 mTransparentBlueValue = 0;
179}
180
181EGLConfig Config::getHandle() const
182{
183 return (EGLConfig)(size_t)mConfigID;
184}
185
186SortConfig::SortConfig(const EGLint *attribList)
187 : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
188{
189 scanForWantedComponents(attribList);
190}
191
192void SortConfig::scanForWantedComponents(const EGLint *attribList)
193{
194 // [EGL] section 3.4.1 page 24
195 // Sorting rule #3: by larger total number of color bits, not considering
196 // components that are 0 or don't-care.
197 for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
198 {
199 if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
200 {
201 switch (attr[0])
202 {
203 case EGL_RED_SIZE: mWantRed = true; break;
204 case EGL_GREEN_SIZE: mWantGreen = true; break;
205 case EGL_BLUE_SIZE: mWantBlue = true; break;
206 case EGL_ALPHA_SIZE: mWantAlpha = true; break;
207 case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
208 }
209 }
210 }
211}
212
213EGLint SortConfig::wantedComponentsSize(const Config &config) const
214{
215 EGLint total = 0;
216
217 if (mWantRed) total += config.mRedSize;
218 if (mWantGreen) total += config.mGreenSize;
219 if (mWantBlue) total += config.mBlueSize;
220 if (mWantAlpha) total += config.mAlphaSize;
221 if (mWantLuminance) total += config.mLuminanceSize;
222
223 return total;
224}
225
226bool SortConfig::operator()(const Config *x, const Config *y) const
227{
228 return (*this)(*x, *y);
229}
230
231bool SortConfig::operator()(const Config &x, const Config &y) const
232{
233 #define SORT(attribute) \
234 if (x.attribute != y.attribute) \
235 { \
236 return x.attribute < y.attribute; \
237 }
238
239 META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
240 SORT(mConfigCaveat);
241
242 META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
243 SORT(mColorBufferType);
244
245 // By larger total number of color bits, only considering those that are requested to be > 0.
246 EGLint xComponentsSize = wantedComponentsSize(x);
247 EGLint yComponentsSize = wantedComponentsSize(y);
248 if (xComponentsSize != yComponentsSize)
249 {
250 return xComponentsSize > yComponentsSize;
251 }
252
253 SORT(mBufferSize);
254 SORT(mSampleBuffers);
255 SORT(mSamples);
256 SORT(mDepthSize);
257 SORT(mStencilSize);
258 SORT(mAlphaMaskSize);
259 SORT(mNativeVisualType);
260 SORT(mConfigID);
261
262 #undef SORT
263
264 return false;
265}
266
267// We'd like to use SortConfig to also eliminate duplicate configs.
268// This works as long as we never have two configs with different per-RGB-component layouts,
269// but the same total.
270// 5551 and 565 are different because R+G+B is different.
271// 5551 and 555 are different because bufferSize is different.
272const EGLint ConfigSet::mSortAttribs[] =
273{
274 EGL_RED_SIZE, 1,
275 EGL_GREEN_SIZE, 1,
276 EGL_BLUE_SIZE, 1,
277 EGL_LUMINANCE_SIZE, 1,
278 // BUT NOT ALPHA
279 EGL_NONE
280};
281
282ConfigSet::ConfigSet()
283 : mSet(SortConfig(mSortAttribs))
284{
285}
286
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000287void 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 +0000288{
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000289 Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000290
291 mSet.insert(config);
292}
293
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294size_t ConfigSet::size() const
295{
296 return mSet.size();
297}
298
299bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
300{
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000301 vector<const Config*> passed;
302 passed.reserve(mSet.size());
303
304 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000305 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000306 bool match = true;
307 const EGLint *attribute = attribList;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000309 while (attribute[0] != EGL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000310 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000311 switch (attribute[0])
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312 {
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000313 case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
314 case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
315 case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
316 case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
317 case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
318 case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
319 case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
320 case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == attribute[1]; break;
321 case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
322 case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
323 case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == attribute[1]; break;
324 case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
325 case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
326 case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
327 case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
328 case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == attribute[1]; break;
329 case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
330 case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
331 case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
332 case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == attribute[1]; break;
333 case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == attribute[1]; break;
334 case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
335 case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
336 case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
337 case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
338 case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == attribute[1]; break;
339 case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
340 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
341 case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000342 case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
343 case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
344 case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000345 default:
346 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000347 }
348
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000349 if (!match)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000351 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000352 }
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000353
354 attribute += 2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000355 }
356
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000357 if (match)
358 {
359 passed.push_back(&*config);
360 }
361 }
362
363 if (configs)
364 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000365 sort(passed.begin(), passed.end(), SortConfig(attribList));
366
367 EGLint index;
368 for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
369 {
370 configs[index] = passed[index]->getHandle();
371 }
372
373 *numConfig = index;
374 }
375 else
376 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000377 *numConfig = passed.size();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000378 }
379
380 return true;
381}
382
383const egl::Config *ConfigSet::get(EGLConfig configHandle)
384{
385 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
386 {
387 if (config->getHandle() == configHandle)
388 {
389 return &(*config);
390 }
391 }
392
393 return NULL;
394}
395}