eglconfig.c revision 554e4fc26a64a90012b0d7dcc1205441273f214c
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 481static INLINE EGLBoolean 482_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr) 483{ 484 if (_eglIndexConfig(conf, attr) < 0) 485 return EGL_FALSE; 486 487 /* there are some holes in the range */ 488 switch (attr) { 489 case 0x3030 /* a gap before EGL_SAMPLES */: 490 case EGL_NONE: 491#ifdef EGL_VERSION_1_4 492 case EGL_MATCH_NATIVE_PIXMAP: 493#endif 494 return EGL_FALSE; 495 default: 496 break; 497 } 498 499 return EGL_TRUE; 500} 501 502/** 503 * Initialize a criteria config from the given attribute list. 504 * Return EGL_FALSE if any of the attribute is invalid. 505 */ 506EGLBoolean 507_eglParseConfigAttribList(_EGLConfig *conf, const EGLint *attrib_list) 508{ 509 EGLint attr, val, i; 510 EGLint config_id = 0, level = 0; 511 EGLBoolean has_native_visual_type = EGL_FALSE; 512 EGLBoolean has_transparent_color = EGL_FALSE; 513 514 /* reset to default values */ 515 for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { 516 attr = _eglValidationTable[i].attr; 517 val = _eglValidationTable[i].default_value; 518 SET_CONFIG_ATTRIB(conf, attr, val); 519 } 520 521 /* parse the list */ 522 for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) { 523 attr = attrib_list[i]; 524 val = attrib_list[i + 1]; 525 526 if (!_eglIsConfigAttribValid(conf, attr)) 527 return EGL_FALSE; 528 529 SET_CONFIG_ATTRIB(conf, attr, val); 530 531 /* rememeber some attributes for post-processing */ 532 switch (attr) { 533 case EGL_CONFIG_ID: 534 config_id = val; 535 break; 536 case EGL_LEVEL: 537 level = val; 538 break; 539 case EGL_NATIVE_VISUAL_TYPE: 540 has_native_visual_type = EGL_TRUE; 541 break; 542 case EGL_TRANSPARENT_RED_VALUE: 543 case EGL_TRANSPARENT_GREEN_VALUE: 544 case EGL_TRANSPARENT_BLUE_VALUE: 545 has_transparent_color = EGL_TRUE; 546 break; 547 default: 548 break; 549 } 550 } 551 552 if (!_eglValidateConfig(conf, EGL_TRUE)) 553 return EGL_FALSE; 554 555 /* the spec says that EGL_LEVEL cannot be EGL_DONT_CARE */ 556 if (level == EGL_DONT_CARE) 557 return EGL_FALSE; 558 559 /* ignore other attributes when EGL_CONFIG_ID is given */ 560 if (config_id > 0) { 561 _eglResetConfigKeys(conf, EGL_DONT_CARE); 562 SET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID, config_id); 563 } 564 else { 565 if (has_native_visual_type) { 566 val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE); 567 if (!(val & EGL_WINDOW_BIT)) 568 SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE); 569 } 570 571 if (has_transparent_color) { 572 val = GET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE); 573 if (val == EGL_NONE) { 574 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, 575 EGL_DONT_CARE); 576 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, 577 EGL_DONT_CARE); 578 SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, 579 EGL_DONT_CARE); 580 } 581 } 582 } 583 584 return EGL_TRUE; 585} 586 587 588/** 589 * Decide the ordering of conf1 and conf2, under the given criteria. 590 * When compare_id is true, this implements the algorithm described 591 * in "Sorting of EGLConfigs". When compare_id is false, 592 * EGL_CONFIG_ID is not compared. 593 * 594 * It returns a negative integer if conf1 is considered to come 595 * before conf2; a positive integer if conf2 is considered to come 596 * before conf1; zero if the ordering cannot be decided. 597 * 598 * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is 599 * ignored here. 600 */ 601EGLint 602_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2, 603 const _EGLConfig *criteria, EGLBoolean compare_id) 604{ 605 const EGLint compare_attribs[] = { 606 EGL_BUFFER_SIZE, 607 EGL_SAMPLE_BUFFERS, 608 EGL_SAMPLES, 609 EGL_DEPTH_SIZE, 610 EGL_STENCIL_SIZE, 611 EGL_ALPHA_MASK_SIZE, 612 }; 613 EGLint val1, val2; 614 EGLBoolean rgb_buffer; 615 EGLint i; 616 617 if (conf1 == conf2) 618 return 0; 619 620 /* the enum values have the desired ordering */ 621 assert(EGL_NONE < EGL_SLOW_CONFIG); 622 assert(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); 623 val1 = GET_CONFIG_ATTRIB(conf1, EGL_CONFIG_CAVEAT); 624 val2 = GET_CONFIG_ATTRIB(conf2, EGL_CONFIG_CAVEAT); 625 if (val1 != val2) 626 return (val1 - val2); 627 628 /* the enum values have the desired ordering */ 629 assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); 630 val1 = GET_CONFIG_ATTRIB(conf1, EGL_COLOR_BUFFER_TYPE); 631 val2 = GET_CONFIG_ATTRIB(conf2, EGL_COLOR_BUFFER_TYPE); 632 if (val1 != val2) 633 return (val1 - val2); 634 rgb_buffer = (val1 == EGL_RGB_BUFFER); 635 636 if (criteria) { 637 val1 = val2 = 0; 638 if (rgb_buffer) { 639 if (GET_CONFIG_ATTRIB(criteria, EGL_RED_SIZE) > 0) { 640 val1 += GET_CONFIG_ATTRIB(conf1, EGL_RED_SIZE); 641 val2 += GET_CONFIG_ATTRIB(conf2, EGL_RED_SIZE); 642 } 643 if (GET_CONFIG_ATTRIB(criteria, EGL_GREEN_SIZE) > 0) { 644 val1 += GET_CONFIG_ATTRIB(conf1, EGL_GREEN_SIZE); 645 val2 += GET_CONFIG_ATTRIB(conf2, EGL_GREEN_SIZE); 646 } 647 if (GET_CONFIG_ATTRIB(criteria, EGL_BLUE_SIZE) > 0) { 648 val1 += GET_CONFIG_ATTRIB(conf1, EGL_BLUE_SIZE); 649 val2 += GET_CONFIG_ATTRIB(conf2, EGL_BLUE_SIZE); 650 } 651 } 652 else { 653 if (GET_CONFIG_ATTRIB(criteria, EGL_LUMINANCE_SIZE) > 0) { 654 val1 += GET_CONFIG_ATTRIB(conf1, EGL_LUMINANCE_SIZE); 655 val2 += GET_CONFIG_ATTRIB(conf2, EGL_LUMINANCE_SIZE); 656 } 657 } 658 if (GET_CONFIG_ATTRIB(criteria, EGL_ALPHA_SIZE) > 0) { 659 val1 += GET_CONFIG_ATTRIB(conf1, EGL_ALPHA_SIZE); 660 val2 += GET_CONFIG_ATTRIB(conf2, EGL_ALPHA_SIZE); 661 } 662 } 663 else { 664 /* assume the default criteria, which gives no specific ordering */ 665 val1 = val2 = 0; 666 } 667 668 /* for color bits, larger one is preferred */ 669 if (val1 != val2) 670 return (val2 - val1); 671 672 for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) { 673 val1 = GET_CONFIG_ATTRIB(conf1, compare_attribs[i]); 674 val2 = GET_CONFIG_ATTRIB(conf2, compare_attribs[i]); 675 if (val1 != val2) 676 return (val1 - val2); 677 } 678 679 /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */ 680 681 if (compare_id) { 682 val1 = GET_CONFIG_ATTRIB(conf1, EGL_CONFIG_ID); 683 val2 = GET_CONFIG_ATTRIB(conf2, EGL_CONFIG_ID); 684 assert(val1 != val2); 685 } 686 else { 687 val1 = val2 = 0; 688 } 689 690 return (val1 - val2); 691} 692 693 694static INLINE 695void _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2) 696{ 697 const _EGLConfig *tmp = *conf1; 698 *conf1 = *conf2; 699 *conf2 = tmp; 700} 701 702 703/** 704 * Quick sort an array of configs. This differs from the standard 705 * qsort() in that the compare function accepts an additional 706 * argument. 707 */ 708void 709_eglSortConfigs(const _EGLConfig **configs, EGLint count, 710 EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, 711 void *), 712 void *priv_data) 713{ 714 const EGLint pivot = 0; 715 EGLint i, j; 716 717 if (count <= 1) 718 return; 719 720 _eglSwapConfigs(&configs[pivot], &configs[count / 2]); 721 i = 1; 722 j = count - 1; 723 do { 724 while (i < count && compare(configs[i], configs[pivot], priv_data) < 0) 725 i++; 726 while (compare(configs[j], configs[pivot], priv_data) > 0) 727 j--; 728 if (i < j) { 729 _eglSwapConfigs(&configs[i], &configs[j]); 730 i++; 731 j--; 732 } 733 else if (i == j) { 734 i++; 735 j--; 736 break; 737 } 738 } while (i <= j); 739 _eglSwapConfigs(&configs[pivot], &configs[j]); 740 741 _eglSortConfigs(configs, j, compare, priv_data); 742 _eglSortConfigs(configs + i, count - i, compare, priv_data); 743} 744 745 746static int 747_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2, 748 void *priv_data) 749{ 750 const _EGLConfig *criteria = (const _EGLConfig *) priv_data; 751 return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE); 752} 753 754 755/** 756 * Typical fallback routine for eglChooseConfig 757 */ 758EGLBoolean 759_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list, 760 EGLConfig *configs, EGLint config_size, EGLint *num_configs) 761{ 762 _EGLConfig **configList, criteria; 763 EGLint i, count; 764 765 if (!num_configs) 766 return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs"); 767 768 _eglInitConfig(&criteria, disp, 0); 769 if (!_eglParseConfigAttribList(&criteria, attrib_list)) 770 return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); 771 772 /* allocate array of config pointers */ 773 configList = (_EGLConfig **) 774 malloc(disp->NumConfigs * sizeof(_EGLConfig *)); 775 if (!configList) 776 return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)"); 777 778 /* perform selection of configs */ 779 count = 0; 780 for (i = 0; i < disp->NumConfigs; i++) { 781 if (_eglMatchConfig(disp->Configs[i], &criteria)) 782 configList[count++] = disp->Configs[i]; 783 } 784 785 /* perform sorting of configs */ 786 if (configs && count) { 787 _eglSortConfigs((const _EGLConfig **) configList, count, 788 _eglFallbackCompare, (void *) &criteria); 789 count = MIN2(count, config_size); 790 for (i = 0; i < count; i++) 791 configs[i] = _eglGetConfigHandle(configList[i]); 792 } 793 794 free(configList); 795 796 *num_configs = count; 797 798 return EGL_TRUE; 799} 800 801 802/** 803 * Fallback for eglGetConfigAttrib. 804 */ 805EGLBoolean 806_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, 807 EGLint attribute, EGLint *value) 808{ 809 if (!_eglIsConfigAttribValid(conf, attribute)) 810 return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); 811 if (!value) 812 return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib"); 813 814 *value = GET_CONFIG_ATTRIB(conf, attribute); 815 return EGL_TRUE; 816} 817 818 819/** 820 * Fallback for eglGetConfigs. 821 */ 822EGLBoolean 823_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs, 824 EGLint config_size, EGLint *num_config) 825{ 826 if (!num_config) 827 return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs"); 828 829 if (configs) { 830 EGLint i; 831 *num_config = MIN2(disp->NumConfigs, config_size); 832 for (i = 0; i < *num_config; i++) 833 configs[i] = _eglGetConfigHandle(disp->Configs[i]); 834 } 835 else { 836 /* just return total number of supported configs */ 837 *num_config = disp->NumConfigs; 838 } 839 840 return EGL_TRUE; 841} 842