Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

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