blob: 0b47d55e2cf448004179aa0456e82d27ccedd298 [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;
Geoff Langfe28ca02013-06-04 10:10:48 -040042 case GL_BGR5_A1_ANGLEX:
43 mBufferSize = 16;
44 mRedSize = 5;
45 mGreenSize = 5;
46 mBlueSize = 5;
47 mAlphaSize = 1;
48 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000049 case GL_RGBA8_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000050 mBufferSize = 32;
51 mRedSize = 8;
52 mGreenSize = 8;
53 mBlueSize = 8;
54 mAlphaSize = 8;
jbauman@chromium.orgae345802011-03-30 22:04:25 +000055 mBindToTextureRGBA = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000056 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000057 case GL_RGB565:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000058 mBufferSize = 16;
59 mRedSize = 5;
60 mGreenSize = 6;
61 mBlueSize = 5;
62 mAlphaSize = 0;
63 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000064 case GL_RGB8_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000065 mBufferSize = 32;
66 mRedSize = 8;
67 mGreenSize = 8;
68 mBlueSize = 8;
69 mAlphaSize = 0;
jbauman@chromium.orgae345802011-03-30 22:04:25 +000070 mBindToTextureRGB = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000071 break;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000072 case GL_BGRA8_EXT:
73 mBufferSize = 32;
74 mRedSize = 8;
75 mGreenSize = 8;
76 mBlueSize = 8;
77 mAlphaSize = 8;
78 mBindToTextureRGBA = true;
79 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000080 default:
81 UNREACHABLE(); // Other formats should not be valid
82 }
83
84 mLuminanceSize = 0;
85 mAlphaMaskSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000086 mColorBufferType = EGL_RGB_BUFFER;
daniel@transgaming.com3281f972012-10-31 18:38:51 +000087 mConfigCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000088 mConfigID = 0;
89 mConformant = EGL_OPENGL_ES2_BIT;
90
daniel@transgaming.com3281f972012-10-31 18:38:51 +000091 switch (desc.depthStencilFormat)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092 {
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000093 case GL_NONE:
daniel@transgaming.coma114c272011-04-22 04:18:50 +000094 mDepthSize = 0;
95 mStencilSize = 0;
96 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000097 case GL_DEPTH_COMPONENT32_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000098 mDepthSize = 32;
99 mStencilSize = 0;
100 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +0000101 case GL_DEPTH24_STENCIL8_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000102 mDepthSize = 24;
103 mStencilSize = 8;
104 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +0000105 case GL_DEPTH_COMPONENT24_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000106 mDepthSize = 24;
107 mStencilSize = 0;
108 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +0000109 case GL_DEPTH_COMPONENT16:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000110 mDepthSize = 16;
111 mStencilSize = 0;
112 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113 default:
114 UNREACHABLE();
115 }
116
117 mLevel = 0;
118 mMatchNativePixmap = EGL_NONE;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000119 mMaxPBufferWidth = texWidth;
120 mMaxPBufferHeight = texHeight;
121 mMaxPBufferPixels = texWidth*texHeight;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000122 mMaxSwapInterval = maxInterval;
123 mMinSwapInterval = minInterval;
124 mNativeRenderable = EGL_FALSE;
125 mNativeVisualID = 0;
126 mNativeVisualType = 0;
127 mRenderableType = EGL_OPENGL_ES2_BIT;
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000128 mSampleBuffers = desc.multiSample ? 1 : 0;
129 mSamples = desc.multiSample;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000130 mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
131 mTransparentType = EGL_NONE;
132 mTransparentRedValue = 0;
133 mTransparentGreenValue = 0;
134 mTransparentBlueValue = 0;
shannon.woods%transgaming.com@gtempaccount.comdcf33d52013-04-13 03:33:11 +0000135
136 if (desc.es3Capable)
137 {
138 mRenderableType |= EGL_OPENGL_ES3_BIT_KHR;
139 mConformant |= EGL_OPENGL_ES3_BIT_KHR;
140 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000141}
142
143EGLConfig Config::getHandle() const
144{
145 return (EGLConfig)(size_t)mConfigID;
146}
147
148SortConfig::SortConfig(const EGLint *attribList)
149 : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
150{
151 scanForWantedComponents(attribList);
152}
153
154void SortConfig::scanForWantedComponents(const EGLint *attribList)
155{
156 // [EGL] section 3.4.1 page 24
157 // Sorting rule #3: by larger total number of color bits, not considering
158 // components that are 0 or don't-care.
159 for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
160 {
161 if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
162 {
163 switch (attr[0])
164 {
165 case EGL_RED_SIZE: mWantRed = true; break;
166 case EGL_GREEN_SIZE: mWantGreen = true; break;
167 case EGL_BLUE_SIZE: mWantBlue = true; break;
168 case EGL_ALPHA_SIZE: mWantAlpha = true; break;
169 case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
170 }
171 }
172 }
173}
174
175EGLint SortConfig::wantedComponentsSize(const Config &config) const
176{
177 EGLint total = 0;
178
179 if (mWantRed) total += config.mRedSize;
180 if (mWantGreen) total += config.mGreenSize;
181 if (mWantBlue) total += config.mBlueSize;
182 if (mWantAlpha) total += config.mAlphaSize;
183 if (mWantLuminance) total += config.mLuminanceSize;
184
185 return total;
186}
187
188bool SortConfig::operator()(const Config *x, const Config *y) const
189{
190 return (*this)(*x, *y);
191}
192
193bool SortConfig::operator()(const Config &x, const Config &y) const
194{
195 #define SORT(attribute) \
196 if (x.attribute != y.attribute) \
197 { \
198 return x.attribute < y.attribute; \
199 }
200
201 META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
202 SORT(mConfigCaveat);
203
204 META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
205 SORT(mColorBufferType);
206
207 // By larger total number of color bits, only considering those that are requested to be > 0.
208 EGLint xComponentsSize = wantedComponentsSize(x);
209 EGLint yComponentsSize = wantedComponentsSize(y);
210 if (xComponentsSize != yComponentsSize)
211 {
212 return xComponentsSize > yComponentsSize;
213 }
214
215 SORT(mBufferSize);
216 SORT(mSampleBuffers);
217 SORT(mSamples);
218 SORT(mDepthSize);
219 SORT(mStencilSize);
220 SORT(mAlphaMaskSize);
221 SORT(mNativeVisualType);
222 SORT(mConfigID);
223
224 #undef SORT
225
226 return false;
227}
228
229// We'd like to use SortConfig to also eliminate duplicate configs.
230// This works as long as we never have two configs with different per-RGB-component layouts,
231// but the same total.
232// 5551 and 565 are different because R+G+B is different.
233// 5551 and 555 are different because bufferSize is different.
234const EGLint ConfigSet::mSortAttribs[] =
235{
236 EGL_RED_SIZE, 1,
237 EGL_GREEN_SIZE, 1,
238 EGL_BLUE_SIZE, 1,
239 EGL_LUMINANCE_SIZE, 1,
240 // BUT NOT ALPHA
241 EGL_NONE
242};
243
244ConfigSet::ConfigSet()
245 : mSet(SortConfig(mSortAttribs))
246{
247}
248
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +0000249void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250{
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000251 Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252 mSet.insert(config);
253}
254
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255size_t ConfigSet::size() const
256{
257 return mSet.size();
258}
259
260bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
261{
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000262 vector<const Config*> passed;
263 passed.reserve(mSet.size());
264
265 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000267 bool match = true;
268 const EGLint *attribute = attribList;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000270 while (attribute[0] != EGL_NONE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000271 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000272 switch (attribute[0])
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000273 {
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000274 case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
275 case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
276 case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
277 case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
278 case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
279 case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
280 case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000281 case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000282 case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
283 case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000284 case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000285 case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
286 case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
287 case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
288 case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000289 case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000290 case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
291 case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
292 case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000293 case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean) attribute[1]; break;
294 case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000295 case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
296 case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
297 case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
298 case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
apatrick@chromium.org9c3a3932012-01-30 20:03:32 +0000299 case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum) attribute[1]; break;
daniel@transgaming.com178adff2010-05-18 18:52:04 +0000300 case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
301 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
302 case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000303 case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
304 case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
305 case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000306 default:
307 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308 }
309
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000310 if (!match)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000311 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000312 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000313 }
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000314
315 attribute += 2;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000316 }
317
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000318 if (match)
319 {
320 passed.push_back(&*config);
321 }
322 }
323
324 if (configs)
325 {
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000326 sort(passed.begin(), passed.end(), SortConfig(attribList));
327
328 EGLint index;
329 for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
330 {
331 configs[index] = passed[index]->getHandle();
332 }
333
334 *numConfig = index;
335 }
336 else
337 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000338 *numConfig = passed.size();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339 }
340
341 return true;
342}
343
344const egl::Config *ConfigSet::get(EGLConfig configHandle)
345{
346 for (Iterator config = mSet.begin(); config != mSet.end(); config++)
347 {
348 if (config->getHandle() == configHandle)
349 {
350 return &(*config);
351 }
352 }
353
354 return NULL;
355}
356}