eglconfig.c revision 2f2cf461c57974abd89e4917945cc8ae6a67a72e
1/** 2 * EGL Configuration (pixel format) functions. 3 */ 4 5 6#include <stdlib.h> 7#include <stdio.h> 8#include <string.h> 9#include <assert.h> 10#include "eglconfig.h" 11#include "egldisplay.h" 12#include "egldriver.h" 13#include "eglglobals.h" 14#include "egllog.h" 15 16 17#define MIN2(A, B) (((A) < (B)) ? (A) : (B)) 18 19 20void 21_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val) 22{ 23 assert(attr >= FIRST_ATTRIB); 24 assert(attr < FIRST_ATTRIB + MAX_ATTRIBS); 25 config->Attrib[attr - FIRST_ATTRIB] = val; 26} 27 28 29/** 30 * Init the given _EGLconfig to default values. 31 * \param id the configuration's ID. 32 */ 33void 34_eglInitConfig(_EGLConfig *config, EGLint id) 35{ 36 memset(config, 0, sizeof(*config)); 37 config->Handle = (EGLConfig) _eglUIntToPointer((unsigned int) id); 38 _eglSetConfigAttrib(config, EGL_CONFIG_ID, id); 39 _eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGB, EGL_DONT_CARE); 40 _eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_DONT_CARE); 41 _eglSetConfigAttrib(config, EGL_CONFIG_CAVEAT, EGL_DONT_CARE); 42 _eglSetConfigAttrib(config, EGL_NATIVE_RENDERABLE, EGL_DONT_CARE); 43 _eglSetConfigAttrib(config, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE); 44 _eglSetConfigAttrib(config, EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE); 45 _eglSetConfigAttrib(config, EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE); 46 _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT); 47 _eglSetConfigAttrib(config, EGL_TRANSPARENT_TYPE, EGL_NONE); 48 _eglSetConfigAttrib(config, EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE); 49 _eglSetConfigAttrib(config, EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE); 50 _eglSetConfigAttrib(config, EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE); 51#ifdef EGL_VERSION_1_2 52 _eglSetConfigAttrib(config, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER); 53 _eglSetConfigAttrib(config, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT); 54#endif /* EGL_VERSION_1_2 */ 55} 56 57 58/** 59 * Return the public handle for an internal _EGLConfig. 60 * This is the inverse of _eglLookupConfig(). 61 */ 62EGLConfig 63_eglGetConfigHandle(_EGLConfig *config) 64{ 65 return config ? config->Handle : 0; 66} 67 68 69/** 70 * Given an EGLConfig handle, return the corresponding _EGLConfig object. 71 * This is the inverse of _eglGetConfigHandle(). 72 */ 73_EGLConfig * 74_eglLookupConfig(EGLConfig config, _EGLDisplay *disp) 75{ 76 EGLint i; 77 for (i = 0; i < disp->NumConfigs; i++) { 78 if (disp->Configs[i]->Handle == config) { 79 return disp->Configs[i]; 80 } 81 } 82 return NULL; 83} 84 85 86/** 87 * Add the given _EGLConfig to the given display. 88 * Note that we just save the ptr to the config (we don't copy the config). 89 */ 90_EGLConfig * 91_eglAddConfig(_EGLDisplay *display, _EGLConfig *config) 92{ 93 _EGLConfig **newConfigs; 94 EGLint n; 95 96 /* do some sanity checks on the config's attribs */ 97 assert(GET_CONFIG_ATTRIB(config, EGL_CONFIG_ID) > 0); 98 assert(GET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE) != 0x0); 99 assert(GET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE) != 0x0); 100 assert(GET_CONFIG_ATTRIB(config, EGL_RED_SIZE) > 0); 101 assert(GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE) > 0); 102 assert(GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE) > 0); 103 104 n = display->NumConfigs; 105 106 /* realloc array of ptrs */ 107 newConfigs = (_EGLConfig **) realloc(display->Configs, 108 (n + 1) * sizeof(_EGLConfig *)); 109 if (newConfigs) { 110 display->Configs = newConfigs; 111 display->Configs[n] = config; 112 display->NumConfigs++; 113 return config; 114 } 115 else { 116 return NULL; 117 } 118} 119 120 121/** 122 * Parse the attrib_list to fill in the fields of the given _eglConfig 123 * Return EGL_FALSE if any errors, EGL_TRUE otherwise. 124 */ 125EGLBoolean 126_eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list) 127{ 128 EGLint i; 129 130 /* set all config attribs to EGL_DONT_CARE */ 131 for (i = 0; i < MAX_ATTRIBS; i++) { 132 config->Attrib[i] = EGL_DONT_CARE; 133 } 134 135 /* by default choose windows unless otherwise specified */ 136 config->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] = EGL_WINDOW_BIT; 137 138 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) { 139 const EGLint attr = attrib_list[i]; 140 if (attr >= EGL_BUFFER_SIZE && 141 attr <= EGL_MAX_SWAP_INTERVAL) { 142 EGLint k = attr - FIRST_ATTRIB; 143 assert(k >= 0); 144 assert(k < MAX_ATTRIBS); 145 config->Attrib[k] = attrib_list[++i]; 146 } 147#ifdef EGL_VERSION_1_2 148 else if (attr == EGL_COLOR_BUFFER_TYPE) { 149 EGLint bufType = attrib_list[++i]; 150 if (bufType != EGL_RGB_BUFFER && bufType != EGL_LUMINANCE_BUFFER) { 151 _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); 152 return EGL_FALSE; 153 } 154 _eglSetConfigAttrib(config, EGL_COLOR_BUFFER_TYPE, bufType); 155 } 156 else if (attr == EGL_RENDERABLE_TYPE) { 157 EGLint renType = attrib_list[++i]; 158 if (renType & ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENVG_BIT)) { 159 _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); 160 return EGL_FALSE; 161 } 162 _eglSetConfigAttrib(config, EGL_RENDERABLE_TYPE, renType); 163 } 164 else if (attr == EGL_ALPHA_MASK_SIZE || 165 attr == EGL_LUMINANCE_SIZE) { 166 EGLint value = attrib_list[++i]; 167 _eglSetConfigAttrib(config, attr, value); 168 } 169#endif /* EGL_VERSION_1_2 */ 170 else { 171 _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); 172 return EGL_FALSE; 173 } 174 } 175 return EGL_TRUE; 176} 177 178 179#define EXACT 1 180#define ATLEAST 2 181#define MASK 3 182#define SMALLER 4 183#define SPECIAL 5 184#define NONE 6 185 186struct sort_info { 187 EGLint Attribute; 188 EGLint MatchCriteria; 189 EGLint SortOrder; 190}; 191 192/* This encodes the info from Table 3.5 of the EGL spec, ordered by 193 * Sort Priority. 194 * 195 * XXX To do: EGL 1.2 attribs 196 */ 197static struct sort_info SortInfo[] = { 198 { EGL_CONFIG_CAVEAT, EXACT, SPECIAL }, 199 { EGL_RED_SIZE, ATLEAST, SPECIAL }, 200 { EGL_GREEN_SIZE, ATLEAST, SPECIAL }, 201 { EGL_BLUE_SIZE, ATLEAST, SPECIAL }, 202 { EGL_ALPHA_SIZE, ATLEAST, SPECIAL }, 203 { EGL_BUFFER_SIZE, ATLEAST, SMALLER }, 204 { EGL_SAMPLE_BUFFERS, ATLEAST, SMALLER }, 205 { EGL_SAMPLES, ATLEAST, SMALLER }, 206 { EGL_DEPTH_SIZE, ATLEAST, SMALLER }, 207 { EGL_STENCIL_SIZE, ATLEAST, SMALLER }, 208 { EGL_NATIVE_VISUAL_TYPE, EXACT, SPECIAL }, 209 { EGL_CONFIG_ID, EXACT, SMALLER }, 210 { EGL_BIND_TO_TEXTURE_RGB, EXACT, NONE }, 211 { EGL_BIND_TO_TEXTURE_RGBA, EXACT, NONE }, 212 { EGL_LEVEL, EXACT, NONE }, 213 { EGL_NATIVE_RENDERABLE, EXACT, NONE }, 214 { EGL_MAX_SWAP_INTERVAL, EXACT, NONE }, 215 { EGL_MIN_SWAP_INTERVAL, EXACT, NONE }, 216 { EGL_SURFACE_TYPE, MASK, NONE }, 217 { EGL_TRANSPARENT_TYPE, EXACT, NONE }, 218 { EGL_TRANSPARENT_RED_VALUE, EXACT, NONE }, 219 { EGL_TRANSPARENT_GREEN_VALUE, EXACT, NONE }, 220 { EGL_TRANSPARENT_BLUE_VALUE, EXACT, NONE }, 221 { 0, 0, 0 } 222}; 223 224 225/** 226 * Return EGL_TRUE if the attributes of c meet or exceed the minimums 227 * specified by min. 228 */ 229static EGLBoolean 230_eglConfigQualifies(const _EGLConfig *c, const _EGLConfig *min) 231{ 232 EGLint i; 233 for (i = 0; SortInfo[i].Attribute != 0; i++) { 234 const EGLint mv = GET_CONFIG_ATTRIB(min, SortInfo[i].Attribute); 235 if (mv != EGL_DONT_CARE) { 236 const EGLint cv = GET_CONFIG_ATTRIB(c, SortInfo[i].Attribute); 237 if (SortInfo[i].MatchCriteria == EXACT) { 238 if (cv != mv) { 239 return EGL_FALSE; 240 } 241 } 242 else if (SortInfo[i].MatchCriteria == ATLEAST) { 243 if (cv < mv) { 244 return EGL_FALSE; 245 } 246 } 247 else { 248 assert(SortInfo[i].MatchCriteria == MASK); 249 if ((mv & cv) != mv) { 250 return EGL_FALSE; 251 } 252 } 253 } 254 } 255 return EGL_TRUE; 256} 257 258 259/** 260 * Compare configs 'a' and 'b' and return -1 if a belongs before b, 261 * 1 if a belongs after b, or 0 if they're equal. 262 * Used by qsort(). 263 */ 264static int 265_eglCompareConfigs(const void *a, const void *b) 266{ 267 const _EGLConfig *aConfig = (const _EGLConfig *) a; 268 const _EGLConfig *bConfig = (const _EGLConfig *) b; 269 EGLint i; 270 271 for (i = 0; SortInfo[i].Attribute != 0; i++) { 272 const EGLint aVal = GET_CONFIG_ATTRIB(aConfig, SortInfo[i].Attribute); 273 const EGLint bVal = GET_CONFIG_ATTRIB(bConfig, SortInfo[i].Attribute); 274 if (SortInfo[i].SortOrder == SMALLER) { 275 if (aVal < bVal) 276 return -1; 277 else if (aVal > bVal) 278 return 1; 279 /* else, continue examining attribute values */ 280 } 281 else if (SortInfo[i].SortOrder == SPECIAL) { 282 if (SortInfo[i].Attribute == EGL_CONFIG_CAVEAT) { 283 /* values are EGL_NONE, SLOW_CONFIG, or NON_CONFORMANT_CONFIG */ 284 if (aVal < bVal) 285 return -1; 286 else if (aVal > bVal) 287 return 1; 288 } 289 else if (SortInfo[i].Attribute == EGL_RED_SIZE || 290 SortInfo[i].Attribute == EGL_GREEN_SIZE || 291 SortInfo[i].Attribute == EGL_BLUE_SIZE || 292 SortInfo[i].Attribute == EGL_ALPHA_SIZE) { 293 if (aVal > bVal) 294 return -1; 295 else if (aVal < bVal) 296 return 1; 297 } 298 else { 299 assert(SortInfo[i].Attribute == EGL_NATIVE_VISUAL_TYPE); 300 if (aVal < bVal) 301 return -1; 302 else if (aVal > bVal) 303 return 1; 304 } 305 } 306 else { 307 assert(SortInfo[i].SortOrder == NONE); 308 /* continue examining attribute values */ 309 } 310 } 311 312 /* all attributes identical */ 313 return 0; 314} 315 316 317/** 318 * Typical fallback routine for eglChooseConfig 319 */ 320EGLBoolean 321_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list, 322 EGLConfig *configs, EGLint config_size, EGLint *num_configs) 323{ 324 _EGLConfig **configList, criteria; 325 EGLint i, count; 326 327 /* parse the attrib_list to initialize criteria */ 328 if (!_eglParseConfigAttribs(&criteria, attrib_list)) { 329 return EGL_FALSE; 330 } 331 332 /* allocate array of config pointers */ 333 configList = (_EGLConfig **) malloc(config_size * sizeof(_EGLConfig *)); 334 if (!configList) { 335 _eglError(EGL_BAD_CONFIG, "eglChooseConfig(out of memory)"); 336 return EGL_FALSE; 337 } 338 339 /* make array of pointers to qualifying configs */ 340 for (i = count = 0; i < disp->NumConfigs && count < config_size; i++) { 341 if (_eglConfigQualifies(disp->Configs[i], &criteria)) { 342 configList[count++] = disp->Configs[i]; 343 } 344 } 345 346 /* sort array of pointers */ 347 qsort(configList, count, sizeof(_EGLConfig *), _eglCompareConfigs); 348 349 /* copy config handles to output array */ 350 if (configs) { 351 for (i = 0; i < count; i++) { 352 configs[i] = configList[i]->Handle; 353 } 354 } 355 356 free(configList); 357 358 *num_configs = count; 359 360 return EGL_TRUE; 361} 362 363 364/** 365 * Fallback for eglGetConfigAttrib. 366 */ 367EGLBoolean 368_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, 369 EGLint attribute, EGLint *value) 370{ 371 const EGLint k = attribute - FIRST_ATTRIB; 372 if (k >= 0 && k < MAX_ATTRIBS) { 373 *value = conf->Attrib[k]; 374 return EGL_TRUE; 375 } 376 else { 377 _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); 378 return EGL_FALSE; 379 } 380} 381 382 383/** 384 * Fallback for eglGetConfigs. 385 */ 386EGLBoolean 387_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs, 388 EGLint config_size, EGLint *num_config) 389{ 390 if (configs) { 391 EGLint i; 392 *num_config = MIN2(disp->NumConfigs, config_size); 393 for (i = 0; i < *num_config; i++) { 394 configs[i] = disp->Configs[i]->Handle; 395 } 396 } 397 else { 398 /* just return total number of supported configs */ 399 *num_config = disp->NumConfigs; 400 } 401 402 return EGL_TRUE; 403} 404