blob: 3bbcb9026d9220e60c90dba122eeedf7ebb728e2 [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
shannon.woods%transgaming.com@gtempaccount.comf26ddae2013-04-13 03:29:13 +000016#include <GLES3/gl3.h>
17#include <GLES3/gl3ext.h>
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000018#include <GLES2/gl2.h>
19#include <GLES2/gl2ext.h>
shannon.woods%transgaming.com@gtempaccount.comdcf33d52013-04-13 03:33:11 +000020#include <EGL/eglext.h>
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000021
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000022#include "common/debug.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000023
24using namespace std;
25
26namespace egl
27{
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +000028Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight)
daniel@transgaming.com3281f972012-10-31 18:38:51 +000029 : mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000030{
jbauman@chromium.orgae345802011-03-30 22:04:25 +000031 mBindToTextureRGB = EGL_FALSE;
32 mBindToTextureRGBA = EGL_FALSE;
daniel@transgaming.com3281f972012-10-31 18:38:51 +000033 switch (desc.renderTargetFormat)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000034 {
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000035 case GL_RGB5_A1:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000036 mBufferSize = 16;
37 mRedSize = 5;
38 mGreenSize = 5;
39 mBlueSize = 5;
40 mAlphaSize = 1;
41 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000042 case GL_RGBA8_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000043 mBufferSize = 32;
44 mRedSize = 8;
45 mGreenSize = 8;
46 mBlueSize = 8;
47 mAlphaSize = 8;
jbauman@chromium.orgae345802011-03-30 22:04:25 +000048 mBindToTextureRGBA = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000049 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000050 case GL_RGB565:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000051 mBufferSize = 16;
52 mRedSize = 5;
53 mGreenSize = 6;
54 mBlueSize = 5;
55 mAlphaSize = 0;
56 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000057 case GL_RGB8_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000058 mBufferSize = 32;
59 mRedSize = 8;
60 mGreenSize = 8;
61 mBlueSize = 8;
62 mAlphaSize = 0;
jbauman@chromium.orgae345802011-03-30 22:04:25 +000063 mBindToTextureRGB = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000064 break;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000065 case GL_BGRA8_EXT:
66 mBufferSize = 32;
67 mRedSize = 8;
68 mGreenSize = 8;
69 mBlueSize = 8;
70 mAlphaSize = 8;
71 mBindToTextureRGBA = true;
72 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000073 default:
74 UNREACHABLE(); // Other formats should not be valid
75 }
76
77 mLuminanceSize = 0;
78 mAlphaMaskSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079 mColorBufferType = EGL_RGB_BUFFER;
daniel@transgaming.com3281f972012-10-31 18:38:51 +000080 mConfigCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081 mConfigID = 0;
82 mConformant = EGL_OPENGL_ES2_BIT;
83
daniel@transgaming.com3281f972012-10-31 18:38:51 +000084 switch (desc.depthStencilFormat)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085 {
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000086 case GL_NONE:
daniel@transgaming.coma114c272011-04-22 04:18:50 +000087 mDepthSize = 0;
88 mStencilSize = 0;
89 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000090 case GL_DEPTH_COMPONENT32_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000091 mDepthSize = 32;
92 mStencilSize = 0;
93 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000094 case GL_DEPTH24_STENCIL8_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095 mDepthSize = 24;
96 mStencilSize = 8;
97 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000098 case GL_DEPTH_COMPONENT24_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099 mDepthSize = 24;
100 mStencilSize = 0;
101 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +0000102 case GL_DEPTH_COMPONENT16:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000103 mDepthSize = 16;
104 mStencilSize = 0;
105 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106 default:
107 UNREACHABLE();
108 }
109
110 mLevel = 0;
111 mMatchNativePixmap = EGL_NONE;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000112 mMaxPBufferWidth = texWidth;
113 mMaxPBufferHeight = texHeight;
114 mMaxPBufferPixels = texWidth*texHeight;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000115 mMaxSwapInterval = maxInterval;
116 mMinSwapInterval = minInterval;
117 mNativeRenderable = EGL_FALSE;
118 mNativeVisualID = 0;
119 mNativeVisualType = 0;
120 mRenderableType = EGL_OPENGL_ES2_BIT;
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000121 mSampleBuffers = desc.multiSample ? 1 : 0;
122 mSamples = desc.multiSample;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123 mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
124 mTransparentType = EGL_NONE;
125 mTransparentRedValue = 0;
126 mTransparentGreenValue = 0;
127 mTransparentBlueValue = 0;
shannon.woods%transgaming.com@gtempaccount.comdcf33d52013-04-13 03:33:11 +0000128
129 if (desc.es3Capable)
130 {
131 mRenderableType |= EGL_OPENGL_ES3_BIT_KHR;
132 mConformant |= EGL_OPENGL_ES3_BIT_KHR;
133 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000134}
135
136EGLConfig Config::getHandle() const
137{
138 return (EGLConfig)(size_t)mConfigID;
139}
140
141SortConfig::SortConfig(const EGLint *attribList)
142 : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
143{
144 scanForWantedComponents(attribList);
145}
146
147void SortConfig::scanForWantedComponents(const EGLint *attribList)
148{
149 // [EGL] section 3.4.1 page 24
150 // Sorting rule #3: by larger total number of color bits, not considering
151 // components that are 0 or don't-care.
152 for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
153 {
154 if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
155 {
156 switch (attr[0])
157 {
158 case EGL_RED_SIZE: mWantRed = true; break;
159 case EGL_GREEN_SIZE: mWantGreen = true; break;
160 case EGL_BLUE_SIZE: mWantBlue = true; break;
161 case EGL_ALPHA_SIZE: mWantAlpha = true; break;
162 case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
163 }
164 }
165 }
166}
167
168EGLint SortConfig::wantedComponentsSize(const Config &config) const
169{
170 EGLint total = 0;
171
172 if (mWantRed) total += config.mRedSize;
173 if (mWantGreen) total += config.mGreenSize;
174 if (mWantBlue) total += config.mBlueSize;
175 if (mWantAlpha) total += config.mAlphaSize;
176 if (mWantLuminance) total += config.mLuminanceSize;
177
178 return total;
179}
180
181bool SortConfig::operator()(const Config *x, const Config *y) const
182{
183 return (*this)(*x, *y);
184}
185
186bool SortConfig::operator()(const Config &x, const Config &y) const
187{
188 #define SORT(attribute) \
189 if (x.attribute != y.attribute) \
190 { \
191 return x.attribute < y.attribute; \
192 }
193
194 META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
195 SORT(mConfigCaveat);
196
197 META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
198 SORT(mColorBufferType);
199
200 // By larger total number of color bits, only considering those that are requested to be > 0.
201 EGLint xComponentsSize = wantedComponentsSize(x);
202 EGLint yComponentsSize = wantedComponentsSize(y);
203 if (xComponentsSize != yComponentsSize)
204 {
205 return xComponentsSize > yComponentsSize;
206 }
207
208 SORT(mBufferSize);
209 SORT(mSampleBuffers);
210 SORT(mSamples);
211 SORT(mDepthSize);
212 SORT(mStencilSize);
213 SORT(mAlphaMaskSize);
214 SORT(mNativeVisualType);
215 SORT(mConfigID);
216
217 #undef SORT
218
219 return false;
220}
221
222// We'd like to use SortConfig to also eliminate duplicate configs.
223// This works as long as we never have two configs with different per-RGB-component layouts,
224// but the same total.
225// 5551 and 565 are different because R+G+B is different.
226// 5551 and 555 are different because bufferSize is different.
227const EGLint ConfigSet::mSortAttribs[] =
228{
229 EGL_RED_SIZE, 1,
230 EGL_GREEN_SIZE, 1,
231 EGL_BLUE_SIZE, 1,
232 EGL_LUMINANCE_SIZE, 1,
233 // BUT NOT ALPHA
234 EGL_NONE
235};
236
237ConfigSet::ConfigSet()
238 : mSet(SortConfig(mSortAttribs))
239{
240}
241
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000242void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000243{
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000244 Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000245 mSet.insert(config);
246}
247
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248size_t ConfigSet::size() const
249{
250 return mSet.size();
251}
252
253bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
254{
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000255 vector<const Config*> passed;
256 passed.reserve(mSet.size());
257
258 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000260 bool match = true;
261 const EGLint *attribute = attribList;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000263 while (attribute[0] != EGL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000264 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000265 switch (attribute[0])
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266 {
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000267 case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
268 case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
269 case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
270 case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
271 case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
272 case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
273 case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000274 case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000275 case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
276 case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000277 case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000278 case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
279 case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
280 case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
281 case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000282 case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000283 case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
284 case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
285 case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000286 case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean) attribute[1]; break;
287 case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000288 case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
289 case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
290 case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
291 case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000292 case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000293 case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
294 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
295 case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000296 case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
297 case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
298 case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000299 default:
300 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301 }
302
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000303 if (!match)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000304 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000305 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000306 }
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000307
308 attribute += 2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000309 }
310
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000311 if (match)
312 {
313 passed.push_back(&*config);
314 }
315 }
316
317 if (configs)
318 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000319 sort(passed.begin(), passed.end(), SortConfig(attribList));
320
321 EGLint index;
322 for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
323 {
324 configs[index] = passed[index]->getHandle();
325 }
326
327 *numConfig = index;
328 }
329 else
330 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000331 *numConfig = passed.size();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000332 }
333
334 return true;
335}
336
337const egl::Config *ConfigSet::get(EGLConfig configHandle)
338{
339 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
340 {
341 if (config->getHandle() == configHandle)
342 {
343 return &(*config);
344 }
345 }
346
347 return NULL;
348}
349}