+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2009-2010 Chia-I Wu <olvaffe@gmail.com>
+ * 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.
*/
* IDs are from 1 to N respectively.
*/
void
-_eglInitConfig(_EGLConfig *config, _EGLDisplay *dpy, EGLint id)
+_eglInitConfig(_EGLConfig *conf, _EGLDisplay *dpy, EGLint id)
{
- memset(config, 0, sizeof(*config));
+ memset(conf, 0, sizeof(*conf));
- config->Display = dpy;
+ conf->Display = dpy;
/* 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;
}
/**
- * 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)
+PUBLIC EGLConfig
+_eglLinkConfig(_EGLConfig *conf)
{
+ _EGLDisplay *dpy = conf->Display;
+
/* sanity check */
- assert(GET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID) > 0);
+ assert(dpy && conf->ConfigID > 0);
if (!dpy->Configs) {
dpy->Configs = _eglCreateArray("Config", 16);
return (EGLConfig) NULL;
}
- conf->Display = dpy;
_eglAppendArray(dpy->Configs, (void *) conf);
return (EGLConfig) conf;
}
-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 *dpy)
{
_EGLConfig *conf;
+ if (!dpy)
+ return NULL;
+
conf = (_EGLConfig *) _eglFindArray(dpy->Configs, (void *) config);
if (conf)
assert(conf->Display == dpy);
- return (conf != NULL);
+ return conf;
}
{
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;
/* 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:
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)
break;
default:
assert(0);
+ mask = 0;
break;
}
if (val & ~mask)
/* 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;
}
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) {
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)
return EGL_FALSE;
switch (attr) {
- case EGL_MATCH_NATIVE_PIXMAP:
- return EGL_FALSE;
case EGL_Y_INVERTED_NOK:
return conf->Display->Extensions.NOK_texture_from_pixmap;
default:
* Return EGL_FALSE if any of the attribute is invalid.
*/
EGLBoolean
-_eglParseConfigAttribList(_EGLConfig *conf, const EGLint *attrib_list)
+_eglParseConfigAttribList(_EGLConfig *conf, _EGLDisplay *dpy,
+ 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, dpy, 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 */
if (!_eglIsConfigAttribValid(conf, attr))
return EGL_FALSE;
-
- SET_CONFIG_ATTRIB(conf, attr, 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 (conf->ConfigID > 0) {
+ if (conf->ConfigID != EGL_DONT_CARE) {
for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
attr = _eglValidationTable[i].attr;
if (attr != EGL_CONFIG_ID)
- SET_CONFIG_ATTRIB(conf, attr, EGL_DONT_CARE);
+ _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;
}
}
EGL_ALPHA_MASK_SIZE,
};
EGLint val1, val2;
- EGLBoolean rgb_buffer;
EGLint i;
if (conf1 == conf2)
/* 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);
+ 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);
+ 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 {
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;
}
* 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 *),
}
-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, disp, 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;
+ }
- configList = (_EGLConfig **) _eglFilterArray(disp->Configs, &count,
- (_EGLArrayForEach) _eglMatchConfig, (void *) &criteria);
+ configList = malloc(sizeof(*configList) * count);
if (!configList)
return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
+ /* 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]);
}
+static EGLBoolean
+_eglFallbackMatch(const _EGLConfig *conf, void *priv_data)
+{
+ return _eglMatchConfig(conf, (const _EGLConfig *) priv_data);
+}
+
+
+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);
+}
+
+
/**
* Fallback for eglGetConfigAttrib.
*/
{
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;
}