blob: af4d8e259163e527679ec9d27af3fad88d5b68c5 [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
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +000028void 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 +000029{
jbauman@chromium.orgae345802011-03-30 22:04:25 +000030 mBindToTextureRGB = EGL_FALSE;
31 mBindToTextureRGBA = EGL_FALSE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000032 switch (renderTargetFormat)
33 {
34 case D3DFMT_A1R5G5B5:
35 mBufferSize = 16;
36 mRedSize = 5;
37 mGreenSize = 5;
38 mBlueSize = 5;
39 mAlphaSize = 1;
40 break;
41 case D3DFMT_A2R10G10B10:
42 mBufferSize = 32;
43 mRedSize = 10;
44 mGreenSize = 10;
45 mBlueSize = 10;
46 mAlphaSize = 2;
47 break;
48 case D3DFMT_A8R8G8B8:
49 mBufferSize = 32;
50 mRedSize = 8;
51 mGreenSize = 8;
52 mBlueSize = 8;
53 mAlphaSize = 8;
jbauman@chromium.orgae345802011-03-30 22:04:25 +000054 mBindToTextureRGBA = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000055 break;
56 case D3DFMT_R5G6B5:
57 mBufferSize = 16;
58 mRedSize = 5;
59 mGreenSize = 6;
60 mBlueSize = 5;
61 mAlphaSize = 0;
62 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000063 case D3DFMT_X8R8G8B8:
64 mBufferSize = 32;
65 mRedSize = 8;
66 mGreenSize = 8;
67 mBlueSize = 8;
68 mAlphaSize = 0;
jbauman@chromium.orgae345802011-03-30 22:04:25 +000069 mBindToTextureRGB = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000070 break;
71 default:
72 UNREACHABLE(); // Other formats should not be valid
73 }
74
75 mLuminanceSize = 0;
76 mAlphaMaskSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000077 mColorBufferType = EGL_RGB_BUFFER;
daniel@transgaming.com73248ec2010-05-12 03:40:40 +000078 mConfigCaveat = (displayMode.Format == renderTargetFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079 mConfigID = 0;
80 mConformant = EGL_OPENGL_ES2_BIT;
81
82 switch (depthStencilFormat)
83 {
daniel@transgaming.coma114c272011-04-22 04:18:50 +000084 case D3DFMT_UNKNOWN:
85 mDepthSize = 0;
86 mStencilSize = 0;
87 break;
daniel@transgaming.comd091b192010-05-07 19:01:47 +000088// case D3DFMT_D16_LOCKABLE:
89// mDepthSize = 16;
90// mStencilSize = 0;
91// break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092 case D3DFMT_D32:
93 mDepthSize = 32;
94 mStencilSize = 0;
95 break;
96 case D3DFMT_D15S1:
daniel@transgaming.comc28e76b2010-05-05 18:47:16 +000097 mDepthSize = 15;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000098 mStencilSize = 1;
99 break;
100 case D3DFMT_D24S8:
101 mDepthSize = 24;
102 mStencilSize = 8;
103 break;
104 case D3DFMT_D24X8:
105 mDepthSize = 24;
106 mStencilSize = 0;
107 break;
108 case D3DFMT_D24X4S4:
109 mDepthSize = 24;
110 mStencilSize = 4;
111 break;
112 case D3DFMT_D16:
113 mDepthSize = 16;
114 mStencilSize = 0;
115 break;
116// case D3DFMT_D32F_LOCKABLE:
daniel@transgaming.comd091b192010-05-07 19:01:47 +0000117// mDepthSize = 32;
118// mStencilSize = 0;
119// break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000120// case D3DFMT_D24FS8:
daniel@transgaming.comd091b192010-05-07 19:01:47 +0000121// mDepthSize = 24;
122// mStencilSize = 8;
123// break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000124 default:
125 UNREACHABLE();
126 }
127
128 mLevel = 0;
129 mMatchNativePixmap = EGL_NONE;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000130 mMaxPBufferWidth = texWidth;
131 mMaxPBufferHeight = texHeight;
132 mMaxPBufferPixels = texWidth*texHeight;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000133 mMaxSwapInterval = maxInterval;
134 mMinSwapInterval = minInterval;
135 mNativeRenderable = EGL_FALSE;
136 mNativeVisualID = 0;
137 mNativeVisualType = 0;
138 mRenderableType = EGL_OPENGL_ES2_BIT;
139 mSampleBuffers = multiSample ? 1 : 0;
140 mSamples = multiSample;
141 mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
142 mTransparentType = EGL_NONE;
143 mTransparentRedValue = 0;
144 mTransparentGreenValue = 0;
145 mTransparentBlueValue = 0;
146}
147
148EGLConfig Config::getHandle() const
149{
150 return (EGLConfig)(size_t)mConfigID;
151}
152
153SortConfig::SortConfig(const EGLint *attribList)
154 : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
155{
156 scanForWantedComponents(attribList);
157}
158
159void SortConfig::scanForWantedComponents(const EGLint *attribList)
160{
161 // [EGL] section 3.4.1 page 24
162 // Sorting rule #3: by larger total number of color bits, not considering
163 // components that are 0 or don't-care.
164 for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
165 {
166 if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
167 {
168 switch (attr[0])
169 {
170 case EGL_RED_SIZE: mWantRed = true; break;
171 case EGL_GREEN_SIZE: mWantGreen = true; break;
172 case EGL_BLUE_SIZE: mWantBlue = true; break;
173 case EGL_ALPHA_SIZE: mWantAlpha = true; break;
174 case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
175 }
176 }
177 }
178}
179
180EGLint SortConfig::wantedComponentsSize(const Config &config) const
181{
182 EGLint total = 0;
183
184 if (mWantRed) total += config.mRedSize;
185 if (mWantGreen) total += config.mGreenSize;
186 if (mWantBlue) total += config.mBlueSize;
187 if (mWantAlpha) total += config.mAlphaSize;
188 if (mWantLuminance) total += config.mLuminanceSize;
189
190 return total;
191}
192
193bool SortConfig::operator()(const Config *x, const Config *y) const
194{
195 return (*this)(*x, *y);
196}
197
198bool SortConfig::operator()(const Config &x, const Config &y) const
199{
200 #define SORT(attribute) \
201 if (x.attribute != y.attribute) \
202 { \
203 return x.attribute < y.attribute; \
204 }
205
206 META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
207 SORT(mConfigCaveat);
208
209 META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
210 SORT(mColorBufferType);
211
212 // By larger total number of color bits, only considering those that are requested to be > 0.
213 EGLint xComponentsSize = wantedComponentsSize(x);
214 EGLint yComponentsSize = wantedComponentsSize(y);
215 if (xComponentsSize != yComponentsSize)
216 {
217 return xComponentsSize > yComponentsSize;
218 }
219
220 SORT(mBufferSize);
221 SORT(mSampleBuffers);
222 SORT(mSamples);
223 SORT(mDepthSize);
224 SORT(mStencilSize);
225 SORT(mAlphaMaskSize);
226 SORT(mNativeVisualType);
227 SORT(mConfigID);
228
229 #undef SORT
230
231 return false;
232}
233
234// We'd like to use SortConfig to also eliminate duplicate configs.
235// This works as long as we never have two configs with different per-RGB-component layouts,
236// but the same total.
237// 5551 and 565 are different because R+G+B is different.
238// 5551 and 555 are different because bufferSize is different.
239const EGLint ConfigSet::mSortAttribs[] =
240{
241 EGL_RED_SIZE, 1,
242 EGL_GREEN_SIZE, 1,
243 EGL_BLUE_SIZE, 1,
244 EGL_LUMINANCE_SIZE, 1,
245 // BUT NOT ALPHA
246 EGL_NONE
247};
248
249ConfigSet::ConfigSet()
250 : mSet(SortConfig(mSortAttribs))
251{
252}
253
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000254void 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 +0000255{
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000256 Config config(displayMode, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, texWidth, texHeight);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000257
258 mSet.insert(config);
259}
260
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000261size_t ConfigSet::size() const
262{
263 return mSet.size();
264}
265
266bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
267{
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000268 vector<const Config*> passed;
269 passed.reserve(mSet.size());
270
271 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000272 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000273 bool match = true;
274 const EGLint *attribute = attribList;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000275
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000276 while (attribute[0] != EGL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000277 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000278 switch (attribute[0])
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000279 {
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000280 case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
281 case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
282 case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
283 case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
284 case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
285 case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
286 case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000287 case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000288 case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
289 case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000290 case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000291 case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
292 case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
293 case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
294 case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000295 case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000296 case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
297 case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
298 case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000299 case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean) attribute[1]; break;
300 case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000301 case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
302 case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
303 case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
304 case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000305 case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000306 case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
307 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
308 case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000309 case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
310 case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
311 case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000312 default:
313 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314 }
315
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000316 if (!match)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000318 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000319 }
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000320
321 attribute += 2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000322 }
323
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000324 if (match)
325 {
326 passed.push_back(&*config);
327 }
328 }
329
330 if (configs)
331 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332 sort(passed.begin(), passed.end(), SortConfig(attribList));
333
334 EGLint index;
335 for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
336 {
337 configs[index] = passed[index]->getHandle();
338 }
339
340 *numConfig = index;
341 }
342 else
343 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000344 *numConfig = passed.size();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000345 }
346
347 return true;
348}
349
350const egl::Config *ConfigSet::get(EGLConfig configHandle)
351{
352 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
353 {
354 if (config->getHandle() == configHandle)
355 {
356 return &(*config);
357 }
358 }
359
360 return NULL;
361}
362}