blob: e89a1c2c4c956403e5a8945a8f8c1d50c7454dad [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),
60 transparentBlueValue(0)
Geoff Lang6812a552015-01-06 17:26:42 -050061{
62}
63
Geoff Lang6812a552015-01-06 17:26:42 -050064EGLint ConfigSet::add(const Config &config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000065{
Geoff Lang6812a552015-01-06 17:26:42 -050066 // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4)
67 EGLint id = mConfigs.size() + 1;
68
69 Config copyConfig(config);
Geoff Langc223dc62015-01-09 13:10:01 -050070 copyConfig.configID = id;
Geoff Lang6812a552015-01-06 17:26:42 -050071 mConfigs.insert(std::make_pair(id, copyConfig));
72
73 return id;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000074}
75
Geoff Lang6812a552015-01-06 17:26:42 -050076const Config &ConfigSet::get(EGLint id) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000077{
Jamie Madill73edef02015-02-17 18:58:21 -050078 ASSERT(mConfigs.find(id) != mConfigs.end());
79 return mConfigs.find(id)->second;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000080}
81
Geoff Lang6812a552015-01-06 17:26:42 -050082void ConfigSet::clear()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000083{
Geoff Lang6812a552015-01-06 17:26:42 -050084 mConfigs.clear();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000085}
86
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087size_t ConfigSet::size() const
88{
Geoff Lang6812a552015-01-06 17:26:42 -050089 return mConfigs.size();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000090}
91
Geoff Lang6812a552015-01-06 17:26:42 -050092bool ConfigSet::contains(const Config *config) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000093{
Geoff Lang6812a552015-01-06 17:26:42 -050094 for (auto i = mConfigs.begin(); i != mConfigs.end(); i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095 {
Geoff Lang6812a552015-01-06 17:26:42 -050096 const Config &item = i->second;
97 if (config == &item)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000098 {
Geoff Lang6812a552015-01-06 17:26:42 -050099 return true;
100 }
101 }
102
103 return false;
104}
105
106// Function object used by STL sorting routines for ordering Configs according to [EGL 1.5] section 3.4.1.2 page 28.
107class ConfigSorter
108{
109 public:
110 explicit ConfigSorter(const AttributeMap &attributeMap)
111 {
112 scanForWantedComponents(attributeMap);
113 }
114
115 bool operator()(const Config *x, const Config *y) const
116 {
117 return (*this)(*x, *y);
118 }
119
120 bool operator()(const Config &x, const Config &y) const
121 {
122 #define SORT(attribute) \
123 if (x.attribute != y.attribute) \
124 { \
125 return x.attribute < y.attribute; \
126 }
127
128 META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
Geoff Langc223dc62015-01-09 13:10:01 -0500129 SORT(configCaveat);
Geoff Lang6812a552015-01-06 17:26:42 -0500130
131 META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
Geoff Langc223dc62015-01-09 13:10:01 -0500132 SORT(colorBufferType);
Geoff Lang6812a552015-01-06 17:26:42 -0500133
134 // By larger total number of color bits, only considering those that are requested to be > 0.
135 EGLint xComponentsSize = wantedComponentsSize(x);
136 EGLint yComponentsSize = wantedComponentsSize(y);
137 if (xComponentsSize != yComponentsSize)
138 {
139 return xComponentsSize > yComponentsSize;
140 }
141
Geoff Langc223dc62015-01-09 13:10:01 -0500142 SORT(bufferSize);
143 SORT(sampleBuffers);
144 SORT(samples);
145 SORT(depthSize);
146 SORT(stencilSize);
147 SORT(alphaMaskSize);
148 SORT(nativeVisualType);
149 SORT(configID);
Geoff Lang6812a552015-01-06 17:26:42 -0500150
151 #undef SORT
152
153 return false;
154 }
155
156 private:
157 void scanForWantedComponents(const AttributeMap &attributeMap)
158 {
159 // [EGL 1.5] section 3.4.1.2 page 30
160 // Sorting rule #3: by larger total number of color bits, not considering
161 // components that are 0 or don't-care.
162 for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
163 {
164 EGLint attributeKey = attribIter->first;
165 EGLint attributeValue = attribIter->second;
166 if (attributeKey != 0 && attributeValue != EGL_DONT_CARE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000167 {
Geoff Lang6812a552015-01-06 17:26:42 -0500168 switch (attributeKey)
169 {
170 case EGL_RED_SIZE: mWantRed = true; break;
171 case EGL_GREEN_SIZE: mWantGreen = true; break;
172 case EGL_BLUE_SIZE: mWantBlue = true; break;
173 case EGL_ALPHA_SIZE: mWantAlpha = true; break;
174 case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
175 }
176 }
177 }
178 }
179
180 EGLint wantedComponentsSize(const Config &config) const
181 {
182 EGLint total = 0;
183
Geoff Langc223dc62015-01-09 13:10:01 -0500184 if (mWantRed) total += config.redSize;
185 if (mWantGreen) total += config.greenSize;
186 if (mWantBlue) total += config.blueSize;
187 if (mWantAlpha) total += config.alphaSize;
188 if (mWantLuminance) total += config.luminanceSize;
Geoff Lang6812a552015-01-06 17:26:42 -0500189
190 return total;
191 }
192
193 bool mWantRed;
194 bool mWantGreen;
195 bool mWantBlue;
196 bool mWantAlpha;
197 bool mWantLuminance;
198};
199
200std::vector<const Config*> ConfigSet::filter(const AttributeMap &attributeMap) const
201{
202 std::vector<const Config*> result;
203 result.reserve(mConfigs.size());
204
205 for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++)
206 {
207 const Config &config = configIter->second;
208 bool match = true;
209
210 for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
211 {
212 EGLint attributeKey = attribIter->first;
213 EGLint attributeValue = attribIter->second;
214
215 switch (attributeKey)
216 {
Geoff Langc223dc62015-01-09 13:10:01 -0500217 case EGL_BUFFER_SIZE: match = config.bufferSize >= attributeValue; break;
218 case EGL_ALPHA_SIZE: match = config.alphaSize >= attributeValue; break;
219 case EGL_BLUE_SIZE: match = config.blueSize >= attributeValue; break;
220 case EGL_GREEN_SIZE: match = config.greenSize >= attributeValue; break;
221 case EGL_RED_SIZE: match = config.redSize >= attributeValue; break;
222 case EGL_DEPTH_SIZE: match = config.depthSize >= attributeValue; break;
223 case EGL_STENCIL_SIZE: match = config.stencilSize >= attributeValue; break;
224 case EGL_CONFIG_CAVEAT: match = config.configCaveat == (EGLenum)attributeValue; break;
225 case EGL_CONFIG_ID: match = config.configID == attributeValue; break;
226 case EGL_LEVEL: match = config.level >= attributeValue; break;
227 case EGL_NATIVE_RENDERABLE: match = config.nativeRenderable == (EGLBoolean)attributeValue; break;
228 case EGL_NATIVE_VISUAL_TYPE: match = config.nativeVisualType == attributeValue; break;
229 case EGL_SAMPLES: match = config.samples >= attributeValue; break;
230 case EGL_SAMPLE_BUFFERS: match = config.sampleBuffers >= attributeValue; break;
231 case EGL_SURFACE_TYPE: match = (config.surfaceType & attributeValue) == attributeValue; break;
232 case EGL_TRANSPARENT_TYPE: match = config.transparentType == (EGLenum)attributeValue; break;
233 case EGL_TRANSPARENT_BLUE_VALUE: match = config.transparentBlueValue == attributeValue; break;
234 case EGL_TRANSPARENT_GREEN_VALUE: match = config.transparentGreenValue == attributeValue; break;
235 case EGL_TRANSPARENT_RED_VALUE: match = config.transparentRedValue == attributeValue; break;
236 case EGL_BIND_TO_TEXTURE_RGB: match = config.bindToTextureRGB == (EGLBoolean)attributeValue; break;
237 case EGL_BIND_TO_TEXTURE_RGBA: match = config.bindToTextureRGBA == (EGLBoolean)attributeValue; break;
238 case EGL_MIN_SWAP_INTERVAL: match = config.minSwapInterval == attributeValue; break;
239 case EGL_MAX_SWAP_INTERVAL: match = config.maxSwapInterval == attributeValue; break;
240 case EGL_LUMINANCE_SIZE: match = config.luminanceSize >= attributeValue; break;
241 case EGL_ALPHA_MASK_SIZE: match = config.alphaMaskSize >= attributeValue; break;
242 case EGL_COLOR_BUFFER_TYPE: match = config.colorBufferType == (EGLenum)attributeValue; break;
243 case EGL_RENDERABLE_TYPE: match = (config.renderableType & attributeValue) == attributeValue; break;
244 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
245 case EGL_CONFORMANT: match = (config.conformant & attributeValue) == attributeValue; break;
246 case EGL_MAX_PBUFFER_WIDTH: match = config.maxPBufferWidth >= attributeValue; break;
247 case EGL_MAX_PBUFFER_HEIGHT: match = config.maxPBufferHeight >= attributeValue; break;
248 case EGL_MAX_PBUFFER_PIXELS: match = config.maxPBufferPixels >= attributeValue; break;
Geoff Lang6812a552015-01-06 17:26:42 -0500249 default: UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250 }
251
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000252 if (!match)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000254 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255 }
256 }
257
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000258 if (match)
259 {
Geoff Lang6812a552015-01-06 17:26:42 -0500260 result.push_back(&config);
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000261 }
262 }
263
Geoff Lang6812a552015-01-06 17:26:42 -0500264 // Sort the result
265 std::sort(result.begin(), result.end(), ConfigSorter(attributeMap));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266
Geoff Lang6812a552015-01-06 17:26:42 -0500267 return result;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268}
269
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270}