Home | History | Annotate | Download | only in libEGL
      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 {
     37 // OpenGL ES 3.0 support is not conformant yet, but can be used for testing purposes. Expose it as conformant configs
     38 // if strict conformance advertisement isn't required. If strict conformance advertisement is required, expose them
     39 // as non-conformant configs, but only when EGL_CONFIG_CAVEAT is EGL_NON_CONFORMANT_CONFIG or EGL_DONT_CARE.
     40 #if defined(__ANDROID__) || defined(STRICT_CONFORMANCE)
     41 const bool strictConformance = true;
     42 #else
     43 const bool strictConformance = false;
     44 #endif
     45 
     46 Config::Config(sw::Format displayFormat, EGLint minInterval, EGLint maxInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample, bool conformant)
     47 	: mRenderTargetFormat(renderTargetFormat), mDepthStencilFormat(depthStencilFormat), mMultiSample(multiSample)
     48 {
     49 	mBindToTextureRGB = EGL_FALSE;
     50 	mBindToTextureRGBA = EGL_FALSE;
     51 
     52 	// Initialize to a high value to lower the preference of formats for which there's no native support
     53 	mNativeVisualID = 0x7FFFFFFF;
     54 
     55 	switch(renderTargetFormat)
     56 	{
     57 	case sw::FORMAT_A1R5G5B5:
     58 		mRedSize = 5;
     59 		mGreenSize = 5;
     60 		mBlueSize = 5;
     61 		mAlphaSize = 1;
     62 		break;
     63 	case sw::FORMAT_A2R10G10B10:
     64 		mRedSize = 10;
     65 		mGreenSize = 10;
     66 		mBlueSize = 10;
     67 		mAlphaSize = 2;
     68 		break;
     69 	case sw::FORMAT_A8R8G8B8:
     70 		mRedSize = 8;
     71 		mGreenSize = 8;
     72 		mBlueSize = 8;
     73 		mAlphaSize = 8;
     74 		mBindToTextureRGBA = EGL_TRUE;
     75 		#ifdef __ANDROID__
     76 			mNativeVisualID = HAL_PIXEL_FORMAT_BGRA_8888;
     77 		#else
     78 			mNativeVisualID = 2;   // Arbitrary; prefer over ABGR
     79 		#endif
     80 		break;
     81 	case sw::FORMAT_A8B8G8R8:
     82 		mRedSize = 8;
     83 		mGreenSize = 8;
     84 		mBlueSize = 8;
     85 		mAlphaSize = 8;
     86 		mBindToTextureRGBA = EGL_TRUE;
     87 		#ifdef __ANDROID__
     88 			mNativeVisualID = HAL_PIXEL_FORMAT_RGBA_8888;
     89 		#endif
     90 		break;
     91 	case sw::FORMAT_R5G6B5:
     92 		mRedSize = 5;
     93 		mGreenSize = 6;
     94 		mBlueSize = 5;
     95 		mAlphaSize = 0;
     96 		#ifdef __ANDROID__
     97 			mNativeVisualID = HAL_PIXEL_FORMAT_RGB_565;
     98 		#endif
     99 		break;
    100 	case sw::FORMAT_X8R8G8B8:
    101 		mRedSize = 8;
    102 		mGreenSize = 8;
    103 		mBlueSize = 8;
    104 		mAlphaSize = 0;
    105 		mBindToTextureRGB = EGL_TRUE;
    106 		#ifdef __ANDROID__
    107 			mNativeVisualID = 0x1FF;   // HAL_PIXEL_FORMAT_BGRX_8888
    108 		#else
    109 			mNativeVisualID = 1;   // Arbitrary; prefer over XBGR
    110 		#endif
    111 		break;
    112 	case sw::FORMAT_X8B8G8R8:
    113 		mRedSize = 8;
    114 		mGreenSize = 8;
    115 		mBlueSize = 8;
    116 		mAlphaSize = 0;
    117 		mBindToTextureRGB = EGL_TRUE;
    118 		#ifdef __ANDROID__
    119 			mNativeVisualID = HAL_PIXEL_FORMAT_RGBX_8888;
    120 		#endif
    121 		break;
    122 	default:
    123 		UNREACHABLE(renderTargetFormat);
    124 	}
    125 
    126 	mLuminanceSize = 0;
    127 	mBufferSize = mRedSize + mGreenSize + mBlueSize + mLuminanceSize + mAlphaSize;
    128 	mAlphaMaskSize = 0;
    129 	mColorBufferType = EGL_RGB_BUFFER;
    130 	mConfigCaveat = (conformant || !strictConformance) ? EGL_NONE : EGL_NON_CONFORMANT_CONFIG;
    131 	mConfigID = 0;
    132 	mConformant = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | (strictConformance ? 0 : EGL_OPENGL_ES3_BIT);
    133 
    134 	switch(depthStencilFormat)
    135 	{
    136 	case sw::FORMAT_NULL:
    137 		mDepthSize = 0;
    138 		mStencilSize = 0;
    139 		break;
    140 //	case sw::FORMAT_D16_LOCKABLE:
    141 //		mDepthSize = 16;
    142 //		mStencilSize = 0;
    143 //		break;
    144 	case sw::FORMAT_D32:
    145 		mDepthSize = 32;
    146 		mStencilSize = 0;
    147 		break;
    148 //	case sw::FORMAT_D15S1:
    149 //		mDepthSize = 15;
    150 //		mStencilSize = 1;
    151 //		break;
    152 	case sw::FORMAT_D24S8:
    153 		mDepthSize = 24;
    154 		mStencilSize = 8;
    155 		break;
    156 	case sw::FORMAT_D24X8:
    157 		mDepthSize = 24;
    158 		mStencilSize = 0;
    159 		break;
    160 //	case sw::FORMAT_D24X4S4:
    161 //		mDepthSize = 24;
    162 //		mStencilSize = 4;
    163 //		break;
    164 	case sw::FORMAT_D16:
    165 		mDepthSize = 16;
    166 		mStencilSize = 0;
    167 		break;
    168 //	case sw::FORMAT_D32F_LOCKABLE:
    169 //		mDepthSize = 32;
    170 //		mStencilSize = 0;
    171 //		break;
    172 //	case sw::FORMAT_D24FS8:
    173 //		mDepthSize = 24;
    174 //		mStencilSize = 8;
    175 //		break;
    176 	default:
    177 		UNREACHABLE(depthStencilFormat);
    178 	}
    179 
    180 	mLevel = 0;
    181 	mMatchNativePixmap = EGL_NONE;
    182 	mMaxPBufferWidth = 4096;
    183 	mMaxPBufferHeight = 4096;
    184 	mMaxPBufferPixels = mMaxPBufferWidth * mMaxPBufferHeight;
    185 	mMaxSwapInterval = maxInterval;
    186 	mMinSwapInterval = minInterval;
    187 	mNativeRenderable = EGL_FALSE;
    188 	mNativeVisualType = 0;
    189 	mRenderableType = EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | ((conformant && strictConformance) ? 0 : EGL_OPENGL_ES3_BIT);
    190 	mSampleBuffers = (multiSample > 0) ? 1 : 0;
    191 	mSamples = multiSample;
    192 	mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
    193 	mTransparentType = EGL_NONE;
    194 	mTransparentRedValue = 0;
    195 	mTransparentGreenValue = 0;
    196 	mTransparentBlueValue = 0;
    197 
    198 	// Although we could support any format as an Android HWComposer compatible config by converting when necessary,
    199 	// the intent of EGL_ANDROID_framebuffer_target is to prevent any copies or conversions.
    200 	mFramebufferTargetAndroid = (displayFormat == renderTargetFormat) ? EGL_TRUE : EGL_FALSE;
    201 	mRecordableAndroid = EGL_TRUE;
    202 }
    203 
    204 EGLConfig Config::getHandle() const
    205 {
    206 	return (EGLConfig)(size_t)mConfigID;
    207 }
    208 
    209 // This ordering determines the config ID
    210 bool CompareConfig::operator()(const Config &x, const Config &y) const
    211 {
    212 	#define SORT_SMALLER(attribute)                \
    213 		if(x.attribute != y.attribute)             \
    214 		{                                          \
    215 			return x.attribute < y.attribute;      \
    216 		}
    217 
    218 	static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
    219 	SORT_SMALLER(mConfigCaveat);
    220 
    221 	static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
    222 	SORT_SMALLER(mColorBufferType);
    223 
    224 	SORT_SMALLER(mRedSize);
    225 	SORT_SMALLER(mGreenSize);
    226 	SORT_SMALLER(mBlueSize);
    227 	SORT_SMALLER(mAlphaSize);
    228 
    229 	SORT_SMALLER(mBufferSize);
    230 	SORT_SMALLER(mSampleBuffers);
    231 	SORT_SMALLER(mSamples);
    232 	SORT_SMALLER(mDepthSize);
    233 	SORT_SMALLER(mStencilSize);
    234 	SORT_SMALLER(mAlphaMaskSize);
    235 	SORT_SMALLER(mNativeVisualType);
    236 	SORT_SMALLER(mNativeVisualID);
    237 
    238 	#undef SORT_SMALLER
    239 
    240 	// Strict ordering requires sorting all non-equal fields above
    241 	assert(memcmp(&x, &y, sizeof(Config)) == 0);
    242 
    243 	return false;
    244 }
    245 
    246 // Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24.
    247 class SortConfig
    248 {
    249 public:
    250 	explicit SortConfig(const EGLint *attribList);
    251 
    252 	bool operator()(const Config *x, const Config *y) const;
    253 
    254 private:
    255 	EGLint wantedComponentsSize(const Config *config) const;
    256 
    257 	bool mWantRed;
    258 	bool mWantGreen;
    259 	bool mWantBlue;
    260 	bool mWantAlpha;
    261 	bool mWantLuminance;
    262 };
    263 
    264 SortConfig::SortConfig(const EGLint *attribList)
    265 	: mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
    266 {
    267 	// [EGL] section 3.4.1 page 24
    268 	// Sorting rule #3: by larger total number of color bits,
    269 	// not considering components that are 0 or don't-care.
    270 	for(const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
    271 	{
    272 		if(attr[1] != 0 && attr[1] != EGL_DONT_CARE)
    273 		{
    274 			switch(attr[0])
    275 			{
    276 			case EGL_RED_SIZE:       mWantRed = true;       break;
    277 			case EGL_GREEN_SIZE:     mWantGreen = true;     break;
    278 			case EGL_BLUE_SIZE:      mWantBlue = true;      break;
    279 			case EGL_ALPHA_SIZE:     mWantAlpha = true;     break;
    280 			case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
    281 			}
    282 		}
    283 	}
    284 }
    285 
    286 EGLint SortConfig::wantedComponentsSize(const Config *config) const
    287 {
    288 	EGLint total = 0;
    289 
    290 	if(mWantRed)       total += config->mRedSize;
    291 	if(mWantGreen)     total += config->mGreenSize;
    292 	if(mWantBlue)      total += config->mBlueSize;
    293 	if(mWantAlpha)     total += config->mAlphaSize;
    294 	if(mWantLuminance) total += config->mLuminanceSize;
    295 
    296 	return total;
    297 }
    298 
    299 bool SortConfig::operator()(const Config *x, const Config *y) const
    300 {
    301 	#define SORT_SMALLER(attribute)                \
    302 		if(x->attribute != y->attribute)           \
    303 		{                                          \
    304 			return x->attribute < y->attribute;    \
    305 		}
    306 
    307 	static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "");
    308 	SORT_SMALLER(mConfigCaveat);
    309 
    310 	static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "");
    311 	SORT_SMALLER(mColorBufferType);
    312 
    313 	// By larger total number of color bits, only considering those that are requested to be > 0.
    314 	EGLint xComponentsSize = wantedComponentsSize(x);
    315 	EGLint yComponentsSize = wantedComponentsSize(y);
    316 	if(xComponentsSize != yComponentsSize)
    317 	{
    318 		return xComponentsSize > yComponentsSize;
    319 	}
    320 
    321 	SORT_SMALLER(mBufferSize);
    322 	SORT_SMALLER(mSampleBuffers);
    323 	SORT_SMALLER(mSamples);
    324 	SORT_SMALLER(mDepthSize);
    325 	SORT_SMALLER(mStencilSize);
    326 	SORT_SMALLER(mAlphaMaskSize);
    327 	SORT_SMALLER(mNativeVisualType);
    328 	SORT_SMALLER(mConfigID);
    329 
    330 	#undef SORT_SMALLER
    331 
    332 	return false;
    333 }
    334 
    335 ConfigSet::ConfigSet()
    336 {
    337 }
    338 
    339 void ConfigSet::add(sw::Format displayFormat, EGLint minSwapInterval, EGLint maxSwapInterval, sw::Format renderTargetFormat, sw::Format depthStencilFormat, EGLint multiSample)
    340 {
    341 	Config conformantConfig(displayFormat, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, true);
    342 	mSet.insert(conformantConfig);
    343 
    344 	if(strictConformance)   // When strict conformance is required, add non-conformant configs explicitly as such.
    345 	{
    346 		Config nonConformantConfig(displayFormat, minSwapInterval, maxSwapInterval, renderTargetFormat, depthStencilFormat, multiSample, false);
    347 		mSet.insert(nonConformantConfig);
    348 	}
    349 }
    350 
    351 size_t ConfigSet::size() const
    352 {
    353 	return mSet.size();
    354 }
    355 
    356 bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
    357 {
    358 	vector<const Config*> passed;
    359 	passed.reserve(mSet.size());
    360 
    361 	for(Iterator config = mSet.begin(); config != mSet.end(); config++)
    362 	{
    363 		bool match = true;
    364 		bool caveatMatch = (config->mConfigCaveat == EGL_NONE);
    365 		const EGLint *attribute = attribList;
    366 
    367 		while(attribute[0] != EGL_NONE)
    368 		{
    369 			if(attribute[1] != EGL_DONT_CARE)
    370 			{
    371 				switch(attribute[0])
    372 				{
    373 				case EGL_BUFFER_SIZE:                match = config->mBufferSize >= attribute[1];                           break;
    374 				case EGL_ALPHA_SIZE:                 match = config->mAlphaSize >= attribute[1];                            break;
    375 				case EGL_BLUE_SIZE:                  match = config->mBlueSize >= attribute[1];                             break;
    376 				case EGL_GREEN_SIZE:                 match = config->mGreenSize >= attribute[1];                            break;
    377 				case EGL_RED_SIZE:                   match = config->mRedSize >= attribute[1];                              break;
    378 				case EGL_DEPTH_SIZE:                 match = config->mDepthSize >= attribute[1];                            break;
    379 				case EGL_STENCIL_SIZE:               match = config->mStencilSize >= attribute[1];                          break;
    380 				case EGL_CONFIG_CAVEAT:              match = config->mConfigCaveat == (EGLenum)attribute[1];                break;
    381 				case EGL_CONFIG_ID:                  match = config->mConfigID == attribute[1];                             break;
    382 				case EGL_LEVEL:                      match = config->mLevel >= attribute[1];                                break;
    383 				case EGL_NATIVE_RENDERABLE:          match = config->mNativeRenderable == (EGLBoolean)attribute[1];         break;
    384 				case EGL_NATIVE_VISUAL_ID:           match = config->mNativeVisualID == attribute[1];                       break;
    385 				case EGL_NATIVE_VISUAL_TYPE:         match = config->mNativeVisualType == attribute[1];                     break;
    386 				case EGL_SAMPLES:                    match = config->mSamples >= attribute[1];                              break;
    387 				case EGL_SAMPLE_BUFFERS:             match = config->mSampleBuffers >= attribute[1];                        break;
    388 				case EGL_SURFACE_TYPE:               match = (config->mSurfaceType & attribute[1]) == attribute[1];         break;
    389 				case EGL_TRANSPARENT_TYPE:           match = config->mTransparentType == (EGLenum)attribute[1];             break;
    390 				case EGL_TRANSPARENT_BLUE_VALUE:     match = config->mTransparentBlueValue == attribute[1];                 break;
    391 				case EGL_TRANSPARENT_GREEN_VALUE:    match = config->mTransparentGreenValue == attribute[1];                break;
    392 				case EGL_TRANSPARENT_RED_VALUE:      match = config->mTransparentRedValue == attribute[1];                  break;
    393 				case EGL_BIND_TO_TEXTURE_RGB:        match = config->mBindToTextureRGB == (EGLBoolean)attribute[1];         break;
    394 				case EGL_BIND_TO_TEXTURE_RGBA:       match = config->mBindToTextureRGBA == (EGLBoolean)attribute[1];        break;
    395 				case EGL_MIN_SWAP_INTERVAL:          match = config->mMinSwapInterval == attribute[1];                      break;
    396 				case EGL_MAX_SWAP_INTERVAL:          match = config->mMaxSwapInterval == attribute[1];                      break;
    397 				case EGL_LUMINANCE_SIZE:             match = config->mLuminanceSize >= attribute[1];                        break;
    398 				case EGL_ALPHA_MASK_SIZE:            match = config->mAlphaMaskSize >= attribute[1];                        break;
    399 				case EGL_COLOR_BUFFER_TYPE:          match = config->mColorBufferType == (EGLenum)attribute[1];             break;
    400 				case EGL_RENDERABLE_TYPE:            match = (config->mRenderableType & attribute[1]) == attribute[1];      break;
    401 				case EGL_MATCH_NATIVE_PIXMAP:        match = false; UNIMPLEMENTED();                                        break;
    402 				case EGL_CONFORMANT:                 match = (config->mConformant & attribute[1]) == attribute[1];          break;
    403 				case EGL_MAX_PBUFFER_WIDTH:          match = config->mMaxPBufferWidth >= attribute[1];                      break;
    404 				case EGL_MAX_PBUFFER_HEIGHT:         match = config->mMaxPBufferHeight >= attribute[1];                     break;
    405 				case EGL_MAX_PBUFFER_PIXELS:         match = config->mMaxPBufferPixels >= attribute[1];                     break;
    406 				case EGL_RECORDABLE_ANDROID:         match = config->mRecordableAndroid == (EGLBoolean)attribute[1];        break;
    407 				case EGL_FRAMEBUFFER_TARGET_ANDROID: match = config->mFramebufferTargetAndroid == (EGLBoolean)attribute[1]; break;
    408 				default:
    409 					*numConfig = 0;
    410 					return false;
    411 				}
    412 
    413 				if(!match)
    414 				{
    415 					break;
    416 				}
    417 			}
    418 
    419 			if(attribute[0] == EGL_CONFIG_CAVEAT)
    420 			{
    421 				caveatMatch = match;
    422 			}
    423 
    424 			attribute += 2;
    425 		}
    426 
    427 		if(match && caveatMatch)   // We require the caveats to be NONE or the requested flags
    428 		{
    429 			passed.push_back(&*config);
    430 		}
    431 	}
    432 
    433 	if(configs)
    434 	{
    435 		sort(passed.begin(), passed.end(), SortConfig(attribList));
    436 
    437 		EGLint index;
    438 		for(index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
    439 		{
    440 			configs[index] = passed[index]->getHandle();
    441 		}
    442 
    443 		*numConfig = index;
    444 	}
    445 	else
    446 	{
    447 		*numConfig = static_cast<EGLint>(passed.size());
    448 	}
    449 
    450 	return true;
    451 }
    452 
    453 const egl::Config *ConfigSet::get(EGLConfig configHandle)
    454 {
    455 	for(Iterator config = mSet.begin(); config != mSet.end(); config++)
    456 	{
    457 		if(config->getHandle() == configHandle)
    458 		{
    459 			return &(*config);
    460 		}
    461 	}
    462 
    463 	return nullptr;
    464 }
    465 }
    466