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