1 //
2 // Copyright 2002 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.5] section 3.4 page 19.
10
11 #include "libANGLE/Config.h"
12 #include "libANGLE/AttributeMap.h"
13
14 #include <algorithm>
15 #include <vector>
16
17 #include <EGL/eglext.h>
18 #include "angle_gl.h"
19
20 #include "common/debug.h"
21
22 namespace egl
23 {
24
Config()25 Config::Config()
26 : 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 bindToTextureTarget(EGL_TEXTURE_2D),
38 colorBufferType(EGL_RGB_BUFFER),
39 configCaveat(EGL_NONE),
40 configID(0),
41 conformant(0),
42 depthSize(0),
43 level(0),
44 matchNativePixmap(EGL_FALSE),
45 maxPBufferWidth(0),
46 maxPBufferHeight(0),
47 maxPBufferPixels(0),
48 maxSwapInterval(0),
49 minSwapInterval(0),
50 nativeRenderable(EGL_FALSE),
51 nativeVisualID(0),
52 nativeVisualType(0),
53 renderableType(0),
54 sampleBuffers(0),
55 samples(0),
56 stencilSize(0),
57 surfaceType(0),
58 transparentType(EGL_NONE),
59 transparentRedValue(0),
60 transparentGreenValue(0),
61 transparentBlueValue(0),
62 optimalOrientation(0),
63 colorComponentType(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT),
64 recordable(EGL_FALSE),
65 framebufferTarget(EGL_FALSE), // TODO: http://anglebug.com/4208
66 yInverted(EGL_FALSE)
67 {}
68
~Config()69 Config::~Config() {}
70
71 Config::Config(const Config &other) = default;
72
73 Config &Config::operator=(const Config &other) = default;
74
75 ConfigSet::ConfigSet() = default;
76
77 ConfigSet::ConfigSet(const ConfigSet &other) = default;
78
79 ConfigSet &ConfigSet::operator=(const ConfigSet &other) = default;
80
81 ConfigSet::~ConfigSet() = default;
82
add(const Config & config)83 EGLint ConfigSet::add(const Config &config)
84 {
85 // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4)
86 EGLint id = static_cast<EGLint>(mConfigs.size()) + 1;
87
88 Config copyConfig(config);
89 copyConfig.configID = id;
90 mConfigs.insert(std::make_pair(id, copyConfig));
91
92 return id;
93 }
94
get(EGLint id) const95 const Config &ConfigSet::get(EGLint id) const
96 {
97 ASSERT(mConfigs.find(id) != mConfigs.end());
98 return mConfigs.find(id)->second;
99 }
100
clear()101 void ConfigSet::clear()
102 {
103 mConfigs.clear();
104 }
105
size() const106 size_t ConfigSet::size() const
107 {
108 return mConfigs.size();
109 }
110
contains(const Config * config) const111 bool ConfigSet::contains(const Config *config) const
112 {
113 for (auto i = mConfigs.begin(); i != mConfigs.end(); i++)
114 {
115 const Config &item = i->second;
116 if (config == &item)
117 {
118 return true;
119 }
120 }
121
122 return false;
123 }
124
125 // Function object used by STL sorting routines for ordering Configs according to [EGL 1.5]
126 // section 3.4.1.2 page 28.
127 class ConfigSorter
128 {
129 public:
ConfigSorter(const AttributeMap & attributeMap)130 explicit ConfigSorter(const AttributeMap &attributeMap)
131 : mWantRed(false),
132 mWantGreen(false),
133 mWantBlue(false),
134 mWantAlpha(false),
135 mWantLuminance(false)
136 {
137 scanForWantedComponents(attributeMap);
138 }
139
operator ()(const Config * x,const Config * y) const140 bool operator()(const Config *x, const Config *y) const { return (*this)(*x, *y); }
141
operator ()(const Config & x,const Config & y) const142 bool operator()(const Config &x, const Config &y) const
143 {
144 #define SORT(attribute) \
145 do \
146 { \
147 if (x.attribute != y.attribute) \
148 return x.attribute < y.attribute; \
149 } while (0)
150
151 static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG,
152 "Unexpected EGL enum value.");
153 SORT(configCaveat);
154
155 static_assert(EGL_COLOR_COMPONENT_TYPE_FIXED_EXT < EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT,
156 "Unexpected order of EGL enums.");
157 SORT(colorComponentType);
158
159 static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "Unexpected EGL enum value.");
160 SORT(colorBufferType);
161
162 // By larger total number of color bits, only considering those that are requested to be >
163 // 0.
164 EGLint xComponentsSize = wantedComponentsSize(x);
165 EGLint yComponentsSize = wantedComponentsSize(y);
166 if (xComponentsSize != yComponentsSize)
167 {
168 return xComponentsSize > yComponentsSize;
169 }
170
171 SORT(bufferSize);
172 SORT(sampleBuffers);
173 SORT(samples);
174 SORT(depthSize);
175 SORT(stencilSize);
176 SORT(alphaMaskSize);
177 SORT(nativeVisualType);
178 SORT(configID);
179
180 #undef SORT
181
182 return false;
183 }
184
185 private:
wantsComponent(const AttributeMap & attributeMap,EGLAttrib component)186 static bool wantsComponent(const AttributeMap &attributeMap, EGLAttrib component)
187 {
188 // [EGL 1.5] section 3.4.1.2 page 30
189 // Sorting rule #3: by larger total number of color bits, not considering
190 // components that are 0 or don't-care.
191 EGLAttrib value = attributeMap.get(component, 0);
192 return value != 0 && value != EGL_DONT_CARE;
193 }
194
scanForWantedComponents(const AttributeMap & attributeMap)195 void scanForWantedComponents(const AttributeMap &attributeMap)
196 {
197 mWantRed = wantsComponent(attributeMap, EGL_RED_SIZE);
198 mWantGreen = wantsComponent(attributeMap, EGL_GREEN_SIZE);
199 mWantBlue = wantsComponent(attributeMap, EGL_BLUE_SIZE);
200 mWantAlpha = wantsComponent(attributeMap, EGL_ALPHA_SIZE);
201 mWantLuminance = wantsComponent(attributeMap, EGL_LUMINANCE_SIZE);
202 }
203
wantedComponentsSize(const Config & config) const204 EGLint wantedComponentsSize(const Config &config) const
205 {
206 EGLint total = 0;
207
208 if (mWantRed)
209 total += config.redSize;
210 if (mWantGreen)
211 total += config.greenSize;
212 if (mWantBlue)
213 total += config.blueSize;
214 if (mWantAlpha)
215 total += config.alphaSize;
216 if (mWantLuminance)
217 total += config.luminanceSize;
218
219 return total;
220 }
221
222 bool mWantRed;
223 bool mWantGreen;
224 bool mWantBlue;
225 bool mWantAlpha;
226 bool mWantLuminance;
227 };
228
filter(const AttributeMap & attributeMap) const229 std::vector<const Config *> ConfigSet::filter(const AttributeMap &attributeMap) const
230 {
231 std::vector<const Config *> result;
232 result.reserve(mConfigs.size());
233
234 for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++)
235 {
236 const Config &config = configIter->second;
237 bool match = true;
238
239 for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
240 {
241 EGLAttrib attributeKey = attribIter->first;
242 EGLAttrib attributeValue = attribIter->second;
243
244 if (attributeValue == EGL_DONT_CARE)
245 {
246 continue;
247 }
248
249 switch (attributeKey)
250 {
251 case EGL_BUFFER_SIZE:
252 match = config.bufferSize >= attributeValue;
253 break;
254 case EGL_ALPHA_SIZE:
255 match = config.alphaSize >= attributeValue;
256 break;
257 case EGL_BLUE_SIZE:
258 match = config.blueSize >= attributeValue;
259 break;
260 case EGL_GREEN_SIZE:
261 match = config.greenSize >= attributeValue;
262 break;
263 case EGL_RED_SIZE:
264 match = config.redSize >= attributeValue;
265 break;
266 case EGL_DEPTH_SIZE:
267 match = config.depthSize >= attributeValue;
268 break;
269 case EGL_STENCIL_SIZE:
270 match = config.stencilSize >= attributeValue;
271 break;
272 case EGL_CONFIG_CAVEAT:
273 match = config.configCaveat == static_cast<EGLenum>(attributeValue);
274 break;
275 case EGL_CONFIG_ID:
276 match = config.configID == attributeValue;
277 break;
278 case EGL_LEVEL:
279 match = config.level == attributeValue;
280 break;
281 case EGL_NATIVE_RENDERABLE:
282 match = config.nativeRenderable == static_cast<EGLBoolean>(attributeValue);
283 break;
284 case EGL_NATIVE_VISUAL_TYPE:
285 match = config.nativeVisualType == attributeValue;
286 break;
287 case EGL_SAMPLES:
288 match = config.samples >= attributeValue;
289 break;
290 case EGL_SAMPLE_BUFFERS:
291 match = config.sampleBuffers >= attributeValue;
292 break;
293 case EGL_SURFACE_TYPE:
294 match = (config.surfaceType & attributeValue) == attributeValue;
295 break;
296 case EGL_TRANSPARENT_TYPE:
297 match = config.transparentType == static_cast<EGLenum>(attributeValue);
298 break;
299 case EGL_TRANSPARENT_BLUE_VALUE:
300 if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE)
301 {
302 match = config.transparentBlueValue == attributeValue;
303 }
304 break;
305 case EGL_TRANSPARENT_GREEN_VALUE:
306 if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE)
307 {
308 match = config.transparentGreenValue == attributeValue;
309 }
310 break;
311 case EGL_TRANSPARENT_RED_VALUE:
312 if (attributeMap.get(EGL_TRANSPARENT_TYPE, EGL_NONE) != EGL_NONE)
313 {
314 match = config.transparentRedValue == attributeValue;
315 }
316 break;
317 case EGL_BIND_TO_TEXTURE_RGB:
318 match = config.bindToTextureRGB == static_cast<EGLBoolean>(attributeValue);
319 break;
320 case EGL_BIND_TO_TEXTURE_RGBA:
321 match = config.bindToTextureRGBA == static_cast<EGLBoolean>(attributeValue);
322 break;
323 case EGL_BIND_TO_TEXTURE_TARGET_ANGLE:
324 match = config.bindToTextureTarget == static_cast<EGLenum>(attributeValue);
325 break;
326 case EGL_MIN_SWAP_INTERVAL:
327 match = config.minSwapInterval == attributeValue;
328 break;
329 case EGL_MAX_SWAP_INTERVAL:
330 match = config.maxSwapInterval == attributeValue;
331 break;
332 case EGL_LUMINANCE_SIZE:
333 match = config.luminanceSize >= attributeValue;
334 break;
335 case EGL_ALPHA_MASK_SIZE:
336 match = config.alphaMaskSize >= attributeValue;
337 break;
338 case EGL_COLOR_BUFFER_TYPE:
339 match = config.colorBufferType == static_cast<EGLenum>(attributeValue);
340 break;
341 case EGL_RENDERABLE_TYPE:
342 match = (config.renderableType & attributeValue) == attributeValue;
343 break;
344 case EGL_MATCH_NATIVE_PIXMAP:
345 match = false;
346 UNIMPLEMENTED();
347 break;
348 case EGL_CONFORMANT:
349 match = (config.conformant & attributeValue) == attributeValue;
350 break;
351 case EGL_MAX_PBUFFER_WIDTH:
352 match = config.maxPBufferWidth >= attributeValue;
353 break;
354 case EGL_MAX_PBUFFER_HEIGHT:
355 match = config.maxPBufferHeight >= attributeValue;
356 break;
357 case EGL_MAX_PBUFFER_PIXELS:
358 match = config.maxPBufferPixels >= attributeValue;
359 break;
360 case EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE:
361 match = config.optimalOrientation == attributeValue;
362 break;
363 case EGL_COLOR_COMPONENT_TYPE_EXT:
364 match = config.colorComponentType == static_cast<EGLenum>(attributeValue);
365 break;
366 case EGL_RECORDABLE_ANDROID:
367 match = config.recordable == static_cast<EGLBoolean>(attributeValue);
368 break;
369 case EGL_FRAMEBUFFER_TARGET_ANDROID:
370 match = config.framebufferTarget == static_cast<EGLBoolean>(attributeValue);
371 break;
372 case EGL_Y_INVERTED_NOK:
373 match = config.yInverted == static_cast<EGLBoolean>(attributeValue);
374 break;
375 default:
376 UNREACHABLE();
377 }
378
379 if (!match)
380 {
381 break;
382 }
383 }
384
385 if (match)
386 {
387 result.push_back(&config);
388 }
389 }
390
391 // Sort the result
392 std::sort(result.begin(), result.end(), ConfigSorter(attributeMap));
393
394 return result;
395 }
396
begin()397 ConfigSet::ConfigMap::iterator ConfigSet::begin()
398 {
399 return mConfigs.begin();
400 }
401
end()402 ConfigSet::ConfigMap::iterator ConfigSet::end()
403 {
404 return mConfigs.end();
405 }
406 } // namespace egl
407