blob: 18019ee3975f2228715317a844f235d08b2618e5 [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
Jamie Madillf51639a2014-06-25 16:04:57 -040017#include "angle_gl.h"
shannon.woods%transgaming.com@gtempaccount.comdcf33d52013-04-13 03:33:11 +000018#include <EGL/eglext.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)
Geoff Lang6812a552015-01-06 17:26:42 -050063{
64}
65
Jamie Madillacf2f3a2017-11-21 19:22:44 -050066Config::~Config()
67{
68}
69
70Config::Config(const Config &other) = default;
71
72Config &Config::operator=(const Config &other) = default;
73
74ConfigSet::ConfigSet() = default;
75
76ConfigSet::ConfigSet(const ConfigSet &other) = default;
77
78ConfigSet &ConfigSet::operator=(const ConfigSet &other) = default;
79
80ConfigSet::~ConfigSet() = default;
81
Geoff Lang6812a552015-01-06 17:26:42 -050082EGLint ConfigSet::add(const Config &config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000083{
Geoff Lang6812a552015-01-06 17:26:42 -050084 // 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 -070085 EGLint id = static_cast<EGLint>(mConfigs.size()) + 1;
Geoff Lang6812a552015-01-06 17:26:42 -050086
87 Config copyConfig(config);
Geoff Langc223dc62015-01-09 13:10:01 -050088 copyConfig.configID = id;
Geoff Lang6812a552015-01-06 17:26:42 -050089 mConfigs.insert(std::make_pair(id, copyConfig));
90
91 return id;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092}
93
Geoff Lang6812a552015-01-06 17:26:42 -050094const Config &ConfigSet::get(EGLint id) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095{
Jamie Madill73edef02015-02-17 18:58:21 -050096 ASSERT(mConfigs.find(id) != mConfigs.end());
97 return mConfigs.find(id)->second;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000098}
99
Geoff Lang6812a552015-01-06 17:26:42 -0500100void ConfigSet::clear()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101{
Geoff Lang6812a552015-01-06 17:26:42 -0500102 mConfigs.clear();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000103}
104
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105size_t ConfigSet::size() const
106{
Geoff Lang6812a552015-01-06 17:26:42 -0500107 return mConfigs.size();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000108}
109
Geoff Lang6812a552015-01-06 17:26:42 -0500110bool ConfigSet::contains(const Config *config) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111{
Geoff Lang6812a552015-01-06 17:26:42 -0500112 for (auto i = mConfigs.begin(); i != mConfigs.end(); i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113 {
Geoff Lang6812a552015-01-06 17:26:42 -0500114 const Config &item = i->second;
115 if (config == &item)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000116 {
Geoff Lang6812a552015-01-06 17:26:42 -0500117 return true;
118 }
119 }
120
121 return false;
122}
123
124// Function object used by STL sorting routines for ordering Configs according to [EGL 1.5] section 3.4.1.2 page 28.
125class ConfigSorter
126{
127 public:
128 explicit ConfigSorter(const AttributeMap &attributeMap)
Jamie Madill56596192015-03-19 10:23:13 -0400129 : mWantRed(false),
130 mWantGreen(false),
131 mWantBlue(false),
132 mWantAlpha(false),
133 mWantLuminance(false)
Geoff Lang6812a552015-01-06 17:26:42 -0500134 {
135 scanForWantedComponents(attributeMap);
136 }
137
138 bool operator()(const Config *x, const Config *y) const
139 {
140 return (*this)(*x, *y);
141 }
142
143 bool operator()(const Config &x, const Config &y) const
144 {
145 #define SORT(attribute) \
146 if (x.attribute != y.attribute) \
147 { \
148 return x.attribute < y.attribute; \
149 }
150
Geoff Langd4475812015-03-18 10:53:05 -0400151 static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "Unexpected EGL enum value.");
Geoff Langc223dc62015-01-09 13:10:01 -0500152 SORT(configCaveat);
Geoff Lang6812a552015-01-06 17:26:42 -0500153
Geoff Langc5a2a172017-01-13 15:55:07 -0500154 static_assert(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT < EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
155 "Unexpected order of EGL enums.");
156 SORT(colorComponentType);
157
Geoff Langd4475812015-03-18 10:53:05 -0400158 static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "Unexpected EGL enum value.");
Geoff Langc223dc62015-01-09 13:10:01 -0500159 SORT(colorBufferType);
Geoff Lang6812a552015-01-06 17:26:42 -0500160
161 // By larger total number of color bits, only considering those that are requested to be > 0.
162 EGLint xComponentsSize = wantedComponentsSize(x);
163 EGLint yComponentsSize = wantedComponentsSize(y);
164 if (xComponentsSize != yComponentsSize)
165 {
166 return xComponentsSize > yComponentsSize;
167 }
168
Geoff Langc223dc62015-01-09 13:10:01 -0500169 SORT(bufferSize);
170 SORT(sampleBuffers);
171 SORT(samples);
172 SORT(depthSize);
173 SORT(stencilSize);
174 SORT(alphaMaskSize);
175 SORT(nativeVisualType);
176 SORT(configID);
Geoff Lang6812a552015-01-06 17:26:42 -0500177
178 #undef SORT
179
180 return false;
181 }
182
183 private:
Geoff Lang2648d922017-06-15 11:36:47 -0400184 static bool wantsComponent(const AttributeMap &attributeMap, EGLAttrib component)
Geoff Lang6812a552015-01-06 17:26:42 -0500185 {
186 // [EGL 1.5] section 3.4.1.2 page 30
187 // Sorting rule #3: by larger total number of color bits, not considering
188 // components that are 0 or don't-care.
Geoff Lang2648d922017-06-15 11:36:47 -0400189 EGLAttrib value = attributeMap.get(component, 0);
190 return value != 0 && value != EGL_DONT_CARE;
191 }
192
193 void scanForWantedComponents(const AttributeMap &attributeMap)
194 {
195 mWantRed = wantsComponent(attributeMap, EGL_RED_SIZE);
196 mWantGreen = wantsComponent(attributeMap, EGL_GREEN_SIZE);
197 mWantBlue = wantsComponent(attributeMap, EGL_BLUE_SIZE);
198 mWantAlpha = wantsComponent(attributeMap, EGL_ALPHA_SIZE);
199 mWantLuminance = wantsComponent(attributeMap, EGL_LUMINANCE_SIZE);
Geoff Lang6812a552015-01-06 17:26:42 -0500200 }
201
202 EGLint wantedComponentsSize(const Config &config) const
203 {
204 EGLint total = 0;
205
Geoff Langc223dc62015-01-09 13:10:01 -0500206 if (mWantRed) total += config.redSize;
207 if (mWantGreen) total += config.greenSize;
208 if (mWantBlue) total += config.blueSize;
209 if (mWantAlpha) total += config.alphaSize;
210 if (mWantLuminance) total += config.luminanceSize;
Geoff Lang6812a552015-01-06 17:26:42 -0500211
212 return total;
213 }
214
215 bool mWantRed;
216 bool mWantGreen;
217 bool mWantBlue;
218 bool mWantAlpha;
219 bool mWantLuminance;
220};
221
222std::vector<const Config*> ConfigSet::filter(const AttributeMap &attributeMap) const
223{
224 std::vector<const Config*> result;
225 result.reserve(mConfigs.size());
226
227 for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++)
228 {
229 const Config &config = configIter->second;
230 bool match = true;
231
232 for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
233 {
Ian Ewellec2c0c52016-04-05 13:46:26 -0400234 EGLAttrib attributeKey = attribIter->first;
235 EGLAttrib attributeValue = attribIter->second;
Geoff Lang6812a552015-01-06 17:26:42 -0500236
Geoff Lang638c7272017-06-13 15:50:26 -0400237 if (attributeValue == EGL_DONT_CARE)
238 {
239 continue;
240 }
241
Geoff Lang6812a552015-01-06 17:26:42 -0500242 switch (attributeKey)
243 {
Geoff Langc223dc62015-01-09 13:10:01 -0500244 case EGL_BUFFER_SIZE: match = config.bufferSize >= attributeValue; break;
245 case EGL_ALPHA_SIZE: match = config.alphaSize >= attributeValue; break;
246 case EGL_BLUE_SIZE: match = config.blueSize >= attributeValue; break;
247 case EGL_GREEN_SIZE: match = config.greenSize >= attributeValue; break;
248 case EGL_RED_SIZE: match = config.redSize >= attributeValue; break;
249 case EGL_DEPTH_SIZE: match = config.depthSize >= attributeValue; break;
250 case EGL_STENCIL_SIZE: match = config.stencilSize >= attributeValue; break;
251 case EGL_CONFIG_CAVEAT: match = config.configCaveat == (EGLenum)attributeValue; break;
252 case EGL_CONFIG_ID: match = config.configID == attributeValue; break;
253 case EGL_LEVEL: match = config.level >= attributeValue; break;
254 case EGL_NATIVE_RENDERABLE: match = config.nativeRenderable == (EGLBoolean)attributeValue; break;
255 case EGL_NATIVE_VISUAL_TYPE: match = config.nativeVisualType == attributeValue; break;
256 case EGL_SAMPLES: match = config.samples >= attributeValue; break;
257 case EGL_SAMPLE_BUFFERS: match = config.sampleBuffers >= attributeValue; break;
258 case EGL_SURFACE_TYPE: match = (config.surfaceType & attributeValue) == attributeValue; break;
259 case EGL_TRANSPARENT_TYPE: match = config.transparentType == (EGLenum)attributeValue; break;
260 case EGL_TRANSPARENT_BLUE_VALUE: match = config.transparentBlueValue == attributeValue; break;
261 case EGL_TRANSPARENT_GREEN_VALUE: match = config.transparentGreenValue == attributeValue; break;
262 case EGL_TRANSPARENT_RED_VALUE: match = config.transparentRedValue == attributeValue; break;
263 case EGL_BIND_TO_TEXTURE_RGB: match = config.bindToTextureRGB == (EGLBoolean)attributeValue; break;
264 case EGL_BIND_TO_TEXTURE_RGBA: match = config.bindToTextureRGBA == (EGLBoolean)attributeValue; break;
265 case EGL_MIN_SWAP_INTERVAL: match = config.minSwapInterval == attributeValue; break;
266 case EGL_MAX_SWAP_INTERVAL: match = config.maxSwapInterval == attributeValue; break;
267 case EGL_LUMINANCE_SIZE: match = config.luminanceSize >= attributeValue; break;
268 case EGL_ALPHA_MASK_SIZE: match = config.alphaMaskSize >= attributeValue; break;
269 case EGL_COLOR_BUFFER_TYPE: match = config.colorBufferType == (EGLenum)attributeValue; break;
270 case EGL_RENDERABLE_TYPE: match = (config.renderableType & attributeValue) == attributeValue; break;
271 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
272 case EGL_CONFORMANT: match = (config.conformant & attributeValue) == attributeValue; break;
273 case EGL_MAX_PBUFFER_WIDTH: match = config.maxPBufferWidth >= attributeValue; break;
274 case EGL_MAX_PBUFFER_HEIGHT: match = config.maxPBufferHeight >= attributeValue; break;
275 case EGL_MAX_PBUFFER_PIXELS: match = config.maxPBufferPixels >= attributeValue; break;
Geoff Lang7f448b52015-12-16 13:31:57 -0500276 case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
277 match = config.optimalOrientation == attributeValue;
278 break;
Geoff Langc5a2a172017-01-13 15:55:07 -0500279 case EGL_COLOR_COMPONENT_TYPE_EXT:
280 match = config.colorComponentType == static_cast<EGLenum>(attributeValue);
281 break;
Geoff Lang6812a552015-01-06 17:26:42 -0500282 default: UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000283 }
284
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000285 if (!match)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000286 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000287 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000288 }
289 }
290
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000291 if (match)
292 {
Geoff Lang6812a552015-01-06 17:26:42 -0500293 result.push_back(&config);
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000294 }
295 }
296
Geoff Lang6812a552015-01-06 17:26:42 -0500297 // Sort the result
298 std::sort(result.begin(), result.end(), ConfigSorter(attributeMap));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000299
Geoff Lang6812a552015-01-06 17:26:42 -0500300 return result;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000301}
302
Geoff Lang2aaa7b42018-01-12 17:17:27 -0500303ConfigSet::ConfigMap::iterator ConfigSet::begin()
304{
305 return mConfigs.begin();
306}
307
308ConfigSet::ConfigMap::iterator ConfigSet::end()
309{
310 return mConfigs.end();
311}
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312}