blob: 68d1b089884901f1c50a3f7b85052881d96c2480 [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)
daniel@transgaming.com3281f972012-10-31 18:38:51 +000030 : mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000031{
jbauman@chromium.orgae345802011-03-30 22:04:25 +000032 mBindToTextureRGB = EGL_FALSE;
33 mBindToTextureRGBA = 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:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000037 mBufferSize = 16;
38 mRedSize = 5;
39 mGreenSize = 5;
40 mBlueSize = 5;
41 mAlphaSize = 1;
42 break;
Geoff Langfe28ca02013-06-04 10:10:48 -040043 case GL_BGR5_A1_ANGLEX:
44 mBufferSize = 16;
45 mRedSize = 5;
46 mGreenSize = 5;
47 mBlueSize = 5;
48 mAlphaSize = 1;
49 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000050 case GL_RGBA8_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000051 mBufferSize = 32;
52 mRedSize = 8;
53 mGreenSize = 8;
54 mBlueSize = 8;
55 mAlphaSize = 8;
jbauman@chromium.orgae345802011-03-30 22:04:25 +000056 mBindToTextureRGBA = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000057 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000058 case GL_RGB565:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000059 mBufferSize = 16;
60 mRedSize = 5;
61 mGreenSize = 6;
62 mBlueSize = 5;
63 mAlphaSize = 0;
64 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000065 case GL_RGB8_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000066 mBufferSize = 32;
67 mRedSize = 8;
68 mGreenSize = 8;
69 mBlueSize = 8;
70 mAlphaSize = 0;
jbauman@chromium.orgae345802011-03-30 22:04:25 +000071 mBindToTextureRGB = 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:
74 mBufferSize = 32;
75 mRedSize = 8;
76 mGreenSize = 8;
77 mBlueSize = 8;
78 mAlphaSize = 8;
79 mBindToTextureRGBA = true;
80 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081 default:
82 UNREACHABLE(); // Other formats should not be valid
83 }
84
85 mLuminanceSize = 0;
86 mAlphaMaskSize = 0;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087 mColorBufferType = EGL_RGB_BUFFER;
daniel@transgaming.com3281f972012-10-31 18:38:51 +000088 mConfigCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000089 mConfigID = 0;
Austin Kinrossaed9f942014-10-23 14:31:03 -070090 mConformant = 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:
daniel@transgaming.coma114c272011-04-22 04:18:50 +000095 mDepthSize = 0;
96 mStencilSize = 0;
97 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +000098 case GL_DEPTH_COMPONENT32_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000099 mDepthSize = 32;
100 mStencilSize = 0;
101 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +0000102 case GL_DEPTH24_STENCIL8_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000103 mDepthSize = 24;
104 mStencilSize = 8;
105 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +0000106 case GL_DEPTH_COMPONENT24_OES:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107 mDepthSize = 24;
108 mStencilSize = 0;
109 break;
daniel@transgaming.com106e1f72012-10-31 18:38:36 +0000110 case GL_DEPTH_COMPONENT16:
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000111 mDepthSize = 16;
112 mStencilSize = 0;
113 break;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114 default:
115 UNREACHABLE();
116 }
117
118 mLevel = 0;
119 mMatchNativePixmap = EGL_NONE;
vladimirv@gmail.com721b7f22011-02-11 00:54:47 +0000120 mMaxPBufferWidth = texWidth;
121 mMaxPBufferHeight = texHeight;
122 mMaxPBufferPixels = texWidth*texHeight;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000123 mMaxSwapInterval = maxInterval;
124 mMinSwapInterval = minInterval;
125 mNativeRenderable = EGL_FALSE;
126 mNativeVisualID = 0;
127 mNativeVisualType = 0;
128 mRenderableType = EGL_OPENGL_ES2_BIT;
daniel@transgaming.com3281f972012-10-31 18:38:51 +0000129 mSampleBuffers = desc.multiSample ? 1 : 0;
130 mSamples = desc.multiSample;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000131 mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
132 mTransparentType = EGL_NONE;
133 mTransparentRedValue = 0;
134 mTransparentGreenValue = 0;
135 mTransparentBlueValue = 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 {
139 mConformant = EGL_OPENGL_ES2_BIT;
140 }
141
shannon.woods%transgaming.com@gtempaccount.comdcf33d52013-04-13 03:33:11 +0000142 if (desc.es3Capable)
143 {
144 mRenderableType |= EGL_OPENGL_ES3_BIT_KHR;
145 mConformant |= EGL_OPENGL_ES3_BIT_KHR;
146 }
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);
155 copyConfig.mConfigID = id;
156 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);
213 SORT(mConfigCaveat);
214
215 META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
216 SORT(mColorBufferType);
217
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
226 SORT(mBufferSize);
227 SORT(mSampleBuffers);
228 SORT(mSamples);
229 SORT(mDepthSize);
230 SORT(mStencilSize);
231 SORT(mAlphaMaskSize);
232 SORT(mNativeVisualType);
233 SORT(mConfigID);
234
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
268 if (mWantRed) total += config.mRedSize;
269 if (mWantGreen) total += config.mGreenSize;
270 if (mWantBlue) total += config.mBlueSize;
271 if (mWantAlpha) total += config.mAlphaSize;
272 if (mWantLuminance) total += config.mLuminanceSize;
273
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 {
301 case EGL_BUFFER_SIZE: match = config.mBufferSize >= attributeValue; break;
302 case EGL_ALPHA_SIZE: match = config.mAlphaSize >= attributeValue; break;
303 case EGL_BLUE_SIZE: match = config.mBlueSize >= attributeValue; break;
304 case EGL_GREEN_SIZE: match = config.mGreenSize >= attributeValue; break;
305 case EGL_RED_SIZE: match = config.mRedSize >= attributeValue; break;
306 case EGL_DEPTH_SIZE: match = config.mDepthSize >= attributeValue; break;
307 case EGL_STENCIL_SIZE: match = config.mStencilSize >= attributeValue; break;
308 case EGL_CONFIG_CAVEAT: match = config.mConfigCaveat == (EGLenum)attributeValue; break;
309 case EGL_CONFIG_ID: match = config.mConfigID == attributeValue; break;
310 case EGL_LEVEL: match = config.mLevel >= attributeValue; break;
311 case EGL_NATIVE_RENDERABLE: match = config.mNativeRenderable == (EGLBoolean)attributeValue; break;
312 case EGL_NATIVE_VISUAL_TYPE: match = config.mNativeVisualType == attributeValue; break;
313 case EGL_SAMPLES: match = config.mSamples >= attributeValue; break;
314 case EGL_SAMPLE_BUFFERS: match = config.mSampleBuffers >= attributeValue; break;
315 case EGL_SURFACE_TYPE: match = (config.mSurfaceType & attributeValue) == attributeValue; break;
316 case EGL_TRANSPARENT_TYPE: match = config.mTransparentType == (EGLenum)attributeValue; break;
317 case EGL_TRANSPARENT_BLUE_VALUE: match = config.mTransparentBlueValue == attributeValue; break;
318 case EGL_TRANSPARENT_GREEN_VALUE: match = config.mTransparentGreenValue == attributeValue; break;
319 case EGL_TRANSPARENT_RED_VALUE: match = config.mTransparentRedValue == attributeValue; break;
320 case EGL_BIND_TO_TEXTURE_RGB: match = config.mBindToTextureRGB == (EGLBoolean)attributeValue; break;
321 case EGL_BIND_TO_TEXTURE_RGBA: match = config.mBindToTextureRGBA == (EGLBoolean)attributeValue; break;
322 case EGL_MIN_SWAP_INTERVAL: match = config.mMinSwapInterval == attributeValue; break;
323 case EGL_MAX_SWAP_INTERVAL: match = config.mMaxSwapInterval == attributeValue; break;
324 case EGL_LUMINANCE_SIZE: match = config.mLuminanceSize >= attributeValue; break;
325 case EGL_ALPHA_MASK_SIZE: match = config.mAlphaMaskSize >= attributeValue; break;
326 case EGL_COLOR_BUFFER_TYPE: match = config.mColorBufferType == (EGLenum)attributeValue; break;
327 case EGL_RENDERABLE_TYPE: match = (config.mRenderableType & attributeValue) == attributeValue; break;
328 case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
329 case EGL_CONFORMANT: match = (config.mConformant & attributeValue) == attributeValue; break;
330 case EGL_MAX_PBUFFER_WIDTH: match = config.mMaxPBufferWidth >= attributeValue; break;
331 case EGL_MAX_PBUFFER_HEIGHT: match = config.mMaxPBufferHeight >= attributeValue; break;
332 case EGL_MAX_PBUFFER_PIXELS: match = config.mMaxPBufferPixels >= attributeValue; break;
333 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}