blob: 316e7f9ad7dce5b3f945d66597d54ebe44678d42 [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.
Geoff Lang6812a552015-01-06 17:26:42 -05009// [EGL 1.5] section 3.4 page 19.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000010
Geoff Lang2b5420c2014-11-19 14:20:15 -050011#include "libANGLE/Config.h"
Geoff Lang6812a552015-01-06 17:26:42 -050012#include "libANGLE/AttributeMap.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000013
14#include <algorithm>
15#include <vector>
16
shannon.woods%transgaming.com@gtempaccount.comdcf33d52013-04-13 03:33:11 +000017#include <EGL/eglext.h>
Jamie Madillb980c562018-11-27 11:34:27 -050018#include "angle_gl.h"
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000019
alokp@chromium.orgea0e1af2010-03-22 19:33:14 +000020#include "common/debug.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000021
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000022namespace egl
23{
Geoff Lang6812a552015-01-06 17:26:42 -050024
25Config::Config()
Geoff Langf21a1082015-01-09 14:41:27 -050026 : renderTargetFormat(GL_NONE),
27 depthStencilFormat(GL_NONE),
28 bufferSize(0),
29 redSize(0),
30 greenSize(0),
31 blueSize(0),
32 luminanceSize(0),
33 alphaSize(0),
34 alphaMaskSize(0),
35 bindToTextureRGB(EGL_FALSE),
36 bindToTextureRGBA(EGL_FALSE),
37 colorBufferType(EGL_NONE),
38 configCaveat(EGL_NONE),
39 configID(0),
40 conformant(0),
41 depthSize(0),
42 level(0),
43 matchNativePixmap(EGL_FALSE),
44 maxPBufferWidth(0),
45 maxPBufferHeight(0),
46 maxPBufferPixels(0),
47 maxSwapInterval(0),
48 minSwapInterval(0),
49 nativeRenderable(EGL_FALSE),
50 nativeVisualID(0),
51 nativeVisualType(0),
52 renderableType(0),
53 sampleBuffers(0),
54 samples(0),
55 stencilSize(0),
56 surfaceType(0),
57 transparentType(EGL_NONE),
58 transparentRedValue(0),
59 transparentGreenValue(0),
Geoff Lang7f448b52015-12-16 13:31:57 -050060 transparentBlueValue(0),
Geoff Langc5a2a172017-01-13 15:55:07 -050061 optimalOrientation(0),
62 colorComponentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT)
Jamie Madillb980c562018-11-27 11:34:27 -050063{}
Geoff Lang6812a552015-01-06 17:26:42 -050064
Jamie Madillb980c562018-11-27 11:34:27 -050065Config::~Config() {}
Jamie Madillacf2f3a2017-11-21 19:22:44 -050066
67Config::Config(const Config &other) = default;
68
69Config &Config::operator=(const Config &other) = default;
70
71ConfigSet::ConfigSet() = default;
72
73ConfigSet::ConfigSet(const ConfigSet &other) = default;
74
75ConfigSet &ConfigSet::operator=(const ConfigSet &other) = default;
76
77ConfigSet::~ConfigSet() = default;
78
Geoff Lang6812a552015-01-06 17:26:42 -050079EGLint ConfigSet::add(const Config &config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000080{
Geoff Lang6812a552015-01-06 17:26:42 -050081 // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4)
Cooper Partin4d61f7e2015-08-12 10:56:50 -070082 EGLint id = static_cast<EGLint>(mConfigs.size()) + 1;
Geoff Lang6812a552015-01-06 17:26:42 -050083
84 Config copyConfig(config);
Geoff Langc223dc62015-01-09 13:10:01 -050085 copyConfig.configID = id;
Geoff Lang6812a552015-01-06 17:26:42 -050086 mConfigs.insert(std::make_pair(id, copyConfig));
87
88 return id;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000089}
90
Geoff Lang6812a552015-01-06 17:26:42 -050091const Config &ConfigSet::get(EGLint id) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092{
Jamie Madill73edef02015-02-17 18:58:21 -050093 ASSERT(mConfigs.find(id) != mConfigs.end());
94 return mConfigs.find(id)->second;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095}
96
Geoff Lang6812a552015-01-06 17:26:42 -050097void ConfigSet::clear()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000098{
Geoff Lang6812a552015-01-06 17:26:42 -050099 mConfigs.clear();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000100}
101
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000102size_t ConfigSet::size() const
103{
Geoff Lang6812a552015-01-06 17:26:42 -0500104 return mConfigs.size();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105}
106
Geoff Lang6812a552015-01-06 17:26:42 -0500107bool ConfigSet::contains(const Config *config) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000108{
Geoff Lang6812a552015-01-06 17:26:42 -0500109 for (auto i = mConfigs.begin(); i != mConfigs.end(); i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000110 {
Geoff Lang6812a552015-01-06 17:26:42 -0500111 const Config &item = i->second;
112 if (config == &item)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113 {
Geoff Lang6812a552015-01-06 17:26:42 -0500114 return true;
115 }
116 }
117
118 return false;
119}
120
Jamie Madillb980c562018-11-27 11:34:27 -0500121// Function object used by STL sorting routines for ordering Configs according to [EGL 1.5]
122// section 3.4.1.2 page 28.
Geoff Lang6812a552015-01-06 17:26:42 -0500123class ConfigSorter
124{
125 public:
126 explicit ConfigSorter(const AttributeMap &attributeMap)
Jamie Madill56596192015-03-19 10:23:13 -0400127 : mWantRed(false),
128 mWantGreen(false),
129 mWantBlue(false),
130 mWantAlpha(false),
131 mWantLuminance(false)
Geoff Lang6812a552015-01-06 17:26:42 -0500132 {
133 scanForWantedComponents(attributeMap);
134 }
135
Jamie Madillb980c562018-11-27 11:34:27 -0500136 bool operator()(const Config *x, const Config *y) const { return (*this)(*x, *y); }
Geoff Lang6812a552015-01-06 17:26:42 -0500137
138 bool operator()(const Config &x, const Config &y) const
139 {
Jamie Madillc09ae152019-02-01 14:16:32 -0500140#define SORT(attribute) \
141 do \
142 { \
143 if (x.attribute != y.attribute) \
144 return x.attribute < y.attribute; \
145 } while (0)
Geoff Lang6812a552015-01-06 17:26:42 -0500146
Jamie Madillb980c562018-11-27 11:34:27 -0500147 static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG,
148 "Unexpected EGL enum value.");
Geoff Langc223dc62015-01-09 13:10:01 -0500149 SORT(configCaveat);
Geoff Lang6812a552015-01-06 17:26:42 -0500150
Geoff Langc5a2a172017-01-13 15:55:07 -0500151 static_assert(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT < EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
152 "Unexpected order of EGL enums.");
153 SORT(colorComponentType);
154
Geoff Langd4475812015-03-18 10:53:05 -0400155 static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "Unexpected EGL enum value.");
Geoff Langc223dc62015-01-09 13:10:01 -0500156 SORT(colorBufferType);
Geoff Lang6812a552015-01-06 17:26:42 -0500157
Jamie Madillb980c562018-11-27 11:34:27 -0500158 // By larger total number of color bits, only considering those that are requested to be >
159 // 0.
Geoff Lang6812a552015-01-06 17:26:42 -0500160 EGLint xComponentsSize = wantedComponentsSize(x);
161 EGLint yComponentsSize = wantedComponentsSize(y);
162 if (xComponentsSize != yComponentsSize)
163 {
164 return xComponentsSize > yComponentsSize;
165 }
166
Geoff Langc223dc62015-01-09 13:10:01 -0500167 SORT(bufferSize);
168 SORT(sampleBuffers);
169 SORT(samples);
170 SORT(depthSize);
171 SORT(stencilSize);
172 SORT(alphaMaskSize);
173 SORT(nativeVisualType);
174 SORT(configID);
Geoff Lang6812a552015-01-06 17:26:42 -0500175
Jamie Madillb980c562018-11-27 11:34:27 -0500176#undef SORT
Geoff Lang6812a552015-01-06 17:26:42 -0500177
178 return false;
179 }
180
181 private:
Geoff Lang2648d922017-06-15 11:36:47 -0400182 static bool wantsComponent(const AttributeMap &attributeMap, EGLAttrib component)
Geoff Lang6812a552015-01-06 17:26:42 -0500183 {
184 // [EGL 1.5] section 3.4.1.2 page 30
185 // Sorting rule #3: by larger total number of color bits, not considering
186 // components that are 0 or don't-care.
Geoff Lang2648d922017-06-15 11:36:47 -0400187 EGLAttrib value = attributeMap.get(component, 0);
188 return value != 0 && value != EGL_DONT_CARE;
189 }
190
191 void scanForWantedComponents(const AttributeMap &attributeMap)
192 {
193 mWantRed = wantsComponent(attributeMap, EGL_RED_SIZE);
194 mWantGreen = wantsComponent(attributeMap, EGL_GREEN_SIZE);
195 mWantBlue = wantsComponent(attributeMap, EGL_BLUE_SIZE);
196 mWantAlpha = wantsComponent(attributeMap, EGL_ALPHA_SIZE);
197 mWantLuminance = wantsComponent(attributeMap, EGL_LUMINANCE_SIZE);
Geoff Lang6812a552015-01-06 17:26:42 -0500198 }
199
200 EGLint wantedComponentsSize(const Config &config) const
201 {
202 EGLint total = 0;
203
Jamie Madillb980c562018-11-27 11:34:27 -0500204 if (mWantRed)
205 total += config.redSize;
206 if (mWantGreen)
207 total += config.greenSize;
208 if (mWantBlue)
209 total += config.blueSize;
210 if (mWantAlpha)
211 total += config.alphaSize;
212 if (mWantLuminance)
213 total += config.luminanceSize;
Geoff Lang6812a552015-01-06 17:26:42 -0500214
215 return total;
216 }
217
218 bool mWantRed;
219 bool mWantGreen;
220 bool mWantBlue;
221 bool mWantAlpha;
222 bool mWantLuminance;
223};
224
Jamie Madillb980c562018-11-27 11:34:27 -0500225std::vector<const Config *> ConfigSet::filter(const AttributeMap &attributeMap) const
Geoff Lang6812a552015-01-06 17:26:42 -0500226{
Jamie Madillb980c562018-11-27 11:34:27 -0500227 std::vector<const Config *> result;
Geoff Lang6812a552015-01-06 17:26:42 -0500228 result.reserve(mConfigs.size());
229
230 for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++)
231 {
232 const Config &config = configIter->second;
Jamie Madillb980c562018-11-27 11:34:27 -0500233 bool match = true;
Geoff Lang6812a552015-01-06 17:26:42 -0500234
235 for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
236 {
Ian Ewellec2c0c52016-04-05 13:46:26 -0400237 EGLAttrib attributeKey = attribIter->first;
238 EGLAttrib attributeValue = attribIter->second;
Geoff Lang6812a552015-01-06 17:26:42 -0500239
Geoff Lang638c7272017-06-13 15:50:26 -0400240 if (attributeValue == EGL_DONT_CARE)
241 {
242 continue;
243 }
244
Geoff Lang6812a552015-01-06 17:26:42 -0500245 switch (attributeKey)
246 {
Jamie Madillb980c562018-11-27 11:34:27 -0500247 case EGL_BUFFER_SIZE:
248 match = config.bufferSize >= attributeValue;
249 break;
250 case EGL_ALPHA_SIZE:
251 match = config.alphaSize >= attributeValue;
252 break;
253 case EGL_BLUE_SIZE:
254 match = config.blueSize >= attributeValue;
255 break;
256 case EGL_GREEN_SIZE:
257 match = config.greenSize >= attributeValue;
258 break;
259 case EGL_RED_SIZE:
260 match = config.redSize >= attributeValue;
261 break;
262 case EGL_DEPTH_SIZE:
263 match = config.depthSize >= attributeValue;
264 break;
265 case EGL_STENCIL_SIZE:
266 match = config.stencilSize >= attributeValue;
267 break;
268 case EGL_CONFIG_CAVEAT:
269 match = config.configCaveat == (EGLenum)attributeValue;
270 break;
271 case EGL_CONFIG_ID:
272 match = config.configID == attributeValue;
273 break;
274 case EGL_LEVEL:
275 match = config.level >= attributeValue;
276 break;
277 case EGL_NATIVE_RENDERABLE:
278 match = config.nativeRenderable == (EGLBoolean)attributeValue;
279 break;
280 case EGL_NATIVE_VISUAL_TYPE:
281 match = config.nativeVisualType == attributeValue;
282 break;
283 case EGL_SAMPLES:
284 match = config.samples >= attributeValue;
285 break;
286 case EGL_SAMPLE_BUFFERS:
287 match = config.sampleBuffers >= attributeValue;
288 break;
289 case EGL_SURFACE_TYPE:
290 match = (config.surfaceType & attributeValue) == attributeValue;
291 break;
292 case EGL_TRANSPARENT_TYPE:
293 match = config.transparentType == (EGLenum)attributeValue;
294 break;
295 case EGL_TRANSPARENT_BLUE_VALUE:
296 match = config.transparentBlueValue == attributeValue;
297 break;
298 case EGL_TRANSPARENT_GREEN_VALUE:
299 match = config.transparentGreenValue == attributeValue;
300 break;
301 case EGL_TRANSPARENT_RED_VALUE:
302 match = config.transparentRedValue == attributeValue;
303 break;
304 case EGL_BIND_TO_TEXTURE_RGB:
305 match = config.bindToTextureRGB == (EGLBoolean)attributeValue;
306 break;
307 case EGL_BIND_TO_TEXTURE_RGBA:
308 match = config.bindToTextureRGBA == (EGLBoolean)attributeValue;
309 break;
310 case EGL_MIN_SWAP_INTERVAL:
311 match = config.minSwapInterval == attributeValue;
312 break;
313 case EGL_MAX_SWAP_INTERVAL:
314 match = config.maxSwapInterval == attributeValue;
315 break;
316 case EGL_LUMINANCE_SIZE:
317 match = config.luminanceSize >= attributeValue;
318 break;
319 case EGL_ALPHA_MASK_SIZE:
320 match = config.alphaMaskSize >= attributeValue;
321 break;
322 case EGL_COLOR_BUFFER_TYPE:
323 match = config.colorBufferType == (EGLenum)attributeValue;
324 break;
325 case EGL_RENDERABLE_TYPE:
326 match = (config.renderableType & attributeValue) == attributeValue;
327 break;
328 case EGL_MATCH_NATIVE_PIXMAP:
329 match = false;
330 UNIMPLEMENTED();
331 break;
332 case EGL_CONFORMANT:
333 match = (config.conformant & attributeValue) == attributeValue;
334 break;
335 case EGL_MAX_PBUFFER_WIDTH:
336 match = config.maxPBufferWidth >= attributeValue;
337 break;
338 case EGL_MAX_PBUFFER_HEIGHT:
339 match = config.maxPBufferHeight >= attributeValue;
340 break;
341 case EGL_MAX_PBUFFER_PIXELS:
342 match = config.maxPBufferPixels >= attributeValue;
343 break;
344 case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
345 match = config.optimalOrientation == attributeValue;
346 break;
347 case EGL_COLOR_COMPONENT_TYPE_EXT:
348 match = config.colorComponentType == static_cast<EGLenum>(attributeValue);
349 break;
350 default:
351 UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000352 }
353
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000354 if (!match)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000355 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000356 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000357 }
358 }
359
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000360 if (match)
361 {
Geoff Lang6812a552015-01-06 17:26:42 -0500362 result.push_back(&config);
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000363 }
364 }
365
Geoff Lang6812a552015-01-06 17:26:42 -0500366 // Sort the result
367 std::sort(result.begin(), result.end(), ConfigSorter(attributeMap));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000368
Geoff Lang6812a552015-01-06 17:26:42 -0500369 return result;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000370}
371
Geoff Lang2aaa7b42018-01-12 17:17:27 -0500372ConfigSet::ConfigMap::iterator ConfigSet::begin()
373{
374 return mConfigs.begin();
375}
376
377ConfigSet::ConfigMap::iterator ConfigSet::end()
378{
379 return mConfigs.end();
380}
Jamie Madillb980c562018-11-27 11:34:27 -0500381} // namespace egl