• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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