X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fegl%2Fmain%2Feglconfig.c;h=0a95e8ee05da9edc0989d8852a5f353b0dd7c74f;hb=2907faee7a3970a63daefd6017bb7b8691e7fc08;hp=4d149603ae5e079596aa19108ed55af78ce02d43;hpb=5e5d0ad08167c178fcda005862e3dbead3e8c482;p=mesa.git diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c index 4d149603ae5..0a95e8ee05d 100644 --- a/src/egl/main/eglconfig.c +++ b/src/egl/main/eglconfig.c @@ -1,21 +1,50 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * Copyright 2009-2010 Chia-I Wu + * Copyright 2010-2011 LunarG, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /** * EGL Configuration (pixel format) functions. */ #include -#include #include #include +#include "c99_compat.h" +#include "util/macros.h" + #include "eglconfig.h" #include "egldisplay.h" -#include "egldriver.h" -#include "eglglobals.h" +#include "eglcurrent.h" #include "egllog.h" -#define MIN2(A, B) (((A) < (B)) ? (A) : (B)) -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) /** @@ -27,103 +56,96 @@ * IDs are from 1 to N respectively. */ void -_eglInitConfig(_EGLConfig *config, EGLint id) +_eglInitConfig(_EGLConfig *conf, _EGLDisplay *disp, EGLint id) { - memset(config, 0, sizeof(*config)); + memset(conf, 0, sizeof(*conf)); + + conf->Display = disp; /* some attributes take non-zero default values */ - SET_CONFIG_ATTRIB(config, EGL_CONFIG_ID, id); - SET_CONFIG_ATTRIB(config, EGL_CONFIG_CAVEAT, EGL_NONE); - SET_CONFIG_ATTRIB(config, EGL_TRANSPARENT_TYPE, EGL_NONE); - SET_CONFIG_ATTRIB(config, EGL_NATIVE_VISUAL_TYPE, EGL_NONE); -#ifdef EGL_VERSION_1_2 - SET_CONFIG_ATTRIB(config, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER); -#endif /* EGL_VERSION_1_2 */ + conf->ConfigID = id; + conf->ConfigCaveat = EGL_NONE; + conf->TransparentType = EGL_NONE; + conf->NativeVisualType = EGL_NONE; + conf->ColorBufferType = EGL_RGB_BUFFER; + conf->ComponentType = EGL_COLOR_COMPONENT_TYPE_FIXED_EXT; } /** - * Link a config to a display and return the handle of the link. + * Link a config to its display and return the handle of the link. * The handle can be passed to client directly. * * Note that we just save the ptr to the config (we don't copy the config). */ EGLConfig -_eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf) +_eglLinkConfig(_EGLConfig *conf) { - _EGLConfig **configs; + _EGLDisplay *disp = conf->Display; /* sanity check */ - assert(GET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID) > 0); + assert(disp); + assert(conf->ConfigID > 0); - configs = dpy->Configs; - if (dpy->NumConfigs >= dpy->MaxConfigs) { - EGLint new_size = dpy->MaxConfigs + 16; - assert(dpy->NumConfigs < new_size); - - configs = realloc(dpy->Configs, new_size * sizeof(dpy->Configs[0])); - if (!configs) + if (!disp->Configs) { + disp->Configs = _eglCreateArray("Config", 16); + if (!disp->Configs) return (EGLConfig) NULL; - - dpy->Configs = configs; - dpy->MaxConfigs = new_size; } - conf->Display = dpy; - dpy->Configs[dpy->NumConfigs++] = conf; + _eglAppendArray(disp->Configs, (void *) conf); return (EGLConfig) conf; } -#ifndef _EGL_SKIP_HANDLE_CHECK - - -EGLBoolean -_eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy) +/** + * Lookup a handle to find the linked config. + * Return NULL if the handle has no corresponding linked config. + */ +_EGLConfig * +_eglLookupConfig(EGLConfig config, _EGLDisplay *disp) { - EGLint num_configs = (dpy) ? dpy->NumConfigs : 0; - EGLint i; + _EGLConfig *conf; - for (i = 0; i < num_configs; i++) { - _EGLConfig *conf = dpy->Configs[i]; - if (conf == (_EGLConfig *) config) { - assert(conf->Display == dpy); - break; - } - } - return (i < num_configs); -} + if (!disp) + return NULL; + conf = (_EGLConfig *) _eglFindArray(disp->Configs, (void *) config); + if (conf) + assert(conf->Display == disp); -#endif /* _EGL_SKIP_HANDLE_CHECK */ + return conf; +} -enum { - /* types */ +enum type { ATTRIB_TYPE_INTEGER, ATTRIB_TYPE_BOOLEAN, ATTRIB_TYPE_BITMASK, ATTRIB_TYPE_ENUM, ATTRIB_TYPE_PSEUDO, /* non-queryable */ ATTRIB_TYPE_PLATFORM, /* platform-dependent */ - /* criteria */ +}; + +enum criterion { ATTRIB_CRITERION_EXACT, ATTRIB_CRITERION_ATLEAST, ATTRIB_CRITERION_MASK, ATTRIB_CRITERION_SPECIAL, - ATTRIB_CRITERION_IGNORE, + ATTRIB_CRITERION_IGNORE }; /* EGL spec Table 3.1 and 3.4 */ static const struct { EGLint attr; - EGLint type; - EGLint criterion; + enum type type; + enum criterion criterion; EGLint default_value; } _eglValidationTable[] = { + /* core */ { EGL_BUFFER_SIZE, ATTRIB_TYPE_INTEGER, ATTRIB_CRITERION_ATLEAST, 0 }, @@ -220,16 +242,22 @@ static const struct { { EGL_TRANSPARENT_BLUE_VALUE, ATTRIB_TYPE_INTEGER, ATTRIB_CRITERION_EXACT, EGL_DONT_CARE }, - /* these are not real attributes */ { EGL_MATCH_NATIVE_PIXMAP, ATTRIB_TYPE_PSEUDO, ATTRIB_CRITERION_SPECIAL, EGL_NONE }, - { EGL_PRESERVED_RESOURCES, ATTRIB_TYPE_PSEUDO, - ATTRIB_CRITERION_IGNORE, - 0 }, - { EGL_NONE, ATTRIB_TYPE_PSEUDO, - ATTRIB_CRITERION_IGNORE, - 0 } + /* extensions */ + { EGL_Y_INVERTED_NOK, ATTRIB_TYPE_BOOLEAN, + ATTRIB_CRITERION_EXACT, + EGL_DONT_CARE }, + { EGL_FRAMEBUFFER_TARGET_ANDROID, ATTRIB_TYPE_BOOLEAN, + ATTRIB_CRITERION_EXACT, + EGL_DONT_CARE }, + { EGL_RECORDABLE_ANDROID, ATTRIB_TYPE_BOOLEAN, + ATTRIB_CRITERION_EXACT, + EGL_DONT_CARE }, + { EGL_COLOR_COMPONENT_TYPE_EXT, ATTRIB_TYPE_ENUM, + ATTRIB_CRITERION_EXACT, + EGL_COLOR_COMPONENT_TYPE_FIXED_EXT }, }; @@ -244,20 +272,16 @@ static const struct { EGLBoolean _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) { + _EGLDisplay *disp = conf->Display; EGLint i, attr, val; EGLBoolean valid = EGL_TRUE; - EGLint red_size = 0, green_size = 0, blue_size = 0, luminance_size = 0; - EGLint alpha_size = 0, buffer_size = 0; - - /* all attributes should have been listed */ - assert(ARRAY_SIZE(_eglValidationTable) == _EGL_CONFIG_NUM_ATTRIBS); /* check attributes by their types */ for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { EGLint mask; attr = _eglValidationTable[i].attr; - val = GET_CONFIG_ATTRIB(conf, attr); + val = _eglGetConfigKey(conf, attr); switch (_eglValidationTable[i].type) { case ATTRIB_TYPE_INTEGER: @@ -269,30 +293,14 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) break; case EGL_SAMPLE_BUFFERS: /* there can be at most 1 sample buffer */ - if (val > 1) + if (val > 1 || val < 0) valid = EGL_FALSE; break; - case EGL_RED_SIZE: - red_size = val; - break; - case EGL_GREEN_SIZE: - green_size = val; - break; - case EGL_BLUE_SIZE: - blue_size = val; - break; - case EGL_LUMINANCE_SIZE: - luminance_size = val; - break; - case EGL_ALPHA_SIZE: - alpha_size = val; - break; - case EGL_BUFFER_SIZE: - buffer_size = val; + default: + if (val < 0) + valid = EGL_FALSE; break; } - if (val < 0) - valid = EGL_FALSE; break; case ATTRIB_TYPE_BOOLEAN: if (val != EGL_TRUE && val != EGL_FALSE) @@ -313,8 +321,13 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER) valid = EGL_FALSE; break; + case EGL_COLOR_COMPONENT_TYPE_EXT: + if (val != EGL_COLOR_COMPONENT_TYPE_FIXED_EXT && + val != EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT) + valid = EGL_FALSE; + break; default: - assert(0); + unreachable("check _eglValidationTable[]"); break; } break; @@ -324,21 +337,24 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) mask = EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT | - EGL_SCREEN_BIT_MESA | /* XXX should check the extension */ EGL_VG_COLORSPACE_LINEAR_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT | EGL_MULTISAMPLE_RESOLVE_BOX_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + if (disp->Extensions.KHR_mutable_render_buffer) + mask |= EGL_MUTABLE_RENDER_BUFFER_BIT_KHR; break; case EGL_RENDERABLE_TYPE: case EGL_CONFORMANT: mask = EGL_OPENGL_ES_BIT | EGL_OPENVG_BIT | EGL_OPENGL_ES2_BIT | + EGL_OPENGL_ES3_BIT_KHR | EGL_OPENGL_BIT; break; default: - assert(0); + unreachable("check _eglValidationTable[]"); + mask = 0; break; } if (val & ~mask) @@ -352,9 +368,6 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) if (val != 0) valid = EGL_FALSE; break; - default: - assert(0); - break; } if (!valid && for_matching) { @@ -364,8 +377,11 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL) valid = EGL_TRUE; } - if (!valid) + if (!valid) { + _eglLog(_EGL_DEBUG, + "attribute 0x%04x has an invalid value 0x%x", attr, val); break; + } } /* any invalid attribute value should have been catched */ @@ -374,36 +390,45 @@ _eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching) /* now check for conflicting attribute values */ - switch (GET_CONFIG_ATTRIB(conf, EGL_COLOR_BUFFER_TYPE)) { + switch (conf->ColorBufferType) { case EGL_RGB_BUFFER: - if (luminance_size) + if (conf->LuminanceSize) valid = EGL_FALSE; - if (red_size + green_size + blue_size + alpha_size != buffer_size) + if (conf->RedSize + conf->GreenSize + + conf->BlueSize + conf->AlphaSize != conf->BufferSize) valid = EGL_FALSE; break; case EGL_LUMINANCE_BUFFER: - if (red_size || green_size || blue_size) + if (conf->RedSize || conf->GreenSize || conf->BlueSize) valid = EGL_FALSE; - if (luminance_size + alpha_size != buffer_size) + if (conf->LuminanceSize + conf->AlphaSize != conf->BufferSize) valid = EGL_FALSE; break; } + if (!valid) { + _eglLog(_EGL_DEBUG, "conflicting color buffer type and channel sizes"); + return EGL_FALSE; + } - val = GET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS); - if (!val && GET_CONFIG_ATTRIB(conf, EGL_SAMPLES)) + if (!conf->SampleBuffers && conf->Samples) valid = EGL_FALSE; + if (!valid) { + _eglLog(_EGL_DEBUG, "conflicting samples and sample buffers"); + return EGL_FALSE; + } - val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE); - if (!(val & EGL_WINDOW_BIT)) { - if (GET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID) != 0 || - GET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE) != EGL_NONE) + if (!(conf->SurfaceType & EGL_WINDOW_BIT)) { + if (conf->NativeVisualID != 0 || conf->NativeVisualType != EGL_NONE) valid = EGL_FALSE; } - if (!(val & EGL_PBUFFER_BIT)) { - if (GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB) || - GET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA)) + if (!(conf->SurfaceType & EGL_PBUFFER_BIT)) { + if (conf->BindToTextureRGB || conf->BindToTextureRGBA) valid = EGL_FALSE; } + if (!valid) { + _eglLog(_EGL_DEBUG, "conflicting surface type and native visual/texture binding"); + return EGL_FALSE; + } return valid; } @@ -429,11 +454,11 @@ _eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria) continue; attr = _eglValidationTable[i].attr; - cmp = GET_CONFIG_ATTRIB(criteria, attr); + cmp = _eglGetConfigKey(criteria, attr); if (cmp == EGL_DONT_CARE) continue; - val = GET_CONFIG_ATTRIB(conf, attr); + val = _eglGetConfigKey(conf, attr); switch (_eglValidationTable[i].criterion) { case ATTRIB_CRITERION_EXACT: if (val != cmp) @@ -450,100 +475,101 @@ _eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria) case ATTRIB_CRITERION_SPECIAL: /* ignored here */ break; - default: - assert(0); + case ATTRIB_CRITERION_IGNORE: + unreachable("already handled above"); break; } - if (!matched) + if (!matched) { +#ifndef DEBUG + /* only print the common errors when DEBUG is not defined */ + if (attr != EGL_RENDERABLE_TYPE) + break; +#endif + _eglLog(_EGL_DEBUG, + "the value (0x%x) of attribute 0x%04x did not meet the criteria (0x%x)", + val, attr, cmp); break; + } } return matched; } +static inline EGLBoolean +_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr) +{ + if (_eglOffsetOfConfig(attr) < 0) + return EGL_FALSE; + + switch (attr) { + case EGL_Y_INVERTED_NOK: + return conf->Display->Extensions.NOK_texture_from_pixmap; + case EGL_FRAMEBUFFER_TARGET_ANDROID: + return conf->Display->Extensions.ANDROID_framebuffer_target; + case EGL_RECORDABLE_ANDROID: + return conf->Display->Extensions.ANDROID_recordable; + default: + break; + } + + return EGL_TRUE; +} /** * Initialize a criteria config from the given attribute list. * Return EGL_FALSE if any of the attribute is invalid. */ EGLBoolean -_eglParseConfigAttribList(_EGLConfig *conf, const EGLint *attrib_list) +_eglParseConfigAttribList(_EGLConfig *conf, _EGLDisplay *disp, + const EGLint *attrib_list) { EGLint attr, val, i; - EGLint config_id = 0, level = 0; - EGLBoolean has_native_visual_type = EGL_FALSE; - EGLBoolean has_transparent_color = EGL_FALSE; + + _eglInitConfig(conf, disp, EGL_DONT_CARE); /* reset to default values */ for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { attr = _eglValidationTable[i].attr; val = _eglValidationTable[i].default_value; - SET_CONFIG_ATTRIB(conf, attr, val); + _eglSetConfigKey(conf, attr, val); } /* parse the list */ for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i += 2) { - EGLint idx; - attr = attrib_list[i]; val = attrib_list[i + 1]; - idx = _eglIndexConfig(conf, attr); - if (idx < 0) + if (!_eglIsConfigAttribValid(conf, attr)) return EGL_FALSE; - conf->Storage[idx] = val; - /* rememeber some attributes for post-processing */ - switch (attr) { - case EGL_CONFIG_ID: - config_id = val; - break; - case EGL_LEVEL: - level = val; - break; - case EGL_NATIVE_VISUAL_TYPE: - has_native_visual_type = EGL_TRUE; - break; - case EGL_TRANSPARENT_RED_VALUE: - case EGL_TRANSPARENT_GREEN_VALUE: - case EGL_TRANSPARENT_BLUE_VALUE: - has_transparent_color = EGL_TRUE; - break; - default: - break; - } + _eglSetConfigKey(conf, attr, val); } if (!_eglValidateConfig(conf, EGL_TRUE)) return EGL_FALSE; - /* the spec says that EGL_LEVEL cannot be EGL_DONT_CARE */ - if (level == EGL_DONT_CARE) + /* EGL_LEVEL and EGL_MATCH_NATIVE_PIXMAP cannot be EGL_DONT_CARE */ + if (conf->Level == EGL_DONT_CARE || + conf->MatchNativePixmap == EGL_DONT_CARE) return EGL_FALSE; /* ignore other attributes when EGL_CONFIG_ID is given */ - if (config_id > 0) { - _eglResetConfigKeys(conf, EGL_DONT_CARE); - SET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID, config_id); + if (conf->ConfigID != EGL_DONT_CARE) { + for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) { + attr = _eglValidationTable[i].attr; + if (attr != EGL_CONFIG_ID) + _eglSetConfigKey(conf, attr, EGL_DONT_CARE); + } } else { - if (has_native_visual_type) { - val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE); - if (!(val & EGL_WINDOW_BIT)) - SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE); - } + if (!(conf->SurfaceType & EGL_WINDOW_BIT)) + conf->NativeVisualType = EGL_DONT_CARE; - if (has_transparent_color) { - val = GET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE); - if (val == EGL_NONE) { - SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, - EGL_DONT_CARE); - SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, - EGL_DONT_CARE); - SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, - EGL_DONT_CARE); - } + if (conf->TransparentType == EGL_NONE) { + conf->TransparentRedValue = EGL_DONT_CARE; + conf->TransparentGreenValue = EGL_DONT_CARE; + conf->TransparentBlueValue = EGL_DONT_CARE; } } @@ -577,53 +603,49 @@ _eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2, EGL_ALPHA_MASK_SIZE, }; EGLint val1, val2; - EGLBoolean rgb_buffer; EGLint i; if (conf1 == conf2) return 0; /* the enum values have the desired ordering */ - assert(EGL_NONE < EGL_SLOW_CONFIG); - assert(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); - val1 = GET_CONFIG_ATTRIB(conf1, EGL_CONFIG_CAVEAT); - val2 = GET_CONFIG_ATTRIB(conf2, EGL_CONFIG_CAVEAT); - if (val1 != val2) - return (val1 - val2); + STATIC_ASSERT(EGL_NONE < EGL_SLOW_CONFIG); + STATIC_ASSERT(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG); + val1 = conf1->ConfigCaveat - conf2->ConfigCaveat; + if (val1) + return val1; /* the enum values have the desired ordering */ - assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); - val1 = GET_CONFIG_ATTRIB(conf1, EGL_COLOR_BUFFER_TYPE); - val2 = GET_CONFIG_ATTRIB(conf2, EGL_COLOR_BUFFER_TYPE); - if (val1 != val2) - return (val1 - val2); - rgb_buffer = (val1 == EGL_RGB_BUFFER); + STATIC_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER); + val1 = conf1->ColorBufferType - conf2->ColorBufferType; + if (val1) + return val1; if (criteria) { val1 = val2 = 0; - if (rgb_buffer) { - if (GET_CONFIG_ATTRIB(criteria, EGL_RED_SIZE) > 0) { - val1 += GET_CONFIG_ATTRIB(conf1, EGL_RED_SIZE); - val2 += GET_CONFIG_ATTRIB(conf2, EGL_RED_SIZE); + if (conf1->ColorBufferType == EGL_RGB_BUFFER) { + if (criteria->RedSize > 0) { + val1 += conf1->RedSize; + val2 += conf2->RedSize; } - if (GET_CONFIG_ATTRIB(criteria, EGL_GREEN_SIZE) > 0) { - val1 += GET_CONFIG_ATTRIB(conf1, EGL_GREEN_SIZE); - val2 += GET_CONFIG_ATTRIB(conf2, EGL_GREEN_SIZE); + if (criteria->GreenSize > 0) { + val1 += conf1->GreenSize; + val2 += conf2->GreenSize; } - if (GET_CONFIG_ATTRIB(criteria, EGL_BLUE_SIZE) > 0) { - val1 += GET_CONFIG_ATTRIB(conf1, EGL_BLUE_SIZE); - val2 += GET_CONFIG_ATTRIB(conf2, EGL_BLUE_SIZE); + if (criteria->BlueSize > 0) { + val1 += conf1->BlueSize; + val2 += conf2->BlueSize; } } else { - if (GET_CONFIG_ATTRIB(criteria, EGL_LUMINANCE_SIZE) > 0) { - val1 += GET_CONFIG_ATTRIB(conf1, EGL_LUMINANCE_SIZE); - val2 += GET_CONFIG_ATTRIB(conf2, EGL_LUMINANCE_SIZE); + if (criteria->LuminanceSize > 0) { + val1 += conf1->LuminanceSize; + val2 += conf2->LuminanceSize; } } - if (GET_CONFIG_ATTRIB(criteria, EGL_ALPHA_SIZE) > 0) { - val1 += GET_CONFIG_ATTRIB(conf1, EGL_ALPHA_SIZE); - val2 += GET_CONFIG_ATTRIB(conf2, EGL_ALPHA_SIZE); + if (criteria->AlphaSize > 0) { + val1 += conf1->AlphaSize; + val2 += conf2->AlphaSize; } } else { @@ -636,28 +658,19 @@ _eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2, return (val2 - val1); for (i = 0; i < ARRAY_SIZE(compare_attribs); i++) { - val1 = GET_CONFIG_ATTRIB(conf1, compare_attribs[i]); - val2 = GET_CONFIG_ATTRIB(conf2, compare_attribs[i]); + val1 = _eglGetConfigKey(conf1, compare_attribs[i]); + val2 = _eglGetConfigKey(conf2, compare_attribs[i]); if (val1 != val2) return (val1 - val2); } /* EGL_NATIVE_VISUAL_TYPE cannot be compared here */ - if (compare_id) { - val1 = GET_CONFIG_ATTRIB(conf1, EGL_CONFIG_ID); - val2 = GET_CONFIG_ATTRIB(conf2, EGL_CONFIG_ID); - assert(val1 != val2); - } - else { - val1 = val2 = 0; - } - - return (val1 - val2); + return (compare_id) ? (conf1->ConfigID - conf2->ConfigID) : 0; } -static INLINE +static inline void _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2) { const _EGLConfig *tmp = *conf1; @@ -671,7 +684,7 @@ void _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2) * qsort() in that the compare function accepts an additional * argument. */ -void +static void _eglSortConfigs(const _EGLConfig **configs, EGLint count, EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, void *), @@ -709,49 +722,41 @@ _eglSortConfigs(const _EGLConfig **configs, EGLint count, } -static int -_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2, - void *priv_data) -{ - const _EGLConfig *criteria = (const _EGLConfig *) priv_data; - return _eglCompareConfigs(conf1, conf2, criteria, EGL_TRUE); -} - - /** - * Typical fallback routine for eglChooseConfig + * A helper function for implementing eglChooseConfig. See _eglFilterArray and + * _eglSortConfigs for the meanings of match and compare. */ EGLBoolean -_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list, - EGLConfig *configs, EGLint config_size, EGLint *num_configs) +_eglFilterConfigArray(_EGLArray *array, EGLConfig *configs, + EGLint config_size, EGLint *num_configs, + EGLBoolean (*match)(const _EGLConfig *, void *), + EGLint (*compare)(const _EGLConfig *, const _EGLConfig *, + void *), + void *priv_data) { - _EGLConfig **configList, criteria; + _EGLConfig **configList; EGLint i, count; - if (!num_configs) - return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs"); - - _eglInitConfig(&criteria, 0); - if (!_eglParseConfigAttribList(&criteria, attrib_list)) - return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); + /* get the number of matched configs */ + count = _eglFilterArray(array, NULL, 0, + (_EGLArrayForEach) match, priv_data); + if (!count) { + *num_configs = count; + return EGL_TRUE; + } - /* allocate array of config pointers */ - configList = (_EGLConfig **) - malloc(disp->NumConfigs * sizeof(_EGLConfig *)); + configList = malloc(sizeof(*configList) * count); if (!configList) return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)"); - /* perform selection of configs */ - count = 0; - for (i = 0; i < disp->NumConfigs; i++) { - if (_eglMatchConfig(disp->Configs[i], &criteria)) - configList[count++] = disp->Configs[i]; - } + /* get the matched configs */ + _eglFilterArray(array, (void **) configList, count, + (_EGLArrayForEach) match, priv_data); /* perform sorting of configs */ if (configs && count) { _eglSortConfigs((const _EGLConfig **) configList, count, - _eglFallbackCompare, (void *) &criteria); + compare, priv_data); count = MIN2(count, config_size); for (i = 0; i < count; i++) configs[i] = _eglGetConfigHandle(configList[i]); @@ -765,25 +770,38 @@ _eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list, } -static INLINE EGLBoolean -_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr) +static EGLBoolean +_eglFallbackMatch(const _EGLConfig *conf, void *priv_data) { - if (_eglIndexConfig(conf, attr) < 0) - return EGL_FALSE; + return _eglMatchConfig(conf, (const _EGLConfig *) priv_data); +} - /* there are some holes in the range */ - switch (attr) { - case EGL_PRESERVED_RESOURCES: - case EGL_NONE: -#ifdef EGL_VERSION_1_4 - case EGL_MATCH_NATIVE_PIXMAP: -#endif - return EGL_FALSE; - default: - break; - } - return EGL_TRUE; +static EGLint +_eglFallbackCompare(const _EGLConfig *conf1, const _EGLConfig *conf2, + void *priv_data) +{ + return _eglCompareConfigs(conf1, conf2, + (const _EGLConfig *) priv_data, EGL_TRUE); +} + + +/** + * Typical fallback routine for eglChooseConfig + */ +EGLBoolean +_eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list, + EGLConfig *configs, EGLint config_size, EGLint *num_configs) +{ + _EGLConfig criteria; + + if (!_eglParseConfigAttribList(&criteria, disp, attrib_list)) + return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig"); + + return _eglFilterConfigArray(disp->Configs, + configs, config_size, num_configs, + _eglFallbackMatch, _eglFallbackCompare, + (void *) &criteria); } @@ -791,19 +809,38 @@ _eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr) * Fallback for eglGetConfigAttrib. */ EGLBoolean -_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, +_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf, EGLint attribute, EGLint *value) { if (!_eglIsConfigAttribValid(conf, attribute)) return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); + + /* nonqueryable attributes */ + switch (attribute) { + case EGL_MATCH_NATIVE_PIXMAP: + return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib"); + break; + default: + break; + } + if (!value) return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib"); - *value = GET_CONFIG_ATTRIB(conf, attribute); + *value = _eglGetConfigKey(conf, attribute); return EGL_TRUE; } +static EGLBoolean +_eglFlattenConfig(void *elem, void *buffer) +{ + _EGLConfig *conf = (_EGLConfig *) elem; + EGLConfig *handle = (EGLConfig *) buffer; + *handle = _eglGetConfigHandle(conf); + return EGL_TRUE; +} + /** * Fallback for eglGetConfigs. */ @@ -811,19 +848,8 @@ EGLBoolean _eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs, EGLint config_size, EGLint *num_config) { - if (!num_config) - return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs"); - - if (configs) { - EGLint i; - *num_config = MIN2(disp->NumConfigs, config_size); - for (i = 0; i < *num_config; i++) - configs[i] = _eglGetConfigHandle(disp->Configs[i]); - } - else { - /* just return total number of supported configs */ - *num_config = disp->NumConfigs; - } + *num_config = _eglFlattenArray(disp->Configs, (void *) configs, + sizeof(configs[0]), config_size, _eglFlattenConfig); return EGL_TRUE; }