+/**************************************************************************
+ *
+ * Copyright 2008 VMware, Inc.
+ * 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.
*/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
+#include "c99_compat.h"
+#include "util/macros.h"
+
#include "eglconfig.h"
#include "egldisplay.h"
#include "eglcurrent.h"
#include "egllog.h"
-#define MIN2(A, B) (((A) < (B)) ? (A) : (B))
/**
* IDs are from 1 to N respectively.
*/
void
-_eglInitConfig(_EGLConfig *conf, _EGLDisplay *dpy, EGLint id)
+_eglInitConfig(_EGLConfig *conf, _EGLDisplay *disp, EGLint id)
{
memset(conf, 0, sizeof(*conf));
- conf->Display = dpy;
+ conf->Display = disp;
/* some attributes take non-zero default values */
conf->ConfigID = id;
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)
{
+ _EGLDisplay *disp = conf->Display;
+
/* sanity check */
+ assert(disp);
assert(conf->ConfigID > 0);
- if (!dpy->Configs) {
- dpy->Configs = _eglCreateArray("Config", 16);
- if (!dpy->Configs)
+ if (!disp->Configs) {
+ disp->Configs = _eglCreateArray("Config", 16);
+ if (!disp->Configs)
return (EGLConfig) NULL;
}
- conf->Display = dpy;
- _eglAppendArray(dpy->Configs, (void *) conf);
+ _eglAppendArray(disp->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 *disp)
{
_EGLConfig *conf;
- conf = (_EGLConfig *) _eglFindArray(dpy->Configs, (void *) config);
+ if (!disp)
+ return NULL;
+
+ conf = (_EGLConfig *) _eglFindArray(disp->Configs, (void *) config);
if (conf)
- assert(conf->Display == dpy);
+ assert(conf->Display == disp);
- return (conf != NULL);
+ 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,
/* 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[] =
{
/* extensions */
{ EGL_Y_INVERTED_NOK, ATTRIB_TYPE_BOOLEAN,
ATTRIB_CRITERION_EXACT,
- EGL_DONT_CARE }
+ 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 },
};
EGLBoolean
_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
{
+ _EGLDisplay *disp = conf->Display;
EGLint i, attr, val;
EGLBoolean valid = EGL_TRUE;
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;
EGL_VG_ALPHA_FORMAT_PRE_BIT |
EGL_MULTISAMPLE_RESOLVE_BOX_BIT |
EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
-#ifdef EGL_MESA_screen_surface
- if (conf->Display->Extensions.MESA_screen_surface)
- mask |= EGL_SCREEN_BIT_MESA;
-#endif
+ 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)
if (val != 0)
valid = EGL_FALSE;
break;
- default:
- assert(0);
- break;
}
if (!valid && for_matching) {
case ATTRIB_CRITERION_SPECIAL:
/* ignored here */
break;
- default:
- assert(0);
+ case ATTRIB_CRITERION_IGNORE:
+ unreachable("already handled above");
break;
}
return matched;
}
-static INLINE EGLBoolean
+static inline EGLBoolean
_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
{
if (_eglOffsetOfConfig(attr) < 0)
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;
+ 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_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;
+ _eglInitConfig(conf, disp, EGL_DONT_CARE);
+
/* reset to default values */
for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
attr = _eglValidationTable[i].attr;
val = attrib_list[i + 1];
if (!_eglIsConfigAttribValid(conf, attr))
- return EGL_FALSE;
+ return EGL_FALSE;
_eglSetConfigKey(conf, attr, val);
}
if (!_eglValidateConfig(conf, EGL_TRUE))
return EGL_FALSE;
- /* the spec says that EGL_LEVEL cannot be EGL_DONT_CARE */
- if (conf->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)
return 0;
/* the enum values have the desired ordering */
- assert(EGL_NONE < EGL_SLOW_CONFIG);
- assert(EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
+ 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);
+ STATIC_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
val1 = conf1->ColorBufferType - conf2->ColorBufferType;
if (val1)
return val1;
}
-static INLINE
+static inline
void _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2)
{
const _EGLConfig *tmp = *conf1;
* 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.
*/
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");
_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs,
EGLint config_size, EGLint *num_config)
{
- if (!num_config)
- return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs");
-
*num_config = _eglFlattenArray(disp->Configs, (void *) configs,
sizeof(configs[0]), config_size, _eglFlattenConfig);