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