eglconfig.c revision 681fd73f1e95d43425b946a250b241bfdb0ce1c8
1/** 2 * EGL Configuration (pixel format) functions. 3 */ 4 5 6#include <stdlib.h> 7#include <string.h> 8#include <assert.h> 9#include "eglconfig.h" 10#include "egldisplay.h" 11#include "eglcurrent.h" 12#include "egllog.h" 13 14 15#define MIN2(A, B) (((A) < (B)) ? (A) : (B)) 16 17 18/** 19 * Init the given _EGLconfig to default values. 20 * \param id the configuration's ID. 21 * 22 * Note that id must be positive for the config to be valid. 23 * It is also recommended that when there are N configs, their 24 * IDs are from 1 to N respectively. 25 */ 26void 27_eglInitConfig(_EGLConfig *config, _EGLDisplay *dpy, EGLint id) 28{ 29 memset(config, 0, sizeof(*config)); 30 31 config->Display = dpy; 32 33 /* some attributes take non-zero default values */ 34 SET_CONFIG_ATTRIB(config, EGL_CONFIG_ID, id); 35 SET_CONFIG_ATTRIB(config, EGL_CONFIG_CAVEAT, EGL_NONE); 36 SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_TYPE, EGL_NONE); 37 SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, EGL_NONE); 38#ifdef EGL_VERSION_1_2 39 SET_CONFIG_ATTRIB(config, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER); 40#endif /* EGL_VERSION_1_2 */ 41} 42 43 44/** 45 * Link a config to a display and return the handle of the link. 46 * The handle can be passed to client directly. 47 * 48 * Note that we just save the ptr to the config (we don't copy the config). 49 */ 50EGLConfig 51_eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf) 52{ 53 _EGLConfig **configs; 54 55 /* sanity check */ 56 assert(GET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID) > 0); 57 58 configs = dpy->Configs; 59 if (dpy->NumConfigs >= dpy->MaxConfigs) { 60 EGLint new_size = dpy->MaxConfigs + 16; 61 assert(dpy->NumConfigs < new_size); 62 63 configs = realloc(dpy->Configs, new_size * sizeof(dpy->Configs[0])); 64 if (!configs) 65 return (EGLConfig) NULL; 66 67 dpy->Configs = configs; 68 dpy->MaxConfigs = new_size; 69 } 70 71 conf->Display = dpy; 72 dpy->Configs[dpy->NumConfigs++] = conf; 73 74 return (EGLConfig) conf; 75} 76 77 78EGLBoolean 79_eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy) 80{ 81 EGLint num_configs = (dpy) ? dpy->NumConfigs : 0; 82 EGLint i; 83 84 for (i = 0; i < num_configs; i++) { 85 _EGLConfig *conf = dpy->Configs[i]; 86 if (conf == (_EGLConfig *) config) { 87 assert(conf->Display == dpy); 88 break; 89 } 90 } 91 return (i < num_configs); 92} 93 94 95enum { 96 /* types */ 97 ATTRIB_TYPE_INTEGER, 98 ATTRIB_TYPE_BOOLEAN, 99 ATTRIB_TYPE_BITMASK, 100 ATTRIB_TYPE_ENUM, 101 ATTRIB_TYPE_PSEUDO, /* non-queryable */ 102 ATTRIB_TYPE_PLATFORM, /* platform-dependent */ 103 /* criteria */ 104 ATTRIB_CRITERION_EXACT, 105 ATTRIB_CRITERION_ATLEAST, 106 ATTRIB_CRITERION_MASK, 107 ATTRIB_CRITERION_SPECIAL, 108 ATTRIB_CRITERION_IGNORE 109}; 110 111 112/* EGL spec Table 3.1 and 3.4 */ 113static const struct { 114 EGLint attr; 115 EGLint type; 116 EGLint criterion; 117 EGLint default_value; 118} _eglValidationTable[] = 119{ 120 { EGL_BUFFER_SIZE, ATTRIB_TYPE_INTEGER, 121 ATTRIB_CRITERION_ATLEAST, 122 0 }, 123 { EGL_RED_SIZE, ATTRIB_TYPE_INTEGER, 124 ATTRIB_CRITERION_ATLEAST, 125 0 }, 126 { EGL_GREEN_SIZE, ATTRIB_TYPE_INTEGER, 127 ATTRIB_CRITERION_ATLEAST, 128 0 }, 129 { EGL_BLUE_SIZE, ATTRIB_TYPE_INTEGER, 130 ATTRIB_CRITERION_ATLEAST, 131 0 }, 132 { EGL_LUMINANCE_SIZE, ATTRIB_TYPE_INTEGER, 133 ATTRIB_CRITERION_ATLEAST, 134 0 }, 135 { EGL_ALPHA_SIZE, ATTRIB_TYPE_INTEGER, 136 ATTRIB_CRITERION_ATLEAST, 137 0 }, 138 { EGL_ALPHA_MASK_SIZE, ATTRIB_TYPE_INTEGER, 139 ATTRIB_CRITERION_ATLEAST, 140 0 }, 141 { EGL_BIND_TO_TEXTURE_RGB, ATTRIB_TYPE_BOOLEAN, 142 ATTRIB_CRITERION_EXACT, 143 EGL_DONT_CARE }, 144 { EGL_BIND_TO_TEXTURE_RGBA, ATTRIB_TYPE_BOOLEAN, 145 ATTRIB_CRITERION_EXACT, 146 EGL_DONT_CARE }, 147 { EGL_COLOR_BUFFER_TYPE, ATTRIB_TYPE_ENUM, 148 ATTRIB_CRITERION_EXACT, 149 EGL_RGB_BUFFER }, 150 { EGL_CONFIG_CAVEAT, ATTRIB_TYPE_ENUM, 151 ATTRIB_CRITERION_EXACT, 152 EGL_DONT_CARE }, 153 { EGL_CONFIG_ID, ATTRIB_TYPE_INTEGER, 154 ATTRIB_CRITERION_EXACT, 155 EGL_DONT_CARE }, 156 { EGL_CONFORMANT, ATTRIB_TYPE_BITMASK, 157 ATTRIB_CRITERION_MASK, 158 0 }, 159 { EGL_DEPTH_SIZE, ATTRIB_TYPE_INTEGER, 160 ATTRIB_CRITERION_ATLEAST, 161 0 }, 162 { EGL_LEVEL, ATTRIB_TYPE_PLATFORM, 163 ATTRIB_CRITERION_EXACT, 164 0 }, 165 { EGL_MAX_PBUFFER_WIDTH, ATTRIB_TYPE_INTEGER, 166 ATTRIB_CRITERION_IGNORE, 167 0 }, 168 { EGL_MAX_PBUFFER_HEIGHT, ATTRIB_TYPE_INTEGER, 169 ATTRIB_CRITERION_IGNORE, 170 0 }, 171 { EGL_MAX_PBUFFER_PIXELS, ATTRIB_TYPE_INTEGER, 172 ATTRIB_CRITERION_IGNORE, 173 0 }, 174 { EGL_MAX_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER, 175 ATTRIB_CRITERION_EXACT, 176 EGL_DONT_CARE }, 177 { EGL_MIN_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER, 178 ATTRIB_CRITERION_EXACT, 179 EGL_DONT_CARE }, 180 { EGL_NATIVE_RENDERABLE, ATTRIB_TYPE_BOOLEAN, 181 ATTRIB_CRITERION_EXACT, 182 EGL_DONT_CARE }, 183 { EGL_NATIVE_VISUAL_ID, ATTRIB_TYPE_PLATFORM, 184 ATTRIB_CRITERION_IGNORE, 185 0 }, 186 { EGL_NATIVE_VISUAL_TYPE, ATTRIB_TYPE_PLATFORM, 187 ATTRIB_CRITERION_EXACT, 188 EGL_DONT_CARE }, 189 { EGL_RENDERABLE_TYPE, ATTRIB_TYPE_BITMASK, 190 ATTRIB_CRITERION_MASK, 191 EGL_OPENGL_ES_BIT }, 192 { EGL_SAMPLE_BUFFERS, ATTRIB_TYPE_INTEGER, 193 ATTRIB_CRITERION_ATLEAST, 194 0 }, 195 { EGL_SAMPLES, ATTRIB_TYPE_INTEGER, 196 ATTRIB_CRITERION_ATLEAST, 197 0 }, 198 { EGL_STENCIL_SIZE, ATTRIB_TYPE_INTEGER, 199 ATTRIB_CRITERION_ATLEAST, 200 0 }, 201 { EGL_SURFACE_TYPE, ATTRIB_TYPE_BITMASK, 202 ATTRIB_CRITERION_MASK, 203 EGL_WINDOW_BIT }, 204 { EGL_TRANSPARENT_TYPE, ATTRIB_TYPE_ENUM, 205 ATTRIB_CRITERION_EXACT, 206 EGL_NONE }, 207 { EGL_TRANSPARENT_RED_VALUE, ATTRIB_TYPE_INTEGER, 208 ATTRIB_CRITERION_EXACT, 209 EGL_DONT_CARE }, 210 { EGL_TRANSPARENT_GREEN_VALUE, ATTRIB_TYPE_INTEGER, 211 ATTRIB_CRITERION_EXACT, 212 EGL_DONT_CARE }, 213 { EGL_TRANSPARENT_BLUE_VALUE, ATTRIB_TYPE_INTEGER, 214 ATTRIB_CRITERION_EXACT, 215 EGL_DONT_CARE }, 216 /* these are not real attributes */ 217 { EGL_MATCH_NATIVE_PIXMAP, ATTRIB_TYPE_PSEUDO, 218 ATTRIB_CRITERION_SPECIAL, 219 EGL_NONE }, 220 /* there is a gap before EGL_SAMPLES */ 221 { 0x3030, ATTRIB_TYPE_PSEUDO, 222 ATTRIB_CRITERION_IGNORE, 223 0 }, 224 { EGL_NONE, ATTRIB_TYPE_PSEUDO, 225 ATTRIB_CRITERION_IGNORE, 226 0 } 227}; 228 229 230/** 231 * Return true if a config is valid. When for_matching is true, 232 * EGL_DONT_CARE is accepted as a valid attribute value, and checks 233 * for conflicting attribute values are skipped. 234 * 235 * Note that some attributes are platform-dependent and are not 236 * checked. 237 */ 238EGLBoolean 239_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) 240{ 241 EGLint i, attr, val; 242 EGLBoolean valid = EGL_TRUE; 243 EGLint red_size = 0, green_size = 0, blue_size = 0, luminance_size = 0; 244 EGLint alpha_size = 0, buffer_size = 0; 245 246 /* all attributes should have been listed */ 247 assert(ARRAY_SIZE(_eglValidationTable) == _EGL_CONFIG_NUM_ATTRIBS); 248 249 /* check attributes by their types */ 250 for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 251 EGLint mask; 252 253 attr = _eglValidationTable[i].attr; 254 val = GET_CONFIG_ATTRIB(conf, attr); 255 256 switch (_eglValidationTable[i].type) { 257 case ATTRIB_TYPE_INTEGER: 258 switch (attr) { 259 case EGL_CONFIG_ID: 260 /* config id must be positive */ 261 if (val <= 0) 262 valid = EGL_FALSE; 263 break; 264 case EGL_SAMPLE_BUFFERS: 265 /* there can be at most 1 sample buffer */ 266 if (val > 1) 267 valid = EGL_FALSE; 268 break; 269 case EGL_RED_SIZE: 270 red_size = val; 271 break; 272 case EGL_GREEN_SIZE: 273 green_size = val; 274 break; 275 case EGL_BLUE_SIZE: 276 blue_size = val; 277 break; 278 case EGL_LUMINANCE_SIZE: 279 luminance_size = val; 280 break; 281 case EGL_ALPHA_SIZE: 282 alpha_size = val; 283 break; 284 case EGL_BUFFER_SIZE: 285 buffer_size = val; 286 break; 287 } 288 if (val < 0) 289 valid = EGL_FALSE; 290 break; 291 case ATTRIB_TYPE_BOOLEAN: 292 if (val != EGL_TRUE && val != EGL_FALSE) 293 valid = EGL_FALSE; 294 break; 295 case ATTRIB_TYPE_ENUM: 296 switch (attr) { 297 case EGL_CONFIG_CAVEAT: 298 if (val != EGL_NONE && val != EGL_SLOW_CONFIG && 299 val != EGL_NON_CONFORMANT_CONFIG) 300 valid = EGL_FALSE; 301 break; 302 case EGL_TRANSPARENT_TYPE: 303 if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB) 304 valid = EGL_FALSE; 305 break; 306 case EGL_COLOR_BUFFER_TYPE: 307 if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER) 308 valid = EGL_FALSE; 309 break; 310 default: 311 assert(0); 312 break; 313 } 314 break; 315 case ATTRIB_TYPE_BITMASK: 316 switch (attr) { 317 case EGL_SURFACE_TYPE: 318 mask = EGL_PBUFFER_BIT | 319 EGL_PIXMAP_BIT | 320 EGL_WINDOW_BIT | 321 EGL_VG_COLORSPACE_LINEAR_BIT | 322 EGL_VG_ALPHA_FORMAT_PRE_BIT | 323 EGL_MULTISAMPLE_RESOLVE_BOX_BIT | 324 EGL_SWAP_BEHAVIOR_PRESERVED_BIT; 325 if (conf->Display->Extensions.MESA_screen_surface) 326 mask |= EGL_SCREEN_BIT_MESA; 327 break; 328 case EGL_RENDERABLE_TYPE: 329 case EGL_CONFORMANT: 330 mask = EGL_OPENGL_ES_BIT | 331 EGL_OPENVG_BIT | 332 EGL_OPENGL_ES2_BIT | 333 EGL_OPENGL_BIT; 334 break; 335 default: 336 assert(0); 337 break; 338 } 339 if (val & ~mask) 340 valid = EGL_FALSE; 341 break; 342 case ATTRIB_TYPE_PLATFORM: 343 /* unable to check platform-dependent attributes here */ 344 break; 345 case ATTRIB_TYPE_PSEUDO: 346 /* pseudo attributes should not be set */ 347 if (val != 0) 348 valid = EGL_FALSE; 349 break; 350 default: 351 assert(0); 352 break; 353 } 354 355 if (!valid && for_matching) { 356 /* accept EGL_DONT_CARE as a valid value */ 357 if (val == EGL_DONT_CARE) 358 valid = EGL_TRUE; 359 if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL) 360 valid = EGL_TRUE; 361 } 362 if (!valid) { 363 _eglLog(_EGL_DEBUG, 364 "attribute 0x%04x has an invalid value 0x%x", attr, val); 365 break; 366 } 367 } 368 369 /* any invalid attribute value should have been catched */ 370 if (!valid || for_matching) 371 return valid; 372 373 /* now check for conflicting attribute values */ 374 375 switch (GET_CONFIG_ATTRIB(conf, EGL_COLOR_BUFFER_TYPE)) { 376 case EGL_RGB_BUFFER: 377 if (luminance_size) 378 valid = EGL_FALSE; 379 if (red_size + green_size + blue_size + alpha_size != buffer_size) 380 valid = EGL_FALSE; 381 break; 382 case EGL_LUMINANCE_BUFFER: 383 if (red_size || green_size || blue_size) 384 valid = EGL_FALSE; 385 if (luminance_size + alpha_size != buffer_size) 386 valid = EGL_FALSE; 387 break; 388 } 389 if (!valid) { 390 _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes"); 391 return EGL_FALSE; 392 } 393 394 val = GET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS); 395 if (!val && GET_CONFIG_ATTRIB(conf, EGL_SAMPLES)) 396 valid = EGL_FALSE; 397 if (!valid) { 398 _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers"); 399 return EGL_FALSE; 400 } 401 402 val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE); 403 if (!(val & EGL_WINDOW_BIT)) { 404 if (GET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID) != 0 || 405 GET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE) != EGL_NONE) 406 valid = EGL_FALSE; 407 } 408 if (!(val & EGL_PBUFFER_BIT)) { 409 if (GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB) || 410 GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA)) 411 valid = EGL_FALSE; 412 } 413 if (!valid) { 414 _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding"); 415 return EGL_FALSE; 416 } 417 418 return valid; 419} 420 421 422/** 423 * Return true if a config matches the criteria. This and 424 * _eglParseConfigAttribList together implement the algorithm 425 * described in "Selection of EGLConfigs". 426 * 427 * Note that attributes that are special (currently, only 428 * EGL_MATCH_NATIVE_PIXMAP) are ignored. 429 */ 430EGLBoolean 431_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria) 432{ 433 EGLint attr, val, i; 434 EGLBoolean matched = EGL_TRUE; 435 436 for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 437 EGLint cmp; 438 if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE) 439 continue; 440 441 attr = _eglValidationTable[i].attr; 442 cmp = GET_CONFIG_ATTRIB(criteria, attr); 443 if (cmp == EGL_DONT_CARE) 444 continue; 445 446 val = GET_CONFIG_ATTRIB(conf, attr); 447 switch (_eglValidationTable[i].criterion) { 448 case ATTRIB_CRITERION_EXACT: 449 if (val != cmp) 450 matched = EGL_FALSE; 451 break; 452 case ATTRIB_CRITERION_ATLEAST: 453 if (val < cmp) 454 matched = EGL_FALSE; 455 break; 456 case ATTRIB_CRITERION_MASK: 457 if ((val & cmp) != cmp) 458 matched = EGL_FALSE; 459 break; 460 case ATTRIB_CRITERION_SPECIAL: 461 /* ignored here */ 462 break; 463 default: 464 assert(0); 465 break; 466 } 467 468 if (!matched) { 469#ifdef DEBUG 470 _eglLog(_EGL_DEBUG, 471 "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)", 472 val, attr, cmp); 473#endif 474 break; 475 } 476 } 477 478 return matched; 479} 480 481 482/** 483 * Initialize a criteria config from the given attribute list. 484 * Return EGL_FALSE if any of the attribute is invalid. 485 */ 486EGLBoolean 487_eglParseConfigAttribList(_EGLConfig *conf, const EGLint *attrib_list) 488{ 489 EGLint attr, val, i; 490 EGLint config_id = 0, level = 0; 491 EGLBoolean has_native_visual_type = EGL_FALSE; 492 EGLBoolean has_transparent_color = EGL_FALSE; 493 494 /* reset to default values */ 495 for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 496 attr = _eglValidationTable[i].attr; 497 val = _eglValidationTable[i].default_value; 498 SET_CONFIG_ATTRIB(conf, attr, val); 499 } 500 501 /* parse the list */ 502 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) { 503 EGLint idx; 504 505 attr = attrib_list[i]; 506 val = attrib_list[i + 1]; 507 508 idx = _eglIndexConfig(conf, attr); 509 if (idx < 0) 510 return EGL_FALSE; 511 conf->Storage[idx] = val; 512 513 /* rememeber some attributes for post-processing */ 514 switch (attr) { 515 case EGL_CONFIG_ID: 516 config_id = val; 517 break; 518 case EGL_LEVEL: 519 level = val; 520 break; 521 case EGL_NATIVE_VISUAL_TYPE: 522 has_native_visual_type = EGL_TRUE; 523 break; 524 case EGL_TRANSPARENT_RED_VALUE: 525 case EGL_TRANSPARENT_GREEN_VALUE: 526 case EGL_TRANSPARENT_BLUE_VALUE: 527 has_transparent_color = EGL_TRUE; 528 break; 529 default: 530 break; 531 } 532 } 533 534 if (!_eglValidateConfig(conf, EGL_TRUE)) 535 return EGL_FALSE; 536 537 /* the spec says that EGL_LEVEL cannot be EGL_DONT_CARE */ 538 if (level == EGL_DONT_CARE) 539 return EGL_FALSE; 540 541 /* ignore other attributes when EGL_CONFIG_ID is given */ 542 if (config_id > 0) { 543 _eglResetConfigKeys(conf, EGL_DONT_CARE); 544 SET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID, config_id); 545 } 546 else { 547 if (has_native_visual_type) { 548 val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE); 549 if (!(val & EGL_WINDOW_BIT)) 550 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE); 551 } 552 553 if (has_transparent_color) { 554 val = GET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE); 555 if (val == EGL_NONE) { 556 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, 557 EGL_DONT_CARE); 558 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, 559 EGL_DONT_CARE); 560 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, 561 EGL_DONT_CARE); 562 } 563 } 564 } 565 566 return EGL_TRUE; 567} 568 569 570/** 571 * Decide the ordering of conf1 and conf2, under the given criteria. 572 * When compare_id is true, this implements the algorithm described 573 * in "Sorting of EGLConfigs". When compare_id is false, 574 * EGL_CONFIG_ID is not compared. 575 * 576 * It returns a negative integer if conf1 is considered to come 577 * before conf2; a positive integer if conf2 is considered to come 578 * before conf1; zero if the ordering cannot be decided. 579 * 580 * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is 581 * ignored here. 582 */ 583EGLint 584_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2, 585 const _EGLConfig *criteria, EGLBoolean compare_id) 586{ 587 const EGLint compare_attribs[] = { 588 EGL_BUFFER_SIZE, 589 EGL_SAMPLE_BUFFERS, 590 EGL_SAMPLES, 591 EGL_DEPTH_SIZE, 592 EGL_STENCIL_SIZE, 593 EGL_ALPHA_MASK_SIZE, 594 }; 595 EGLint val1, val2; 596 EGLBoolean rgb_buffer; 597 EGLint i; 598 599 if (conf1 == conf2) 600 return 0; 601 602 /* the enum values have the desired ordering */ 603 assert(EGL_NONE < EGL_SLOW_CONFIG); 604 assert(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); 605 val1 = GET_CONFIG_ATTRIB(conf1, EGL_CONFIG_CAVEAT); 606 val2 = GET_CONFIG_ATTRIB(conf2, EGL_CONFIG_CAVEAT); 607 if (val1 != val2) 608 return (val1 - val2); 609 610 /* the enum values have the desired ordering */ 611 assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); 612 val1 = GET_CONFIG_ATTRIB(conf1, EGL_COLOR_BUFFER_TYPE); 613 val2 = GET_CONFIG_ATTRIB(conf2, EGL_COLOR_BUFFER_TYPE); 614 if (val1 != val2) 615 return (val1 - val2); 616 rgb_buffer = (val1 == EGL_RGB_BUFFER); 617 618 if (criteria) { 619 val1 = val2 = 0; 620 if (rgb_buffer) { 621 if (GET_CONFIG_ATTRIB(criteria, EGL_RED_SIZE) > 0) { 622 val1 += GET_CONFIG_ATTRIB(conf1, EGL_RED_SIZE); 623 val2 += GET_CONFIG_ATTRIB(conf2, EGL_RED_SIZE); 624 } 625 if (GET_CONFIG_ATTRIB(criteria, EGL_GREEN_SIZE) > 0) { 626 val1 += GET_CONFIG_ATTRIB(conf1, EGL_GREEN_SIZE); 627 val2 += GET_CONFIG_ATTRIB(conf2, EGL_GREEN_SIZE); 628 } 629 if (GET_CONFIG_ATTRIB(criteria, EGL_BLUE_SIZE) > 0) { 630 val1 += GET_CONFIG_ATTRIB(conf1, EGL_BLUE_SIZE); 631 val2 += GET_CONFIG_ATTRIB(conf2, EGL_BLUE_SIZE); 632 } 633 } 634 else { 635 if (GET_CONFIG_ATTRIB(criteria, EGL_LUMINANCE_SIZE) > 0) { 636 val1 += GET_CONFIG_ATTRIB(conf1, EGL_LUMINANCE_SIZE); 637 val2 += GET_CONFIG_ATTRIB(conf2, EGL_LUMINANCE_SIZE); 638 } 639 } 640 if (GET_CONFIG_ATTRIB(criteria, EGL_ALPHA_SIZE) > 0) { 641 val1 += GET_CONFIG_ATTRIB(conf1, EGL_ALPHA_SIZE); 642 val2 += GET_CONFIG_ATTRIB(conf2, EGL_ALPHA_SIZE); 643 } 644 } 645 else { 646 /* assume the default criteria, which gives no specific ordering */ 647 val1 = val2 = 0; 648 } 649 650 /* for color bits, larger one is preferred */ 651 if (val1 != val2) 652 return (val2 - val1); 653 654 for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) { 655 val1 = GET_CONFIG_ATTRIB(conf1, compare_attribs[i]); 656 val2 = GET_CONFIG_ATTRIB(conf2, compare_attribs[i]); 657 if (val1 != val2) 658 return (val1 - val2); 659 } 660 661 /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */ 662 663 if (compare_id) { 664 val1 = GET_CONFIG_ATTRIB(conf1, EGL_CONFIG_ID); 665 val2 = GET_CONFIG_ATTRIB(conf2, EGL_CONFIG_ID); 666 assert(val1 != val2); 667 } 668 else { 669 val1 = val2 = 0; 670 } 671 672 return (val1 - val2); 673} 674 675 676static INLINE 677void _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2) 678{ 679 const _EGLConfig *tmp = *conf1; 680 *conf1 = *conf2; 681 *conf2 = tmp; 682} 683 684 685/** 686 * Quick sort an array of configs. This differs from the standard 687 * qsort() in that the compare function accepts an additional 688 * argument. 689 */ 690void 691_eglSortConfigs(const _EGLConfig **configs, EGLint count, 692 EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, 693 void *), 694 void *priv_data) 695{ 696 const EGLint pivot = 0; 697 EGLint i, j; 698 699 if (count <= 1) 700 return; 701 702 _eglSwapConfigs(&configs[pivot], &configs[count / 2]); 703 i = 1; 704 j = count - 1; 705 do { 706 while (i < count && compare(configs[i], configs[pivot], priv_data) < 0) 707 i++; 708 while (compare(configs[j], configs[pivot], priv_data) > 0) 709 j--; 710 if (i < j) { 711 _eglSwapConfigs(&configs[i], &configs[j]); 712 i++; 713 j--; 714 } 715 else if (i == j) { 716 i++; 717 j--; 718 break; 719 } 720 } while (i <= j); 721 _eglSwapConfigs(&configs[pivot], &configs[j]); 722 723 _eglSortConfigs(configs, j, compare, priv_data); 724 _eglSortConfigs(configs + i, count - i, compare, priv_data); 725} 726 727 728static int 729_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2, 730 void *priv_data) 731{ 732 const _EGLConfig *criteria = (const _EGLConfig *) priv_data; 733 return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE); 734} 735 736 737/** 738 * Typical fallback routine for eglChooseConfig 739 */ 740EGLBoolean 741_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list, 742 EGLConfig *configs, EGLint config_size, EGLint *num_configs) 743{ 744 _EGLConfig **configList, criteria; 745 EGLint i, count; 746 747 if (!num_configs) 748 return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs"); 749 750 _eglInitConfig(&criteria, disp, 0); 751 if (!_eglParseConfigAttribList(&criteria, attrib_list)) 752 return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); 753 754 /* allocate array of config pointers */ 755 configList = (_EGLConfig **) 756 malloc(disp->NumConfigs * sizeof(_EGLConfig *)); 757 if (!configList) 758 return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)"); 759 760 /* perform selection of configs */ 761 count = 0; 762 for (i = 0; i < disp->NumConfigs; i++) { 763 if (_eglMatchConfig(disp->Configs[i], &criteria)) 764 configList[count++] = disp->Configs[i]; 765 } 766 767 /* perform sorting of configs */ 768 if (configs && count) { 769 _eglSortConfigs((const _EGLConfig **) configList, count, 770 _eglFallbackCompare, (void *) &criteria); 771 count = MIN2(count, config_size); 772 for (i = 0; i < count; i++) 773 configs[i] = _eglGetConfigHandle(configList[i]); 774 } 775 776 free(configList); 777 778 *num_configs = count; 779 780 return EGL_TRUE; 781} 782 783 784static INLINE EGLBoolean 785_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr) 786{ 787 if (_eglIndexConfig(conf, attr) < 0) 788 return EGL_FALSE; 789 790 /* there are some holes in the range */ 791 switch (attr) { 792 case 0x3030 /* a gap before EGL_SAMPLES */: 793 case EGL_NONE: 794#ifdef EGL_VERSION_1_4 795 case EGL_MATCH_NATIVE_PIXMAP: 796#endif 797 return EGL_FALSE; 798 default: 799 break; 800 } 801 802 return EGL_TRUE; 803} 804 805 806/** 807 * Fallback for eglGetConfigAttrib. 808 */ 809EGLBoolean 810_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, 811 EGLint attribute, EGLint *value) 812{ 813 if (!_eglIsConfigAttribValid(conf, attribute)) 814 return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); 815 if (!value) 816 return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib"); 817 818 *value = GET_CONFIG_ATTRIB(conf, attribute); 819 return EGL_TRUE; 820} 821 822 823/** 824 * Fallback for eglGetConfigs. 825 */ 826EGLBoolean 827_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs, 828 EGLint config_size, EGLint *num_config) 829{ 830 if (!num_config) 831 return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs"); 832 833 if (configs) { 834 EGLint i; 835 *num_config = MIN2(disp->NumConfigs, config_size); 836 for (i = 0; i < *num_config; i++) 837 configs[i] = _eglGetConfigHandle(disp->Configs[i]); 838 } 839 else { 840 /* just return total number of supported configs */ 841 *num_config = disp->NumConfigs; 842 } 843 844 return EGL_TRUE; 845} 846