blob: 2e90b32e6e622b3d4feaae2e54a695150e3c410a [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
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000016#include <GLES2/gl2.h>
17#include <GLES2/gl2ext.h>
18
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000019#include "common/debug.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000020
21using namespace std;
22
23namespace egl
24{
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +000025Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight)
daniel@transgaming.com3281f972012-10-31 18:38:51 +000026 : mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000027{
jbauman@chromium.orgae345802011-03-30 22:04:25 +000028 mBindToTextureRGB = EGL_FALSE;
29 mBindToTextureRGBA = EGL_FALSE;
daniel@transgaming.com3281f972012-10-31 18:38:51 +000030 switch (desc.renderTargetFormat)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000031 {
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000032 case GL_RGB5_A1:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000033 mBufferSize = 16;
34 mRedSize = 5;
35 mGreenSize = 5;
36 mBlueSize = 5;
37 mAlphaSize = 1;
38 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000039 case GL_RGBA8_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000040 mBufferSize = 32;
41 mRedSize = 8;
42 mGreenSize = 8;
43 mBlueSize = 8;
44 mAlphaSize = 8;
jbauman@chromium.orgae345802011-03-30 22:04:25 +000045 mBindToTextureRGBA = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000046 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000047 case GL_RGB565:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000048 mBufferSize = 16;
49 mRedSize = 5;
50 mGreenSize = 6;
51 mBlueSize = 5;
52 mAlphaSize = 0;
53 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000054 case GL_RGB8_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000055 mBufferSize = 32;
56 mRedSize = 8;
57 mGreenSize = 8;
58 mBlueSize = 8;
59 mAlphaSize = 0;
jbauman@chromium.orgae345802011-03-30 22:04:25 +000060 mBindToTextureRGB = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000061 break;
62 default:
63 UNREACHABLE(); // Other formats should not be valid
64 }
65
66 mLuminanceSize = 0;
67 mAlphaMaskSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000068 mColorBufferType = EGL_RGB_BUFFER;
daniel@transgaming.com3281f972012-10-31 18:38:51 +000069 mConfigCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000070 mConfigID = 0;
71 mConformant = EGL_OPENGL_ES2_BIT;
72
daniel@transgaming.com3281f972012-10-31 18:38:51 +000073 switch (desc.depthStencilFormat)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000074 {
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000075 case GL_NONE:
daniel@transgaming.coma114c272011-04-22 04:18:50 +000076 mDepthSize = 0;
77 mStencilSize = 0;
78 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000079 case GL_DEPTH_COMPONENT32_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000080 mDepthSize = 32;
81 mStencilSize = 0;
82 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000083 case GL_DEPTH24_STENCIL8_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000084 mDepthSize = 24;
85 mStencilSize = 8;
86 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000087 case GL_DEPTH_COMPONENT24_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000088 mDepthSize = 24;
89 mStencilSize = 0;
90 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000091 case GL_DEPTH_COMPONENT16:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092 mDepthSize = 16;
93 mStencilSize = 0;
94 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095 default:
96 UNREACHABLE();
97 }
98
99 mLevel = 0;
100 mMatchNativePixmap = EGL_NONE;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000101 mMaxPBufferWidth = texWidth;
102 mMaxPBufferHeight = texHeight;
103 mMaxPBufferPixels = texWidth*texHeight;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000104 mMaxSwapInterval = maxInterval;
105 mMinSwapInterval = minInterval;
106 mNativeRenderable = EGL_FALSE;
107 mNativeVisualID = 0;
108 mNativeVisualType = 0;
109 mRenderableType = EGL_OPENGL_ES2_BIT;
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000110 mSampleBuffers = desc.multiSample ? 1 : 0;
111 mSamples = desc.multiSample;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000112 mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
113 mTransparentType = EGL_NONE;
114 mTransparentRedValue = 0;
115 mTransparentGreenValue = 0;
116 mTransparentBlueValue = 0;
117}
118
119EGLConfig Config::getHandle() const
120{
121 return (EGLConfig)(size_t)mConfigID;
122}
123
124SortConfig::SortConfig(const EGLint *attribList)
125 : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
126{
127 scanForWantedComponents(attribList);
128}
129
130void SortConfig::scanForWantedComponents(const EGLint *attribList)
131{
132 // [EGL] section 3.4.1 page 24
133 // Sorting rule #3: by larger total number of color bits, not considering
134 // components that are 0 or don't-care.
135 for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
136 {
137 if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
138 {
139 switch (attr[0])
140 {
141 case EGL_RED_SIZE: mWantRed = true; break;
142 case EGL_GREEN_SIZE: mWantGreen = true; break;
143 case EGL_BLUE_SIZE: mWantBlue = true; break;
144 case EGL_ALPHA_SIZE: mWantAlpha = true; break;
145 case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
146 }
147 }
148 }
149}
150
151EGLint SortConfig::wantedComponentsSize(const Config &config) const
152{
153 EGLint total = 0;
154
155 if (mWantRed) total += config.mRedSize;
156 if (mWantGreen) total += config.mGreenSize;
157 if (mWantBlue) total += config.mBlueSize;
158 if (mWantAlpha) total += config.mAlphaSize;
159 if (mWantLuminance) total += config.mLuminanceSize;
160
161 return total;
162}
163
164bool SortConfig::operator()(const Config *x, const Config *y) const
165{
166 return (*this)(*x, *y);
167}
168
169bool SortConfig::operator()(const Config &x, const Config &y) const
170{
171 #define SORT(attribute) \
172 if (x.attribute != y.attribute) \
173 { \
174 return x.attribute < y.attribute; \
175 }
176
177 META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
178 SORT(mConfigCaveat);
179
180 META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
181 SORT(mColorBufferType);
182
183 // By larger total number of color bits, only considering those that are requested to be > 0.
184 EGLint xComponentsSize = wantedComponentsSize(x);
185 EGLint yComponentsSize = wantedComponentsSize(y);
186 if (xComponentsSize != yComponentsSize)
187 {
188 return xComponentsSize > yComponentsSize;
189 }
190
191 SORT(mBufferSize);
192 SORT(mSampleBuffers);
193 SORT(mSamples);
194 SORT(mDepthSize);
195 SORT(mStencilSize);
196 SORT(mAlphaMaskSize);
197 SORT(mNativeVisualType);
198 SORT(mConfigID);
199
200 #undef SORT
201
202 return false;
203}
204
205// We'd like to use SortConfig to also eliminate duplicate configs.
206// This works as long as we never have two configs with different per-RGB-component layouts,
207// but the same total.
208// 5551 and 565 are different because R+G+B is different.
209// 5551 and 555 are different because bufferSize is different.
210const EGLint ConfigSet::mSortAttribs[] =
211{
212 EGL_RED_SIZE, 1,
213 EGL_GREEN_SIZE, 1,
214 EGL_BLUE_SIZE, 1,
215 EGL_LUMINANCE_SIZE, 1,
216 // BUT NOT ALPHA
217 EGL_NONE
218};
219
220ConfigSet::ConfigSet()
221 : mSet(SortConfig(mSortAttribs))
222{
223}
224
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000225void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000226{
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000227 Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228 mSet.insert(config);
229}
230
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000231size_t ConfigSet::size() const
232{
233 return mSet.size();
234}
235
236bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
237{
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000238 vector<const Config*> passed;
239 passed.reserve(mSet.size());
240
241 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000243 bool match = true;
244 const EGLint *attribute = attribList;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000245
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000246 while (attribute[0] != EGL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000248 switch (attribute[0])
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249 {
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000250 case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
251 case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
252 case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
253 case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
254 case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
255 case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
256 case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000257 case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000258 case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
259 case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000260 case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000261 case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
262 case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
263 case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
264 case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000265 case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000266 case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
267 case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
268 case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000269 case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean) attribute[1]; break;
270 case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000271 case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
272 case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
273 case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
274 case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000275 case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000276 case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
277 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
278 case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000279 case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
280 case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
281 case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000282 default:
283 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000284 }
285
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000286 if (!match)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000287 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000288 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000289 }
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000290
291 attribute += 2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292 }
293
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000294 if (match)
295 {
296 passed.push_back(&*config);
297 }
298 }
299
300 if (configs)
301 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302 sort(passed.begin(), passed.end(), SortConfig(attribList));
303
304 EGLint index;
305 for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
306 {
307 configs[index] = passed[index]->getHandle();
308 }
309
310 *numConfig = index;
311 }
312 else
313 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000314 *numConfig = passed.size();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000315 }
316
317 return true;
318}
319
320const egl::Config *ConfigSet::get(EGLConfig configHandle)
321{
322 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
323 {
324 if (config->getHandle() == configHandle)
325 {
326 return &(*config);
327 }
328 }
329
330 return NULL;
331}
332}