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