blob: 79dc12885cab4ccfbd994fc42a9806a0ba6c8a7b [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()
26{
27}
28
daniel@transgaming.com76d3e6e2012-10-31 19:55:33 +000029Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight)
Geoff Langc223dc62015-01-09 13:10:01 -050030 : renderTargetFormat(desc.renderTargetFormat), depthStencilFormat(desc.depthStencilFormat), multiSample(desc.multiSample)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000031{
Geoff Langc223dc62015-01-09 13:10:01 -050032 bindToTextureRGB = EGL_FALSE;
33 bindToTextureRGBA = EGL_FALSE;
daniel@transgaming.com3281f972012-10-31 18:38:51 +000034 switch (desc.renderTargetFormat)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000035 {
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000036 case GL_RGB5_A1:
Geoff Langc223dc62015-01-09 13:10:01 -050037 bufferSize = 16;
38 redSize = 5;
39 greenSize = 5;
40 blueSize = 5;
41 alphaSize = 1;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000042 break;
Geoff Langfe28ca02013-06-04 10:10:48 -040043 case GL_BGR5_A1_ANGLEX:
Geoff Langc223dc62015-01-09 13:10:01 -050044 bufferSize = 16;
45 redSize = 5;
46 greenSize = 5;
47 blueSize = 5;
48 alphaSize = 1;
Geoff Langfe28ca02013-06-04 10:10:48 -040049 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000050 case GL_RGBA8_OES:
Geoff Langc223dc62015-01-09 13:10:01 -050051 bufferSize = 32;
52 redSize = 8;
53 greenSize = 8;
54 blueSize = 8;
55 alphaSize = 8;
56 bindToTextureRGBA = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000057 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000058 case GL_RGB565:
Geoff Langc223dc62015-01-09 13:10:01 -050059 bufferSize = 16;
60 redSize = 5;
61 greenSize = 6;
62 blueSize = 5;
63 alphaSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000064 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000065 case GL_RGB8_OES:
Geoff Langc223dc62015-01-09 13:10:01 -050066 bufferSize = 32;
67 redSize = 8;
68 greenSize = 8;
69 blueSize = 8;
70 alphaSize = 0;
71 bindToTextureRGB = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000072 break;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000073 case GL_BGRA8_EXT:
Geoff Langc223dc62015-01-09 13:10:01 -050074 bufferSize = 32;
75 redSize = 8;
76 greenSize = 8;
77 blueSize = 8;
78 alphaSize = 8;
79 bindToTextureRGBA = true;
shannon.woods@transgaming.comc60c5212013-01-25 21:54:01 +000080 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081 default:
82 UNREACHABLE(); // Other formats should not be valid
83 }
84
Geoff Langc223dc62015-01-09 13:10:01 -050085 luminanceSize = 0;
86 alphaMaskSize = 0;
87 colorBufferType = EGL_RGB_BUFFER;
88 configCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG;
89 configID = 0;
90 conformant = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000091
daniel@transgaming.com3281f972012-10-31 18:38:51 +000092 switch (desc.depthStencilFormat)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000093 {
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000094 case GL_NONE:
Geoff Langc223dc62015-01-09 13:10:01 -050095 depthSize = 0;
96 stencilSize = 0;
daniel@transgaming.coma114c272011-04-22 04:18:50 +000097 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000098 case GL_DEPTH_COMPONENT32_OES:
Geoff Langc223dc62015-01-09 13:10:01 -050099 depthSize = 32;
100 stencilSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000101 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +0000102 case GL_DEPTH24_STENCIL8_OES:
Geoff Langc223dc62015-01-09 13:10:01 -0500103 depthSize = 24;
104 stencilSize = 8;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000105 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +0000106 case GL_DEPTH_COMPONENT24_OES:
Geoff Langc223dc62015-01-09 13:10:01 -0500107 depthSize = 24;
108 stencilSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +0000110 case GL_DEPTH_COMPONENT16:
Geoff Langc223dc62015-01-09 13:10:01 -0500111 depthSize = 16;
112 stencilSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000113 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114 default:
115 UNREACHABLE();
116 }
117
Geoff Langc223dc62015-01-09 13:10:01 -0500118 level = 0;
119 matchNativePixmap = EGL_NONE;
120 maxPBufferWidth = texWidth;
121 maxPBufferHeight = texHeight;
122 maxPBufferPixels = texWidth*texHeight;
123 maxSwapInterval = maxInterval;
124 minSwapInterval = minInterval;
125 nativeRenderable = EGL_FALSE;
126 nativeVisualID = 0;
127 nativeVisualType = 0;
128 renderableType = EGL_OPENGL_ES2_BIT;
129 sampleBuffers = desc.multiSample ? 1 : 0;
130 samples = desc.multiSample;
131 surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
132 transparentType = EGL_NONE;
133 transparentRedValue = 0;
134 transparentGreenValue = 0;
135 transparentBlueValue = 0;
shannon.woods%transgaming.com@gtempaccount.comdcf33d52013-04-13 03:33:11 +0000136
Austin Kinrossaed9f942014-10-23 14:31:03 -0700137 if (desc.es2Conformant)
138 {
Geoff Langc223dc62015-01-09 13:10:01 -0500139 conformant = EGL_OPENGL_ES2_BIT;
Austin Kinrossaed9f942014-10-23 14:31:03 -0700140 }
141
shannon.woods%transgaming.com@gtempaccount.comdcf33d52013-04-13 03:33:11 +0000142 if (desc.es3Capable)
143 {
Geoff Langc223dc62015-01-09 13:10:01 -0500144 renderableType |= EGL_OPENGL_ES3_BIT_KHR;
145 conformant |= EGL_OPENGL_ES3_BIT_KHR;
shannon.woods%transgaming.com@gtempaccount.comdcf33d52013-04-13 03:33:11 +0000146 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000147}
148
Geoff Lang6812a552015-01-06 17:26:42 -0500149EGLint ConfigSet::add(const Config &config)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000150{
Geoff Lang6812a552015-01-06 17:26:42 -0500151 // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4)
152 EGLint id = mConfigs.size() + 1;
153
154 Config copyConfig(config);
Geoff Langc223dc62015-01-09 13:10:01 -0500155 copyConfig.configID = id;
Geoff Lang6812a552015-01-06 17:26:42 -0500156 mConfigs.insert(std::make_pair(id, copyConfig));
157
158 return id;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159}
160
Geoff Lang6812a552015-01-06 17:26:42 -0500161const Config &ConfigSet::get(EGLint id) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162{
Geoff Lang6812a552015-01-06 17:26:42 -0500163 return mConfigs.at(id);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000164}
165
Geoff Lang6812a552015-01-06 17:26:42 -0500166void ConfigSet::clear()
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000167{
Geoff Lang6812a552015-01-06 17:26:42 -0500168 mConfigs.clear();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000169}
170
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000171size_t ConfigSet::size() const
172{
Geoff Lang6812a552015-01-06 17:26:42 -0500173 return mConfigs.size();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174}
175
Geoff Lang6812a552015-01-06 17:26:42 -0500176bool ConfigSet::contains(const Config *config) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000177{
Geoff Lang6812a552015-01-06 17:26:42 -0500178 for (auto i = mConfigs.begin(); i != mConfigs.end(); i++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179 {
Geoff Lang6812a552015-01-06 17:26:42 -0500180 const Config &item = i->second;
181 if (config == &item)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182 {
Geoff Lang6812a552015-01-06 17:26:42 -0500183 return true;
184 }
185 }
186
187 return false;
188}
189
190// Function object used by STL sorting routines for ordering Configs according to [EGL 1.5] section 3.4.1.2 page 28.
191class ConfigSorter
192{
193 public:
194 explicit ConfigSorter(const AttributeMap &attributeMap)
195 {
196 scanForWantedComponents(attributeMap);
197 }
198
199 bool operator()(const Config *x, const Config *y) const
200 {
201 return (*this)(*x, *y);
202 }
203
204 bool operator()(const Config &x, const Config &y) const
205 {
206 #define SORT(attribute) \
207 if (x.attribute != y.attribute) \
208 { \
209 return x.attribute < y.attribute; \
210 }
211
212 META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
Geoff Langc223dc62015-01-09 13:10:01 -0500213 SORT(configCaveat);
Geoff Lang6812a552015-01-06 17:26:42 -0500214
215 META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
Geoff Langc223dc62015-01-09 13:10:01 -0500216 SORT(colorBufferType);
Geoff Lang6812a552015-01-06 17:26:42 -0500217
218 // By larger total number of color bits, only considering those that are requested to be > 0.
219 EGLint xComponentsSize = wantedComponentsSize(x);
220 EGLint yComponentsSize = wantedComponentsSize(y);
221 if (xComponentsSize != yComponentsSize)
222 {
223 return xComponentsSize > yComponentsSize;
224 }
225
Geoff Langc223dc62015-01-09 13:10:01 -0500226 SORT(bufferSize);
227 SORT(sampleBuffers);
228 SORT(samples);
229 SORT(depthSize);
230 SORT(stencilSize);
231 SORT(alphaMaskSize);
232 SORT(nativeVisualType);
233 SORT(configID);
Geoff Lang6812a552015-01-06 17:26:42 -0500234
235 #undef SORT
236
237 return false;
238 }
239
240 private:
241 void scanForWantedComponents(const AttributeMap &attributeMap)
242 {
243 // [EGL 1.5] section 3.4.1.2 page 30
244 // Sorting rule #3: by larger total number of color bits, not considering
245 // components that are 0 or don't-care.
246 for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
247 {
248 EGLint attributeKey = attribIter->first;
249 EGLint attributeValue = attribIter->second;
250 if (attributeKey != 0 && attributeValue != EGL_DONT_CARE)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251 {
Geoff Lang6812a552015-01-06 17:26:42 -0500252 switch (attributeKey)
253 {
254 case EGL_RED_SIZE: mWantRed = true; break;
255 case EGL_GREEN_SIZE: mWantGreen = true; break;
256 case EGL_BLUE_SIZE: mWantBlue = true; break;
257 case EGL_ALPHA_SIZE: mWantAlpha = true; break;
258 case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
259 }
260 }
261 }
262 }
263
264 EGLint wantedComponentsSize(const Config &config) const
265 {
266 EGLint total = 0;
267
Geoff Langc223dc62015-01-09 13:10:01 -0500268 if (mWantRed) total += config.redSize;
269 if (mWantGreen) total += config.greenSize;
270 if (mWantBlue) total += config.blueSize;
271 if (mWantAlpha) total += config.alphaSize;
272 if (mWantLuminance) total += config.luminanceSize;
Geoff Lang6812a552015-01-06 17:26:42 -0500273
274 return total;
275 }
276
277 bool mWantRed;
278 bool mWantGreen;
279 bool mWantBlue;
280 bool mWantAlpha;
281 bool mWantLuminance;
282};
283
284std::vector<const Config*> ConfigSet::filter(const AttributeMap &attributeMap) const
285{
286 std::vector<const Config*> result;
287 result.reserve(mConfigs.size());
288
289 for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++)
290 {
291 const Config &config = configIter->second;
292 bool match = true;
293
294 for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
295 {
296 EGLint attributeKey = attribIter->first;
297 EGLint attributeValue = attribIter->second;
298
299 switch (attributeKey)
300 {
Geoff Langc223dc62015-01-09 13:10:01 -0500301 case EGL_BUFFER_SIZE: match = config.bufferSize >= attributeValue; break;
302 case EGL_ALPHA_SIZE: match = config.alphaSize >= attributeValue; break;
303 case EGL_BLUE_SIZE: match = config.blueSize >= attributeValue; break;
304 case EGL_GREEN_SIZE: match = config.greenSize >= attributeValue; break;
305 case EGL_RED_SIZE: match = config.redSize >= attributeValue; break;
306 case EGL_DEPTH_SIZE: match = config.depthSize >= attributeValue; break;
307 case EGL_STENCIL_SIZE: match = config.stencilSize >= attributeValue; break;
308 case EGL_CONFIG_CAVEAT: match = config.configCaveat == (EGLenum)attributeValue; break;
309 case EGL_CONFIG_ID: match = config.configID == attributeValue; break;
310 case EGL_LEVEL: match = config.level >= attributeValue; break;
311 case EGL_NATIVE_RENDERABLE: match = config.nativeRenderable == (EGLBoolean)attributeValue; break;
312 case EGL_NATIVE_VISUAL_TYPE: match = config.nativeVisualType == attributeValue; break;
313 case EGL_SAMPLES: match = config.samples >= attributeValue; break;
314 case EGL_SAMPLE_BUFFERS: match = config.sampleBuffers >= attributeValue; break;
315 case EGL_SURFACE_TYPE: match = (config.surfaceType & attributeValue) == attributeValue; break;
316 case EGL_TRANSPARENT_TYPE: match = config.transparentType == (EGLenum)attributeValue; break;
317 case EGL_TRANSPARENT_BLUE_VALUE: match = config.transparentBlueValue == attributeValue; break;
318 case EGL_TRANSPARENT_GREEN_VALUE: match = config.transparentGreenValue == attributeValue; break;
319 case EGL_TRANSPARENT_RED_VALUE: match = config.transparentRedValue == attributeValue; break;
320 case EGL_BIND_TO_TEXTURE_RGB: match = config.bindToTextureRGB == (EGLBoolean)attributeValue; break;
321 case EGL_BIND_TO_TEXTURE_RGBA: match = config.bindToTextureRGBA == (EGLBoolean)attributeValue; break;
322 case EGL_MIN_SWAP_INTERVAL: match = config.minSwapInterval == attributeValue; break;
323 case EGL_MAX_SWAP_INTERVAL: match = config.maxSwapInterval == attributeValue; break;
324 case EGL_LUMINANCE_SIZE: match = config.luminanceSize >= attributeValue; break;
325 case EGL_ALPHA_MASK_SIZE: match = config.alphaMaskSize >= attributeValue; break;
326 case EGL_COLOR_BUFFER_TYPE: match = config.colorBufferType == (EGLenum)attributeValue; break;
327 case EGL_RENDERABLE_TYPE: match = (config.renderableType & attributeValue) == attributeValue; break;
328 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
329 case EGL_CONFORMANT: match = (config.conformant & attributeValue) == attributeValue; break;
330 case EGL_MAX_PBUFFER_WIDTH: match = config.maxPBufferWidth >= attributeValue; break;
331 case EGL_MAX_PBUFFER_HEIGHT: match = config.maxPBufferHeight >= attributeValue; break;
332 case EGL_MAX_PBUFFER_PIXELS: match = config.maxPBufferPixels >= attributeValue; break;
Geoff Lang6812a552015-01-06 17:26:42 -0500333 default: UNREACHABLE();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000334 }
335
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000336 if (!match)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337 {
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000338 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339 }
340 }
341
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000342 if (match)
343 {
Geoff Lang6812a552015-01-06 17:26:42 -0500344 result.push_back(&config);
daniel@transgaming.com6a94b972010-05-13 02:02:34 +0000345 }
346 }
347
Geoff Lang6812a552015-01-06 17:26:42 -0500348 // Sort the result
349 std::sort(result.begin(), result.end(), ConfigSorter(attributeMap));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350
Geoff Lang6812a552015-01-06 17:26:42 -0500351 return result;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000352}
353
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000354}