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