• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2016 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //    http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 // Config.cpp: Implements the egl::Config class, describing the format, type
16 // and size for an egl::Surface. Implements EGLConfig and related functionality.
17 // [EGL 1.4] section 3.4 page 15.
18 
19 #include "Config.h"
20 
21 #include "common/debug.h"
22 
23 #include <EGL/eglext.h>
24 #ifdef __ANDROID__
25 #include <system/graphics.h>
26 #endif
27 
28 #include <string.h>
29 #include <algorithm>
30 #include <cstring>
31 #include <vector>
32 
33 using namespace std;
34 
35 namespace egl
36 {
Config(sw::Format displayFormat,EGLint minInterval,EGLint maxInterval,sw::Format renderTargetFormat,sw::Format depthStencilFormat,EGLint multiSample)37 Config::Config(sw::Format displayFormat, EGLint minInterval, EGLint maxInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
38 	: mDisplayFormat(displayFormat), mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
39 {
40 	mBindToTextureRGB = EGL_FALSE;
41 	mBindToTextureRGBA = EGL_FALSE;
42 
43 	// Initialize to a high value to lower the preference of formats for which there's no native support
44 	mNativeVisualID = 0x7FFFFFFF;
45 
46 	switch(renderTargetFormat)
47 	{
48 	case sw::FORMAT_A1R5G5B5:
49 		mRedSize = 5;
50 		mGreenSize = 5;
51 		mBlueSize = 5;
52 		mAlphaSize = 1;
53 		break;
54 	case sw::FORMAT_A2R10G10B10:
55 		mRedSize = 10;
56 		mGreenSize = 10;
57 		mBlueSize = 10;
58 		mAlphaSize = 2;
59 		break;
60 	case sw::FORMAT_A8R8G8B8:
61 		mRedSize = 8;
62 		mGreenSize = 8;
63 		mBlueSize = 8;
64 		mAlphaSize = 8;
65 		mBindToTextureRGBA = EGL_TRUE;
66 		#ifdef __ANDROID__
67 			mNativeVisualID = HAL_PIXEL_FORMAT_BGRA_8888;
68 		#else
69 			mNativeVisualID = 2;   // Arbitrary; prefer over ABGR
70 		#endif
71 		break;
72 	case sw::FORMAT_A8B8G8R8:
73 		mRedSize = 8;
74 		mGreenSize = 8;
75 		mBlueSize = 8;
76 		mAlphaSize = 8;
77 		mBindToTextureRGBA = EGL_TRUE;
78 		#ifdef __ANDROID__
79 			mNativeVisualID = HAL_PIXEL_FORMAT_RGBA_8888;
80 		#endif
81 		break;
82 	case sw::FORMAT_R5G6B5:
83 		mRedSize = 5;
84 		mGreenSize = 6;
85 		mBlueSize = 5;
86 		mAlphaSize = 0;
87 		#ifdef __ANDROID__
88 			mNativeVisualID = HAL_PIXEL_FORMAT_RGB_565;
89 		#endif
90 		break;
91 	case sw::FORMAT_X8R8G8B8:
92 		mRedSize = 8;
93 		mGreenSize = 8;
94 		mBlueSize = 8;
95 		mAlphaSize = 0;
96 		mBindToTextureRGB = EGL_TRUE;
97 		#ifdef __ANDROID__
98 			mNativeVisualID = 0x1FF;   // HAL_PIXEL_FORMAT_BGRX_8888
99 		#else
100 			mNativeVisualID = 1;   // Arbitrary; prefer over XBGR
101 		#endif
102 		break;
103 	case sw::FORMAT_X8B8G8R8:
104 		mRedSize = 8;
105 		mGreenSize = 8;
106 		mBlueSize = 8;
107 		mAlphaSize = 0;
108 		mBindToTextureRGB = EGL_TRUE;
109 		#ifdef __ANDROID__
110 			mNativeVisualID = HAL_PIXEL_FORMAT_RGBX_8888;
111 		#endif
112 		break;
113 	default:
114 		UNREACHABLE(renderTargetFormat);
115 	}
116 
117 	mLuminanceSize = 0;
118 	mBufferSize = mRedSize + mGreenSize + mBlueSize + mLuminanceSize + mAlphaSize;
119 	mAlphaMaskSize = 0;
120 	mColorBufferType = EGL_RGB_BUFFER;
121 	mConfigCaveat = EGL_NONE;
122 	mConfigID = 0;
123 	mConformant = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT
124 #ifndef __ANDROID__ // Do not allow GLES 3.0 on Android
125 		| EGL_OPENGL_ES3_BIT
126 #endif
127 		;
128 
129 	switch(depthStencilFormat)
130 	{
131 	case sw::FORMAT_NULL:
132 		mDepthSize = 0;
133 		mStencilSize = 0;
134 		break;
135 //	case sw::FORMAT_D16_LOCKABLE:
136 //		mDepthSize = 16;
137 //		mStencilSize = 0;
138 //		break;
139 	case sw::FORMAT_D32:
140 		mDepthSize = 32;
141 		mStencilSize = 0;
142 		break;
143 //	case sw::FORMAT_D15S1:
144 //		mDepthSize = 15;
145 //		mStencilSize = 1;
146 //		break;
147 	case sw::FORMAT_D24S8:
148 		mDepthSize = 24;
149 		mStencilSize = 8;
150 		break;
151 	case sw::FORMAT_D24X8:
152 		mDepthSize = 24;
153 		mStencilSize = 0;
154 		break;
155 //	case sw::FORMAT_D24X4S4:
156 //		mDepthSize = 24;
157 //		mStencilSize = 4;
158 //		break;
159 	case sw::FORMAT_D16:
160 		mDepthSize = 16;
161 		mStencilSize = 0;
162 		break;
163 //	case sw::FORMAT_D32F_LOCKABLE:
164 //		mDepthSize = 32;
165 //		mStencilSize = 0;
166 //		break;
167 //	case sw::FORMAT_D24FS8:
168 //		mDepthSize = 24;
169 //		mStencilSize = 8;
170 //		break;
171 	default:
172 		UNREACHABLE(depthStencilFormat);
173 	}
174 
175 	mLevel = 0;
176 	mMatchNativePixmap = EGL_NONE;
177 	mMaxPBufferWidth = 4096;
178 	mMaxPBufferHeight = 4096;
179 	mMaxPBufferPixels = mMaxPBufferWidth * mMaxPBufferHeight;
180 	mMaxSwapInterval = maxInterval;
181 	mMinSwapInterval = minInterval;
182 	mNativeRenderable = EGL_FALSE;
183 	mNativeVisualType = 0;
184 	mRenderableType = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT
185 #ifndef __ANDROID__ // Do not allow GLES 3.0 on Android
186 		| EGL_OPENGL_ES3_BIT
187 #endif
188 		;
189 	mSampleBuffers = (multiSample > 0) ? 1 : 0;
190 	mSamples = multiSample;
191 	mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
192 	mTransparentType = EGL_NONE;
193 	mTransparentRedValue = 0;
194 	mTransparentGreenValue = 0;
195 	mTransparentBlueValue = 0;
196 
197 	mRecordableAndroid = EGL_TRUE;
198 	mFramebufferTargetAndroid = (displayFormat == renderTargetFormat) ? EGL_TRUE : EGL_FALSE;
199 }
200 
getHandle() const201 EGLConfig Config::getHandle() const
202 {
203 	return (EGLConfig)(size_t)mConfigID;
204 }
205 
206 // This ordering determines the config ID
operator ()(const Config & x,const Config & y) const207 bool CompareConfig::operator()(const Config &x, const Config &y) const
208 {
209 	#define SORT_SMALLER(attribute)                \
210 		if(x.attribute != y.attribute)             \
211 		{                                          \
212 			return x.attribute < y.attribute;      \
213 		}
214 
215 	static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
216 	SORT_SMALLER(mConfigCaveat);
217 
218 	static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
219 	SORT_SMALLER(mColorBufferType);
220 
221 	SORT_SMALLER(mRedSize);
222 	SORT_SMALLER(mGreenSize);
223 	SORT_SMALLER(mBlueSize);
224 	SORT_SMALLER(mAlphaSize);
225 
226 	SORT_SMALLER(mBufferSize);
227 	SORT_SMALLER(mSampleBuffers);
228 	SORT_SMALLER(mSamples);
229 	SORT_SMALLER(mDepthSize);
230 	SORT_SMALLER(mStencilSize);
231 	SORT_SMALLER(mAlphaMaskSize);
232 	SORT_SMALLER(mNativeVisualType);
233 	SORT_SMALLER(mNativeVisualID);
234 
235 	#undef SORT_SMALLER
236 
237 	// Strict ordering requires sorting all non-equal fields above
238 	assert(memcmp(&x, &y, sizeof(Config)) == 0);
239 
240 	return false;
241 }
242 
243 // Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24.
244 class SortConfig
245 {
246 public:
247 	explicit SortConfig(const EGLint *attribList);
248 
249 	bool operator()(const Config *x, const Config *y) const;
250 
251 private:
252 	EGLint wantedComponentsSize(const Config *config) const;
253 
254 	bool mWantRed;
255 	bool mWantGreen;
256 	bool mWantBlue;
257 	bool mWantAlpha;
258 	bool mWantLuminance;
259 };
260 
SortConfig(const EGLint * attribList)261 SortConfig::SortConfig(const EGLint *attribList)
262 	: mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
263 {
264 	// [EGL] section 3.4.1 page 24
265 	// Sorting rule #3: by larger total number of color bits,
266 	// not considering components that are 0 or don't-care.
267 	for(const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
268 	{
269 		if(attr[1] != 0 && attr[1] != EGL_DONT_CARE)
270 		{
271 			switch(attr[0])
272 			{
273 			case EGL_RED_SIZE:       mWantRed = true;       break;
274 			case EGL_GREEN_SIZE:     mWantGreen = true;     break;
275 			case EGL_BLUE_SIZE:      mWantBlue = true;      break;
276 			case EGL_ALPHA_SIZE:     mWantAlpha = true;     break;
277 			case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
278 			}
279 		}
280 	}
281 }
282 
wantedComponentsSize(const Config * config) const283 EGLint SortConfig::wantedComponentsSize(const Config *config) const
284 {
285 	EGLint total = 0;
286 
287 	if(mWantRed)       total += config->mRedSize;
288 	if(mWantGreen)     total += config->mGreenSize;
289 	if(mWantBlue)      total += config->mBlueSize;
290 	if(mWantAlpha)     total += config->mAlphaSize;
291 	if(mWantLuminance) total += config->mLuminanceSize;
292 
293 	return total;
294 }
295 
operator ()(const Config * x,const Config * y) const296 bool SortConfig::operator()(const Config *x, const Config *y) const
297 {
298 	#define SORT_SMALLER(attribute)                \
299 		if(x->attribute != y->attribute)           \
300 		{                                          \
301 			return x->attribute < y->attribute;    \
302 		}
303 
304 	static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
305 	SORT_SMALLER(mConfigCaveat);
306 
307 	static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
308 	SORT_SMALLER(mColorBufferType);
309 
310 	// By larger total number of color bits, only considering those that are requested to be > 0.
311 	EGLint xComponentsSize = wantedComponentsSize(x);
312 	EGLint yComponentsSize = wantedComponentsSize(y);
313 	if(xComponentsSize != yComponentsSize)
314 	{
315 		return xComponentsSize > yComponentsSize;
316 	}
317 
318 	SORT_SMALLER(mBufferSize);
319 	SORT_SMALLER(mSampleBuffers);
320 	SORT_SMALLER(mSamples);
321 	SORT_SMALLER(mDepthSize);
322 	SORT_SMALLER(mStencilSize);
323 	SORT_SMALLER(mAlphaMaskSize);
324 	SORT_SMALLER(mNativeVisualType);
325 	SORT_SMALLER(mConfigID);
326 
327 	#undef SORT_SMALLER
328 
329 	return false;
330 }
331 
ConfigSet()332 ConfigSet::ConfigSet()
333 {
334 }
335 
add(sw::Format displayFormat,EGLint minSwapInterval,EGLint maxSwapInterval,sw::Format renderTargetFormat,sw::Format depthStencilFormat,EGLint multiSample)336 void ConfigSet::add(sw::Format displayFormat, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
337 {
338 	Config config(displayFormat, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample);
339 
340 	mSet.insert(config);
341 }
342 
size() const343 size_t ConfigSet::size() const
344 {
345 	return mSet.size();
346 }
347 
getConfigs(EGLConfig * configs,const EGLint * attribList,EGLint configSize,EGLint * numConfig)348 bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
349 {
350 	vector<const Config*> passed;
351 	passed.reserve(mSet.size());
352 
353 	for(Iterator config = mSet.begin(); config != mSet.end(); config++)
354 	{
355 		bool match = true;
356 		const EGLint *attribute = attribList;
357 
358 		while(attribute[0] != EGL_NONE)
359 		{
360 			if(attribute[1] != EGL_DONT_CARE)
361 			{
362 				switch(attribute[0])
363 				{
364 				case EGL_BUFFER_SIZE:                match = config->mBufferSize >= attribute[1];                           break;
365 				case EGL_ALPHA_SIZE:                 match = config->mAlphaSize >= attribute[1];                            break;
366 				case EGL_BLUE_SIZE:                  match = config->mBlueSize >= attribute[1];                             break;
367 				case EGL_GREEN_SIZE:                 match = config->mGreenSize >= attribute[1];                            break;
368 				case EGL_RED_SIZE:                   match = config->mRedSize >= attribute[1];                              break;
369 				case EGL_DEPTH_SIZE:                 match = config->mDepthSize >= attribute[1];                            break;
370 				case EGL_STENCIL_SIZE:               match = config->mStencilSize >= attribute[1];                          break;
371 				case EGL_CONFIG_CAVEAT:              match = config->mConfigCaveat == (EGLenum)attribute[1];                break;
372 				case EGL_CONFIG_ID:                  match = config->mConfigID == attribute[1];                             break;
373 				case EGL_LEVEL:                      match = config->mLevel >= attribute[1];                                break;
374 				case EGL_NATIVE_RENDERABLE:          match = config->mNativeRenderable == (EGLBoolean)attribute[1];         break;
375 				case EGL_NATIVE_VISUAL_ID:           match = config->mNativeVisualID == attribute[1];                       break;
376 				case EGL_NATIVE_VISUAL_TYPE:         match = config->mNativeVisualType == attribute[1];                     break;
377 				case EGL_SAMPLES:                    match = config->mSamples >= attribute[1];                              break;
378 				case EGL_SAMPLE_BUFFERS:             match = config->mSampleBuffers >= attribute[1];                        break;
379 				case EGL_SURFACE_TYPE:               match = (config->mSurfaceType & attribute[1]) == attribute[1];         break;
380 				case EGL_TRANSPARENT_TYPE:           match = config->mTransparentType == (EGLenum)attribute[1];             break;
381 				case EGL_TRANSPARENT_BLUE_VALUE:     match = config->mTransparentBlueValue == attribute[1];                 break;
382 				case EGL_TRANSPARENT_GREEN_VALUE:    match = config->mTransparentGreenValue == attribute[1];                break;
383 				case EGL_TRANSPARENT_RED_VALUE:      match = config->mTransparentRedValue == attribute[1];                  break;
384 				case EGL_BIND_TO_TEXTURE_RGB:        match = config->mBindToTextureRGB == (EGLBoolean)attribute[1];         break;
385 				case EGL_BIND_TO_TEXTURE_RGBA:       match = config->mBindToTextureRGBA == (EGLBoolean)attribute[1];        break;
386 				case EGL_MIN_SWAP_INTERVAL:          match = config->mMinSwapInterval == attribute[1];                      break;
387 				case EGL_MAX_SWAP_INTERVAL:          match = config->mMaxSwapInterval == attribute[1];                      break;
388 				case EGL_LUMINANCE_SIZE:             match = config->mLuminanceSize >= attribute[1];                        break;
389 				case EGL_ALPHA_MASK_SIZE:            match = config->mAlphaMaskSize >= attribute[1];                        break;
390 				case EGL_COLOR_BUFFER_TYPE:          match = config->mColorBufferType == (EGLenum)attribute[1];             break;
391 				case EGL_RENDERABLE_TYPE:            match = (config->mRenderableType & attribute[1]) == attribute[1];      break;
392 				case EGL_MATCH_NATIVE_PIXMAP:        match = false; UNIMPLEMENTED();                                        break;
393 				case EGL_CONFORMANT:                 match = (config->mConformant & attribute[1]) == attribute[1];          break;
394 				case EGL_MAX_PBUFFER_WIDTH:          match = config->mMaxPBufferWidth >= attribute[1];                      break;
395 				case EGL_MAX_PBUFFER_HEIGHT:         match = config->mMaxPBufferHeight >= attribute[1];                     break;
396 				case EGL_MAX_PBUFFER_PIXELS:         match = config->mMaxPBufferPixels >= attribute[1];                     break;
397 				case EGL_RECORDABLE_ANDROID:         match = config->mRecordableAndroid == (EGLBoolean)attribute[1];        break;
398 				case EGL_FRAMEBUFFER_TARGET_ANDROID: match = config->mFramebufferTargetAndroid == (EGLBoolean)attribute[1]; break;
399 				default:
400 					*numConfig = 0;
401 					return false;
402 				}
403 
404 				if(!match)
405 				{
406 					break;
407 				}
408 			}
409 
410 			attribute += 2;
411 		}
412 
413 		if(match)
414 		{
415 			passed.push_back(&*config);
416 		}
417 	}
418 
419 	if(configs)
420 	{
421 		sort(passed.begin(), passed.end(), SortConfig(attribList));
422 
423 		EGLint index;
424 		for(index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
425 		{
426 			configs[index] = passed[index]->getHandle();
427 		}
428 
429 		*numConfig = index;
430 	}
431 	else
432 	{
433 		*numConfig = static_cast<EGLint>(passed.size());
434 	}
435 
436 	return true;
437 }
438 
get(EGLConfig configHandle)439 const egl::Config *ConfigSet::get(EGLConfig configHandle)
440 {
441 	for(Iterator config = mSet.begin(); config != mSet.end(); config++)
442 	{
443 		if(config->getHandle() == configHandle)
444 		{
445 			return &(*config);
446 		}
447 	}
448 
449 	return nullptr;
450 }
451 }
452