summaryrefslogtreecommitdiff
path: root/src/egl
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl')
-rw-r--r--src/egl/drivers/demo/demo.c2
-rw-r--r--src/egl/drivers/glx/egl_glx.c903
-rw-r--r--src/egl/drivers/xdri/egl_xdri.c97
-rw-r--r--src/egl/main/eglapi.c237
-rw-r--r--src/egl/main/eglapi.h8
-rw-r--r--src/egl/main/eglconfig.c939
-rw-r--r--src/egl/main/eglconfig.h157
-rw-r--r--src/egl/main/eglconfigutil.c77
-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/eglcurrent.c4
-rw-r--r--src/egl/main/eglcurrent.h23
-rw-r--r--src/egl/main/egldisplay.h1
-rw-r--r--src/egl/main/egldriver.c159
-rw-r--r--src/egl/main/eglglobals.c8
-rw-r--r--src/egl/main/eglglobals.h3
-rw-r--r--src/egl/main/egllog.c187
-rw-r--r--src/egl/main/egllog.h11
-rw-r--r--src/egl/main/eglmisc.c3
-rw-r--r--src/egl/main/eglmisc.h2
-rw-r--r--src/egl/main/eglsurface.c27
-rw-r--r--src/egl/main/eglsurface.h2
23 files changed, 1917 insertions, 989 deletions
diff --git a/src/egl/drivers/demo/demo.c b/src/egl/drivers/demo/demo.c
index aea4894448..0933c0bdaa 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/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c
index 4685f600e2..96292b0e9e 100644
--- a/src/egl/drivers/glx/egl_glx.c
+++ b/src/egl/drivers/glx/egl_glx.c
@@ -33,23 +33,12 @@
* Authors: Alan Hourihane <alanh@tungstengraphics.com>
*/
-/*
- * TODO:
- *
- * test eglBind/ReleaseTexImage
- */
-
-
-#include <assert.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "dlfcn.h"
+#include <stdlib.h>
+#include <string.h>
#include <X11/Xlib.h>
-#include <GL/gl.h>
-#include "glxclient.h"
+#include <GL/glx.h>
+#include "eglconfigutil.h"
#include "eglconfig.h"
#include "eglcontext.h"
#include "egldisplay.h"
@@ -58,46 +47,19 @@
#include "egllog.h"
#include "eglsurface.h"
-#include <GL/gl.h>
-
#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
-static const EGLint all_apis = (EGL_OPENGL_ES_BIT
- | EGL_OPENGL_ES2_BIT
- | EGL_OPENVG_BIT
- /* | EGL_OPENGL_BIT */); /* can't do */
+#ifndef GLX_VERSION_1_4
+#error "GL/glx.h must be equal to or greater than GLX 1.4"
+#endif
+
+/*
+ * report OpenGL ES bits because apps usually forget to specify
+ * EGL_RENDERABLE_TYPE when choosing configs
+ */
+#define GLX_EGL_APIS (EGL_OPENGL_BIT | EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)
-struct visual_attribs
-{
- /* X visual attribs */
- int id;
- int klass;
- int depth;
- int redMask, greenMask, blueMask;
- int colormapSize;
- int bitsPerRGB;
-
- /* GL visual attribs */
- int supportsGL;
- int transparentType;
- int transparentRedValue;
- int transparentGreenValue;
- int transparentBlueValue;
- int transparentAlphaValue;
- int transparentIndexValue;
- int bufferSize;
- int level;
- int render_type;
- int doubleBuffer;
- int stereo;
- int auxBuffers;
- int redSize, greenSize, blueSize, alphaSize;
- int depthSize;
- int stencilSize;
- int accumRedSize, accumGreenSize, accumBlueSize, accumAlphaSize;
- int numSamples, numMultisample;
- int visualCaveat;
-};
/** subclass of _EGLDriver */
struct GLX_egl_driver
@@ -114,6 +76,21 @@ struct GLX_egl_display
GLXFBConfig *fbconfigs;
int glx_maj, glx_min;
+
+ const char *extensions;
+ EGLBoolean have_1_3;
+ EGLBoolean have_make_current_read;
+ EGLBoolean have_fbconfig;
+ EGLBoolean have_pbuffer;
+
+ /* GLX_SGIX_pbuffer */
+ PFNGLXCREATEGLXPBUFFERSGIXPROC glXCreateGLXPbufferSGIX;
+ PFNGLXDESTROYGLXPBUFFERSGIXPROC glXDestroyGLXPbufferSGIX;
+
+ /* workaround quirks of different GLX implementations */
+ EGLBoolean single_buffered_quirk;
+ EGLBoolean glx_window_quirk;
+
};
@@ -131,7 +108,8 @@ struct GLX_egl_surface
{
_EGLSurface Base; /**< base class */
- GLXDrawable drawable;
+ Drawable drawable;
+ GLXDrawable glx_drawable;
};
@@ -139,6 +117,7 @@ struct GLX_egl_surface
struct GLX_egl_config
{
_EGLConfig Base; /**< base class */
+ EGLBoolean double_buffered;
int index;
};
@@ -173,288 +152,369 @@ GLX_egl_config_index(_EGLConfig *conf)
return ((struct GLX_egl_config *) conf)->index;
}
-static GLboolean
-get_visual_attribs(Display *dpy, XVisualInfo *vInfo,
- struct visual_attribs *attribs)
-{
- const char *ext = glXQueryExtensionsString(dpy, vInfo->screen);
- int rgba;
- memset(attribs, 0, sizeof(struct visual_attribs));
+#define MAP_ATTRIB(attr, memb) \
+ { attr, offsetof(__GLcontextModes, memb) }
+
+
+static const struct {
+ int attr;
+ int offset;
+} fbconfig_attributes[] = {
+ /* table 3.1 of GLX 1.4 */
+ MAP_ATTRIB(GLX_FBCONFIG_ID, fbconfigID),
+ MAP_ATTRIB(GLX_BUFFER_SIZE, rgbBits),
+ MAP_ATTRIB(GLX_LEVEL, level),
+ MAP_ATTRIB(GLX_DOUBLEBUFFER, doubleBufferMode),
+ MAP_ATTRIB(GLX_STEREO, stereoMode),
+ MAP_ATTRIB(GLX_AUX_BUFFERS, numAuxBuffers),
+ MAP_ATTRIB(GLX_RED_SIZE, redBits),
+ MAP_ATTRIB(GLX_GREEN_SIZE, greenBits),
+ MAP_ATTRIB(GLX_BLUE_SIZE, blueBits),
+ MAP_ATTRIB(GLX_ALPHA_SIZE, alphaBits),
+ MAP_ATTRIB(GLX_DEPTH_SIZE, depthBits),
+ MAP_ATTRIB(GLX_STENCIL_SIZE, stencilBits),
+ MAP_ATTRIB(GLX_ACCUM_RED_SIZE, accumRedBits),
+ MAP_ATTRIB(GLX_ACCUM_GREEN_SIZE, accumGreenBits),
+ MAP_ATTRIB(GLX_ACCUM_BLUE_SIZE, accumBlueBits),
+ MAP_ATTRIB(GLX_ACCUM_ALPHA_SIZE, accumAlphaBits),
+ MAP_ATTRIB(GLX_SAMPLE_BUFFERS, sampleBuffers),
+ MAP_ATTRIB(GLX_SAMPLES, samples),
+ MAP_ATTRIB(GLX_RENDER_TYPE, renderType),
+ MAP_ATTRIB(GLX_DRAWABLE_TYPE, drawableType),
+ MAP_ATTRIB(GLX_X_RENDERABLE, xRenderable),
+ MAP_ATTRIB(GLX_X_VISUAL_TYPE, visualType),
+ MAP_ATTRIB(GLX_CONFIG_CAVEAT, visualRating),
+ MAP_ATTRIB(GLX_TRANSPARENT_TYPE, transparentPixel),
+ MAP_ATTRIB(GLX_TRANSPARENT_INDEX_VALUE, transparentIndex),
+ MAP_ATTRIB(GLX_TRANSPARENT_RED_VALUE, transparentRed),
+ MAP_ATTRIB(GLX_TRANSPARENT_GREEN_VALUE, transparentGreen),
+ MAP_ATTRIB(GLX_TRANSPARENT_BLUE_VALUE, transparentBlue),
+ MAP_ATTRIB(GLX_TRANSPARENT_ALPHA_VALUE, transparentAlpha),
+ MAP_ATTRIB(GLX_MAX_PBUFFER_WIDTH, maxPbufferWidth),
+ MAP_ATTRIB(GLX_MAX_PBUFFER_HEIGHT, maxPbufferHeight),
+ MAP_ATTRIB(GLX_MAX_PBUFFER_PIXELS, maxPbufferPixels),
+ MAP_ATTRIB(GLX_VISUAL_ID, visualID),
+};
- attribs->id = vInfo->visualid;
-#if defined(__cplusplus) || defined(c_plusplus)
- attribs->klass = vInfo->c_class;
-#else
- attribs->klass = vInfo->class;
-#endif
- attribs->depth = vInfo->depth;
- attribs->redMask = vInfo->red_mask;
- attribs->greenMask = vInfo->green_mask;
- attribs->blueMask = vInfo->blue_mask;
- attribs->colormapSize = vInfo->colormap_size;
- attribs->bitsPerRGB = vInfo->bits_per_rgb;
-
- if (glXGetConfig(dpy, vInfo, GLX_USE_GL, &attribs->supportsGL) != 0 ||
- !attribs->supportsGL)
- return GL_FALSE;
- glXGetConfig(dpy, vInfo, GLX_BUFFER_SIZE, &attribs->bufferSize);
- glXGetConfig(dpy, vInfo, GLX_LEVEL, &attribs->level);
- glXGetConfig(dpy, vInfo, GLX_RGBA, &rgba);
- if (!rgba)
- return GL_FALSE;
- attribs->render_type = GLX_RGBA_BIT;
-
- glXGetConfig(dpy, vInfo, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
- if (!attribs->doubleBuffer)
- return GL_FALSE;
-
- glXGetConfig(dpy, vInfo, GLX_STEREO, &attribs->stereo);
- glXGetConfig(dpy, vInfo, GLX_AUX_BUFFERS, &attribs->auxBuffers);
- glXGetConfig(dpy, vInfo, GLX_RED_SIZE, &attribs->redSize);
- glXGetConfig(dpy, vInfo, GLX_GREEN_SIZE, &attribs->greenSize);
- glXGetConfig(dpy, vInfo, GLX_BLUE_SIZE, &attribs->blueSize);
- glXGetConfig(dpy, vInfo, GLX_ALPHA_SIZE, &attribs->alphaSize);
- glXGetConfig(dpy, vInfo, GLX_DEPTH_SIZE, &attribs->depthSize);
- glXGetConfig(dpy, vInfo, GLX_STENCIL_SIZE, &attribs->stencilSize);
- glXGetConfig(dpy, vInfo, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
- glXGetConfig(dpy, vInfo, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
- glXGetConfig(dpy, vInfo, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
- glXGetConfig(dpy, vInfo, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
-
- /* get transparent pixel stuff */
- glXGetConfig(dpy, vInfo,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
- if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
- glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
- glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
- glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
- glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
- }
- else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
- glXGetConfig(dpy, vInfo, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
- }
-
- /* multisample attribs */
-#ifdef GLX_ARB_multisample
- if (ext && strstr(ext, "GLX_ARB_multisample")) {
- glXGetConfig(dpy, vInfo, GLX_SAMPLE_BUFFERS_ARB, &attribs->numMultisample);
- glXGetConfig(dpy, vInfo, GLX_SAMPLES_ARB, &attribs->numSamples);
- }
-#endif
- else {
- attribs->numSamples = 0;
- attribs->numMultisample = 0;
- }
-#if defined(GLX_EXT_visual_rating)
- if (ext && strstr(ext, "GLX_EXT_visual_rating")) {
- glXGetConfig(dpy, vInfo, GLX_VISUAL_CAVEAT_EXT, &attribs->visualCaveat);
- }
- else {
- attribs->visualCaveat = GLX_NONE_EXT;
+static EGLBoolean
+convert_fbconfig(Display *dpy, GLXFBConfig fbconfig,
+ struct GLX_egl_config *GLX_conf)
+{
+ __GLcontextModes mode;
+ int err = 0, attr, val, i;
+
+ memset(&mode, 0, sizeof(mode));
+
+ for (i = 0; i < ARRAY_SIZE(fbconfig_attributes); i++) {
+ int offset = fbconfig_attributes[i].offset;
+ attr = fbconfig_attributes[i].attr;
+ err = glXGetFBConfigAttrib(dpy, fbconfig, attr, &val);
+ if (err) {
+ if (err == GLX_BAD_ATTRIBUTE) {
+ err = 0;
+ continue;
+ }
+ break;
+ }
+ *((int *) ((char *) &mode + offset)) = val;
}
-#else
- attribs->visualCaveat = 0;
-#endif
-
- return GL_TRUE;
-}
+ if (err)
+ return EGL_FALSE;
-#ifdef GLX_VERSION_1_3
+ /* must have rgba bit */
+ if (!(mode.renderType & GLX_RGBA_BIT))
+ return EGL_FALSE;
-static int
-glx_token_to_visual_class(int visual_type)
-{
- switch (visual_type) {
- case GLX_TRUE_COLOR:
- return TrueColor;
- case GLX_DIRECT_COLOR:
- return DirectColor;
- case GLX_PSEUDO_COLOR:
- return PseudoColor;
- case GLX_STATIC_COLOR:
- return StaticColor;
- case GLX_GRAY_SCALE:
- return GrayScale;
- case GLX_STATIC_GRAY:
- return StaticGray;
- case GLX_NONE:
- default:
- return None;
+ /* pixmap and pbuffer surfaces must be single-buffered in EGL */
+ if (mode.doubleBufferMode) {
+ mode.drawableType &= ~(GLX_PIXMAP_BIT | GLX_PBUFFER_BIT);
+ if (!mode.drawableType)
+ return EGL_FALSE;
}
+
+ mode.rgbMode = GL_TRUE;
+ mode.haveAccumBuffer = (mode.accumRedBits +
+ mode.accumGreenBits +
+ mode.accumBlueBits +
+ mode.accumAlphaBits > 0);
+ mode.haveDepthBuffer = (mode.depthBits > 0);
+ mode.haveStencilBuffer = (mode.stencilBits > 0);
+
+ GLX_conf->double_buffered = (mode.doubleBufferMode != 0);
+ return _eglConfigFromContextModesRec(&GLX_conf->Base, &mode,
+ GLX_EGL_APIS, GLX_EGL_APIS);
}
-static int
-get_fbconfig_attribs(Display *dpy, GLXFBConfig fbconfig,
- struct visual_attribs *attribs)
-{
- int visual_type;
- int fbconfig_id;
- memset(attribs, 0, sizeof(struct visual_attribs));
+static const struct {
+ int attr;
+ int offset;
+} visual_attributes[] = {
+ /* table 3.7 of GLX 1.4 */
+ /* no GLX_USE_GL */
+ MAP_ATTRIB(GLX_BUFFER_SIZE, rgbBits),
+ MAP_ATTRIB(GLX_LEVEL, level),
+ MAP_ATTRIB(GLX_RGBA, rgbMode),
+ MAP_ATTRIB(GLX_DOUBLEBUFFER, doubleBufferMode),
+ MAP_ATTRIB(GLX_STEREO, stereoMode),
+ MAP_ATTRIB(GLX_AUX_BUFFERS, numAuxBuffers),
+ MAP_ATTRIB(GLX_RED_SIZE, redBits),
+ MAP_ATTRIB(GLX_GREEN_SIZE, greenBits),
+ MAP_ATTRIB(GLX_BLUE_SIZE, blueBits),
+ MAP_ATTRIB(GLX_ALPHA_SIZE, alphaBits),
+ MAP_ATTRIB(GLX_DEPTH_SIZE, depthBits),
+ MAP_ATTRIB(GLX_STENCIL_SIZE, stencilBits),
+ MAP_ATTRIB(GLX_ACCUM_RED_SIZE, accumRedBits),
+ MAP_ATTRIB(GLX_ACCUM_GREEN_SIZE, accumGreenBits),
+ MAP_ATTRIB(GLX_ACCUM_BLUE_SIZE, accumBlueBits),
+ MAP_ATTRIB(GLX_ACCUM_ALPHA_SIZE, accumAlphaBits),
+ MAP_ATTRIB(GLX_SAMPLE_BUFFERS, sampleBuffers),
+ MAP_ATTRIB(GLX_SAMPLES, samples),
+ MAP_ATTRIB(GLX_FBCONFIG_ID, fbconfigID),
+ /* GLX_EXT_visual_rating */
+ MAP_ATTRIB(GLX_VISUAL_CAVEAT_EXT, visualRating),
+};
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_FBCONFIG_ID, &fbconfig_id);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_VISUAL_ID, &attribs->id);
+static int
+get_visual_type(const XVisualInfo *vis)
+{
+ int klass;
-#if 0
- attribs->depth = vInfo->depth;
- attribs->redMask = vInfo->red_mask;
- attribs->greenMask = vInfo->green_mask;
- attribs->blueMask = vInfo->blue_mask;
- attribs->colormapSize = vInfo->colormap_size;
- attribs->bitsPerRGB = vInfo->bits_per_rgb;
+#if defined(__cplusplus) || defined(c_plusplus)
+ klass = vis->c_class;
+#else
+ klass = vis->class;
#endif
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_X_VISUAL_TYPE, &visual_type);
- attribs->klass = glx_token_to_visual_class(visual_type);
+ switch (klass) {
+ case TrueColor:
+ return GLX_TRUE_COLOR;
+ case DirectColor:
+ return GLX_DIRECT_COLOR;
+ case PseudoColor:
+ return GLX_PSEUDO_COLOR;
+ case StaticColor:
+ return GLX_STATIC_COLOR;
+ case GrayScale:
+ return GLX_GRAY_SCALE;
+ case StaticGray:
+ return GLX_STATIC_GRAY;
+ default:
+ return GLX_NONE;
+ }
+}
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_BUFFER_SIZE, &attribs->bufferSize);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_LEVEL, &attribs->level);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_RENDER_TYPE, &attribs->render_type);
- if (!(attribs->render_type & GLX_RGBA_BIT))
- return 0;
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_DOUBLEBUFFER, &attribs->doubleBuffer);
- if (!attribs->doubleBuffer)
- return 0;
+static EGLBoolean
+convert_visual(Display *dpy, XVisualInfo *vinfo,
+ struct GLX_egl_config *GLX_conf)
+{
+ __GLcontextModes mode;
+ int err, attr, val, i;
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_STEREO, &attribs->stereo);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_AUX_BUFFERS, &attribs->auxBuffers);
+ /* the visual must support OpenGL */
+ err = glXGetConfig(dpy, vinfo, GLX_USE_GL, &val);
+ if (err || !val)
+ return EGL_FALSE;
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_RED_SIZE, &attribs->redSize);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_GREEN_SIZE, &attribs->greenSize);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_BLUE_SIZE, &attribs->blueSize);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_ALPHA_SIZE, &attribs->alphaSize);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_DEPTH_SIZE, &attribs->depthSize);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_STENCIL_SIZE, &attribs->stencilSize);
+ memset(&mode, 0, sizeof(mode));
+
+ for (i = 0; i < ARRAY_SIZE(visual_attributes); i++) {
+ int offset = visual_attributes[i].offset;
+ attr = visual_attributes[i].attr;
+ err = glXGetConfig(dpy, vinfo, attr, &val);
+ if (err) {
+ if (err == GLX_BAD_ATTRIBUTE) {
+ err = 0;
+ continue;
+ }
+ break;
+ }
+ *((int *) ((char *) &mode + offset)) = val;
+ }
+ if (err)
+ return EGL_FALSE;
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_RED_SIZE, &attribs->accumRedSize);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_GREEN_SIZE, &attribs->accumGreenSize);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_BLUE_SIZE, &attribs->accumBlueSize);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_ACCUM_ALPHA_SIZE, &attribs->accumAlphaSize);
+ /* must be RGB mode */
+ if (!mode.rgbMode)
+ return EGL_FALSE;
- /* get transparent pixel stuff */
- glXGetFBConfigAttrib(dpy, fbconfig,GLX_TRANSPARENT_TYPE, &attribs->transparentType);
- if (attribs->transparentType == GLX_TRANSPARENT_RGB) {
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_RED_VALUE, &attribs->transparentRedValue);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_GREEN_VALUE, &attribs->transparentGreenValue);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_BLUE_VALUE, &attribs->transparentBlueValue);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_ALPHA_VALUE, &attribs->transparentAlphaValue);
- }
- else if (attribs->transparentType == GLX_TRANSPARENT_INDEX) {
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_TRANSPARENT_INDEX_VALUE, &attribs->transparentIndexValue);
- }
+ mode.visualID = vinfo->visualid;
+ mode.visualType = get_visual_type(vinfo);
+ mode.redMask = vinfo->red_mask;
+ mode.greenMask = vinfo->green_mask;
+ mode.blueMask = vinfo->blue_mask;
+
+ mode.drawableType = GLX_WINDOW_BIT;
+ /* pixmap surfaces must be single-buffered in EGL */
+ if (!mode.doubleBufferMode)
+ mode.drawableType |= GLX_PIXMAP_BIT;
+
+ mode.renderType = GLX_RGBA_BIT;
+ mode.xRenderable = GL_TRUE;
+ mode.haveAccumBuffer = (mode.accumRedBits +
+ mode.accumGreenBits +
+ mode.accumBlueBits +
+ mode.accumAlphaBits > 0);
+ mode.haveDepthBuffer = (mode.depthBits > 0);
+ mode.haveStencilBuffer = (mode.stencilBits > 0);
+
+ GLX_conf->double_buffered = (mode.doubleBufferMode != 0);
+ return _eglConfigFromContextModesRec(&GLX_conf->Base, &mode,
+ GLX_EGL_APIS, GLX_EGL_APIS);
+}
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLE_BUFFERS, &attribs->numMultisample);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_SAMPLES, &attribs->numSamples);
- glXGetFBConfigAttrib(dpy, fbconfig, GLX_CONFIG_CAVEAT, &attribs->visualCaveat);
+static void
+fix_config(struct GLX_egl_display *GLX_dpy, struct GLX_egl_config *GLX_conf)
+{
+ _EGLConfig *conf = &GLX_conf->Base;
+ EGLint surface_type, r, g, b, a;
+
+ surface_type = GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE);
+ if (!GLX_conf->double_buffered && GLX_dpy->single_buffered_quirk) {
+ /* some GLX impls do not like single-buffered window surface */
+ surface_type &= ~EGL_WINDOW_BIT;
+ /* pbuffer bit is usually not set */
+ if (GLX_dpy->have_pbuffer)
+ surface_type |= EGL_PBUFFER_BIT;
+ SET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE, surface_type);
+ }
- if (attribs->id == 0) {
- attribs->id = fbconfig_id;
- return EGL_PBUFFER_BIT | EGL_PIXMAP_BIT;
+ /* no visual attribs unless window bit is set */
+ if (!(surface_type & EGL_WINDOW_BIT)) {
+ SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_ID, 0);
+ SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, EGL_NONE);
}
- return EGL_WINDOW_BIT;
+ /* make sure buffer size is set correctly */
+ r = GET_CONFIG_ATTRIB(conf, EGL_RED_SIZE);
+ g = GET_CONFIG_ATTRIB(conf, EGL_GREEN_SIZE);
+ b = GET_CONFIG_ATTRIB(conf, EGL_BLUE_SIZE);
+ a = GET_CONFIG_ATTRIB(conf, EGL_ALPHA_SIZE);
+ SET_CONFIG_ATTRIB(conf, EGL_BUFFER_SIZE, r + g + b + a);
}
-#endif
static EGLBoolean
-create_configs(_EGLDisplay *disp, struct GLX_egl_display *GLX_dpy)
+create_configs(_EGLDisplay *dpy, struct GLX_egl_display *GLX_dpy,
+ EGLint screen)
{
- XVisualInfo theTemplate;
- int numVisuals;
- long mask;
- int i;
- struct visual_attribs attribs;
+ EGLint num_configs = 0, i;
+ EGLint id = 1;
- GLX_dpy->fbconfigs = NULL;
-
-#ifdef GLX_VERSION_1_3
- /* get list of all fbconfigs on this screen */
- GLX_dpy->fbconfigs = glXGetFBConfigs(GLX_dpy->dpy, DefaultScreen(GLX_dpy->dpy), &numVisuals);
+ if (GLX_dpy->have_fbconfig) {
+ GLX_dpy->fbconfigs = glXGetFBConfigs(GLX_dpy->dpy, screen, &num_configs);
+ }
+ else {
+ XVisualInfo vinfo_template;
+ long mask;
- if (numVisuals == 0) {
- GLX_dpy->fbconfigs = NULL;
- goto xvisual;
+ vinfo_template.screen = screen;
+ mask = VisualScreenMask;
+ GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &vinfo_template,
+ &num_configs);
}
- for (i = 0; i < numVisuals; i++) {
- struct GLX_egl_config *config;
- int bit;
+ if (!num_configs)
+ return EGL_FALSE;
- bit = get_fbconfig_attribs(GLX_dpy->dpy, GLX_dpy->fbconfigs[i], &attribs);
- if (!bit)
+ for (i = 0; i < num_configs; i++) {
+ struct GLX_egl_config *GLX_conf, template;
+ EGLBoolean ok;
+
+ memset(&template, 0, sizeof(template));
+ _eglInitConfig(&template.Base, id);
+ if (GLX_dpy->have_fbconfig)
+ ok = convert_fbconfig(GLX_dpy->dpy, GLX_dpy->fbconfigs[i], &template);
+ else
+ ok = convert_visual(GLX_dpy->dpy, &GLX_dpy->visuals[i], &template);
+ if (!ok)
+ continue;
+
+ fix_config(GLX_dpy, &template);
+ if (!_eglValidateConfig(&template.Base, EGL_FALSE)) {
+ _eglLog(_EGL_DEBUG, "GLX: failed to validate config %d", i);
continue;
+ }
- config = CALLOC_STRUCT(GLX_egl_config);
-
- config->index = i;
- _eglInitConfig(&config->Base, (i+1));
- SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id);
- SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples);
- SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample);
- 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, bit);
-
- /* XXX possibly other things to init... */
+ GLX_conf = CALLOC_STRUCT(GLX_egl_config);
+ if (GLX_conf) {
+ memcpy(GLX_conf, &template, sizeof(template));
+ GLX_conf->index = i;
- _eglAddConfig(disp, &config->Base);
+ _eglAddConfig(dpy, &GLX_conf->Base);
+ id++;
+ }
}
- goto end;
-#endif
-
-xvisual:
- /* get list of all visuals on this screen */
- theTemplate.screen = DefaultScreen(GLX_dpy->dpy);
- mask = VisualScreenMask;
- GLX_dpy->visuals = XGetVisualInfo(GLX_dpy->dpy, mask, &theTemplate, &numVisuals);
+ return EGL_TRUE;
+}
- for (i = 0; i < numVisuals; i++) {
- struct GLX_egl_config *config;
- if (!get_visual_attribs(GLX_dpy->dpy, &GLX_dpy->visuals[i], &attribs))
- continue;
+static void
+check_extensions(struct GLX_egl_display *GLX_dpy, EGLint screen)
+{
+ GLX_dpy->extensions =
+ glXQueryExtensionsString(GLX_dpy->dpy, screen);
+ if (GLX_dpy->extensions) {
+ /* glXGetProcAddress is assumed */
+
+ if (strstr(GLX_dpy->extensions, "GLX_SGI_make_current_read")) {
+ /* GLX 1.3 entry points are used */
+ GLX_dpy->have_make_current_read = EGL_TRUE;
+ }
- config = CALLOC_STRUCT(GLX_egl_config);
+ if (strstr(GLX_dpy->extensions, "GLX_SGIX_fbconfig")) {
+ /* GLX 1.3 entry points are used */
+ GLX_dpy->have_fbconfig = EGL_TRUE;
+ }
- config->index = i;
- _eglInitConfig(&config->Base, (i+1));
- SET_CONFIG_ATTRIB(&config->Base, EGL_NATIVE_VISUAL_ID, attribs.id);
- SET_CONFIG_ATTRIB(&config->Base, EGL_BUFFER_SIZE, attribs.bufferSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_RED_SIZE, attribs.redSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_GREEN_SIZE, attribs.greenSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_BLUE_SIZE, attribs.blueSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_ALPHA_SIZE, attribs.alphaSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_DEPTH_SIZE, attribs.depthSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_STENCIL_SIZE, attribs.stencilSize);
- SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLES, attribs.numSamples);
- SET_CONFIG_ATTRIB(&config->Base, EGL_SAMPLE_BUFFERS, attribs.numMultisample);
- 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 /*| EGL_PBUFFER_BIT | EGL_PIXMAP_BIT*/));
+ if (strstr(GLX_dpy->extensions, "GLX_SGIX_pbuffer")) {
+ GLX_dpy->glXCreateGLXPbufferSGIX = (PFNGLXCREATEGLXPBUFFERSGIXPROC)
+ glXGetProcAddress((const GLubyte *) "glXCreateGLXPbufferSGIX");
+ GLX_dpy->glXDestroyGLXPbufferSGIX = (PFNGLXDESTROYGLXPBUFFERSGIXPROC)
+ glXGetProcAddress((const GLubyte *) "glXDestroyGLXPbufferSGIX");
- /* XXX possibly other things to init... */
+ if (GLX_dpy->glXCreateGLXPbufferSGIX &&
+ GLX_dpy->glXDestroyGLXPbufferSGIX &&
+ GLX_dpy->have_fbconfig)
+ GLX_dpy->have_pbuffer = EGL_TRUE;
+ }
+ }
- _eglAddConfig(disp, &config->Base);
+ if (GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3) {
+ GLX_dpy->have_1_3 = EGL_TRUE;
+ GLX_dpy->have_make_current_read = EGL_TRUE;
+ GLX_dpy->have_fbconfig = EGL_TRUE;
+ GLX_dpy->have_pbuffer = EGL_TRUE;
}
+}
-end:
- return EGL_TRUE;
+
+static void
+check_quirks(struct GLX_egl_display *GLX_dpy, EGLint screen)
+{
+ const char *vendor;
+
+ GLX_dpy->single_buffered_quirk = EGL_TRUE;
+ GLX_dpy->glx_window_quirk = EGL_TRUE;
+
+ vendor = glXGetClientString(GLX_dpy->dpy, GLX_VENDOR);
+ if (vendor && strstr(vendor, "NVIDIA")) {
+ vendor = glXQueryServerString(GLX_dpy->dpy, screen, GLX_VENDOR);
+ if (vendor && strstr(vendor, "NVIDIA")) {
+ _eglLog(_EGL_DEBUG, "disable quirks");
+ GLX_dpy->single_buffered_quirk = EGL_FALSE;
+ GLX_dpy->glx_window_quirk = EGL_FALSE;
+ }
+ }
}
+
/**
* Called via eglInitialize(), GLX_drv->API.Initialize().
*/
@@ -478,17 +538,33 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
}
}
- disp->DriverData = (void *) GLX_dpy;
- disp->ClientAPIsMask = all_apis;
+ if (!glXQueryVersion(GLX_dpy->dpy, &GLX_dpy->glx_maj, &GLX_dpy->glx_min)) {
+ _eglLog(_EGL_WARNING, "GLX: glXQueryVersion failed");
+ if (!disp->NativeDisplay)
+ XCloseDisplay(GLX_dpy->dpy);
+ free(GLX_dpy);
+ return EGL_FALSE;
+ }
- glXQueryVersion(GLX_dpy->dpy, &GLX_dpy->glx_maj, &GLX_dpy->glx_min);
+ check_extensions(GLX_dpy, DefaultScreen(GLX_dpy->dpy));
+ check_quirks(GLX_dpy, DefaultScreen(GLX_dpy->dpy));
+
+ create_configs(disp, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
+ if (!disp->NumConfigs) {
+ _eglLog(_EGL_WARNING, "GLX: failed to create any config");
+ if (!disp->NativeDisplay)
+ XCloseDisplay(GLX_dpy->dpy);
+ free(GLX_dpy);
+ return EGL_FALSE;
+ }
+
+ disp->DriverData = (void *) GLX_dpy;
+ disp->ClientAPIsMask = GLX_EGL_APIS;
/* we're supporting EGL 1.4 */
*major = 1;
*minor = 4;
- create_configs(disp, GLX_dpy);
-
return EGL_TRUE;
}
@@ -539,8 +615,7 @@ GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
return NULL;
}
-#ifdef GLX_VERSION_1_3
- if (GLX_dpy->fbconfigs)
+ if (GLX_dpy->have_fbconfig)
GLX_ctx->context =
glXCreateNewContext(GLX_dpy->dpy,
GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
@@ -548,7 +623,6 @@ GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
GLX_ctx_shared ? GLX_ctx_shared->context : NULL,
GL_TRUE);
else
-#endif
GLX_ctx->context =
glXCreateContext(GLX_dpy->dpy,
&GLX_dpy->visuals[GLX_egl_config_index(conf)],
@@ -559,15 +633,6 @@ GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
return NULL;
}
-#if 1
- /* (maybe?) need to have a direct rendering context */
- if (!glXIsDirect(GLX_dpy->dpy, GLX_ctx->context)) {
- glXDestroyContext(GLX_dpy->dpy, GLX_ctx->context);
- free(GLX_ctx);
- return NULL;
- }
-#endif
-
return &GLX_ctx->Base;
}
@@ -589,17 +654,14 @@ GLX_eglMakeCurrent(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *dsurf,
if (!_eglMakeCurrent(drv, disp, dsurf, rsurf, ctx))
return EGL_FALSE;
- ddraw = (GLX_dsurf) ? GLX_dsurf->drawable : None;
- rdraw = (GLX_rsurf) ? GLX_rsurf->drawable : None;
+ ddraw = (GLX_dsurf) ? GLX_dsurf->glx_drawable : None;
+ rdraw = (GLX_rsurf) ? GLX_rsurf->glx_drawable : None;
cctx = (GLX_ctx) ? GLX_ctx->context : NULL;
-#ifdef GLX_VERSION_1_3
- if (glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx))
- return EGL_TRUE;
-#endif
-
- if (ddraw == rdraw && glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx))
- return EGL_TRUE;
+ if (GLX_dpy->have_make_current_read)
+ return glXMakeContextCurrent(GLX_dpy->dpy, ddraw, rdraw, cctx);
+ else if (ddraw == rdraw)
+ return glXMakeCurrent(GLX_dpy->dpy, ddraw, cctx);
return EGL_FALSE;
}
@@ -642,6 +704,20 @@ GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
}
GLX_surf->drawable = window;
+
+ if (GLX_dpy->have_1_3 && !GLX_dpy->glx_window_quirk)
+ GLX_surf->glx_drawable =
+ glXCreateWindow(GLX_dpy->dpy,
+ GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
+ GLX_surf->drawable, NULL);
+ else
+ GLX_surf->glx_drawable = GLX_surf->drawable;
+
+ if (!GLX_surf->glx_drawable) {
+ free(GLX_surf);
+ return NULL;
+ }
+
get_drawable_size(GLX_dpy->dpy, window, &width, &height);
GLX_surf->Base.Width = width;
GLX_surf->Base.Height = height;
@@ -649,18 +725,13 @@ GLX_eglCreateWindowSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
return &GLX_surf->Base;
}
-#ifdef GLX_VERSION_1_3
static _EGLSurface *
GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
NativePixmapType pixmap, const EGLint *attrib_list)
{
struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
struct GLX_egl_surface *GLX_surf;
- int i;
-
- /* GLX must >= 1.3 */
- if (!(GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3))
- return NULL;
+ uint width, height;
GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
if (!GLX_surf) {
@@ -674,25 +745,39 @@ GLX_eglCreatePixmapSurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
return NULL;
}
- for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
- switch (attrib_list[i]) {
- /* no attribs at this time */
- default:
- _eglError(EGL_BAD_ATTRIBUTE, "eglCreatePixmapSurface");
- free(GLX_surf);
- return NULL;
+ GLX_surf->drawable = pixmap;
+
+ if (GLX_dpy->have_1_3) {
+ GLX_surf->glx_drawable =
+ glXCreatePixmap(GLX_dpy->dpy,
+ GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
+ GLX_surf->drawable, NULL);
+ }
+ else if (GLX_dpy->have_fbconfig) {
+ GLXFBConfig fbconfig = GLX_dpy->fbconfigs[GLX_egl_config_index(conf)];
+ XVisualInfo *vinfo = glXGetVisualFromFBConfig(GLX_dpy->dpy, fbconfig);
+ if (vinfo) {
+ GLX_surf->glx_drawable =
+ glXCreateGLXPixmap(GLX_dpy->dpy, vinfo, GLX_surf->drawable);
+ XFree(vinfo);
}
}
+ else {
+ GLX_surf->glx_drawable =
+ glXCreateGLXPixmap(GLX_dpy->dpy,
+ &GLX_dpy->visuals[GLX_egl_config_index(conf)],
+ GLX_surf->drawable);
+ }
- GLX_surf->drawable =
- glXCreatePixmap(GLX_dpy->dpy,
- GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
- pixmap, NULL);
- if (!GLX_surf->drawable) {
+ if (!GLX_surf->glx_drawable) {
free(GLX_surf);
return NULL;
}
+ get_drawable_size(GLX_dpy->dpy, pixmap, &width, &height);
+ GLX_surf->Base.Width = width;
+ GLX_surf->Base.Height = height;
+
return &GLX_surf->Base;
}
@@ -703,11 +788,7 @@ GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp,
struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
struct GLX_egl_surface *GLX_surf;
int attribs[5];
- int i = 0, j = 0;
-
- /* GLX must >= 1.3 */
- if (!(GLX_dpy->glx_maj == 1 && GLX_dpy->glx_min >= 3))
- return NULL;
+ int i;
GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
if (!GLX_surf) {
@@ -721,33 +802,44 @@ GLX_eglCreatePbufferSurface(_EGLDriver *drv, _EGLDisplay *disp,
return NULL;
}
- while(attrib_list[i] != EGL_NONE) {
- switch (attrib_list[i]) {
- case EGL_WIDTH:
- attribs[j++] = GLX_PBUFFER_WIDTH;
- attribs[j++] = attrib_list[i+1];
- break;
- case EGL_HEIGHT:
- attribs[j++] = GLX_PBUFFER_HEIGHT;
- attribs[j++] = attrib_list[i+1];
- break;
+ i = 0;
+ attribs[i] = None;
+
+ GLX_surf->drawable = None;
+
+ if (GLX_dpy->have_1_3) {
+ /* put geometry in attribs */
+ if (GLX_surf->Base.Width) {
+ attribs[i++] = GLX_PBUFFER_WIDTH;
+ attribs[i++] = GLX_surf->Base.Width;
+ }
+ if (GLX_surf->Base.Height) {
+ attribs[i++] = GLX_PBUFFER_HEIGHT;
+ attribs[i++] = GLX_surf->Base.Height;
}
- i++;
+ attribs[i] = None;
+
+ GLX_surf->glx_drawable =
+ glXCreatePbuffer(GLX_dpy->dpy,
+ GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
+ attribs);
+ }
+ else if (GLX_dpy->have_pbuffer) {
+ GLX_surf->glx_drawable = GLX_dpy->glXCreateGLXPbufferSGIX(
+ GLX_dpy->dpy,
+ GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
+ GLX_surf->Base.Width,
+ GLX_surf->Base.Height,
+ attribs);
}
- attribs[j++] = 0;
- GLX_surf->drawable =
- glXCreatePbuffer(GLX_dpy->dpy,
- GLX_dpy->fbconfigs[GLX_egl_config_index(conf)],
- attribs);
- if (!GLX_surf->drawable) {
+ if (!GLX_surf->glx_drawable) {
free(GLX_surf);
return NULL;
}
return &GLX_surf->Base;
}
-#endif
static EGLBoolean
GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
@@ -755,15 +847,35 @@ GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
if (!_eglIsSurfaceBound(surf)) {
struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
- switch (surf->Type) {
- case EGL_PBUFFER_BIT:
- glXDestroyPbuffer(GLX_dpy->dpy, GLX_surf->drawable);
- break;
- case EGL_PIXMAP_BIT:
- glXDestroyPixmap(GLX_dpy->dpy, GLX_surf->drawable);
- break;
- default:
- break;
+
+ if (GLX_dpy->have_1_3) {
+ switch (surf->Type) {
+ case EGL_WINDOW_BIT:
+ if (!GLX_dpy->glx_window_quirk)
+ glXDestroyWindow(GLX_dpy->dpy, GLX_surf->glx_drawable);
+ break;
+ case EGL_PBUFFER_BIT:
+ glXDestroyPbuffer(GLX_dpy->dpy, GLX_surf->glx_drawable);
+ break;
+ case EGL_PIXMAP_BIT:
+ glXDestroyPixmap(GLX_dpy->dpy, GLX_surf->glx_drawable);
+ break;
+ default:
+ break;
+ }
+ }
+ else {
+ switch (surf->Type) {
+ case EGL_PBUFFER_BIT:
+ GLX_dpy->glXDestroyGLXPbufferSGIX(GLX_dpy->dpy,
+ GLX_surf->glx_drawable);
+ break;
+ case EGL_PIXMAP_BIT:
+ glXDestroyGLXPixmap(GLX_dpy->dpy, GLX_surf->glx_drawable);
+ break;
+ default:
+ break;
+ }
}
free(surf);
}
@@ -773,44 +885,12 @@ GLX_eglDestroySurface(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf)
static EGLBoolean
-GLX_eglBindTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
- EGLint buffer)
-{
- struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
- struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
-
- /* buffer ?? */
- glXBindTexImageEXT(GLX_dpy->dpy, GLX_surf->drawable,
- GLX_FRONT_LEFT_EXT, NULL);
-
- return EGL_TRUE;
-}
-
-
-static EGLBoolean
-GLX_eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *surf,
- EGLint buffer)
-{
- struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
- struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
-
- /* buffer ?? */
- glXReleaseTexImageEXT(GLX_dpy->dpy, GLX_surf->drawable,
- GLX_FRONT_LEFT_EXT);
-
- return EGL_TRUE;
-}
-
-
-static EGLBoolean
GLX_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
{
struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
struct GLX_egl_surface *GLX_surf = GLX_egl_surface(draw);
- _eglLog(_EGL_DEBUG, "GLX: EGL SwapBuffers 0x%x",draw);
-
- glXSwapBuffers(GLX_dpy->dpy, GLX_surf->drawable);
+ glXSwapBuffers(GLX_dpy->dpy, GLX_surf->glx_drawable);
return EGL_TRUE;
}
@@ -821,23 +901,24 @@ GLX_eglSwapBuffers(_EGLDriver *drv, _EGLDisplay *disp, _EGLSurface *draw)
static _EGLProc
GLX_eglGetProcAddress(const char *procname)
{
- /* This is a bit of a hack to get at the gallium/Mesa state tracker
- * function st_get_proc_address(). This will probably change at
- * some point.
- */
- _EGLProc (*get_proc_addr)(const char *procname);
- _EGLProc proc_addr;
- get_proc_addr = dlsym(NULL, "st_get_proc_address");
- if (get_proc_addr)
- return get_proc_addr(procname);
-
- proc_addr = glXGetProcAddress((const GLubyte *)procname);
- if (proc_addr)
- return proc_addr;
-
- return (_EGLProc)dlsym(NULL, procname);
+ return (_EGLProc) glXGetProcAddress((const GLubyte *) procname);
}
+static EGLBoolean
+GLX_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
+{
+ glXWaitGL();
+ return EGL_TRUE;
+}
+
+static EGLBoolean
+GLX_eglWaitNative(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine)
+{
+ if (engine != EGL_CORE_NATIVE_ENGINE)
+ return _eglError(EGL_BAD_PARAMETER, "eglWaitNative");
+ glXWaitX();
+ return EGL_TRUE;
+}
static void
GLX_Unload(_EGLDriver *drv)
@@ -865,15 +946,13 @@ _eglMain(const char *args)
GLX_drv->Base.API.CreateContext = GLX_eglCreateContext;
GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent;
GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface;
-#ifdef GLX_VERSION_1_3
GLX_drv->Base.API.CreatePixmapSurface = GLX_eglCreatePixmapSurface;
GLX_drv->Base.API.CreatePbufferSurface = GLX_eglCreatePbufferSurface;
-#endif
GLX_drv->Base.API.DestroySurface = GLX_eglDestroySurface;
- GLX_drv->Base.API.BindTexImage = GLX_eglBindTexImage;
- GLX_drv->Base.API.ReleaseTexImage = GLX_eglReleaseTexImage;
GLX_drv->Base.API.SwapBuffers = GLX_eglSwapBuffers;
GLX_drv->Base.API.GetProcAddress = GLX_eglGetProcAddress;
+ GLX_drv->Base.API.WaitClient = GLX_eglWaitClient;
+ GLX_drv->Base.API.WaitNative = GLX_eglWaitNative;
GLX_drv->Base.Name = "GLX";
GLX_drv->Base.Unload = GLX_Unload;
diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c
index 518091a2d1..d2affc66dd 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/eglapi.c b/src/egl/main/eglapi.c
index 29617b7aff..14cc5fa613 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -9,12 +9,36 @@
* heterogeneous hardware devices in the future.
*
* The EGLDisplay, EGLConfig, EGLContext and EGLSurface types are
- * opaque handles implemented with 32-bit unsigned integers.
- * It's up to the driver function or fallback function to look up the
- * handle and get an object.
- * By using opaque handles, we leave open the possibility of having
- * indirect rendering in the future, like GLX.
+ * opaque handles. Internal objects are linked to a display to
+ * create the handles.
*
+ * For each public API entry point, the opaque handles are looked up
+ * before being dispatched to the drivers. When it fails to look up
+ * a handle, one of
+ *
+ * EGL_BAD_DISPLAY
+ * EGL_BAD_CONFIG
+ * EGL_BAD_CONTEXT
+ * EGL_BAD_SURFACE
+ * EGL_BAD_SCREEN_MESA
+ * EGL_BAD_MODE_MESA
+ *
+ * is generated and the driver function is not called. An
+ * uninitialized EGLDisplay has no driver associated with it. When
+ * such display is detected,
+ *
+ * EGL_NOT_INITIALIZED
+ *
+ * is generated.
+ *
+ * Some of the entry points use current display, context, or surface
+ * implicitly. For such entry points, the implicit objects are also
+ * checked before calling the driver function. Other than the
+ * errors listed above,
+ *
+ * EGL_BAD_CURRENT_SURFACE
+ *
+ * may also be generated.
*
* Notes on naming conventions:
*
@@ -92,8 +116,8 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
snprintf(disp->Version, sizeof(disp->Version),
"%d.%d (%s)", major_int, minor_int, drv->Name);
- /* update the global notion of supported APIs */
- _eglGlobal.ClientAPIsMask |= disp->ClientAPIsMask;
+ /* limit to APIs supported by core */
+ disp->ClientAPIsMask &= _EGL_API_ALL_BITS;
disp->Driver = drv;
} else {
@@ -496,15 +520,31 @@ eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
EGLBoolean EGLAPIENTRY
eglSwapInterval(EGLDisplay dpy, EGLint interval)
{
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLSurface *surf;
_EGL_DECLARE_DD(dpy);
- return drv->API.SwapInterval(drv, disp, interval);
+
+ if (!ctx || !_eglIsContextLinked(ctx) || ctx->Display != disp)
+ return _eglError(EGL_BAD_CONTEXT, __FUNCTION__);
+
+ surf = ctx->DrawSurface;
+ if (!_eglIsSurfaceLinked(surf))
+ return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+
+ return drv->API.SwapInterval(drv, disp, surf, interval);
}
EGLBoolean EGLAPIENTRY
eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
{
+ _EGLContext *ctx = _eglGetCurrentContext();
_EGL_DECLARE_DD_AND_SURFACE(dpy, surface);
+
+ /* surface must be bound to current context in EGL 1.4 */
+ if (!ctx || !_eglIsContextLinked(ctx) || surf != ctx->DrawSurface)
+ return _eglError(EGL_BAD_SURFACE, __FUNCTION__);
+
return drv->API.SwapBuffers(drv, disp, surf);
}
@@ -518,32 +558,66 @@ eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
EGLBoolean EGLAPIENTRY
-eglWaitGL(void)
+eglWaitClient(void)
{
- _EGLDisplay *disp = _eglGetCurrentDisplay();
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLDisplay *disp;
_EGLDriver *drv;
- if (!disp)
+ if (!ctx)
return EGL_TRUE;
+ /* let bad current context imply bad current surface */
+ if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
+ return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
- /* a current display is always initialized */
+ /* a valid current context implies an initialized current display */
+ disp = ctx->Display;
drv = disp->Driver;
+ assert(drv);
- return drv->API.WaitGL(drv, disp);
+ return drv->API.WaitClient(drv, disp, ctx);
+}
+
+
+EGLBoolean EGLAPIENTRY
+eglWaitGL(void)
+{
+#ifdef EGL_VERSION_1_2
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ EGLint api_index = t->CurrentAPIIndex;
+ EGLint es_index = _eglConvertApiToIndex(EGL_OPENGL_ES_API);
+ EGLBoolean ret;
+
+ if (api_index != es_index && _eglIsCurrentThreadDummy())
+ return _eglError(EGL_BAD_ALLOC, "eglWaitGL");
+
+ t->CurrentAPIIndex = es_index;
+ ret = eglWaitClient();
+ t->CurrentAPIIndex = api_index;
+ return ret;
+#else
+ return eglWaitClient();
+#endif
}
EGLBoolean EGLAPIENTRY
eglWaitNative(EGLint engine)
{
- _EGLDisplay *disp = _eglGetCurrentDisplay();
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLDisplay *disp;
_EGLDriver *drv;
- if (!disp)
+ if (!ctx)
return EGL_TRUE;
+ /* let bad current context imply bad current surface */
+ if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface))
+ return _eglError(EGL_BAD_CURRENT_SURFACE, __FUNCTION__);
- /* a current display is always initialized */
+ /* a valid current context implies an initialized current display */
+ disp = ctx->Display;
drv = disp->Driver;
+ assert(drv);
return drv->API.WaitNative(drv, disp, engine);
}
@@ -568,8 +642,26 @@ eglGetCurrentContext(void)
EGLSurface EGLAPIENTRY
eglGetCurrentSurface(EGLint readdraw)
{
- _EGLSurface *s = _eglGetCurrentSurface(readdraw);
- return _eglGetSurfaceHandle(s);
+ _EGLContext *ctx = _eglGetCurrentContext();
+ _EGLSurface *surf;
+
+ if (!ctx)
+ return EGL_NO_SURFACE;
+
+ switch (readdraw) {
+ case EGL_DRAW:
+ surf = ctx->DrawSurface;
+ break;
+ case EGL_READ:
+ surf = ctx->ReadSurface;
+ break;
+ default:
+ _eglError(EGL_BAD_PARAMETER, __FUNCTION__);
+ surf = NULL;
+ break;
+ }
+
+ return _eglGetSurfaceHandle(surf);
}
@@ -586,43 +678,11 @@ eglGetError(void)
void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
{
- typedef void (*genericFunc)();
- struct name_function {
+ static const struct {
const char *name;
_EGLProc function;
- };
- static struct name_function egl_functions[] = {
- /* alphabetical order */
- { "eglBindTexImage", (_EGLProc) eglBindTexImage },
- { "eglChooseConfig", (_EGLProc) eglChooseConfig },
- { "eglCopyBuffers", (_EGLProc) eglCopyBuffers },
- { "eglCreateContext", (_EGLProc) eglCreateContext },
- { "eglCreatePbufferSurface", (_EGLProc) eglCreatePbufferSurface },
- { "eglCreatePixmapSurface", (_EGLProc) eglCreatePixmapSurface },
- { "eglCreateWindowSurface", (_EGLProc) eglCreateWindowSurface },
- { "eglDestroyContext", (_EGLProc) eglDestroyContext },
- { "eglDestroySurface", (_EGLProc) eglDestroySurface },
- { "eglGetConfigAttrib", (_EGLProc) eglGetConfigAttrib },
- { "eglGetConfigs", (_EGLProc) eglGetConfigs },
- { "eglGetCurrentContext", (_EGLProc) eglGetCurrentContext },
- { "eglGetCurrentDisplay", (_EGLProc) eglGetCurrentDisplay },
- { "eglGetCurrentSurface", (_EGLProc) eglGetCurrentSurface },
- { "eglGetDisplay", (_EGLProc) eglGetDisplay },
- { "eglGetError", (_EGLProc) eglGetError },
- { "eglGetProcAddress", (_EGLProc) eglGetProcAddress },
- { "eglInitialize", (_EGLProc) eglInitialize },
- { "eglMakeCurrent", (_EGLProc) eglMakeCurrent },
- { "eglQueryContext", (_EGLProc) eglQueryContext },
- { "eglQueryString", (_EGLProc) eglQueryString },
- { "eglQuerySurface", (_EGLProc) eglQuerySurface },
- { "eglReleaseTexImage", (_EGLProc) eglReleaseTexImage },
- { "eglSurfaceAttrib", (_EGLProc) eglSurfaceAttrib },
- { "eglSwapBuffers", (_EGLProc) eglSwapBuffers },
- { "eglSwapInterval", (_EGLProc) eglSwapInterval },
- { "eglTerminate", (_EGLProc) eglTerminate },
- { "eglWaitGL", (_EGLProc) eglWaitGL },
- { "eglWaitNative", (_EGLProc) eglWaitNative },
- /* Extensions */
+ } egl_functions[] = {
+ /* extensions only */
#ifdef EGL_MESA_screen_surface
{ "eglChooseModeMESA", (_EGLProc) eglChooseModeMESA },
{ "eglGetModesMESA", (_EGLProc) eglGetModesMESA },
@@ -637,22 +697,23 @@ void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
{ "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
{ "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
#endif /* EGL_MESA_screen_surface */
-#ifdef EGL_VERSION_1_2
- { "eglBindAPI", (_EGLProc) eglBindAPI },
- { "eglCreatePbufferFromClientBuffer", (_EGLProc) eglCreatePbufferFromClientBuffer },
- { "eglQueryAPI", (_EGLProc) eglQueryAPI },
- { "eglReleaseThread", (_EGLProc) eglReleaseThread },
- { "eglWaitClient", (_EGLProc) eglWaitClient },
-#endif /* EGL_VERSION_1_2 */
{ NULL, NULL }
};
EGLint i;
- for (i = 0; egl_functions[i].name; i++) {
- if (strcmp(egl_functions[i].name, procname) == 0) {
- return (genericFunc) egl_functions[i].function;
+
+ if (!procname)
+ return NULL;
+ if (strncmp(procname, "egl", 3) == 0) {
+ for (i = 0; egl_functions[i].name; i++) {
+ if (strcmp(egl_functions[i].name, procname) == 0)
+ return egl_functions[i].function;
}
}
+ /* preload a driver if there isn't one */
+ if (!_eglGlobal.NumDrivers)
+ _eglPreloadDriver(NULL);
+
/* now loop over drivers to query their procs */
for (i = 0; i < _eglGlobal.NumDrivers; i++) {
_EGLProc p = _eglGlobal.Drivers[i]->API.GetProcAddress(procname);
@@ -664,6 +725,9 @@ void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
}
+#ifdef EGL_MESA_screen_surface
+
+
/*
* EGL_MESA_screen extension
*/
@@ -838,6 +902,9 @@ eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
}
+#endif /* EGL_MESA_screen_surface */
+
+
/**
** EGL 1.2
**/
@@ -867,33 +934,7 @@ eglBindAPI(EGLenum api)
if (!_eglIsApiValid(api))
return _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
- switch (api) {
-#ifdef EGL_VERSION_1_4
- case EGL_OPENGL_API:
- if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_BIT) {
- t->CurrentAPIIndex = _eglConvertApiToIndex(api);
- return EGL_TRUE;
- }
- _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
- return EGL_FALSE;
-#endif
- case EGL_OPENGL_ES_API:
- if (_eglGlobal.ClientAPIsMask & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)) {
- t->CurrentAPIIndex = _eglConvertApiToIndex(api);
- return EGL_TRUE;
- }
- _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
- return EGL_FALSE;
- case EGL_OPENVG_API:
- if (_eglGlobal.ClientAPIsMask & EGL_OPENVG_BIT) {
- t->CurrentAPIIndex = _eglConvertApiToIndex(api);
- return EGL_TRUE;
- }
- _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
- return EGL_FALSE;
- default:
- return EGL_FALSE;
- }
+ t->CurrentAPIIndex = _eglConvertApiToIndex(api);
return EGL_TRUE;
}
@@ -951,20 +992,4 @@ eglReleaseThread(void)
}
-EGLBoolean
-eglWaitClient(void)
-{
- _EGLDisplay *disp = _eglGetCurrentDisplay();
- _EGLDriver *drv;
-
- if (!disp)
- return EGL_TRUE;
-
- /* a current display is always initialized */
- drv = disp->Driver;
-
- return drv->API.WaitClient(drv, disp);
-}
-
-
#endif /* EGL_VERSION_1_2 */
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index 6081e58892..aa0abe3eb6 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -35,13 +35,13 @@ typedef EGLBoolean (*QuerySurface_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurf
typedef EGLBoolean (*SurfaceAttrib_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint attribute, EGLint value);
typedef EGLBoolean (*BindTexImage_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint buffer);
typedef EGLBoolean (*ReleaseTexImage_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, EGLint buffer);
-typedef EGLBoolean (*SwapInterval_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint interval);
+typedef EGLBoolean (*SwapInterval_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint interval);
typedef EGLBoolean (*SwapBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *draw);
typedef EGLBoolean (*CopyBuffers_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface, NativePixmapType target);
/* misc funcs */
typedef const char *(*QueryString_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name);
-typedef EGLBoolean (*WaitGL_t)(_EGLDriver *drv, _EGLDisplay *dpy);
+typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx);
typedef EGLBoolean (*WaitNative_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine);
typedef _EGLProc (*GetProcAddress_t)(const char *procname);
@@ -65,7 +65,6 @@ typedef const char * (*QueryModeStringMESA_t)(_EGLDriver *drv, _EGLDisplay *dpy,
#ifdef EGL_VERSION_1_2
-typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, _EGLDisplay *dpy);
typedef _EGLSurface *(*CreatePbufferFromClientBuffer_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLenum buftype, EGLClientBuffer buffer, _EGLConfig *config, const EGLint *attrib_list);
#endif /* EGL_VERSION_1_2 */
@@ -101,7 +100,7 @@ struct _egl_api
CopyBuffers_t CopyBuffers;
QueryString_t QueryString;
- WaitGL_t WaitGL;
+ WaitClient_t WaitClient;
WaitNative_t WaitNative;
GetProcAddress_t GetProcAddress;
@@ -120,7 +119,6 @@ struct _egl_api
QueryModeStringMESA_t QueryModeStringMESA;
#ifdef EGL_VERSION_1_2
- WaitClient_t WaitClient;
CreatePbufferFromClientBuffer_t CreatePbufferFromClientBuffer;
#endif
};
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index d47b99eed4..31d69a7708 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -15,302 +15,705 @@
#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)
{
+ EGLint num_configs = (dpy) ? dpy->NumConfigs : 0;
EGLint i;
- for (i = 0; i < disp->NumConfigs; i++) {
- if (disp->Configs[i]->Handle == config) {
- return disp->Configs[i];
+
+ for (i = 0; i < num_configs; i++) {
+ _EGLConfig *conf = dpy->Configs[i];
+ if (conf == (_EGLConfig *) config) {
+ assert(conf->Display == dpy);
+ break;
}
}
- return NULL;
+ return (i < num_configs);
}
-/**
- * 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 +727,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 +764,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 +793,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 +810,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 36ed96ae95..6b8a259984 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 c9d00e7982..36e94f0d2d 100644
--- a/src/egl/main/eglconfigutil.c
+++ b/src/egl/main/eglconfigutil.c
@@ -52,6 +52,83 @@ _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);
+
+ if (m->visualType != GLX_NONE)
+ SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, m->visualType);
+ else
+ SET_CONFIG_ATTRIB(conf, EGL_NATIVE_VISUAL_TYPE, EGL_NONE);
+
+ 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 c477b94737..8c923ee206 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 "GL/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 b094f49bfc..ee4b1b59f5 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 647f24488f..45c7b4717b 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/eglcurrent.c b/src/egl/main/eglcurrent.c
index 4431f964f6..df506151b5 100644
--- a/src/egl/main/eglcurrent.c
+++ b/src/egl/main/eglcurrent.c
@@ -9,14 +9,14 @@
/* This should be kept in sync with _eglInitThreadInfo() */
#define _EGL_THREAD_INFO_INITIALIZER \
- { EGL_SUCCESS, { NULL }, 1 }
+ { EGL_SUCCESS, { NULL }, 0 }
/* a fallback thread info to guarantee that every thread always has one */
static _EGLThreadInfo dummy_thread = _EGL_THREAD_INFO_INITIALIZER;
#ifdef GLX_USE_TLS
-static __thread const _EGLThreadInfo *_egl_TSD;
+static __thread const _EGLThreadInfo *_egl_TSD
__attribute__ ((tls_model("initial-exec")));
static INLINE void _eglSetTSD(const _EGLThreadInfo *t)
diff --git a/src/egl/main/eglcurrent.h b/src/egl/main/eglcurrent.h
index 8eb241029e..9503e0aba0 100644
--- a/src/egl/main/eglcurrent.h
+++ b/src/egl/main/eglcurrent.h
@@ -4,8 +4,16 @@
#include "egltypedefs.h"
-#define _EGL_API_NUM_INDICES \
- (EGL_OPENGL_API - EGL_OPENGL_ES_API + 2) /* idx 0 is for EGL_NONE */
+#define _EGL_API_ALL_BITS \
+ (EGL_OPENGL_ES_BIT | \
+ EGL_OPENVG_BIT | \
+ EGL_OPENGL_ES2_BIT | \
+ EGL_OPENGL_BIT)
+
+
+#define _EGL_API_FIRST_API EGL_OPENGL_ES_API
+#define _EGL_API_LAST_API EGL_OPENGL_API
+#define _EGL_API_NUM_APIS (_EGL_API_LAST_API - _EGL_API_FIRST_API + 1)
/**
@@ -14,20 +22,19 @@
struct _egl_thread_info
{
EGLint LastError;
- _EGLContext *CurrentContexts[_EGL_API_NUM_INDICES];
+ _EGLContext *CurrentContexts[_EGL_API_NUM_APIS];
/* use index for fast access to current context */
EGLint CurrentAPIIndex;
};
/**
- * Return true if a client API enum can be converted to an index.
+ * Return true if a client API enum is recognized.
*/
static INLINE EGLBoolean
_eglIsApiValid(EGLenum api)
{
- return ((api >= EGL_OPENGL_ES_API && api <= EGL_OPENGL_API) ||
- api == EGL_NONE);
+ return (api >= _EGL_API_FIRST_API && api <= _EGL_API_LAST_API);
}
@@ -38,7 +45,7 @@ _eglIsApiValid(EGLenum api)
static INLINE EGLint
_eglConvertApiToIndex(EGLenum api)
{
- return (api != EGL_NONE) ? api - EGL_OPENGL_ES_API + 1 : 0;
+ return api - _EGL_API_FIRST_API;
}
@@ -49,7 +56,7 @@ _eglConvertApiToIndex(EGLenum api)
static INLINE EGLenum
_eglConvertApiFromIndex(EGLint idx)
{
- return (idx) ? EGL_OPENGL_ES_API + idx - 1 : EGL_NONE;
+ return _EGL_API_FIRST_API + idx;
}
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 6575fdf198..ea4e35a8b3 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 */
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
index 87786e36bb..018b06d3be 100644
--- a/src/egl/main/egldriver.c
+++ b/src/egl/main/egldriver.c
@@ -22,59 +22,70 @@
#if defined(_EGL_PLATFORM_X)
#include <dlfcn.h>
-#elif defined(_EGL_PLATFORM_WINDOWS)
-/* Use static linking on Windows for now */
-#define WINDOWS_STATIC_LINK
#endif
+
/**
* Wrappers for dlopen/dlclose()
*/
#if defined(_EGL_PLATFORM_WINDOWS)
-#ifdef WINDOWS_STATIC_LINK
- static const char *DefaultDriverName = "Windows EGL Static Library";
-#else
- /* XXX Need to decide how to do dynamic name lookup on Windows */
- static const char *DefaultDriverName = "TBD";
-#endif
- typedef HMODULE lib_handle;
-
- static HMODULE
- open_library(const char *filename)
- {
-#ifdef WINDOWS_STATIC_LINK
- return 0;
-#else
- return LoadLibrary(filename);
-#endif
- }
- static void
- close_library(HMODULE lib)
- {
-#ifdef WINDOWS_STATIC_LINK
-#else
- FreeLibrary(lib);
-#endif
- }
+
+/* XXX Need to decide how to do dynamic name lookup on Windows */
+static const char DefaultDriverName[] = "TBD";
+
+typedef HMODULE lib_handle;
+
+static HMODULE
+open_library(const char *filename)
+{
+ return LoadLibrary(filename);
+}
+
+static void
+close_library(HMODULE lib)
+{
+ FreeLibrary(lib);
+}
+
#elif defined(_EGL_PLATFORM_X)
- static const char *DefaultDriverName = "egl_softpipe";
- typedef void * lib_handle;
- static void *
- open_library(const char *filename)
- {
- return dlopen(filename, RTLD_LAZY);
- }
+static const char DefaultDriverName[] = "egl_softpipe";
+
+typedef void * lib_handle;
+
+static void *
+open_library(const char *filename)
+{
+ return dlopen(filename, RTLD_LAZY);
+}
+
+static void
+close_library(void *lib)
+{
+ dlclose(lib);
+}
+
+#else /* _EGL_PLATFORM_NO_OS */
+
+static const char DefaultDriverName[] = "builtin";
+
+typedef void *lib_handle;
+
+static INLINE void *
+open_library(const char *filename)
+{
+ return (void *) filename;
+}
+
+static INLINE void
+close_library(void *lib)
+{
+}
+
- static void
- close_library(void *lib)
- {
- dlclose(lib);
- }
-
#endif
@@ -95,14 +106,22 @@ _eglChooseDriver(_EGLDisplay *dpy, char **argsRet)
path = _eglstrdup(path);
#if defined(_EGL_PLATFORM_X)
- if (!path && dpy->NativeDisplay) {
+ if (!path && dpy && dpy->NativeDisplay) {
/* assume (wrongly!) that the native display is a display string */
path = _eglSplitDisplayString((const char *) dpy->NativeDisplay, &args);
}
suffix = "so";
#elif defined(_EGL_PLATFORM_WINDOWS)
suffix = "dll";
-#endif /* _EGL_PLATFORM_X */
+#else /* _EGL_PLATFORM_NO_OS */
+ if (path) {
+ /* force the use of the default driver */
+ _eglLog(_EGL_DEBUG, "ignore EGL_DRIVER");
+ free(path);
+ path = NULL;
+ }
+ suffix = NULL;
+#endif
if (!path)
path = _eglstrdup(DefaultDriverName);
@@ -136,43 +155,48 @@ _eglChooseDriver(_EGLDisplay *dpy, char **argsRet)
static _EGLMain_t
_eglOpenLibrary(const char *driverPath, lib_handle *handle)
{
- _EGLMain_t mainFunc;
lib_handle lib;
+ _EGLMain_t mainFunc = NULL;
+ const char *error = "unknown error";
assert(driverPath);
-#if defined(_EGL_PLATFORM_WINDOWS)
-/* Use static linking on Windows for now */
-#ifdef WINDOWS_STATIC_LINK
- lib = 0;
- mainFunc = (_EGLMain_t)_eglMain;
-#else
- /* XXX untested */
_eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath);
lib = open_library(driverPath);
- if (!lib) {
- _eglLog(_EGL_WARNING, "Could not open %s",
- driverPath);
- return NULL;
+
+#if defined(_EGL_PLATFORM_WINDOWS)
+ /* XXX untested */
+ if (lib)
+ mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
+#elif defined(_EGL_PLATFORM_X)
+ if (lib) {
+ mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
+ if (!mainFunc)
+ error = dlerror();
+ }
+ else {
+ error = dlerror();
}
- mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
+#else /* _EGL_PLATFORM_NO_OS */
+ /* must be the default driver name */
+ if (strcmp(driverPath, DefaultDriverName) == 0)
+ mainFunc = (_EGLMain_t) _eglMain;
+ else
+ error = "not builtin driver";
#endif
-#elif defined(_EGL_PLATFORM_X)
- _eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath);
- lib = open_library(driverPath);
+
if (!lib) {
- _eglLog(_EGL_WARNING, "Could not open %s (%s)",
- driverPath, dlerror());
+ _eglLog(_EGL_WARNING, "Could not open driver %s (%s)",
+ driverPath, error);
if (!getenv("EGL_DRIVER"))
_eglLog(_EGL_WARNING,
"The driver can be overridden by setting EGL_DRIVER");
return NULL;
}
- mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
-#endif
if (!mainFunc) {
- _eglLog(_EGL_WARNING, "_eglMain not found in %s", driverPath);
+ _eglLog(_EGL_WARNING, "_eglMain not found in %s (%s)",
+ driverPath, error);
if (lib)
close_library(lib);
return NULL;
@@ -384,7 +408,7 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
drv->API.CopyBuffers = _eglCopyBuffers;
drv->API.QueryString = _eglQueryString;
- drv->API.WaitGL = _eglWaitGL;
+ drv->API.WaitClient = _eglWaitClient;
drv->API.WaitNative = _eglWaitNative;
#ifdef EGL_MESA_screen_surface
@@ -428,6 +452,11 @@ _eglFindAPIs(void)
const char *es2_libname = "libGLESv2.so";
const char *gl_libname = "libGL.so";
const char *vg_libname = "libOpenVG.so";
+#else /* _EGL_PLATFORM_NO_OS */
+ const char *es1_libname = NULL;
+ const char *es2_libname = NULL;
+ const char *gl_libname = NULL;
+ const char *vg_libname = NULL;
#endif
if ((lib = open_library(es1_libname))) {
diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c
index 3ae4c1ad3a..443d0f072c 100644
--- a/src/egl/main/eglglobals.c
+++ b/src/egl/main/eglglobals.c
@@ -15,13 +15,13 @@ struct _egl_global _eglGlobal =
&_eglGlobalMutex, /* Mutex */
NULL, /* DisplayList */
1, /* FreeScreenHandle */
- 0x0, /* ClientAPIsMask */
0, /* NumDrivers */
{ NULL }, /* Drivers */
2, /* NumAtExitCalls */
- { /* AtExitCalls */
- _eglFiniDisplay,
- _eglUnloadDrivers
+ {
+ /* default AtExitCalls, called in reverse order */
+ _eglUnloadDrivers, /* always called last */
+ _eglFiniDisplay
},
};
diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h
index 58511076d4..5ebb914ca7 100644
--- a/src/egl/main/eglglobals.h
+++ b/src/egl/main/eglglobals.h
@@ -19,9 +19,6 @@ struct _egl_global
EGLScreenMESA FreeScreenHandle;
- /* bitmaks of supported APIs (supported by _some_ driver) */
- EGLint ClientAPIsMask;
-
EGLint NumDrivers;
_EGLDriver *Drivers[10];
diff --git a/src/egl/main/egllog.c b/src/egl/main/egllog.c
index 1d7a0a388c..11a9bf7275 100644
--- a/src/egl/main/egllog.c
+++ b/src/egl/main/egllog.c
@@ -9,51 +9,140 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+
#include "egllog.h"
+#include "eglmutex.h"
#define MAXSTRING 1000
-#define FALLBACK_LOG_LEVEL _EGL_WARNING
-#define FALLBACK_LOG_LEVEL_STR "warning"
+#define FALLBACK_LOG_LEVEL _EGL_WARNING
-static EGLint ReportingLevel = -1;
+static struct {
+ _EGLMutex mutex;
-static void
-log_level_initialize(void)
+ EGLBoolean initialized;
+ EGLint level;
+ _EGLLogProc logger;
+ EGLint num_messages;
+} logging = {
+ _EGL_MUTEX_INITIALIZER,
+ EGL_FALSE,
+ FALLBACK_LOG_LEVEL,
+ NULL,
+ 0
+};
+
+static const char *level_strings[] = {
+ /* the order is important */
+ "fatal",
+ "warning",
+ "info",
+ "debug",
+ NULL
+};
+
+
+/**
+ * Set the function to be called when there is a message to log.
+ * Note that the function will be called with an internal lock held.
+ * Recursive logging is not allowed.
+ */
+void
+_eglSetLogProc(_EGLLogProc logger)
{
-#if defined(_EGL_PLATFORM_X)
- char *log_env = getenv("EGL_LOG_LEVEL");
-#else
- char *log_env = NULL;
-#endif
-
- if (log_env == NULL) {
- ReportingLevel = FALLBACK_LOG_LEVEL;
- }
- else if (strcasecmp(log_env, "fatal") == 0) {
- ReportingLevel = _EGL_FATAL;
- }
- else if (strcasecmp(log_env, "warning") == 0) {
- ReportingLevel = _EGL_WARNING;
+ EGLint num_messages = 0;
+
+ _eglLockMutex(&logging.mutex);
+
+ if (logging.logger != logger) {
+ logging.logger = logger;
+
+ num_messages = logging.num_messages;
+ logging.num_messages = 0;
}
- else if (strcasecmp(log_env, "info") == 0) {
- ReportingLevel = _EGL_INFO;
+
+ _eglUnlockMutex(&logging.mutex);
+
+ if (num_messages)
+ _eglLog(_EGL_DEBUG,
+ "New logger installed. "
+ "Messages before the new logger might not be available.");
+}
+
+
+/**
+ * Set the log reporting level.
+ */
+void
+_eglSetLogLevel(EGLint level)
+{
+ switch (level) {
+ case _EGL_FATAL:
+ case _EGL_WARNING:
+ case _EGL_INFO:
+ case _EGL_DEBUG:
+ _eglLockMutex(&logging.mutex);
+ logging.level = level;
+ _eglUnlockMutex(&logging.mutex);
+ break;
+ default:
+ break;
}
- else if (strcasecmp(log_env, "debug") == 0) {
- ReportingLevel = _EGL_DEBUG;
+}
+
+
+/**
+ * The default logger. It prints the message to stderr.
+ */
+static void
+_eglDefaultLogger(EGLint level, const char *msg)
+{
+ fprintf(stderr, "libEGL %s: %s\n", level_strings[level], msg);
+}
+
+
+/**
+ * Initialize the logging facility.
+ */
+static void
+_eglInitLogger(void)
+{
+ const char *log_env;
+ EGLint i, level = -1;
+
+ if (logging.initialized)
+ return;
+
+ log_env = getenv("EGL_LOG_LEVEL");
+ if (log_env) {
+ for (i = 0; level_strings[i]; i++) {
+ if (strcasecmp(log_env, level_strings[i]) == 0) {
+ level = i;
+ break;
+ }
+ }
}
else {
- fprintf(stderr, "Unrecognized EGL_LOG_LEVEL environment variable value. "
+ level = FALLBACK_LOG_LEVEL;
+ }
+
+ logging.logger = _eglDefaultLogger;
+ logging.level = (level >= 0) ? level : FALLBACK_LOG_LEVEL;
+ logging.initialized = EGL_TRUE;
+
+ /* it is fine to call _eglLog now */
+ if (log_env && level < 0) {
+ _eglLog(_EGL_WARNING,
+ "Unrecognized EGL_LOG_LEVEL environment variable value. "
"Expected one of \"fatal\", \"warning\", \"info\", \"debug\". "
- "Got \"%s\". Falling back to \"%s\".\n",
- log_env, FALLBACK_LOG_LEVEL_STR);
- ReportingLevel = FALLBACK_LOG_LEVEL;
+ "Got \"%s\". Falling back to \"%s\".",
+ log_env, level_strings[FALLBACK_LOG_LEVEL]);
}
}
/**
- * Log a message to stderr.
+ * Log a message with message logger.
* \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG.
*/
void
@@ -61,40 +150,26 @@ _eglLog(EGLint level, const char *fmtStr, ...)
{
va_list args;
char msg[MAXSTRING];
- const char *levelStr;
- static int log_level_initialized = 0;
- if (!log_level_initialized) {
- log_level_initialize();
- log_level_initialized = 1;
- }
+ /* one-time initialization; a little race here is fine */
+ if (!logging.initialized)
+ _eglInitLogger();
+ if (level > logging.level || level < 0)
+ return;
- if (level <= ReportingLevel) {
- switch (level) {
- case _EGL_FATAL:
- levelStr = "Fatal";
- break;
- case _EGL_WARNING:
- levelStr = "Warning";
- break;
- case _EGL_INFO:
- levelStr = "Info";
- break;
- case _EGL_DEBUG:
- levelStr = "Debug";
- break;
- default:
- levelStr = "";
- }
+ _eglLockMutex(&logging.mutex);
+ if (logging.logger) {
va_start(args, fmtStr);
vsnprintf(msg, MAXSTRING, fmtStr, args);
va_end(args);
- fprintf(stderr, "libEGL %s: %s\n", levelStr, msg);
-
- if (level == _EGL_FATAL) {
- exit(1); /* or abort()? */
- }
+ logging.logger(level, msg);
+ logging.num_messages++;
}
+
+ _eglUnlockMutex(&logging.mutex);
+
+ if (level == _EGL_FATAL)
+ exit(1); /* or abort()? */
}
diff --git a/src/egl/main/egllog.h b/src/egl/main/egllog.h
index 2fa352f155..83c8bb72a6 100644
--- a/src/egl/main/egllog.h
+++ b/src/egl/main/egllog.h
@@ -9,6 +9,17 @@
#define _EGL_DEBUG 3 /* useful info for debugging */
+typedef void (*_EGLLogProc)(EGLint level, const char *msg);
+
+
+extern void
+_eglSetLogProc(_EGLLogProc logger);
+
+
+extern void
+_eglSetLogLevel(EGLint level);
+
+
extern void
_eglLog(EGLint level, const char *fmtStr, ...);
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
index b37213faf1..e66913320b 100644
--- a/src/egl/main/eglmisc.c
+++ b/src/egl/main/eglmisc.c
@@ -108,11 +108,12 @@ _eglQueryString(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name)
EGLBoolean
-_eglWaitGL(_EGLDriver *drv, _EGLDisplay *dpy)
+_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx)
{
/* just a placeholder */
(void) drv;
(void) dpy;
+ (void) ctx;
return EGL_TRUE;
}
diff --git a/src/egl/main/eglmisc.h b/src/egl/main/eglmisc.h
index a15c839be2..829d4cde79 100644
--- a/src/egl/main/eglmisc.h
+++ b/src/egl/main/eglmisc.h
@@ -37,7 +37,7 @@ _eglQueryString(_EGLDriver *drv, _EGLDisplay *dpy, EGLint name);
extern EGLBoolean
-_eglWaitGL(_EGLDriver *drv, _EGLDisplay *dpy);
+_eglWaitClient(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx);
extern EGLBoolean
diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c
index e7a1a8329e..940a1b760c 100644
--- a/src/egl/main/eglsurface.c
+++ b/src/egl/main/eglsurface.c
@@ -15,6 +15,22 @@
#include "eglsurface.h"
+static void
+_eglClampSwapInterval(_EGLSurface *surf, EGLint interval)
+{
+ EGLint bound = GET_CONFIG_ATTRIB(surf->Config, EGL_MAX_SWAP_INTERVAL);
+ if (interval >= bound) {
+ interval = bound;
+ }
+ else {
+ bound = GET_CONFIG_ATTRIB(surf->Config, EGL_MIN_SWAP_INTERVAL);
+ if (interval < bound)
+ interval = bound;
+ }
+ surf->SwapInterval = interval;
+}
+
+
/**
* Do error check on parameters and initialize the given _EGLSurface object.
* \return EGL_TRUE if no errors, EGL_FALSE otherwise.
@@ -194,7 +210,9 @@ _eglInitSurface(_EGLDriver *drv, _EGLSurface *surf, EGLint type,
surf->TextureTarget = texTarget;
surf->MipmapTexture = mipmapTex;
surf->MipmapLevel = 0;
- surf->SwapInterval = 0;
+ /* the default swap interval is 1 */
+ _eglClampSwapInterval(surf, 1);
+
#ifdef EGL_VERSION_1_2
surf->SwapBehavior = EGL_BUFFER_DESTROYED; /* XXX ok? */
surf->HorizontalResolution = EGL_UNKNOWN; /* set by caller */
@@ -466,11 +484,10 @@ _eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surface,
EGLBoolean
-_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, EGLint interval)
+_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf,
+ EGLint interval)
{
- _EGLSurface *surf = _eglGetCurrentSurface(EGL_DRAW);
- if (surf)
- surf->SwapInterval = interval;
+ _eglClampSwapInterval(surf, interval);
return EGL_TRUE;
}
diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h
index f6d44b5922..b75fa9c368 100644
--- a/src/egl/main/eglsurface.h
+++ b/src/egl/main/eglsurface.h
@@ -86,7 +86,7 @@ _eglReleaseTexImage(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint
extern EGLBoolean
-_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, EGLint interval);
+_eglSwapInterval(_EGLDriver *drv, _EGLDisplay *dpy, _EGLSurface *surf, EGLint interval);
#ifdef EGL_VERSION_1_2