summaryrefslogtreecommitdiffstats
path: root/src/egl
diff options
context:
space:
mode:
authorNicolai Hähnle <[email protected]>2009-10-03 19:30:48 +0200
committerNicolai Hähnle <[email protected]>2009-10-03 19:30:48 +0200
commit6d25b9125ec1e66e0e255b0ee20fe18dfe1076fa (patch)
treec376951940eac2875567979a81e6a03a019942b7 /src/egl
parent81c7561d9d3faf70ac22c6a5f3fbea18f53eed92 (diff)
parent7d2699aedc084d9cb9c2bd2f8bdb5f038271ac1e (diff)
Merge branch 'master' into r300-compiler
Diffstat (limited to 'src/egl')
-rw-r--r--src/egl/drivers/demo/demo.c2
-rw-r--r--src/egl/drivers/xdri/egl_xdri.c97
-rw-r--r--src/egl/main/eglconfig.c940
-rw-r--r--src/egl/main/eglconfig.h157
-rw-r--r--src/egl/main/eglconfigutil.c72
-rw-r--r--src/egl/main/eglconfigutil.h13
-rw-r--r--src/egl/main/eglcontext.c40
-rw-r--r--src/egl/main/eglcontext.h3
-rw-r--r--src/egl/main/egldisplay.h1
9 files changed, 1005 insertions, 320 deletions
diff --git a/src/egl/drivers/demo/demo.c b/src/egl/drivers/demo/demo.c
index aea4894448b..0933c0bdaa5 100644
--- a/src/egl/drivers/demo/demo.c
+++ b/src/egl/drivers/demo/demo.c
@@ -177,7 +177,7 @@ demoCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf, Nat
}
}
- if (conf->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] == 0) {
+ if (GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE) == 0) {
_eglError(EGL_BAD_MATCH, "eglCreatePixmapSurface");
return NULL;
}
diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c
index 518091a2d14..d2affc66dd4 100644
--- a/src/egl/drivers/xdri/egl_xdri.c
+++ b/src/egl/drivers/xdri/egl_xdri.c
@@ -48,6 +48,7 @@
#include "glapi/glapi.h" /* for glapi functions */
#include "eglconfig.h"
+#include "eglconfigutil.h"
#include "eglcontext.h"
#include "egldisplay.h"
#include "egldriver.h"
@@ -104,6 +105,7 @@ struct xdri_egl_config
_EGLConfig Base; /**< base class */
const __GLcontextModes *mode; /**< corresponding GLX mode */
+ EGLint window_render_buffer;
};
@@ -162,46 +164,76 @@ get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
}
+static EGLBoolean
+convert_config(_EGLConfig *conf, EGLint id, const __GLcontextModes *m)
+{
+ static const EGLint all_apis = (EGL_OPENGL_ES_BIT |
+ EGL_OPENGL_ES2_BIT |
+ EGL_OPENVG_BIT |
+ EGL_OPENGL_BIT);
+ EGLint val;
+
+ _eglInitConfig(conf, id);
+ if (!_eglConfigFromContextModesRec(conf, m, all_apis, all_apis))
+ return EGL_FALSE;
+
+ if (m->doubleBufferMode) {
+ /* pixmap and pbuffer surfaces are always single-buffered */
+ val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
+ val &= ~(EGL_PIXMAP_BIT | EGL_PBUFFER_BIT);
+ SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, val);
+ }
+ else {
+ /* EGL requires OpenGL ES context to be double-buffered */
+ val = GET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE);
+ val &= ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT);
+ SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, val);
+ }
+ /* skip "empty" config */
+ if (!val)
+ return EGL_FALSE;
+
+ val = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
+ if (!(val & EGL_PBUFFER_BIT)) {
+ /* bind-to-texture cannot be EGL_TRUE without pbuffer bit */
+ SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, EGL_FALSE);
+ SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, EGL_FALSE);
+ }
+
+ /* EGL_NATIVE_RENDERABLE is a boolean */
+ val = GET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE);
+ if (val != EGL_TRUE)
+ SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, EGL_FALSE);
+
+ return _eglValidateConfig(conf, EGL_FALSE);
+}
+
+
/**
* Produce a set of EGL configs.
*/
static EGLint
create_configs(_EGLDisplay *disp, const __GLcontextModes *m, EGLint first_id)
{
- static const EGLint all_apis = (EGL_OPENGL_ES_BIT |
- EGL_OPENGL_ES2_BIT |
- EGL_OPENVG_BIT |
- EGL_OPENGL_BIT);
int id = first_id;
for (; m; m = m->next) {
- /* add double buffered visual */
- if (m->doubleBufferMode) {
- struct xdri_egl_config *config = CALLOC_STRUCT(xdri_egl_config);
-
- _eglInitConfig(&config->Base, id++);
-
- SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, m->rgbBits);
- SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, m->redBits);
- SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, m->greenBits);
- SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, m->blueBits);
- SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, m->alphaBits);
- SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, m->depthBits);
- SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, m->stencilBits);
- SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, m->samples);
- SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, m->sampleBuffers);
- SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, m->visualID);
- SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_TYPE, m->visualType);
- SET_CONFIG_ATTRIB(&config->Base, EGL_CONFORMANT, all_apis);
- SET_CONFIG_ATTRIB(&config->Base, EGL_RENDERABLE_TYPE, all_apis);
- SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
-
- /* XXX possibly other things to init... */
-
- /* Ptr from EGL config to GLcontextMode. Used in CreateContext(). */
- config->mode = m;
-
- _eglAddConfig(disp, &config->Base);
+ struct xdri_egl_config *xdri_conf;
+ _EGLConfig conf;
+ EGLint rb;
+
+ if (!convert_config(&conf, id, m))
+ continue;
+
+ rb = (m->doubleBufferMode) ? EGL_BACK_BUFFER : EGL_SINGLE_BUFFER;
+
+ xdri_conf = CALLOC_STRUCT(xdri_egl_config);
+ if (xdri_conf) {
+ memcpy(&xdri_conf->Base, &conf, sizeof(conf));
+ xdri_conf->mode = m;
+ xdri_conf->window_render_buffer = rb;
+ _eglAddConfig(disp, &xdri_conf->Base);
+ id++;
}
}
@@ -363,6 +395,9 @@ xdri_eglCreateContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
return NULL;
}
+ /* the config decides the render buffer for the context */
+ xdri_ctx->Base.WindowRenderBuffer = xdri_config->window_render_buffer;
+
xdri_ctx->driContext =
psc->driScreen->createContext(psc,
xdri_config->mode,
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index d47b99eed4b..2c8d1c4055b 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -15,302 +15,706 @@
#define MIN2(A, B) (((A) < (B)) ? (A) : (B))
-
-
-void
-_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val)
-{
- assert(attr >= FIRST_ATTRIB);
- assert(attr < FIRST_ATTRIB + MAX_ATTRIBS);
- config->Attrib[attr - FIRST_ATTRIB] = val;
-}
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
/**
* Init the given _EGLconfig to default values.
* \param id the configuration's ID.
+ *
+ * Note that id must be positive for the config to be valid.
+ * It is also recommended that when there are N configs, their
+ * IDs are from 1 to N respectively.
*/
void
_eglInitConfig(_EGLConfig *config, EGLint id)
{
memset(config, 0, sizeof(*config));
- config->Handle = (EGLConfig) _eglUIntToPointer((unsigned int) id);
- _eglSetConfigAttrib(config, EGL_CONFIG_ID, id);
- _eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGB, EGL_DONT_CARE);
- _eglSetConfigAttrib(config, EGL_BIND_TO_TEXTURE_RGBA, EGL_DONT_CARE);
- _eglSetConfigAttrib(config, EGL_CONFIG_CAVEAT, EGL_DONT_CARE);
- _eglSetConfigAttrib(config, EGL_NATIVE_RENDERABLE, EGL_DONT_CARE);
- _eglSetConfigAttrib(config, EGL_NATIVE_VISUAL_TYPE, EGL_DONT_CARE);
- _eglSetConfigAttrib(config, EGL_MIN_SWAP_INTERVAL, EGL_DONT_CARE);
- _eglSetConfigAttrib(config, EGL_MAX_SWAP_INTERVAL, EGL_DONT_CARE);
- _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_WINDOW_BIT);
- _eglSetConfigAttrib(config, EGL_TRANSPARENT_TYPE, EGL_NONE);
- _eglSetConfigAttrib(config, EGL_TRANSPARENT_RED_VALUE, EGL_DONT_CARE);
- _eglSetConfigAttrib(config, EGL_TRANSPARENT_GREEN_VALUE, EGL_DONT_CARE);
- _eglSetConfigAttrib(config, EGL_TRANSPARENT_BLUE_VALUE, EGL_DONT_CARE);
+
+ /* 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
- _eglSetConfigAttrib(config, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
- _eglSetConfigAttrib(config, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT);
+ SET_CONFIG_ATTRIB(config, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
#endif /* EGL_VERSION_1_2 */
}
/**
- * Return the public handle for an internal _EGLConfig.
- * This is the inverse of _eglLookupConfig().
+ * Link a config to a 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
-_eglGetConfigHandle(_EGLConfig *config)
+_eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf)
{
- return config ? config->Handle : 0;
+ _EGLConfig **configs;
+
+ /* sanity check */
+ assert(GET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID) > 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)
+ return (EGLConfig) NULL;
+
+ dpy->Configs = configs;
+ dpy->MaxConfigs = new_size;
+ }
+
+ conf->Display = dpy;
+ dpy->Configs[dpy->NumConfigs++] = conf;
+
+ return (EGLConfig) conf;
}
-/**
- * Given an EGLConfig handle, return the corresponding _EGLConfig object.
- * This is the inverse of _eglGetConfigHandle().
- */
-_EGLConfig *
-_eglLookupConfig(EGLConfig config, _EGLDisplay *disp)
+#ifndef _EGL_SKIP_HANDLE_CHECK
+
+
+EGLBoolean
+_eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy)
{
+ _EGLConfig *conf = NULL;
EGLint i;
- for (i = 0; i < disp->NumConfigs; i++) {
- if (disp->Configs[i]->Handle == config) {
- return disp->Configs[i];
+
+ for (i = 0; dpy && i < dpy->NumConfigs; i++) {
+ conf = dpy->Configs[i];
+ if (conf == (_EGLConfig *) config) {
+ assert(conf->Display == dpy);
+ break;
}
}
- return NULL;
+
+ return (conf != NULL);
}
-/**
- * Add the given _EGLConfig to the given display.
- * Note that we just save the ptr to the config (we don't copy the config).
- */
-_EGLConfig *
-_eglAddConfig(_EGLDisplay *display, _EGLConfig *config)
+#endif /* _EGL_SKIP_HANDLE_CHECK */
+
+
+enum {
+ /* types */
+ ATTRIB_TYPE_INTEGER,
+ ATTRIB_TYPE_BOOLEAN,
+ ATTRIB_TYPE_BITMASK,
+ ATTRIB_TYPE_ENUM,
+ ATTRIB_TYPE_PSEUDO, /* non-queryable */
+ ATTRIB_TYPE_PLATFORM, /* platform-dependent */
+ /* criteria */
+ ATTRIB_CRITERION_EXACT,
+ ATTRIB_CRITERION_ATLEAST,
+ ATTRIB_CRITERION_MASK,
+ ATTRIB_CRITERION_SPECIAL,
+ ATTRIB_CRITERION_IGNORE,
+};
+
+
+/* EGL spec Table 3.1 and 3.4 */
+static const struct {
+ EGLint attr;
+ EGLint type;
+ EGLint criterion;
+ EGLint default_value;
+} _eglValidationTable[] =
{
- _EGLConfig **newConfigs;
- EGLint n;
-
- /* do some sanity checks on the config's attribs */
- assert(GET_CONFIG_ATTRIB(config, EGL_CONFIG_ID) > 0);
- assert(GET_CONFIG_ATTRIB(config, EGL_RENDERABLE_TYPE) != 0x0);
- assert(GET_CONFIG_ATTRIB(config, EGL_SURFACE_TYPE) != 0x0);
- assert(GET_CONFIG_ATTRIB(config, EGL_RED_SIZE) > 0);
- assert(GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE) > 0);
- assert(GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE) > 0);
-
- n = display->NumConfigs;
-
- /* realloc array of ptrs */
- newConfigs = (_EGLConfig **) realloc(display->Configs,
- (n + 1) * sizeof(_EGLConfig *));
- if (newConfigs) {
- display->Configs = newConfigs;
- display->Configs[n] = config;
- display->NumConfigs++;
- return config;
- }
- else {
- return NULL;
- }
-}
+ { EGL_BUFFER_SIZE, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_ATLEAST,
+ 0 },
+ { EGL_RED_SIZE, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_ATLEAST,
+ 0 },
+ { EGL_GREEN_SIZE, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_ATLEAST,
+ 0 },
+ { EGL_BLUE_SIZE, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_ATLEAST,
+ 0 },
+ { EGL_LUMINANCE_SIZE, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_ATLEAST,
+ 0 },
+ { EGL_ALPHA_SIZE, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_ATLEAST,
+ 0 },
+ { EGL_ALPHA_MASK_SIZE, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_ATLEAST,
+ 0 },
+ { EGL_BIND_TO_TEXTURE_RGB, ATTRIB_TYPE_BOOLEAN,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_BIND_TO_TEXTURE_RGBA, ATTRIB_TYPE_BOOLEAN,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_COLOR_BUFFER_TYPE, ATTRIB_TYPE_ENUM,
+ ATTRIB_CRITERION_EXACT,
+ EGL_RGB_BUFFER },
+ { EGL_CONFIG_CAVEAT, ATTRIB_TYPE_ENUM,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_CONFIG_ID, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_CONFORMANT, ATTRIB_TYPE_BITMASK,
+ ATTRIB_CRITERION_MASK,
+ 0 },
+ { EGL_DEPTH_SIZE, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_ATLEAST,
+ 0 },
+ { EGL_LEVEL, ATTRIB_TYPE_PLATFORM,
+ ATTRIB_CRITERION_EXACT,
+ 0 },
+ { EGL_MAX_PBUFFER_WIDTH, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_IGNORE,
+ 0 },
+ { EGL_MAX_PBUFFER_HEIGHT, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_IGNORE,
+ 0 },
+ { EGL_MAX_PBUFFER_PIXELS, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_IGNORE,
+ 0 },
+ { EGL_MAX_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_MIN_SWAP_INTERVAL, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_NATIVE_RENDERABLE, ATTRIB_TYPE_BOOLEAN,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_NATIVE_VISUAL_ID, ATTRIB_TYPE_PLATFORM,
+ ATTRIB_CRITERION_IGNORE,
+ 0 },
+ { EGL_NATIVE_VISUAL_TYPE, ATTRIB_TYPE_PLATFORM,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_RENDERABLE_TYPE, ATTRIB_TYPE_BITMASK,
+ ATTRIB_CRITERION_MASK,
+ EGL_OPENGL_ES_BIT },
+ { EGL_SAMPLE_BUFFERS, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_ATLEAST,
+ 0 },
+ { EGL_SAMPLES, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_ATLEAST,
+ 0 },
+ { EGL_STENCIL_SIZE, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_ATLEAST,
+ 0 },
+ { EGL_SURFACE_TYPE, ATTRIB_TYPE_BITMASK,
+ ATTRIB_CRITERION_MASK,
+ EGL_WINDOW_BIT },
+ { EGL_TRANSPARENT_TYPE, ATTRIB_TYPE_ENUM,
+ ATTRIB_CRITERION_EXACT,
+ EGL_NONE },
+ { EGL_TRANSPARENT_RED_VALUE, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { EGL_TRANSPARENT_GREEN_VALUE, ATTRIB_TYPE_INTEGER,
+ ATTRIB_CRITERION_EXACT,
+ EGL_DONT_CARE },
+ { 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 }
+};
/**
- * Parse the attrib_list to fill in the fields of the given _eglConfig
- * Return EGL_FALSE if any errors, EGL_TRUE otherwise.
+ * Return true if a config is valid. When for_matching is true,
+ * EGL_DONT_CARE is accepted as a valid attribute value, and checks
+ * for conflicting attribute values are skipped.
+ *
+ * Note that some attributes are platform-dependent and are not
+ * checked.
*/
EGLBoolean
-_eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list)
+_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching)
{
- EGLint i;
-
- /* set all config attribs to EGL_DONT_CARE */
- for (i = 0; i < MAX_ATTRIBS; i++) {
- config->Attrib[i] = EGL_DONT_CARE;
- }
-
- /* by default choose windows unless otherwise specified */
- config->Attrib[EGL_SURFACE_TYPE - FIRST_ATTRIB] = EGL_WINDOW_BIT;
-
- for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
- const EGLint attr = attrib_list[i];
- if (attr >= EGL_BUFFER_SIZE &&
- attr <= EGL_MAX_SWAP_INTERVAL) {
- EGLint k = attr - FIRST_ATTRIB;
- assert(k >= 0);
- assert(k < MAX_ATTRIBS);
- config->Attrib[k] = attrib_list[++i];
- }
-#ifdef EGL_VERSION_1_2
- else if (attr == EGL_COLOR_BUFFER_TYPE) {
- EGLint bufType = attrib_list[++i];
- if (bufType != EGL_RGB_BUFFER && bufType != EGL_LUMINANCE_BUFFER) {
- _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
- return EGL_FALSE;
+ 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);
+
+ switch (_eglValidationTable[i].type) {
+ case ATTRIB_TYPE_INTEGER:
+ switch (attr) {
+ case EGL_CONFIG_ID:
+ /* config id must be positive */
+ if (val <= 0)
+ valid = EGL_FALSE;
+ break;
+ case EGL_SAMPLE_BUFFERS:
+ /* there can be at most 1 sample buffer */
+ if (val > 1)
+ 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;
+ break;
}
- _eglSetConfigAttrib(config, EGL_COLOR_BUFFER_TYPE, bufType);
- }
- else if (attr == EGL_RENDERABLE_TYPE) {
- EGLint renType = attrib_list[++i];
- if (renType & ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENVG_BIT)) {
- _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
- return EGL_FALSE;
+ if (val < 0)
+ valid = EGL_FALSE;
+ break;
+ case ATTRIB_TYPE_BOOLEAN:
+ if (val != EGL_TRUE && val != EGL_FALSE)
+ valid = EGL_FALSE;
+ break;
+ case ATTRIB_TYPE_ENUM:
+ switch (attr) {
+ case EGL_CONFIG_CAVEAT:
+ if (val != EGL_NONE && val != EGL_SLOW_CONFIG &&
+ val != EGL_NON_CONFORMANT_CONFIG)
+ valid = EGL_FALSE;
+ break;
+ case EGL_TRANSPARENT_TYPE:
+ if (val != EGL_NONE && val != EGL_TRANSPARENT_RGB)
+ valid = EGL_FALSE;
+ break;
+ case EGL_COLOR_BUFFER_TYPE:
+ if (val != EGL_RGB_BUFFER && val != EGL_LUMINANCE_BUFFER)
+ valid = EGL_FALSE;
+ break;
+ default:
+ assert(0);
+ break;
}
- _eglSetConfigAttrib(config, EGL_RENDERABLE_TYPE, renType);
- }
- else if (attr == EGL_ALPHA_MASK_SIZE ||
- attr == EGL_LUMINANCE_SIZE) {
- EGLint value = attrib_list[++i];
- _eglSetConfigAttrib(config, attr, value);
+ break;
+ case ATTRIB_TYPE_BITMASK:
+ switch (attr) {
+ case EGL_SURFACE_TYPE:
+ mask = EGL_PBUFFER_BIT |
+ EGL_PIXMAP_BIT |
+ EGL_WINDOW_BIT |
+ EGL_VG_COLORSPACE_LINEAR_BIT |
+ EGL_VG_ALPHA_FORMAT_PRE_BIT |
+ EGL_MULTISAMPLE_RESOLVE_BOX_BIT |
+ EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+ break;
+ case EGL_RENDERABLE_TYPE:
+ case EGL_CONFORMANT:
+ mask = EGL_OPENGL_ES_BIT |
+ EGL_OPENVG_BIT |
+ EGL_OPENGL_ES2_BIT |
+ EGL_OPENGL_BIT;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ if (val & ~mask)
+ valid = EGL_FALSE;
+ break;
+ case ATTRIB_TYPE_PLATFORM:
+ /* unable to check platform-dependent attributes here */
+ break;
+ case ATTRIB_TYPE_PSEUDO:
+ /* pseudo attributes should not be set */
+ if (val != 0)
+ valid = EGL_FALSE;
+ break;
+ default:
+ assert(0);
+ break;
}
-#endif /* EGL_VERSION_1_2 */
- else {
- _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
- return EGL_FALSE;
+
+ if (!valid && for_matching) {
+ /* accept EGL_DONT_CARE as a valid value */
+ if (val == EGL_DONT_CARE)
+ valid = EGL_TRUE;
+ if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_SPECIAL)
+ valid = EGL_TRUE;
}
+ if (!valid)
+ break;
}
- return EGL_TRUE;
-}
+ /* any invalid attribute value should have been catched */
+ if (!valid || for_matching)
+ return valid;
+
+ /* now check for conflicting attribute values */
+
+ switch (GET_CONFIG_ATTRIB(conf, EGL_COLOR_BUFFER_TYPE)) {
+ case EGL_RGB_BUFFER:
+ if (luminance_size)
+ valid = EGL_FALSE;
+ if (red_size + green_size + blue_size + alpha_size != buffer_size)
+ valid = EGL_FALSE;
+ break;
+ case EGL_LUMINANCE_BUFFER:
+ if (red_size || green_size || blue_size)
+ valid = EGL_FALSE;
+ if (luminance_size + alpha_size != buffer_size)
+ valid = EGL_FALSE;
+ break;
+ }
-#define EXACT 1
-#define ATLEAST 2
-#define MASK 3
-#define SMALLER 4
-#define SPECIAL 5
-#define NONE 6
+ val = GET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS);
+ if (!val && GET_CONFIG_ATTRIB(conf, EGL_SAMPLES))
+ valid = 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)
+ 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))
+ valid = EGL_FALSE;
+ }
+
+ return valid;
+}
-struct sort_info {
- EGLint Attribute;
- EGLint MatchCriteria;
- EGLint SortOrder;
-};
-/* This encodes the info from Table 3.5 of the EGL spec, ordered by
- * Sort Priority.
+/**
+ * Return true if a config matches the criteria. This and
+ * _eglParseConfigAttribList together implement the algorithm
+ * described in "Selection of EGLConfigs".
*
- * XXX To do: EGL 1.2 attribs
+ * Note that attributes that are special (currently, only
+ * EGL_MATCH_NATIVE_PIXMAP) are ignored.
*/
-static struct sort_info SortInfo[] = {
- { EGL_CONFIG_CAVEAT, EXACT, SPECIAL },
- { EGL_RED_SIZE, ATLEAST, SPECIAL },
- { EGL_GREEN_SIZE, ATLEAST, SPECIAL },
- { EGL_BLUE_SIZE, ATLEAST, SPECIAL },
- { EGL_ALPHA_SIZE, ATLEAST, SPECIAL },
- { EGL_BUFFER_SIZE, ATLEAST, SMALLER },
- { EGL_SAMPLE_BUFFERS, ATLEAST, SMALLER },
- { EGL_SAMPLES, ATLEAST, SMALLER },
- { EGL_DEPTH_SIZE, ATLEAST, SMALLER },
- { EGL_STENCIL_SIZE, ATLEAST, SMALLER },
- { EGL_NATIVE_VISUAL_TYPE, EXACT, SPECIAL },
- { EGL_CONFIG_ID, EXACT, SMALLER },
- { EGL_BIND_TO_TEXTURE_RGB, EXACT, NONE },
- { EGL_BIND_TO_TEXTURE_RGBA, EXACT, NONE },
- { EGL_LEVEL, EXACT, NONE },
- { EGL_NATIVE_RENDERABLE, EXACT, NONE },
- { EGL_MAX_SWAP_INTERVAL, EXACT, NONE },
- { EGL_MIN_SWAP_INTERVAL, EXACT, NONE },
- { EGL_SURFACE_TYPE, MASK, NONE },
- { EGL_TRANSPARENT_TYPE, EXACT, NONE },
- { EGL_TRANSPARENT_RED_VALUE, EXACT, NONE },
- { EGL_TRANSPARENT_GREEN_VALUE, EXACT, NONE },
- { EGL_TRANSPARENT_BLUE_VALUE, EXACT, NONE },
- { 0, 0, 0 }
-};
+EGLBoolean
+_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria)
+{
+ EGLint attr, val, i;
+ EGLBoolean matched = EGL_TRUE;
+
+ for (i = 0; i < ARRAY_SIZE(_eglValidationTable); i++) {
+ EGLint cmp;
+ if (_eglValidationTable[i].criterion == ATTRIB_CRITERION_IGNORE)
+ continue;
+
+ attr = _eglValidationTable[i].attr;
+ cmp = GET_CONFIG_ATTRIB(criteria, attr);
+ if (cmp == EGL_DONT_CARE)
+ continue;
+
+ val = GET_CONFIG_ATTRIB(conf, attr);
+ switch (_eglValidationTable[i].criterion) {
+ case ATTRIB_CRITERION_EXACT:
+ if (val != cmp)
+ matched = EGL_FALSE;
+ break;
+ case ATTRIB_CRITERION_ATLEAST:
+ if (val < cmp)
+ matched = EGL_FALSE;
+ break;
+ case ATTRIB_CRITERION_MASK:
+ if ((val & cmp) != cmp)
+ matched = EGL_FALSE;
+ break;
+ case ATTRIB_CRITERION_SPECIAL:
+ /* ignored here */
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ if (!matched)
+ break;
+ }
+
+ return matched;
+}
/**
- * Return EGL_TRUE if the attributes of c meet or exceed the minimums
- * specified by min.
+ * Initialize a criteria config from the given attribute list.
+ * Return EGL_FALSE if any of the attribute is invalid.
*/
-static EGLBoolean
-_eglConfigQualifies(const _EGLConfig *c, const _EGLConfig *min)
+EGLBoolean
+_eglParseConfigAttribList(_EGLConfig *conf, const EGLint *attrib_list)
{
- EGLint i;
- for (i = 0; SortInfo[i].Attribute != 0; i++) {
- const EGLint mv = GET_CONFIG_ATTRIB(min, SortInfo[i].Attribute);
- if (mv != EGL_DONT_CARE) {
- const EGLint cv = GET_CONFIG_ATTRIB(c, SortInfo[i].Attribute);
- if (SortInfo[i].MatchCriteria == EXACT) {
- if (cv != mv) {
- return EGL_FALSE;
- }
- }
- else if (SortInfo[i].MatchCriteria == ATLEAST) {
- if (cv < mv) {
- return EGL_FALSE;
- }
- }
- else {
- assert(SortInfo[i].MatchCriteria == MASK);
- if ((mv & cv) != mv) {
- return EGL_FALSE;
- }
+ EGLint attr, val, i;
+ EGLint config_id = 0, level = 0;
+ EGLBoolean has_native_visual_type = EGL_FALSE;
+ EGLBoolean has_transparent_color = EGL_FALSE;
+
+ /* 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);
+ }
+
+ /* 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)
+ 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;
+ }
+ }
+
+ if (!_eglValidateConfig(conf, EGL_TRUE))
+ return EGL_FALSE;
+
+ /* the spec says that EGL_LEVEL cannot be EGL_DONT_CARE */
+ if (level == 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);
+ }
+ 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 (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);
}
}
}
+
return EGL_TRUE;
}
/**
- * Compare configs 'a' and 'b' and return -1 if a belongs before b,
- * 1 if a belongs after b, or 0 if they're equal.
- * Used by qsort().
+ * Decide the ordering of conf1 and conf2, under the given criteria.
+ * When compare_id is true, this implements the algorithm described
+ * in "Sorting of EGLConfigs". When compare_id is false,
+ * EGL_CONFIG_ID is not compared.
+ *
+ * It returns a negative integer if conf1 is considered to come
+ * before conf2; a positive integer if conf2 is considered to come
+ * before conf1; zero if the ordering cannot be decided.
+ *
+ * Note that EGL_NATIVE_VISUAL_TYPE is platform-dependent and is
+ * ignored here.
*/
-static int
-_eglCompareConfigs(const void *a, const void *b)
+EGLint
+_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
+ const _EGLConfig *criteria, EGLBoolean compare_id)
{
- const _EGLConfig *aConfig = (const _EGLConfig *) a;
- const _EGLConfig *bConfig = (const _EGLConfig *) b;
+ const EGLint compare_attribs[] = {
+ EGL_BUFFER_SIZE,
+ EGL_SAMPLE_BUFFERS,
+ EGL_SAMPLES,
+ EGL_DEPTH_SIZE,
+ EGL_STENCIL_SIZE,
+ EGL_ALPHA_MASK_SIZE,
+ };
+ EGLint val1, val2;
+ EGLBoolean rgb_buffer;
EGLint i;
- for (i = 0; SortInfo[i].Attribute != 0; i++) {
- const EGLint aVal = GET_CONFIG_ATTRIB(aConfig, SortInfo[i].Attribute);
- const EGLint bVal = GET_CONFIG_ATTRIB(bConfig, SortInfo[i].Attribute);
- if (SortInfo[i].SortOrder == SMALLER) {
- if (aVal < bVal)
- return -1;
- else if (aVal > bVal)
- return 1;
- /* else, continue examining attribute values */
- }
- else if (SortInfo[i].SortOrder == SPECIAL) {
- if (SortInfo[i].Attribute == EGL_CONFIG_CAVEAT) {
- /* values are EGL_NONE, SLOW_CONFIG, or NON_CONFORMANT_CONFIG */
- if (aVal < bVal)
- return -1;
- else if (aVal > bVal)
- return 1;
+ 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);
+
+ /* 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);
+
+ 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);
}
- else if (SortInfo[i].Attribute == EGL_RED_SIZE ||
- SortInfo[i].Attribute == EGL_GREEN_SIZE ||
- SortInfo[i].Attribute == EGL_BLUE_SIZE ||
- SortInfo[i].Attribute == EGL_ALPHA_SIZE) {
- if (aVal > bVal)
- return -1;
- else if (aVal < bVal)
- return 1;
+ 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);
}
- else {
- assert(SortInfo[i].Attribute == EGL_NATIVE_VISUAL_TYPE);
- if (aVal < bVal)
- return -1;
- else if (aVal > bVal)
- return 1;
+ 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);
}
}
else {
- assert(SortInfo[i].SortOrder == NONE);
- /* continue examining attribute values */
+ 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 (GET_CONFIG_ATTRIB(criteria, EGL_ALPHA_SIZE) > 0) {
+ val1 += GET_CONFIG_ATTRIB(conf1, EGL_ALPHA_SIZE);
+ val2 += GET_CONFIG_ATTRIB(conf2, EGL_ALPHA_SIZE);
}
}
+ else {
+ /* assume the default criteria, which gives no specific ordering */
+ val1 = val2 = 0;
+ }
+
+ /* for color bits, larger one is preferred */
+ if (val1 != val2)
+ 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]);
+ 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);
+}
+
+
+static INLINE
+void _eglSwapConfigs(const _EGLConfig **conf1, const _EGLConfig **conf2)
+{
+ const _EGLConfig *tmp = *conf1;
+ *conf1 = *conf2;
+ *conf2 = tmp;
+}
+
+
+/**
+ * Quick sort an array of configs. This differs from the standard
+ * qsort() in that the compare function accepts an additional
+ * argument.
+ */
+void
+_eglSortConfigs(const _EGLConfig **configs, EGLint count,
+ EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
+ void *),
+ void *priv_data)
+{
+ const EGLint pivot = 0;
+ EGLint i, j;
+
+ if (count <= 1)
+ return;
+
+ _eglSwapConfigs(&configs[pivot], &configs[count / 2]);
+ i = 1;
+ j = count - 1;
+ do {
+ while (i < count && compare(configs[i], configs[pivot], priv_data) < 0)
+ i++;
+ while (compare(configs[j], configs[pivot], priv_data) > 0)
+ j--;
+ if (i < j) {
+ _eglSwapConfigs(&configs[i], &configs[j]);
+ i++;
+ j--;
+ }
+ else if (i == j) {
+ i++;
+ j--;
+ break;
+ }
+ } while (i <= j);
+ _eglSwapConfigs(&configs[pivot], &configs[j]);
- /* all attributes identical */
- return 0;
+ _eglSortConfigs(configs, j, compare, priv_data);
+ _eglSortConfigs(configs + i, count - i, compare, priv_data);
+}
+
+
+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);
}
@@ -324,33 +728,33 @@ _eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
_EGLConfig **configList, criteria;
EGLint i, count;
- /* parse the attrib_list to initialize criteria */
- if (!_eglParseConfigAttribs(&criteria, attrib_list)) {
- return EGL_FALSE;
- }
+ if (!num_configs)
+ return _eglError(EGL_BAD_PARAMETER, "eglChooseConfigs");
+
+ _eglInitConfig(&criteria, 0);
+ if (!_eglParseConfigAttribList(&criteria, attrib_list))
+ return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
/* allocate array of config pointers */
- configList = (_EGLConfig **) malloc(config_size * sizeof(_EGLConfig *));
- if (!configList) {
- _eglError(EGL_BAD_CONFIG, "eglChooseConfig(out of memory)");
- return EGL_FALSE;
- }
+ configList = (_EGLConfig **)
+ malloc(disp->NumConfigs * sizeof(_EGLConfig *));
+ if (!configList)
+ return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
- /* make array of pointers to qualifying configs */
- for (i = count = 0; i < disp->NumConfigs && count < config_size; i++) {
- if (_eglConfigQualifies(disp->Configs[i], &criteria)) {
+ /* perform selection of configs */
+ count = 0;
+ for (i = 0; i < disp->NumConfigs; i++) {
+ if (_eglMatchConfig(disp->Configs[i], &criteria))
configList[count++] = disp->Configs[i];
- }
}
- /* sort array of pointers */
- qsort(configList, count, sizeof(_EGLConfig *), _eglCompareConfigs);
-
- /* copy config handles to output array */
- if (configs) {
- for (i = 0; i < count; i++) {
- configs[i] = configList[i]->Handle;
- }
+ /* perform sorting of configs */
+ if (configs && count) {
+ _eglSortConfigs((const _EGLConfig **) configList, count,
+ _eglFallbackCompare, (void *) &criteria);
+ count = MIN2(count, config_size);
+ for (i = 0; i < count; i++)
+ configs[i] = _eglGetConfigHandle(configList[i]);
}
free(configList);
@@ -361,6 +765,28 @@ _eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
}
+static INLINE EGLBoolean
+_eglIsConfigAttribValid(_EGLConfig *conf, EGLint attr)
+{
+ if (_eglIndexConfig(conf, attr) < 0)
+ return EGL_FALSE;
+
+ /* 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;
+}
+
+
/**
* Fallback for eglGetConfigAttrib.
*/
@@ -368,15 +794,13 @@ EGLBoolean
_eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
EGLint attribute, EGLint *value)
{
- const EGLint k = attribute - FIRST_ATTRIB;
- if (k >= 0 && k < MAX_ATTRIBS) {
- *value = conf->Attrib[k];
- return EGL_TRUE;
- }
- else {
- _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
- return EGL_FALSE;
- }
+ if (!_eglIsConfigAttribValid(conf, attribute))
+ return _eglError(EGL_BAD_ATTRIBUTE, "eglGetConfigAttrib");
+ if (!value)
+ return _eglError(EGL_BAD_PARAMETER, "eglGetConfigAttrib");
+
+ *value = GET_CONFIG_ATTRIB(conf, attribute);
+ return EGL_TRUE;
}
@@ -387,12 +811,14 @@ 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] = disp->Configs[i]->Handle;
- }
+ for (i = 0; i < *num_config; i++)
+ configs[i] = _eglGetConfigHandle(disp->Configs[i]);
}
else {
/* just return total number of supported configs */
diff --git a/src/egl/main/eglconfig.h b/src/egl/main/eglconfig.h
index 36ed96ae956..6b8a259984e 100644
--- a/src/egl/main/eglconfig.h
+++ b/src/egl/main/eglconfig.h
@@ -2,27 +2,93 @@
#define EGLCONFIG_INCLUDED
+#include <assert.h>
#include "egltypedefs.h"
-#include <GLES/gl.h>
-#define MAX_ATTRIBS 128
-#define FIRST_ATTRIB EGL_BUFFER_SIZE
+#define _EGL_CONFIG_FIRST_ATTRIB EGL_BUFFER_SIZE
+#define _EGL_CONFIG_LAST_ATTRIB EGL_CONFORMANT
+#define _EGL_CONFIG_NUM_ATTRIBS \
+ (_EGL_CONFIG_LAST_ATTRIB - _EGL_CONFIG_FIRST_ATTRIB + 1)
+
+#define _EGL_CONFIG_STORAGE_SIZE _EGL_CONFIG_NUM_ATTRIBS
struct _egl_config
{
- EGLConfig Handle; /* the public/opaque handle which names this config */
- EGLint Attrib[MAX_ATTRIBS];
+ _EGLDisplay *Display;
+ EGLint Storage[_EGL_CONFIG_STORAGE_SIZE];
};
-#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) \
- assert((ATTR) - FIRST_ATTRIB < MAX_ATTRIBS); \
- ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB] = VAL)
+#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) _eglSetConfigKey(CONF, ATTR, VAL)
+#define GET_CONFIG_ATTRIB(CONF, ATTR) _eglGetConfigKey(CONF, ATTR)
+
+
+/**
+ * Given a key, return an index into the storage of the config.
+ * Return -1 if the key is invalid.
+ */
+static INLINE EGLint
+_eglIndexConfig(const _EGLConfig *conf, EGLint key)
+{
+ (void) conf;
+ if (key >= _EGL_CONFIG_FIRST_ATTRIB &&
+ key < _EGL_CONFIG_FIRST_ATTRIB + _EGL_CONFIG_NUM_ATTRIBS)
+ return key - _EGL_CONFIG_FIRST_ATTRIB;
+ else
+ return -1;
+}
+
+
+/**
+ * Reset all keys in the config to a given value.
+ */
+static INLINE void
+_eglResetConfigKeys(_EGLConfig *conf, EGLint val)
+{
+ EGLint i;
+ for (i = 0; i < _EGL_CONFIG_NUM_ATTRIBS; i++)
+ conf->Storage[i] = val;
+}
-#define GET_CONFIG_ATTRIB(CONF, ATTR) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB])
+/**
+ * Update a config for a given key.
+ */
+static INLINE void
+_eglSetConfigKey(_EGLConfig *conf, EGLint key, EGLint val)
+{
+ EGLint idx = _eglIndexConfig(conf, key);
+ assert(idx >= 0);
+ conf->Storage[idx] = val;
+}
+
+
+/**
+ * Return the value for a given key.
+ */
+static INLINE EGLint
+_eglGetConfigKey(const _EGLConfig *conf, EGLint key)
+{
+ EGLint idx = _eglIndexConfig(conf, key);
+ assert(idx >= 0);
+ return conf->Storage[idx];
+}
+
+
+/**
+ * Set a given attribute.
+ *
+ * Because _eglGetConfigAttrib is already used as a fallback driver
+ * function, this function is not considered to have a good name.
+ * SET_CONFIG_ATTRIB is preferred over this function.
+ */
+static INLINE void
+_eglSetConfigAttrib(_EGLConfig *conf, EGLint attr, EGLint val)
+{
+ SET_CONFIG_ATTRIB(conf, attr, val);
+}
extern void
@@ -30,19 +96,76 @@ _eglInitConfig(_EGLConfig *config, EGLint id);
extern EGLConfig
-_eglGetConfigHandle(_EGLConfig *config);
+_eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf);
+
+
+#ifndef _EGL_SKIP_HANDLE_CHECK
+
+
+extern EGLBoolean
+_eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy);
+
+
+#else
+
+static INLINE EGLBoolean
+_eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy)
+{
+ _EGLConfig *conf = (_EGLConfig *) config;
+ return (dpy && conf && conf->Display == dpy);
+}
+
+
+#endif /* _EGL_SKIP_HANDLE_CHECK */
-extern _EGLConfig *
-_eglLookupConfig(EGLConfig config, _EGLDisplay *dpy);
+
+/**
+ * Lookup a handle to find the linked config.
+ * Return NULL if the handle has no corresponding linked config.
+ */
+static INLINE _EGLConfig *
+_eglLookupConfig(EGLConfig config, _EGLDisplay *dpy)
+{
+ _EGLConfig *conf = (_EGLConfig *) config;
+ if (!_eglCheckConfigHandle(config, dpy))
+ conf = NULL;
+ return conf;
+}
+
+
+/**
+ * Return the handle of a linked config, or NULL.
+ */
+static INLINE EGLConfig
+_eglGetConfigHandle(_EGLConfig *conf)
+{
+ return (EGLConfig) ((conf && conf->Display) ? conf : NULL);
+}
+
+
+extern EGLBoolean
+_eglValidateConfig(const _EGLConfig *conf, EGLBoolean for_matching);
-extern _EGLConfig *
-_eglAddConfig(_EGLDisplay *display, _EGLConfig *config);
+extern EGLBoolean
+_eglMatchConfig(const _EGLConfig *conf, const _EGLConfig *criteria);
extern EGLBoolean
-_eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list);
+_eglParseConfigAttribList(_EGLConfig *conf, const EGLint *attrib_list);
+
+
+extern EGLint
+_eglCompareConfigs(const _EGLConfig *conf1, const _EGLConfig *conf2,
+ const _EGLConfig *criteria, EGLBoolean compare_id);
+
+
+extern void
+_eglSortConfigs(const _EGLConfig **configs, EGLint count,
+ EGLint (*compare)(const _EGLConfig *, const _EGLConfig *,
+ void *),
+ void *priv_data);
extern EGLBoolean
@@ -57,8 +180,4 @@ extern EGLBoolean
_eglGetConfigs(_EGLDriver *drv, _EGLDisplay *dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
-extern void
-_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val);
-
-
#endif /* EGLCONFIG_INCLUDED */
diff --git a/src/egl/main/eglconfigutil.c b/src/egl/main/eglconfigutil.c
index c9d00e79826..a5fcdcd2876 100644
--- a/src/egl/main/eglconfigutil.c
+++ b/src/egl/main/eglconfigutil.c
@@ -52,6 +52,78 @@ _eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode)
}
+/**
+ * Convert a __GLcontextModes object to an _EGLConfig.
+ */
+EGLBoolean
+_eglConfigFromContextModesRec(_EGLConfig *conf, const __GLcontextModes *m,
+ EGLint conformant, EGLint renderable_type)
+{
+ EGLint config_caveat, surface_type;
+
+ /* must be RGBA */
+ if (!m->rgbMode || !(m->renderType & GLX_RGBA_BIT))
+ return EGL_FALSE;
+
+ config_caveat = EGL_NONE;
+ if (m->visualRating == GLX_SLOW_CONFIG)
+ config_caveat = EGL_SLOW_CONFIG;
+
+ if (m->visualRating == GLX_NON_CONFORMANT_CONFIG)
+ conformant &= ~EGL_OPENGL_BIT;
+ if (!(conformant & EGL_OPENGL_ES_BIT))
+ config_caveat = EGL_NON_CONFORMANT_CONFIG;
+
+ surface_type = 0;
+ if (m->drawableType & GLX_WINDOW_BIT)
+ surface_type |= EGL_WINDOW_BIT;
+ if (m->drawableType & GLX_PIXMAP_BIT)
+ surface_type |= EGL_PIXMAP_BIT;
+ if (m->drawableType & GLX_PBUFFER_BIT)
+ surface_type |= EGL_PBUFFER_BIT;
+
+ SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, m->rgbBits);
+ SET_CONFIG_ATTRIB(conf, EGL_RED_SIZE, m->redBits);
+ SET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE, m->greenBits);
+ SET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE, m->blueBits);
+ SET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE, m->alphaBits);
+
+ SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGB, m->bindToTextureRgb);
+ SET_CONFIG_ATTRIB(conf, EGL_BIND_TO_TEXTURE_RGBA, m->bindToTextureRgba);
+ SET_CONFIG_ATTRIB(conf, EGL_COLOR_BUFFER_TYPE, EGL_RGB_BUFFER);
+ SET_CONFIG_ATTRIB(conf, EGL_CONFIG_CAVEAT, config_caveat);
+
+ SET_CONFIG_ATTRIB(conf, EGL_CONFORMANT, conformant);
+ SET_CONFIG_ATTRIB(conf, EGL_DEPTH_SIZE, m->depthBits);
+ SET_CONFIG_ATTRIB(conf, EGL_LEVEL, m->level);
+ SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_WIDTH, m->maxPbufferWidth);
+ SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_HEIGHT, m->maxPbufferHeight);
+ SET_CONFIG_ATTRIB(conf, EGL_MAX_PBUFFER_PIXELS, m->maxPbufferPixels);
+
+ SET_CONFIG_ATTRIB(conf, EGL_NATIVE_RENDERABLE, m->xRenderable);
+ SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, m->visualID);
+ SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, m->visualType);
+ SET_CONFIG_ATTRIB(conf, EGL_RENDERABLE_TYPE, renderable_type);
+ SET_CONFIG_ATTRIB(conf, EGL_SAMPLE_BUFFERS, m->sampleBuffers);
+ SET_CONFIG_ATTRIB(conf, EGL_SAMPLES, m->samples);
+ SET_CONFIG_ATTRIB(conf, EGL_STENCIL_SIZE, m->stencilBits);
+
+ SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type);
+
+ /* what to do with GLX_TRANSPARENT_INDEX? */
+ if (m->transparentPixel == GLX_TRANSPARENT_RGB) {
+ SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_TRANSPARENT_RGB);
+ SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_RED_VALUE, m->transparentRed);
+ SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_GREEN_VALUE, m->transparentGreen);
+ SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_BLUE_VALUE, m->transparentBlue);
+ }
+ else {
+ SET_CONFIG_ATTRIB(conf, EGL_TRANSPARENT_TYPE, EGL_NONE);
+ }
+
+ return EGL_TRUE;
+}
+
/**
* Creates a set of \c _EGLConfigs that a driver will expose.
diff --git a/src/egl/main/eglconfigutil.h b/src/egl/main/eglconfigutil.h
index c477b94737d..ad850798908 100644
--- a/src/egl/main/eglconfigutil.h
+++ b/src/egl/main/eglconfigutil.h
@@ -1,12 +1,10 @@
-
#ifndef EGLCONFIGUTIL_INCLUDED
#define EGLCONFIGUTIL_INCLUDED
-#include "eglconfig.h"
+
+#include "GLES/gl.h"
#include "GL/internal/glcore.h"
-#if (!defined(WIN32) && !defined(_WIN32_WCE))
-#include "stdint.h"
-#endif
+#include "eglconfig.h"
extern void
@@ -14,6 +12,11 @@ _eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode);
extern EGLBoolean
+_eglConfigFromContextModesRec(_EGLConfig *conf, const __GLcontextModes *m,
+ EGLint conformant, EGLint renderable_type);
+
+
+extern EGLBoolean
_eglFillInConfigs( _EGLConfig *configs,
EGLenum fb_format, EGLenum fb_type,
const uint8_t * depth_bits, const uint8_t * stencil_bits,
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
index b094f49bfc1..ee4b1b59f5b 100644
--- a/src/egl/main/eglcontext.c
+++ b/src/egl/main/eglcontext.c
@@ -45,6 +45,7 @@ _eglInitContext(_EGLDriver *drv, _EGLContext *ctx,
ctx->DrawSurface = EGL_NO_SURFACE;
ctx->ReadSurface = EGL_NO_SURFACE;
ctx->ClientAPI = api;
+ ctx->WindowRenderBuffer = EGL_NONE;
return EGL_TRUE;
}
@@ -87,6 +88,24 @@ _eglDestroyContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
}
+#ifdef EGL_VERSION_1_2
+static EGLint
+_eglQueryContextRenderBuffer(_EGLContext *ctx)
+{
+ _EGLSurface *surf = ctx->DrawSurface;
+ EGLint rb;
+
+ if (!surf)
+ return EGL_NONE;
+ if (surf->Type == EGL_WINDOW_BIT && ctx->WindowRenderBuffer != EGL_NONE)
+ rb = ctx->WindowRenderBuffer;
+ else
+ rb = surf->RenderBuffer;
+ return rb;
+}
+#endif /* EGL_VERSION_1_2 */
+
+
EGLBoolean
_eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
EGLint attribute, EGLint *value)
@@ -94,22 +113,29 @@ _eglQueryContext(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *c,
(void) drv;
(void) dpy;
+ if (!value)
+ return _eglError(EGL_BAD_PARAMETER, "eglQueryContext");
+
switch (attribute) {
case EGL_CONFIG_ID:
*value = GET_CONFIG_ATTRIB(c->Config, EGL_CONFIG_ID);
- return EGL_TRUE;
+ break;
+ case EGL_CONTEXT_CLIENT_VERSION:
+ *value = c->ClientVersion;
+ break;
#ifdef EGL_VERSION_1_2
case EGL_CONTEXT_CLIENT_TYPE:
*value = c->ClientAPI;
- return EGL_TRUE;
+ break;
+ case EGL_RENDER_BUFFER:
+ *value = _eglQueryContextRenderBuffer(c);
+ break;
#endif /* EGL_VERSION_1_2 */
- case EGL_CONTEXT_CLIENT_VERSION:
- *value = c->ClientVersion;
- return EGL_TRUE;
default:
- _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
- return EGL_FALSE;
+ return _eglError(EGL_BAD_ATTRIBUTE, "eglQueryContext");
}
+
+ return EGL_TRUE;
}
diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h
index 647f24488ff..45c7b4717b7 100644
--- a/src/egl/main/eglcontext.h
+++ b/src/egl/main/eglcontext.h
@@ -24,6 +24,9 @@ struct _egl_context
EGLint ClientAPI; /**< EGL_OPENGL_ES_API, EGL_OPENGL_API, EGL_OPENVG_API */
EGLint ClientVersion; /**< 1 = OpenGLES 1.x, 2 = OpenGLES 2.x */
+
+ /* The real render buffer when a window surface is bound */
+ EGLint WindowRenderBuffer;
};
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 6575fdf198f..ea4e35a8b3f 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -44,6 +44,7 @@ struct _egl_display
EGLint NumScreens;
_EGLScreen **Screens; /* array [NumScreens] */
+ EGLint MaxConfigs;
EGLint NumConfigs;
_EGLConfig **Configs; /* array [NumConfigs] of ptr to _EGLConfig */