summaryrefslogtreecommitdiffstats
path: root/src/egl
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl')
-rw-r--r--src/egl/Makefile2
-rw-r--r--src/egl/drivers/Makefile25
-rw-r--r--src/egl/drivers/demo/demo.c34
-rw-r--r--src/egl/drivers/dri/Makefile9
-rw-r--r--src/egl/drivers/dri/egldri.c98
-rw-r--r--src/egl/drivers/dri/egldri.h9
-rw-r--r--src/egl/drivers/glx/Makefile74
-rw-r--r--src/egl/drivers/glx/egl_glx.c584
-rw-r--r--src/egl/drivers/xdri/Makefile70
-rw-r--r--src/egl/drivers/xdri/egl_xdri.c1177
-rw-r--r--src/egl/main/Makefile27
-rw-r--r--src/egl/main/README.txt71
-rw-r--r--src/egl/main/eglapi.c191
-rw-r--r--src/egl/main/eglapi.h11
-rw-r--r--src/egl/main/eglconfig.c308
-rw-r--r--src/egl/main/eglconfig.h27
-rw-r--r--src/egl/main/eglconfigutil.c258
-rw-r--r--src/egl/main/eglconfigutil.h26
-rw-r--r--src/egl/main/eglcontext.c69
-rw-r--r--src/egl/main/eglcontext.h12
-rw-r--r--src/egl/main/egldefines.h45
-rw-r--r--src/egl/main/egldisplay.c102
-rw-r--r--src/egl/main/egldisplay.h21
-rw-r--r--src/egl/main/egldriver.c363
-rw-r--r--src/egl/main/egldriver.h52
-rw-r--r--src/egl/main/eglglobals.c14
-rw-r--r--src/egl/main/eglglobals.h11
-rw-r--r--src/egl/main/egllog.c34
-rw-r--r--src/egl/main/eglmisc.c129
-rw-r--r--src/egl/main/eglmisc.h47
-rw-r--r--src/egl/main/eglmode.h3
-rw-r--r--src/egl/main/eglstring.c24
-rw-r--r--src/egl/main/eglstring.h9
-rw-r--r--src/egl/main/eglsurface.c114
-rw-r--r--src/egl/main/eglsurface.h5
-rw-r--r--src/egl/main/egltypedefs.h8
-rw-r--r--src/egl/main/eglx.c100
-rw-r--r--src/egl/main/eglx.h12
38 files changed, 3542 insertions, 633 deletions
diff --git a/src/egl/Makefile b/src/egl/Makefile
index fb4db8f9b9f..024453f8bb1 100644
--- a/src/egl/Makefile
+++ b/src/egl/Makefile
@@ -2,7 +2,7 @@
TOP = ../..
-SUBDIRS = main drivers/demo drivers/dri
+SUBDIRS = main drivers
default: subdirs
diff --git a/src/egl/drivers/Makefile b/src/egl/drivers/Makefile
new file mode 100644
index 00000000000..f0538f563f7
--- /dev/null
+++ b/src/egl/drivers/Makefile
@@ -0,0 +1,25 @@
+# src/egl/drivers/Makefile
+
+TOP = ../../..
+include $(TOP)/configs/current
+
+SUBDIRS = $(EGL_DRIVERS_DIRS)
+
+
+default: subdirs
+
+
+subdirs:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir ; $(MAKE)) || exit 1 ; \
+ fi \
+ done
+
+
+clean:
+ @for dir in $(SUBDIRS) ; do \
+ if [ -d $$dir ] ; then \
+ (cd $$dir ; $(MAKE) clean) ; \
+ fi \
+ done
diff --git a/src/egl/drivers/demo/demo.c b/src/egl/drivers/demo/demo.c
index 45545755c00..1750e976b84 100644
--- a/src/egl/drivers/demo/demo.c
+++ b/src/egl/drivers/demo/demo.c
@@ -21,7 +21,7 @@
typedef struct demo_driver
{
_EGLDriver Base; /* base class/object */
- GLuint DemoStuff;
+ unsigned DemoStuff;
} DemoDriver;
#define DEMO_DRIVER(D) ((DemoDriver *) (D))
@@ -33,7 +33,7 @@ typedef struct demo_driver
typedef struct demo_surface
{
_EGLSurface Base; /* base class/object */
- GLuint DemoStuff;
+ unsigned DemoStuff;
} DemoSurface;
@@ -43,7 +43,7 @@ typedef struct demo_surface
typedef struct demo_context
{
_EGLContext Base; /* base class/object */
- GLuint DemoStuff;
+ unsigned DemoStuff;
} DemoContext;
@@ -67,22 +67,22 @@ demoInitialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
/* Create the display's visual configs - silly example */
for (i = 0; i < 4; i++) {
- _EGLConfig config;
- _eglInitConfig(&config, i + 1);
- _eglSetConfigAttrib(&config, EGL_RED_SIZE, 8);
- _eglSetConfigAttrib(&config, EGL_GREEN_SIZE, 8);
- _eglSetConfigAttrib(&config, EGL_BLUE_SIZE, 8);
- _eglSetConfigAttrib(&config, EGL_ALPHA_SIZE, 8);
- _eglSetConfigAttrib(&config, EGL_BUFFER_SIZE, 32);
+ _EGLConfig *config = calloc(1, sizeof(_EGLConfig));
+ _eglInitConfig(config, i + 1);
+ _eglSetConfigAttrib(config, EGL_RED_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32);
if (i & 1) {
- _eglSetConfigAttrib(&config, EGL_DEPTH_SIZE, 32);
+ _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 32);
}
if (i & 2) {
- _eglSetConfigAttrib(&config, EGL_STENCIL_SIZE, 8);
+ _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8);
}
- _eglSetConfigAttrib(&config, EGL_SURFACE_TYPE,
+ _eglSetConfigAttrib(config, EGL_SURFACE_TYPE,
(EGL_WINDOW_BIT | EGL_PIXMAP_BIT | EGL_PBUFFER_BIT));
- _eglAddConfig(disp, &config);
+ _eglAddConfig(disp, config);
}
drv->Initialized = EGL_TRUE;
@@ -152,9 +152,9 @@ demoCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext
/* generate handle and insert into hash table */
_eglSaveContext(&c->Base);
- assert(c->Base.Handle);
+ assert(_eglGetContextHandle(&c->Base));
- return c->Base.Handle;
+ return _eglGetContextHandle(&c->Base);
}
@@ -286,7 +286,7 @@ demoMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface rea
* plug in API functions.
*/
_EGLDriver *
-_eglMain(_EGLDisplay *dpy)
+_eglMain(_EGLDisplay *dpy, const char *args)
{
DemoDriver *demo;
diff --git a/src/egl/drivers/dri/Makefile b/src/egl/drivers/dri/Makefile
index af0c40fe2b7..d7eba653b2d 100644
--- a/src/egl/drivers/dri/Makefile
+++ b/src/egl/drivers/dri/Makefile
@@ -8,7 +8,7 @@ include $(TOP)/configs/current
INCLUDE_DIRS = \
-I. \
-I/usr/include \
- -I/usr/include/drm \
+ $(shell pkg-config --cflags-only-I libdrm) \
-I$(TOP)/include \
-I$(TOP)/include/GL/internal \
-I$(TOP)/src/mesa \
@@ -29,6 +29,8 @@ SOURCES = egldri.c
OBJECTS = $(SOURCES:.c=.o)
+DRM_LIB = `pkg-config --libs libdrm`
+
.c.o:
$(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
@@ -44,7 +46,7 @@ library: $(TOP)/$(LIB_DIR)/libEGLdri.so
$(TOP)/$(LIB_DIR)/libEGLdri.so: $(OBJECTS)
$(MKLIB) -o EGLdri -linker '$(CC)' -ldflags '$(LDFLAGS)' \
-major 1 -minor 0 \
- -install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS)
+ -install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS) $(LIBS)
clean:
@@ -53,9 +55,10 @@ clean:
depend: $(SOURCES) $(HEADERS)
@ echo "running $(MKDEP)"
+ @ rm -f depend
@ touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \
- $(SOURCES) $(HEADERS) > /dev/null
+ $(SOURCES) $(HEADERS) >/dev/null 2>/dev/null
include depend
# DO NOT DELETE
diff --git a/src/egl/drivers/dri/egldri.c b/src/egl/drivers/dri/egldri.c
index cab0be2bd18..57661cc3ab8 100644
--- a/src/egl/drivers/dri/egldri.c
+++ b/src/egl/drivers/dri/egldri.c
@@ -1,5 +1,6 @@
/**
- * Generic EGL driver for DRI.
+ * Generic EGL driver for DRI. This is basically an "adaptor" driver
+ * that allows libEGL to load/use regular DRI drivers.
*
* This file contains all the code needed to interface DRI-based drivers
* with libEGL.
@@ -23,6 +24,7 @@
#include "egldisplay.h"
#include "eglcontext.h"
#include "eglconfig.h"
+#include "eglconfigutil.h"
#include "eglsurface.h"
#include "eglscreen.h"
#include "eglglobals.h"
@@ -32,18 +34,72 @@
#include "egldri.h"
const char *sysfs = "/sys/class";
-#define None 0
+
static const int empty_attribute_list[1] = { None };
+
+/**
+ * Given a card number, return the name of the DRI driver to use.
+ * This generally means reading the contents of
+ * /sys/class/drm/cardX/dri_library_name, where X is the card number
+ */
+static EGLBoolean
+driver_name_from_card_number(int card, char *driverName, int maxDriverName)
+{
+ char path[2000];
+ FILE *f;
+ int length;
+
+ snprintf(path, sizeof(path), "%s/drm/card%d/dri_library_name", sysfs, card);
+
+ f = fopen(path, "r");
+ if (!f)
+ return EGL_FALSE;
+
+ fgets(driverName, maxDriverName, f);
+ fclose(f);
+
+ if ((length = strlen(driverName)) > 1) {
+ /* remove the trailing newline from sysfs */
+ driverName[length - 1] = '\0';
+ strncat(driverName, "_dri", maxDriverName);
+ return EGL_TRUE;
+ }
+ else {
+ return EGL_FALSE;
+ }
+}
+
+
+
/**
* The bootstrap function.
* Return a new driDriver object and plug in API functions.
* This function, in turn, loads a specific DRI driver (ex: r200_dri.so).
*/
_EGLDriver *
-_eglMain(_EGLDisplay *dpy)
+_eglMain(_EGLDisplay *dpy, const char *args)
{
+#if 1
+ const int card = args ? atoi(args) : 0;
+ _EGLDriver *driver = NULL;
+ char driverName[1000];
+
+ if (!driver_name_from_card_number(card, driverName, sizeof(driverName))) {
+ _eglLog(_EGL_WARNING,
+ "Unable to determine driver name for card %d\n", card);
+ return NULL;
+ }
+
+ _eglLog(_EGL_DEBUG, "Driver name: %s\n", driverName);
+
+ driver = _eglOpenDriver(dpy, driverName, args);
+
+ return driver;
+
+#else
+
int length;
char path[NAME_MAX];
struct dirent *dirent;
@@ -58,14 +114,19 @@ _eglMain(_EGLDisplay *dpy)
_eglLog(_EGL_WARNING, "%s DRM devices not found.", path);
return EGL_FALSE;
}
+
+ /* loop over dir entries looking for cardX where "X" is in the
+ * dpy->DriverName ":X" string.
+ */
while ((dirent = readdir(dir))) {
if (strncmp(&dirent->d_name[0], "card", 4) != 0)
continue;
- if (strcmp(&dirent->d_name[4], &dpy->Name[1]) != 0)
+ if (strcmp(&dirent->d_name[4], &driverName[1]) != 0)
continue;
- snprintf(path, sizeof(path), "%s/drm/card%s/dri_library_name", sysfs, &dpy->Name[1]);
+ snprintf(path, sizeof(path), "%s/drm/card%s/dri_library_name",
+ sysfs, &driverName[1]);
_eglLog(_EGL_INFO, "Opening %s", path);
#if 1
file = fopen(path, "r");
@@ -89,6 +150,7 @@ _eglMain(_EGLDisplay *dpy)
closedir(dir);
return driver;
+#endif
}
@@ -141,7 +203,7 @@ _eglDRICreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
/* generate handle and insert into hash table */
_eglSaveContext(&c->Base);
- return c->Base.Handle;
+ return _eglGetContextHandle(&c->Base);
}
@@ -152,13 +214,15 @@ _eglDRIMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw,
driDisplay *disp = Lookup_driDisplay(dpy);
driContext *ctx = Lookup_driContext(context);
EGLBoolean b;
+ __DRIid drawBuf = (__DRIid) draw;
+ __DRIid readBuf = (__DRIid) read;
b = _eglMakeCurrent(drv, dpy, draw, read, context);
if (!b)
return EGL_FALSE;
if (ctx) {
- ctx->driContext.bindContext(disp, 0, read, draw, &ctx->driContext);
+ ctx->driContext.bindContext(disp, 0, drawBuf, readBuf, &ctx->driContext);
}
else {
/* what's this??? */
@@ -190,7 +254,7 @@ _eglDRICreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
#if 0
GLcontext *ctx = NULL; /* this _should_ be OK */
#endif
- GLvisual visMode;
+ __GLcontextModes visMode;
_EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
assert(conf); /* bad config should be caught earlier */
_eglConfigToContextModesRec(conf, &visMode);
@@ -267,7 +331,8 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
_EGLConfig *config = _eglLookupConfig(drv, dpy, cfg);
driDisplay *disp = Lookup_driDisplay(dpy);
driSurface *surface;
- GLvisual visMode;
+ __GLcontextModes visMode;
+ __DRIid drawBuf;
surface = (driSurface *) calloc(1, sizeof(*surface));
if (!surface) {
@@ -292,8 +357,10 @@ _eglDRICreateScreenSurfaceMESA(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
/* convert EGLConfig to GLvisual */
_eglConfigToContextModesRec(config, &visMode);
+ drawBuf = (__DRIid) _eglGetSurfaceHandle(&surface->Base);
+
/* Create a new DRI drawable */
- if (!disp->driScreen.createNewDrawable(disp, &visMode, surface->Base.Handle,
+ if (!disp->driScreen.createNewDrawable(disp, &visMode, drawBuf,
&surface->drawable, GLX_WINDOW_BIT,
empty_attribute_list)) {
_eglRemoveSurface(&surface->Base);
@@ -715,7 +782,7 @@ __eglGetDrawableInfo(__DRInativeDisplay * ndpy, int screen, __DRIid drawable,
{
__DRIscreen *pDRIScreen;
__DRIscreenPrivate *psp;
- driSurface *surf = Lookup_driSurface(drawable);
+ driSurface *surf = Lookup_driSurface((EGLSurface) drawable);
pDRIScreen = __eglFindDRIScreen(ndpy, screen);
@@ -1019,8 +1086,10 @@ _eglDRICreateDisplay(driDisplay *dpy, __DRIframebuffer *framebuffer)
api_ver,
& interface_methods,
NULL);
- if (!dpy->driScreen.private)
+ if (!dpy->driScreen.private) {
+ _eglLog(_EGL_WARNING, "egldri.c: DRI create new screen failed");
return EGL_FALSE;
+ }
DRM_UNLOCK( dpy->drmFD, dpy->pSAREA, dpy->serverContext );
@@ -1080,6 +1149,7 @@ _eglDRIInitialize(_EGLDriver *drv, EGLDisplay dpy,
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
driDisplay *display;
+ const char *driverName = (const char *) disp->NativeDisplay;
assert(disp);
@@ -1088,13 +1158,13 @@ _eglDRIInitialize(_EGLDriver *drv, EGLDisplay dpy,
*/
display = calloc(1, sizeof(*display));
display->Base = *disp;
- _eglHashInsert(_eglGlobal.Displays, disp->Handle, display);
+ _eglSaveDisplay(&display->Base);
free(disp);
*major = 1;
*minor = 0;
- sscanf(&disp->Name[1], "%d", &display->minor);
+ sscanf(driverName + 1, "%d", &display->minor);
drv->Initialized = EGL_TRUE;
return EGL_TRUE;
diff --git a/src/egl/drivers/dri/egldri.h b/src/egl/drivers/dri/egldri.h
index 34b12d64fcd..54a9a4ea269 100644
--- a/src/egl/drivers/dri/egldri.h
+++ b/src/egl/drivers/dri/egldri.h
@@ -1,11 +1,14 @@
#ifndef EGLDRI_INCLUDED
#define EGLDRI_INCLUDED
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
#include "egldisplay.h"
#include "eglscreen.h"
#include "eglsurface.h"
#include "eglcontext.h"
-#include "mtypes.h"
+
#include "dri_util.h"
#include "drm_sarea.h"
@@ -14,7 +17,7 @@
*/
typedef struct dri_display
{
- _EGLDisplay Base; /* base class/object */
+ _EGLDisplay Base; /**< base class */
void *pFB;
int drmFD; /**< \brief DRM device file descriptor */
int minor;
@@ -32,7 +35,7 @@ typedef struct dri_display
unsigned long FBStart; /**< \brief physical address of the framebuffer */
void *driverClientMsg;
int driverClientMsgSize;
- int chipset;
+ unsigned chipset;
void *driverPrivate;
drm_magic_t magic;
diff --git a/src/egl/drivers/glx/Makefile b/src/egl/drivers/glx/Makefile
new file mode 100644
index 00000000000..3cd52765133
--- /dev/null
+++ b/src/egl/drivers/glx/Makefile
@@ -0,0 +1,74 @@
+# src/egl/drivers/glx/Makefile
+
+# Build XEGL DRI driver loader library: egl_glx.so
+
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+
+EXTRA_DEFINES = -DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\"
+
+DRIVER_NAME = egl_glx.so
+
+
+INCLUDE_DIRS = \
+ -I. \
+ -I/usr/include \
+ $(shell pkg-config --cflags-only-I libdrm) \
+ -I$(TOP)/include \
+ -I$(TOP)/include/GL/internal \
+ -I$(TOP)/src/mesa/glapi \
+ -I$(TOP)/src/mesa/drivers/dri/common \
+ -I$(TOP)/src/mesa/main \
+ -I$(TOP)/src/mesa \
+ -I$(TOP)/src/egl/main \
+ -I$(TOP)/src/glx/x11
+
+SOURCES = egl_glx.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+DRM_LIB = `pkg-config --libs libdrm`
+
+MISC_LIBS = -ldl -lXext -lGL
+
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(EXTRA_DEFINES) $< -o $@
+
+
+.PHONY: library
+
+
+default: depend library Makefile
+
+
+library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME)
+
+
+# Make the egl_glx.so library
+$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(OBJECTS)
+ $(TOP)/bin/mklib -o $(DRIVER_NAME) \
+ -noprefix \
+ -major 1 -minor 0 \
+ -L$(TOP)/$(LIB_DIR) \
+ -install $(TOP)/$(LIB_DIR) \
+ $(OBJECTS) $(DRM_LIB) $(MISC_LIBS)
+
+
+clean:
+ rm -f *.o
+ rm -f *.so
+ rm -f depend depend.bak
+
+
+depend: $(SOURCES) $(HEADERS)
+ @ echo "running $(MKDEP)"
+ @ rm -f depend
+ @ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \
+ $(SOURCES) $(HEADERS) >/dev/null 2>/dev/null
+
+include depend
+# DO NOT DELETE
diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c
new file mode 100644
index 00000000000..9a421b5a80b
--- /dev/null
+++ b/src/egl/drivers/glx/egl_glx.c
@@ -0,0 +1,584 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * This is an EGL driver that wraps GLX. This gives the benefit of being
+ * completely agnostic of the direct rendering implementation.
+ *
+ * Authors: Alan Hourihane <[email protected]>
+ */
+
+/*
+ * TODO:
+ *
+ * Add GLXFBConfig support
+ * Pbuffer & Pixmap support
+ * test eglBind/ReleaseTexImage
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "dlfcn.h"
+#include <X11/Xlib.h>
+#include <GL/gl.h>
+#include "glxclient.h"
+
+#define _EGL_PLATFORM_X
+
+#include "eglconfig.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "eglhash.h"
+#include "egllog.h"
+#include "eglsurface.h"
+
+#include <GL/gl.h>
+
+#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
+
+static const EGLint all_apis = (EGL_OPENGL_ES_BIT
+ | EGL_OPENGL_ES2_BIT
+ | EGL_OPENVG_BIT
+ /* | EGL_OPENGL_BIT */); /* can't do */
+
+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
+{
+ _EGLDriver Base; /**< base class */
+
+ XVisualInfo *visuals;
+
+ /* GLXFBConfig *fbconfigs - todo */
+};
+
+
+/** subclass of _EGLContext */
+struct GLX_egl_context
+{
+ _EGLContext Base; /**< base class */
+
+ GLXContext context;
+};
+
+
+/** subclass of _EGLSurface */
+struct GLX_egl_surface
+{
+ _EGLSurface Base; /**< base class */
+
+ GLXDrawable drawable;
+};
+
+
+/** subclass of _EGLConfig */
+struct GLX_egl_config
+{
+ _EGLConfig Base; /**< base class */
+};
+
+/** cast wrapper */
+static struct GLX_egl_driver *
+GLX_egl_driver(_EGLDriver *drv)
+{
+ return (struct GLX_egl_driver *) drv;
+}
+
+static struct GLX_egl_context *
+GLX_egl_context(_EGLContext *ctx)
+{
+ return (struct GLX_egl_context *) ctx;
+}
+
+static struct GLX_egl_surface *
+GLX_egl_surface(_EGLSurface *surf)
+{
+ return (struct GLX_egl_surface *) surf;
+}
+
+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));
+
+ 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;
+ }
+#else
+ attribs->visualCaveat = 0;
+#endif
+
+ return GL_TRUE;
+}
+
+static EGLBoolean
+create_configs(_EGLDisplay *disp, struct GLX_egl_driver *GLX_drv)
+{
+ XVisualInfo theTemplate;
+ int numVisuals;
+ long mask;
+ int i;
+ struct visual_attribs attribs;
+
+ /* get list of all visuals on this screen */
+ theTemplate.screen = DefaultScreen(disp->Xdpy);
+ mask = VisualScreenMask;
+ GLX_drv->visuals = XGetVisualInfo(disp->Xdpy, mask, &theTemplate, &numVisuals);
+
+ for (i = 0; i < numVisuals; i++) {
+ struct GLX_egl_config *config;
+
+ if (!get_visual_attribs(disp->Xdpy, &GLX_drv->visuals[i], &attribs))
+ continue;
+
+ config = CALLOC_STRUCT(GLX_egl_config);
+
+ _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*/));
+
+ /* XXX possibly other things to init... */
+
+ _eglAddConfig(disp, &config->Base);
+ }
+
+ return EGL_TRUE;
+}
+
+/**
+ * Called via eglInitialize(), GLX_drv->API.Initialize().
+ */
+static EGLBoolean
+GLX_eglInitialize(_EGLDriver *drv, EGLDisplay dpy,
+ EGLint *minor, EGLint *major)
+{
+ struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+
+ _eglLog(_EGL_DEBUG, "XDRI: eglInitialize");
+
+ if (!disp->Xdpy) {
+ disp->Xdpy = XOpenDisplay(NULL);
+ if (!disp->Xdpy) {
+ _eglLog(_EGL_WARNING, "XDRI: XOpenDisplay failed");
+ return EGL_FALSE;
+ }
+ }
+
+ GLX_drv->Base.Initialized = EGL_TRUE;
+
+ GLX_drv->Base.Name = "GLX";
+
+ /* we're supporting EGL 1.4 */
+ *minor = 1;
+ *major = 4;
+
+ create_configs(disp, GLX_drv);
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Called via eglTerminate(), drv->API.Terminate().
+ */
+static EGLBoolean
+GLX_eglTerminate(_EGLDriver *drv, EGLDisplay dpy)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+
+ _eglLog(_EGL_DEBUG, "XDRI: eglTerminate");
+
+// XCloseDisplay(disp->Xdpy);
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Called via eglCreateContext(), drv->API.CreateContext().
+ */
+static EGLContext
+GLX_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+ EGLContext share_list, const EGLint *attrib_list)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ struct GLX_egl_context *GLX_ctx = CALLOC_STRUCT(GLX_egl_context);
+ struct GLX_egl_driver *GLX_drv = GLX_egl_driver(drv);
+ struct GLX_egl_context *GLX_ctx_shared = NULL;
+ _EGLConfig *conf;
+
+ if (!GLX_ctx)
+ return EGL_NO_CONTEXT;
+
+ if (!_eglInitContext(drv, dpy, &GLX_ctx->Base, config, attrib_list)) {
+ free(GLX_ctx);
+ return EGL_NO_CONTEXT;
+ }
+
+ if (share_list != EGL_NO_CONTEXT) {
+ _EGLContext *shareCtx = _eglLookupContext(share_list);
+ if (!shareCtx) {
+ _eglError(EGL_BAD_CONTEXT, "eglCreateContext(share_list)");
+ return EGL_FALSE;
+ }
+ GLX_ctx_shared = GLX_egl_context(shareCtx);
+ }
+
+ conf = _eglLookupConfig(drv, dpy, config);
+ assert(conf);
+
+ GLX_ctx->context = glXCreateContext(disp->Xdpy, &GLX_drv->visuals[(int)config-1], GLX_ctx_shared ? GLX_ctx_shared->context : NULL, GL_TRUE);
+ if (!GLX_ctx->context)
+ return EGL_FALSE;
+
+ /* need to have a direct rendering context */
+ if (!glXIsDirect(disp->Xdpy, GLX_ctx->context))
+ return EGL_FALSE;
+
+ return _eglGetContextHandle(&GLX_ctx->Base);
+}
+
+
+/**
+ * Called via eglMakeCurrent(), drv->API.MakeCurrent().
+ */
+static EGLBoolean
+GLX_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
+ EGLSurface r, EGLContext context)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLContext *ctx = _eglLookupContext(context);
+ _EGLSurface *dsurf = _eglLookupSurface(d);
+ _EGLSurface *rsurf = _eglLookupSurface(r);
+ struct GLX_egl_surface *GLX_dsurf = GLX_egl_surface(dsurf);
+ struct GLX_egl_surface *GLX_rsurf = GLX_egl_surface(rsurf);
+ struct GLX_egl_context *GLX_ctx = GLX_egl_context(ctx);
+
+ if (!_eglMakeCurrent(drv, dpy, d, r, context))
+ return EGL_FALSE;
+
+// if (!glXMakeContextCurrent(disp->Xdpy, GLX_dsurf->drawable, GLX_rsurf->drawable, GLX_ctx->context))
+ if (!glXMakeCurrent(disp->Xdpy, GLX_dsurf ? GLX_dsurf->drawable : 0, GLX_ctx ? GLX_ctx->context : NULL))
+ return EGL_FALSE;
+
+ return EGL_TRUE;
+}
+
+/** Get size of given window */
+static Status
+get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
+{
+ Window root;
+ Status stat;
+ int xpos, ypos;
+ unsigned int w, h, bw, depth;
+ stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
+ *width = w;
+ *height = h;
+ return stat;
+}
+
+/**
+ * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
+ */
+static EGLSurface
+GLX_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+ NativeWindowType window, const EGLint *attrib_list)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ struct GLX_egl_surface *GLX_surf;
+ uint width, height;
+
+ GLX_surf = CALLOC_STRUCT(GLX_egl_surface);
+ if (!GLX_surf)
+ return EGL_NO_SURFACE;
+
+ if (!_eglInitSurface(drv, dpy, &GLX_surf->Base, EGL_WINDOW_BIT,
+ config, attrib_list)) {
+ free(GLX_surf);
+ return EGL_FALSE;
+ }
+
+ _eglSaveSurface(&GLX_surf->Base);
+
+ GLX_surf->drawable = window;
+ get_drawable_size(disp->Xdpy, window, &width, &height);
+ GLX_surf->Base.Width = width;
+ GLX_surf->Base.Height = height;
+
+ return _eglGetSurfaceHandle(&GLX_surf->Base);
+}
+
+static EGLBoolean
+GLX_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLSurface *surf = _eglLookupSurface(surface);
+ return EGL_TRUE;
+ if (surf) {
+ _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface);
+ if (surf->IsBound) {
+ surf->DeletePending = EGL_TRUE;
+ }
+ else {
+ free(surf);
+ }
+
+ return EGL_TRUE;
+ }
+ else {
+ _eglError(EGL_BAD_SURFACE, "eglDestroySurface");
+ return EGL_FALSE;
+ }
+}
+
+
+static EGLBoolean
+GLX_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
+ EGLint buffer)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLSurface *surf = _eglLookupSurface(surface);
+ struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+
+ /* buffer ?? */
+ glXBindTexImageEXT(disp->Xdpy, GLX_surf->drawable, GLX_FRONT_LEFT_EXT, NULL);
+
+ return EGL_TRUE;
+}
+
+
+static EGLBoolean
+GLX_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
+ EGLint buffer)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLSurface *surf = _eglLookupSurface(surface);
+ struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+
+ /* buffer ?? */
+ glXReleaseTexImageEXT(disp->Xdpy, GLX_surf->drawable, GLX_FRONT_LEFT_EXT);
+
+ return EGL_TRUE;
+}
+
+
+static EGLBoolean
+GLX_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ _EGLSurface *surf = _eglLookupSurface(draw);
+ struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
+
+ _eglLog(_EGL_DEBUG, "XDRI: EGL SwapBuffers 0x%x",draw);
+
+ /* error checking step: */
+ if (!_eglSwapBuffers(drv, dpy, draw))
+ return EGL_FALSE;
+
+ glXSwapBuffers(disp->Xdpy, GLX_surf->drawable);
+
+ return EGL_TRUE;
+}
+
+/*
+ * Called from eglGetProcAddress() via drv->API.GetProcAddress().
+ */
+static _EGLProc
+GLX_eglGetProcAddress(const char *procname)
+{
+ return (_EGLProc)glXGetProcAddress((const GLubyte *)procname);
+}
+
+
+/**
+ * This is the main entrypoint into the driver, called by libEGL.
+ * Create a new _EGLDriver object and init its dispatch table.
+ */
+_EGLDriver *
+_eglMain(_EGLDisplay *disp, const char *args)
+{
+ struct GLX_egl_driver *GLX_drv = CALLOC_STRUCT(GLX_egl_driver);
+ char *env;
+
+ if (!GLX_drv)
+ return NULL;
+
+ _eglInitDriverFallbacks(&GLX_drv->Base);
+ GLX_drv->Base.API.Initialize = GLX_eglInitialize;
+ GLX_drv->Base.API.Terminate = GLX_eglTerminate;
+ GLX_drv->Base.API.CreateContext = GLX_eglCreateContext;
+ GLX_drv->Base.API.MakeCurrent = GLX_eglMakeCurrent;
+ GLX_drv->Base.API.CreateWindowSurface = GLX_eglCreateWindowSurface;
+ 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.ClientAPIsMask = all_apis;
+ GLX_drv->Base.Name = "GLX";
+
+ _eglLog(_EGL_DEBUG, "GLX: main(%s)", args);
+
+ /* set new DRI path to pick up EGL version (which doesn't contain any mesa
+ * code), but don't override if one is already set.
+ */
+ env = getenv("LIBGL_DRIVERS_PATH");
+ if (env) {
+ if (!strstr(env, "egl")) {
+ sprintf(env, "%s/egl", env);
+ setenv("LIBGL_DRIVERS_PATH", env, 1);
+ }
+ } else
+ setenv("LIBGL_DRIVERS_PATH", DEFAULT_DRIVER_DIR"/egl", 0);
+
+ return &GLX_drv->Base;
+}
diff --git a/src/egl/drivers/xdri/Makefile b/src/egl/drivers/xdri/Makefile
new file mode 100644
index 00000000000..a721b997e69
--- /dev/null
+++ b/src/egl/drivers/xdri/Makefile
@@ -0,0 +1,70 @@
+# src/egl/drivers/xdri/Makefile
+
+# Build XEGL DRI driver loader library: egl_xdri.so
+
+
+TOP = ../../../..
+include $(TOP)/configs/current
+
+
+DRIVER_NAME = egl_xdri.so
+
+
+INCLUDE_DIRS = \
+ -I. \
+ -I/usr/include \
+ $(shell pkg-config --cflags-only-I libdrm) \
+ -I$(TOP)/include \
+ -I$(TOP)/include/GL/internal \
+ -I$(TOP)/src/mesa/glapi \
+ -I$(TOP)/src/mesa/drivers/dri/common \
+ -I$(TOP)/src/egl/main \
+ -I$(TOP)/src/glx/x11
+
+SOURCES = egl_xdri.c
+
+OBJECTS = $(SOURCES:.c=.o)
+
+DRM_LIB = `pkg-config --libs libdrm`
+
+MISC_LIBS = -ldl -lXext -lGL
+
+
+.c.o:
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+
+
+.PHONY: library
+
+
+default: depend library Makefile
+
+
+library: $(TOP)/$(LIB_DIR)/$(DRIVER_NAME)
+
+
+# Make the egl_xdri.so library
+$(TOP)/$(LIB_DIR)/$(DRIVER_NAME): $(OBJECTS)
+ $(TOP)/bin/mklib -o $(DRIVER_NAME) \
+ -noprefix \
+ -major 1 -minor 0 \
+ -L$(TOP)/$(LIB_DIR) \
+ -install $(TOP)/$(LIB_DIR) \
+ $(OBJECTS) $(DRM_LIB) $(MISC_LIBS)
+
+
+clean:
+ rm -f *.o
+ rm -f *.so
+ rm -f depend depend.bak
+
+
+depend: $(SOURCES) $(HEADERS)
+ @ echo "running $(MKDEP)"
+ @ rm -f depend
+ @ touch depend
+ $(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \
+ $(SOURCES) $(HEADERS) >/dev/null 2>/dev/null
+
+include depend
+# DO NOT DELETE
diff --git a/src/egl/drivers/xdri/egl_xdri.c b/src/egl/drivers/xdri/egl_xdri.c
new file mode 100644
index 00000000000..3b3e312746e
--- /dev/null
+++ b/src/egl/drivers/xdri/egl_xdri.c
@@ -0,0 +1,1177 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Code to interface a DRI driver to libEGL.
+ * Note that unlike previous DRI/EGL interfaces, this one is meant to
+ * be used _with_ X. Applications will use eglCreateWindowSurface()
+ * to render into X-created windows.
+ *
+ * This is an EGL driver that, in turn, loads a regular DRI driver.
+ * There are some dependencies on code in libGL, but those could be
+ * removed with some effort.
+ *
+ * Authors: Brian Paul
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "dlfcn.h"
+#include <X11/Xlib.h>
+#include <GL/gl.h>
+#include "xf86dri.h"
+#include "glxclient.h"
+#include "dri_util.h"
+#include "drm_sarea.h"
+
+#define _EGL_PLATFORM_X
+
+#include "eglconfig.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "eglhash.h"
+#include "egllog.h"
+#include "eglsurface.h"
+
+#include <GL/gl.h>
+
+typedef void (*glGetIntegerv_t)(GLenum, GLint *);
+typedef void (*glBindTexture_t)(GLenum, GLuint);
+typedef void (*glCopyTexImage2D_t)(GLenum, GLint, GLenum, GLint, GLint,
+ GLint, GLint, GLint);
+
+
+#define CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
+
+
+/** subclass of _EGLDriver */
+struct xdri_egl_driver
+{
+ _EGLDriver Base; /**< base class */
+
+ const char *dri_driver_name; /**< name of DRI driver to load */
+ void *dri_driver_handle; /**< returned by dlopen(dri_driver_name) */
+
+ __GLXdisplayPrivate *glx_priv;
+
+
+ /* XXX we're not actually using these at this time: */
+ int chipset;
+ int minor;
+ int drmFD;
+
+ __DRIframebuffer framebuffer;
+ drm_handle_t hSAREA;
+ drmAddress pSAREA;
+ char *busID;
+ drm_magic_t magic;
+};
+
+
+/** subclass of _EGLContext */
+struct xdri_egl_context
+{
+ _EGLContext Base; /**< base class */
+
+ __DRIcontext driContext;
+
+ GLint bound_tex_object;
+};
+
+
+/** subclass of _EGLSurface */
+struct xdri_egl_surface
+{
+ _EGLSurface Base; /**< base class */
+
+ __DRIid driDrawable; /**< DRI surface */
+ drm_drawable_t hDrawable;
+};
+
+
+/** subclass of _EGLConfig */
+struct xdri_egl_config
+{
+ _EGLConfig Base; /**< base class */
+
+ const __GLcontextModes *mode; /**< corresponding GLX mode */
+};
+
+
+
+/** cast wrapper */
+static struct xdri_egl_driver *
+xdri_egl_driver(_EGLDriver *drv)
+{
+ return (struct xdri_egl_driver *) drv;
+}
+
+
+/** Map EGLSurface handle to xdri_egl_surface object */
+static struct xdri_egl_surface *
+lookup_surface(EGLSurface surf)
+{
+ _EGLSurface *surface = _eglLookupSurface(surf);
+ return (struct xdri_egl_surface *) surface;
+}
+
+
+/** Map EGLContext handle to xdri_egl_context object */
+static struct xdri_egl_context *
+lookup_context(EGLContext c)
+{
+ _EGLContext *context = _eglLookupContext(c);
+ return (struct xdri_egl_context *) context;
+}
+
+static struct xdri_egl_context *
+current_context(void)
+{
+ return (struct xdri_egl_context *) _eglGetCurrentContext();
+}
+
+/** Map EGLConfig handle to xdri_egl_config object */
+static struct xdri_egl_config *
+lookup_config(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config)
+{
+ _EGLConfig *conf = _eglLookupConfig(drv, dpy, config);
+ return (struct xdri_egl_config *) conf;
+}
+
+
+
+/** Get size of given window */
+static Status
+get_drawable_size(Display *dpy, Drawable d, uint *width, uint *height)
+{
+ Window root;
+ Status stat;
+ int xpos, ypos;
+ unsigned int w, h, bw, depth;
+ stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth);
+ *width = w;
+ *height = h;
+ return stat;
+}
+
+
+/**
+ * Produce a set of EGL configs.
+ * Note that we get the list of GLcontextModes from the GLX library.
+ * This dependency on GLX lib will be removed someday.
+ */
+static void
+create_configs(_EGLDisplay *disp, __GLXdisplayPrivate *glx_priv)
+{
+ static const EGLint all_apis = (EGL_OPENGL_ES_BIT |
+ EGL_OPENGL_ES2_BIT |
+ EGL_OPENVG_BIT |
+ EGL_OPENGL_BIT);
+ __GLXscreenConfigs *scrn = glx_priv->screenConfigs;
+ const __GLcontextModes *m;
+ int id = 1;
+
+ for (m = scrn->configs; m; m = m->next) {
+ /* EGL requires double-buffered configs */
+ 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);
+ /* XXX only window rendering allowed ATM */
+ SET_CONFIG_ATTRIB(&config->Base, EGL_SURFACE_TYPE,
+ (EGL_WINDOW_BIT | EGL_PBUFFER_BIT));
+
+ /* XXX possibly other things to init... */
+
+ /* Ptr from EGL config to GLcontextMode. Used in CreateContext(). */
+ config->mode = m;
+
+ _eglAddConfig(disp, &config->Base);
+ }
+ }
+}
+
+
+/**
+ * Called via __DRIinterfaceMethods object
+ */
+static __DRIfuncPtr
+dri_get_proc_address(const char * proc_name)
+{
+ return NULL;
+}
+
+
+static void
+dri_context_modes_destroy(__GLcontextModes *modes)
+{
+ _eglLog(_EGL_DEBUG, "%s", __FUNCTION__);
+
+ while (modes) {
+ __GLcontextModes * const next = modes->next;
+ free(modes);
+ modes = next;
+ }
+}
+
+
+/**
+ * Create a linked list of 'count' GLcontextModes.
+ * These are used during the client/server visual negotiation phase,
+ * then discarded.
+ */
+static __GLcontextModes *
+dri_context_modes_create(unsigned count, size_t minimum_size)
+{
+ /* This code copied from libGLX, and modified */
+ const size_t size = (minimum_size > sizeof(__GLcontextModes))
+ ? minimum_size : sizeof(__GLcontextModes);
+ __GLcontextModes * head = NULL;
+ __GLcontextModes ** next;
+ unsigned i;
+
+ next = & head;
+ for (i = 0 ; i < count ; i++) {
+ *next = (__GLcontextModes *) calloc(1, size);
+ if (*next == NULL) {
+ dri_context_modes_destroy(head);
+ head = NULL;
+ break;
+ }
+
+ (*next)->doubleBufferMode = 1;
+ (*next)->visualID = GLX_DONT_CARE;
+ (*next)->visualType = GLX_DONT_CARE;
+ (*next)->visualRating = GLX_NONE;
+ (*next)->transparentPixel = GLX_NONE;
+ (*next)->transparentRed = GLX_DONT_CARE;
+ (*next)->transparentGreen = GLX_DONT_CARE;
+ (*next)->transparentBlue = GLX_DONT_CARE;
+ (*next)->transparentAlpha = GLX_DONT_CARE;
+ (*next)->transparentIndex = GLX_DONT_CARE;
+ (*next)->xRenderable = GLX_DONT_CARE;
+ (*next)->fbconfigID = GLX_DONT_CARE;
+ (*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
+ (*next)->bindToTextureRgb = GLX_DONT_CARE;
+ (*next)->bindToTextureRgba = GLX_DONT_CARE;
+ (*next)->bindToMipmapTexture = GLX_DONT_CARE;
+ (*next)->bindToTextureTargets = 0;
+ (*next)->yInverted = GLX_DONT_CARE;
+
+ next = & ((*next)->next);
+ }
+
+ return head;
+}
+
+
+static __DRIscreen *
+dri_find_dri_screen(__DRInativeDisplay *ndpy, int scrn)
+{
+ __GLXdisplayPrivate *priv = __glXInitialize(ndpy);
+ __GLXscreenConfigs *scrnConf = priv->screenConfigs;
+ return &scrnConf->driScreen;
+}
+
+
+static GLboolean
+dri_window_exists(__DRInativeDisplay *ndpy, __DRIid draw)
+{
+ return EGL_TRUE;
+}
+
+
+static GLboolean
+dri_create_context(__DRInativeDisplay *ndpy, int screenNum, int configID,
+ void * contextID, drm_context_t * hw_context)
+{
+ assert(configID >= 0);
+ return XF86DRICreateContextWithConfig(ndpy, screenNum,
+ configID, contextID, hw_context);
+}
+
+
+static GLboolean
+dri_destroy_context(__DRInativeDisplay * ndpy, int screen, __DRIid context)
+{
+ return XF86DRIDestroyContext(ndpy, screen, context);
+}
+
+
+static GLboolean
+dri_create_drawable(__DRInativeDisplay * ndpy, int screen,
+ __DRIid drawable, drm_drawable_t * hHWDrawable)
+{
+ _eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__);
+
+ /* Create DRI drawable for given window ID (drawable) */
+ if (!XF86DRICreateDrawable(ndpy, screen, drawable, hHWDrawable))
+ return EGL_FALSE;
+
+ return EGL_TRUE;
+}
+
+
+static GLboolean
+dri_destroy_drawable(__DRInativeDisplay * ndpy, int screen, __DRIid drawable)
+{
+ _eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__);
+ return XF86DRIDestroyDrawable(ndpy, screen, drawable);
+}
+
+
+static GLboolean
+dri_get_drawable_info(__DRInativeDisplay *ndpy, int scrn,
+ __DRIid draw, unsigned int * index, unsigned int * stamp,
+ int * x, int * y, int * width, int * height,
+ int * numClipRects, drm_clip_rect_t ** pClipRects,
+ int * backX, int * backY,
+ int * numBackClipRects,
+ drm_clip_rect_t ** pBackClipRects)
+{
+ _eglLog(_EGL_DEBUG, "XDRI: %s", __FUNCTION__);
+
+ if (!XF86DRIGetDrawableInfo(ndpy, scrn, draw, index, stamp,
+ x, y, width, height,
+ numClipRects, pClipRects,
+ backX, backY,
+ numBackClipRects, pBackClipRects)) {
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Table of functions exported by the loader to the driver.
+ */
+static const __DRIinterfaceMethods interface_methods = {
+ dri_get_proc_address,
+
+ dri_context_modes_create,
+ dri_context_modes_destroy,
+
+ dri_find_dri_screen,
+ dri_window_exists,
+
+ dri_create_context,
+ dri_destroy_context,
+
+ dri_create_drawable,
+ dri_destroy_drawable,
+ dri_get_drawable_info,
+
+ NULL,/*__eglGetUST,*/
+ NULL,/*__eglGetMSCRate,*/
+};
+
+
+
+static EGLBoolean
+init_drm(struct xdri_egl_driver *xdri_drv, _EGLDisplay *disp)
+{
+ __DRIversion ddx_version;
+ __DRIversion dri_version;
+ __DRIversion drm_version;
+ drmVersionPtr version;
+ drm_handle_t hFB;
+ int newlyopened;
+ int status;
+ int scrn = DefaultScreen(disp->Xdpy);
+
+#if 0
+ createNewScreen = (PFNCREATENEWSCREENFUNC)
+ dlsym(xdri_drv->dri_driver_handle, createNewScreenName);
+ if (!createNewScreen) {
+ _eglLog(_EGL_WARNING, "XDRI: Couldn't find %s function in the driver.",
+ createNewScreenName);
+ return EGL_FALSE;
+ }
+ else {
+ _eglLog(_EGL_DEBUG, "XDRI: Found %s", createNewScreenName);
+ }
+#endif
+
+ /*
+ * Get the DRI X extension version.
+ */
+ dri_version.major = 4;
+ dri_version.minor = 0;
+ dri_version.patch = 0;
+
+ if (!XF86DRIOpenConnection(disp->Xdpy, scrn,
+ &xdri_drv->hSAREA, &xdri_drv->busID)) {
+ _eglLog(_EGL_WARNING, "XF86DRIOpenConnection failed");
+ }
+
+ xdri_drv->drmFD = drmOpenOnce(NULL, xdri_drv->busID, &newlyopened);
+ if (xdri_drv->drmFD < 0) {
+ perror("drmOpenOnce failed: ");
+ return EGL_FALSE;
+ }
+ else {
+ _eglLog(_EGL_DEBUG, "XDRI: drmOpenOnce returned %d", xdri_drv->drmFD);
+ }
+
+
+ if (drmGetMagic(xdri_drv->drmFD, &xdri_drv->magic)) {
+ perror("drmGetMagic failed: ");
+ return EGL_FALSE;
+ }
+
+ version = drmGetVersion(xdri_drv->drmFD);
+ if (version) {
+ drm_version.major = version->version_major;
+ drm_version.minor = version->version_minor;
+ drm_version.patch = version->version_patchlevel;
+ drmFreeVersion(version);
+ _eglLog(_EGL_DEBUG, "XDRI: Got DRM version %d.%d.%d",
+ drm_version.major,
+ drm_version.minor,
+ drm_version.patch);
+ }
+ else {
+ drm_version.major = -1;
+ drm_version.minor = -1;
+ drm_version.patch = -1;
+ _eglLog(_EGL_WARNING, "XDRI: drmGetVersion() failed");
+ return EGL_FALSE;
+ }
+
+ /* Authenticate w/ server.
+ */
+ if (!XF86DRIAuthConnection(disp->Xdpy, scrn, xdri_drv->magic)) {
+ _eglLog(_EGL_WARNING, "XDRI: XF86DRIAuthConnection() failed");
+ return EGL_FALSE;
+ }
+ else {
+ _eglLog(_EGL_DEBUG, "XDRI: XF86DRIAuthConnection() success");
+ }
+
+ /* Get ddx version.
+ */
+ {
+ char *driverName;
+
+ /*
+ * Get device name (like "tdfx") and the ddx version
+ * numbers. We'll check the version in each DRI driver's
+ * "createNewScreen" function.
+ */
+ if (!XF86DRIGetClientDriverName(disp->Xdpy, scrn,
+ &ddx_version.major,
+ &ddx_version.minor,
+ &ddx_version.patch,
+ &driverName)) {
+ _eglLog(_EGL_WARNING, "XDRI: XF86DRIGetClientDriverName failed");
+ return EGL_FALSE;
+ }
+ else {
+ _eglLog(_EGL_DEBUG, "XDRI: XF86DRIGetClientDriverName returned %s", driverName);
+ }
+ }
+
+ /* Get framebuffer info.
+ */
+ {
+ int junk;
+ if (!XF86DRIGetDeviceInfo(disp->Xdpy, scrn,
+ &hFB,
+ &junk,
+ &xdri_drv->framebuffer.size,
+ &xdri_drv->framebuffer.stride,
+ &xdri_drv->framebuffer.dev_priv_size,
+ &xdri_drv->framebuffer.dev_priv)) {
+ _eglLog(_EGL_WARNING, "XDRI: XF86DRIGetDeviceInfo() failed");
+ return EGL_FALSE;
+ }
+ else {
+ _eglLog(_EGL_DEBUG, "XDRI: XF86DRIGetDeviceInfo() success");
+ }
+ xdri_drv->framebuffer.width = DisplayWidth(disp->Xdpy, scrn);
+ xdri_drv->framebuffer.height = DisplayHeight(disp->Xdpy, scrn);
+ }
+
+ /* Map the framebuffer region. (this may not be needed)
+ */
+ status = drmMap(xdri_drv->drmFD, hFB, xdri_drv->framebuffer.size,
+ (drmAddressPtr) &xdri_drv->framebuffer.base);
+ if (status != 0) {
+ _eglLog(_EGL_WARNING, "XDRI: drmMap(framebuffer) failed");
+ return EGL_FALSE;
+ }
+ else {
+ _eglLog(_EGL_DEBUG, "XDRI: drmMap(framebuffer) success");
+ }
+
+ /* Map the SAREA region.
+ */
+ status = drmMap(xdri_drv->drmFD, xdri_drv->hSAREA, SAREA_MAX, &xdri_drv->pSAREA);
+ if (status != 0) {
+ _eglLog(_EGL_WARNING, "XDRI: drmMap(sarea) failed");
+ return EGL_FALSE;
+ }
+ else {
+ _eglLog(_EGL_DEBUG, "XDRI: drmMap(sarea) success");
+ }
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Load the DRI driver named by "xdri_drv->dri_driver_name".
+ * Basically, dlopen() the library to set "xdri_drv->dri_driver_handle".
+ *
+ * Later, we'll call dlsym(createNewScreenName) to get a pointer to
+ * the driver's createNewScreen() function which is the bootstrap function.
+ *
+ * \return EGL_TRUE for success, EGL_FALSE for failure
+ */
+static EGLBoolean
+load_dri_driver(struct xdri_egl_driver *xdri_drv)
+{
+ char filename[100];
+ int flags = RTLD_NOW;
+
+ /* try "egl_xxx_dri.so" first */
+ snprintf(filename, sizeof(filename), "egl_%s.so", xdri_drv->dri_driver_name);
+ _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s)", filename);
+ xdri_drv->dri_driver_handle = dlopen(filename, flags);
+ if (xdri_drv->dri_driver_handle) {
+ _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s) OK", filename);
+ return EGL_TRUE;
+ }
+ else {
+ _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s) fail (%s)", filename, dlerror());
+ }
+
+ /* try regular "xxx_dri.so" next */
+ snprintf(filename, sizeof(filename), "%s.so", xdri_drv->dri_driver_name);
+ _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s)", filename);
+ xdri_drv->dri_driver_handle = dlopen(filename, flags);
+ if (xdri_drv->dri_driver_handle) {
+ _eglLog(_EGL_DEBUG, "XDRI: dlopen(%s) OK", filename);
+ return EGL_TRUE;
+ }
+
+ _eglLog(_EGL_WARNING, "XDRI Could not open %s (%s)", filename, dlerror());
+ return EGL_FALSE;
+}
+
+
+/**
+ * Called via eglInitialize(), xdri_drv->API.Initialize().
+ */
+static EGLBoolean
+xdri_eglInitialize(_EGLDriver *drv, EGLDisplay dpy,
+ EGLint *minor, EGLint *major)
+{
+ struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ static char name[100];
+
+ _eglLog(_EGL_DEBUG, "XDRI: eglInitialize");
+
+ if (!disp->Xdpy) {
+ disp->Xdpy = XOpenDisplay(NULL);
+ if (!disp->Xdpy) {
+ _eglLog(_EGL_WARNING, "XDRI: XOpenDisplay failed");
+ return EGL_FALSE;
+ }
+ }
+
+#if 0
+ /* choose the DRI driver to load */
+ xdri_drv->dri_driver_name = _eglChooseDRMDriver(0);
+ if (!load_dri_driver(xdri_drv))
+ return EGL_FALSE;
+#else
+ (void) load_dri_driver;
+#endif
+
+#if 0
+ if (!init_drm(xdri_drv, disp))
+ return EGL_FALSE;
+#else
+ (void) init_drm;
+#endif
+
+ /*
+ * NOTE: this call to __glXInitialize() bootstraps the whole GLX/DRI
+ * interface, loads the DRI driver, etc.
+ * This replaces the load_dri_driver() and init_drm() code above.
+ */
+ xdri_drv->glx_priv = __glXInitialize(disp->Xdpy);
+
+ create_configs(disp, xdri_drv->glx_priv);
+
+ xdri_drv->Base.Initialized = EGL_TRUE;
+
+ if (xdri_drv->dri_driver_name)
+ snprintf(name, sizeof(name), "X/DRI:%s", xdri_drv->dri_driver_name);
+ else
+ snprintf(name, sizeof(name), "X/DRI");
+ xdri_drv->Base.Name = name;
+
+ /* we're supporting EGL 1.4 */
+ *minor = 1;
+ *major = 4;
+
+ return EGL_TRUE;
+}
+
+
+/*
+ * Do some clean-up that normally occurs in XCloseDisplay().
+ * We do this here because we're about to unload a dynamic library
+ * that has added some per-display extension data and callbacks.
+ * If we don't do this here we'll crash in XCloseDisplay() because it'll
+ * try to call functions that went away when the driver library was unloaded.
+ */
+static void
+FreeDisplayExt(Display *dpy)
+{
+ _XExtension *ext, *next;
+
+ for (ext = dpy->ext_procs; ext; ext = next) {
+ next = ext->next;
+ if (ext->close_display) {
+ ext->close_display(dpy, &ext->codes);
+ ext->close_display = NULL;
+ }
+ if (ext->name)
+ Xfree(ext->name);
+ Xfree(ext);
+ }
+ dpy->ext_procs = NULL;
+
+ _XFreeExtData (dpy->ext_data);
+ dpy->ext_data = NULL;
+}
+
+
+/**
+ * Called via eglTerminate(), drv->API.Terminate().
+ */
+static EGLBoolean
+xdri_eglTerminate(_EGLDriver *drv, EGLDisplay dpy)
+{
+ struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+
+ _eglLog(_EGL_DEBUG, "XDRI: eglTerminate");
+
+ _eglLog(_EGL_DEBUG, "XDRI: Closing %s", xdri_drv->dri_driver_name);
+
+ FreeDisplayExt(disp->Xdpy);
+
+#if 0
+ /* this causes a segfault for some reason */
+ dlclose(xdri_drv->dri_driver_handle);
+#endif
+ xdri_drv->dri_driver_handle = NULL;
+
+ free((void*) xdri_drv->dri_driver_name);
+
+ return EGL_TRUE;
+}
+
+
+/*
+ * Called from eglGetProcAddress() via drv->API.GetProcAddress().
+ */
+static _EGLProc
+xdri_eglGetProcAddress(const char *procname)
+{
+#if 0
+ _EGLDriver *drv = NULL;
+
+ struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
+ /*_EGLDisplay *disp = _eglLookupDisplay(dpy);*/
+ _EGLProc *proc = xdri_drv->driScreen.getProcAddress(procname);
+ return proc;
+#elif 1
+ /* 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 (*st_get_proc_addr)(const char *procname);
+ st_get_proc_addr = dlsym(NULL, "st_get_proc_address");
+ if (st_get_proc_addr) {
+ return st_get_proc_addr(procname);
+ }
+ return NULL;
+#else
+ return NULL;
+#endif
+}
+
+
+/**
+ * Called via eglCreateContext(), drv->API.CreateContext().
+ */
+static EGLContext
+xdri_eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+ EGLContext share_list, const EGLint *attrib_list)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config);
+ void *shared = NULL;
+ int renderType = GLX_RGBA_BIT;
+
+ struct xdri_egl_context *xdri_ctx = CALLOC_STRUCT(xdri_egl_context);
+ if (!xdri_ctx)
+ return EGL_NO_CONTEXT;
+
+ if (!_eglInitContext(drv, dpy, &xdri_ctx->Base, config, attrib_list)) {
+ free(xdri_ctx);
+ return EGL_NO_CONTEXT;
+ }
+
+ assert(xdri_config);
+
+ {
+ struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
+ __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs;
+ xdri_ctx->driContext.private =
+ scrnConf->driScreen.createNewContext(disp->Xdpy,
+ xdri_config->mode, renderType,
+ shared, &xdri_ctx->driContext);
+ }
+
+ if (!xdri_ctx->driContext.private) {
+ _eglLog(_EGL_DEBUG, "driScreen.createNewContext failed");
+ free(xdri_ctx);
+ return EGL_NO_CONTEXT;
+ }
+
+ xdri_ctx->driContext.mode = xdri_config->mode;
+
+ return _eglGetContextHandle(&xdri_ctx->Base);
+}
+
+
+/**
+ * Called via eglMakeCurrent(), drv->API.MakeCurrent().
+ */
+static EGLBoolean
+xdri_eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
+ EGLSurface r, EGLContext context)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ struct xdri_egl_context *xdri_ctx = lookup_context(context);
+ struct xdri_egl_surface *xdri_draw = lookup_surface(d);
+ struct xdri_egl_surface *xdri_read = lookup_surface(r);
+ __DRIid draw = xdri_draw ? xdri_draw->driDrawable : 0;
+ __DRIid read = xdri_read ? xdri_read->driDrawable : 0;
+ int scrn = DefaultScreen(disp->Xdpy);
+
+ if (!_eglMakeCurrent(drv, dpy, d, r, context))
+ return EGL_FALSE;
+
+
+ if (xdri_ctx &&
+ !xdri_ctx->driContext.bindContext(disp->Xdpy, scrn, draw, read,
+ &xdri_ctx->driContext)) {
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Called via eglCreateWindowSurface(), drv->API.CreateWindowSurface().
+ */
+static EGLSurface
+xdri_eglCreateWindowSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+ NativeWindowType window, const EGLint *attrib_list)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ struct xdri_egl_surface *xdri_surf;
+ int scrn = DefaultScreen(disp->Xdpy);
+ uint width, height;
+
+ xdri_surf = CALLOC_STRUCT(xdri_egl_surface);
+ if (!xdri_surf)
+ return EGL_NO_SURFACE;
+
+ if (!_eglInitSurface(drv, dpy, &xdri_surf->Base, EGL_WINDOW_BIT,
+ config, attrib_list)) {
+ free(xdri_surf);
+ return EGL_FALSE;
+ }
+
+ if (!XF86DRICreateDrawable(disp->Xdpy, scrn, window, &xdri_surf->hDrawable)) {
+ free(xdri_surf);
+ return EGL_FALSE;
+ }
+
+ xdri_surf->driDrawable = window;
+
+ _eglSaveSurface(&xdri_surf->Base);
+
+ get_drawable_size(disp->Xdpy, window, &width, &height);
+ xdri_surf->Base.Width = width;
+ xdri_surf->Base.Height = height;
+
+ _eglLog(_EGL_DEBUG,
+ "XDRI: CreateWindowSurface win 0x%x handle %d hDrawable %d",
+ (int) window, _eglGetSurfaceHandle(&xdri_surf->Base),
+ (int) xdri_surf->hDrawable);
+
+ return _eglGetSurfaceHandle(&xdri_surf->Base);
+}
+
+
+/**
+ * Called via eglCreatePbufferSurface(), drv->API.CreatePbufferSurface().
+ */
+static EGLSurface
+xdri_eglCreatePbufferSurface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
+ const EGLint *attrib_list)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+ struct xdri_egl_surface *xdri_surf;
+ struct xdri_egl_config *xdri_config = lookup_config(drv, dpy, config);
+ int scrn = DefaultScreen(disp->Xdpy);
+ Window window;
+
+ xdri_surf = CALLOC_STRUCT(xdri_egl_surface);
+ if (!xdri_surf)
+ return EGL_NO_SURFACE;
+
+ if (!_eglInitSurface(drv, dpy, &xdri_surf->Base, EGL_PBUFFER_BIT,
+ config, attrib_list)) {
+ free(xdri_surf);
+ return EGL_FALSE;
+ }
+
+ /* Create a dummy X window */
+ {
+ Window root = RootWindow(disp->Xdpy, scrn);
+ XSetWindowAttributes attr;
+ XVisualInfo *visInfo, visTemplate;
+ unsigned mask;
+ int nvis;
+
+ visTemplate.visualid = xdri_config->mode->visualID;
+ visInfo = XGetVisualInfo(disp->Xdpy, VisualIDMask, &visTemplate, &nvis);
+ if (!visInfo) {
+ return EGL_NO_SURFACE;
+ }
+
+ attr.background_pixel = 0;
+ attr.border_pixel = 0;
+ attr.colormap = XCreateColormap(disp->Xdpy, root,
+ visInfo->visual, AllocNone);
+ attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
+ mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
+
+ window = XCreateWindow(disp->Xdpy, root, 0, 0,
+ xdri_surf->Base.Width, xdri_surf->Base.Height,
+ 0, visInfo->depth, InputOutput,
+ visInfo->visual, mask, &attr);
+
+ /*XMapWindow(disp->Xdpy, window);*/
+ XFree(visInfo);
+
+ /* set hints and properties */
+ /*
+ sizehints.width = xdri_surf->Base.Width;
+ sizehints.height = xdri_surf->Base.Height;
+ sizehints.flags = USPosition;
+ XSetNormalHints(disp->Xdpy, window, &sizehints);
+ */
+ }
+
+ if (!XF86DRICreateDrawable(disp->Xdpy, scrn, window, &xdri_surf->hDrawable)) {
+ free(xdri_surf);
+ return EGL_FALSE;
+ }
+
+ xdri_surf->driDrawable = window;
+
+ _eglSaveSurface(&xdri_surf->Base);
+
+ _eglLog(_EGL_DEBUG,
+ "XDRI: CreatePbufferSurface handle %d hDrawable %d",
+ _eglGetSurfaceHandle(&xdri_surf->Base),
+ (int) xdri_surf->hDrawable);
+
+ return _eglGetSurfaceHandle(&xdri_surf->Base);
+}
+
+
+
+static EGLBoolean
+xdri_eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
+{
+ struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
+ if (xdri_surf) {
+ _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface);
+ if (xdri_surf->Base.IsBound) {
+ xdri_surf->Base.DeletePending = EGL_TRUE;
+ }
+ else {
+ /*
+ st_unreference_framebuffer(surf->Framebuffer);
+ */
+ free(xdri_surf);
+ }
+ return EGL_TRUE;
+ }
+ else {
+ _eglError(EGL_BAD_SURFACE, "eglDestroySurface");
+ return EGL_FALSE;
+ }
+}
+
+
+static EGLBoolean
+xdri_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
+ EGLint buffer)
+{
+ typedef int (*bind_teximage)(__DRInativeDisplay *dpy,
+ __DRIid surface, __DRIscreen *psc,
+ int buffer, int target, int format,
+ int level, int mipmap);
+
+ bind_teximage egl_dri_bind_teximage;
+
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+
+ struct xdri_egl_context *xdri_ctx = current_context();
+ struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
+ struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
+
+ __DRIid dri_surf = xdri_surf ? xdri_surf->driDrawable : 0;
+
+ __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs;
+ __DRIscreen *psc = &scrnConf->driScreen;
+
+ /* this call just does error checking */
+ if (!_eglBindTexImage(drv, dpy, surface, buffer)) {
+ return EGL_FALSE;
+ }
+
+ egl_dri_bind_teximage =
+ (bind_teximage) dlsym(NULL, "egl_dri_bind_teximage");
+ if (egl_dri_bind_teximage) {
+ return egl_dri_bind_teximage(disp->Xdpy, dri_surf, psc,
+ buffer,
+ xdri_surf->Base.TextureTarget,
+ xdri_surf->Base.TextureFormat,
+ xdri_surf->Base.MipmapLevel,
+ xdri_surf->Base.MipmapTexture);
+ }
+ else {
+ /* fallback path based on glCopyTexImage() */
+ /* Get/save currently bound 2D texobj name */
+ glGetIntegerv_t glGetIntegerv_func =
+ (glGetIntegerv_t) dlsym(NULL, "glGetIntegerv");
+ GLint curTexObj = 0;
+ if (glGetIntegerv_func) {
+ (*glGetIntegerv_func)(GL_TEXTURE_BINDING_2D, &curTexObj);
+ }
+ xdri_ctx->bound_tex_object = curTexObj;
+ }
+
+ return EGL_FALSE;
+}
+
+
+static EGLBoolean
+xdri_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface,
+ EGLint buffer)
+{
+ typedef int (*release_teximage)(__DRInativeDisplay *dpy,
+ __DRIid surface, __DRIscreen *psc,
+ int buffer, int target, int format,
+ int level, int mipmap);
+ release_teximage egl_dri_release_teximage;
+
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+
+ struct xdri_egl_context *xdri_ctx = current_context();
+ struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
+ struct xdri_egl_surface *xdri_surf = lookup_surface(surface);
+
+ __DRIid dri_surf = xdri_surf ? xdri_surf->driDrawable : 0;
+
+ __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs;
+ __DRIscreen *psc = &scrnConf->driScreen;
+
+ /* this call just does error checking */
+ if (!_eglReleaseTexImage(drv, dpy, surface, buffer)) {
+ return EGL_FALSE;
+ }
+
+ egl_dri_release_teximage =
+ (release_teximage) dlsym(NULL, "egl_dri_release_teximage");
+ if (egl_dri_release_teximage) {
+ return egl_dri_release_teximage(disp->Xdpy, dri_surf, psc,
+ buffer,
+ xdri_surf->Base.TextureTarget,
+ xdri_surf->Base.TextureFormat,
+ xdri_surf->Base.MipmapLevel,
+ xdri_surf->Base.MipmapTexture);
+ }
+ else {
+ /* fallback path based on glCopyTexImage() */
+ glGetIntegerv_t glGetIntegerv_func =
+ (glGetIntegerv_t) dlsym(NULL, "glGetIntegerv");
+ glBindTexture_t glBindTexture_func =
+ (glBindTexture_t) dlsym(NULL, "glBindTexture");
+ glCopyTexImage2D_t glCopyTexImage2D_func =
+ (glCopyTexImage2D_t) dlsym(NULL, "glCopyTexImage2D");
+ GLint curTexObj;
+ GLenum intFormat;
+ GLint level, width, height;
+
+ if (xdri_surf->Base.TextureFormat == EGL_TEXTURE_RGBA)
+ intFormat = GL_RGBA;
+ else
+ intFormat = GL_RGB;
+ level = xdri_surf->Base.MipmapLevel;
+ width = xdri_surf->Base.Width >> level;
+ height = xdri_surf->Base.Height >> level;
+
+ if (width > 0 && height > 0 &&
+ glGetIntegerv_func && glBindTexture_func && glCopyTexImage2D_func) {
+ glGetIntegerv_func(GL_TEXTURE_BINDING_2D, &curTexObj);
+ /* restore texobj from time of eglBindTexImage() call */
+ if (curTexObj != xdri_ctx->bound_tex_object)
+ glBindTexture_func(GL_TEXTURE_2D, xdri_ctx->bound_tex_object);
+ /* copy pbuffer image to texture */
+ glCopyTexImage2D_func(GL_TEXTURE_2D,
+ level,
+ intFormat,
+ 0, 0, width, height, 0);
+ /* restore current texture */
+ if (curTexObj != xdri_ctx->bound_tex_object)
+ glBindTexture_func(GL_TEXTURE_2D, curTexObj);
+ }
+ xdri_ctx->bound_tex_object = -1;
+ }
+
+ return EGL_FALSE;
+}
+
+
+static EGLBoolean
+xdri_eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
+{
+ _EGLDisplay *disp = _eglLookupDisplay(dpy);
+
+ _eglLog(_EGL_DEBUG, "XDRI: EGL SwapBuffers");
+
+ /* error checking step: */
+ if (!_eglSwapBuffers(drv, dpy, draw))
+ return EGL_FALSE;
+
+ {
+ struct xdri_egl_surface *xdri_surf = lookup_surface(draw);
+ struct xdri_egl_driver *xdri_drv = xdri_egl_driver(drv);
+ __GLXscreenConfigs *scrnConf = xdri_drv->glx_priv->screenConfigs;
+ __DRIscreen *psc = &scrnConf->driScreen;
+ __DRIdrawable * const pdraw = psc->getDrawable(disp->Xdpy,
+ xdri_surf->driDrawable,
+ psc->private);
+
+ if (pdraw)
+ pdraw->swapBuffers(disp->Xdpy, pdraw->private);
+ else
+ _eglLog(_EGL_WARNING, "pdraw is null in SwapBuffers");
+ }
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * This is the main entrypoint into the driver, called by libEGL.
+ * Create a new _EGLDriver object and init its dispatch table.
+ */
+_EGLDriver *
+_eglMain(_EGLDisplay *disp, const char *args)
+{
+ struct xdri_egl_driver *xdri_drv = CALLOC_STRUCT(xdri_egl_driver);
+ if (!xdri_drv)
+ return NULL;
+
+ /* Tell libGL to prefer the EGL drivers over regular DRI drivers */
+ __glXPreferEGL(1);
+
+ _eglInitDriverFallbacks(&xdri_drv->Base);
+ xdri_drv->Base.API.Initialize = xdri_eglInitialize;
+ xdri_drv->Base.API.Terminate = xdri_eglTerminate;
+
+ xdri_drv->Base.API.GetProcAddress = xdri_eglGetProcAddress;
+
+ xdri_drv->Base.API.CreateContext = xdri_eglCreateContext;
+ xdri_drv->Base.API.MakeCurrent = xdri_eglMakeCurrent;
+ xdri_drv->Base.API.CreateWindowSurface = xdri_eglCreateWindowSurface;
+ xdri_drv->Base.API.CreatePbufferSurface = xdri_eglCreatePbufferSurface;
+ xdri_drv->Base.API.DestroySurface = xdri_eglDestroySurface;
+ xdri_drv->Base.API.BindTexImage = xdri_eglBindTexImage;
+ xdri_drv->Base.API.ReleaseTexImage = xdri_eglReleaseTexImage;
+ xdri_drv->Base.API.SwapBuffers = xdri_eglSwapBuffers;
+
+ xdri_drv->Base.ClientAPIsMask = (EGL_OPENGL_BIT |
+ EGL_OPENGL_ES_BIT |
+ EGL_OPENGL_ES2_BIT |
+ EGL_OPENVG_BIT);
+ xdri_drv->Base.Name = "X/DRI";
+
+ _eglLog(_EGL_DEBUG, "XDRI: main(%s)", args);
+
+ return &xdri_drv->Base;
+}
diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile
index 7ab78197c7b..8ea60c0199d 100644
--- a/src/egl/main/Makefile
+++ b/src/egl/main/Makefile
@@ -8,34 +8,49 @@ INCLUDE_DIRS = -I$(TOP)/include -I$(TOP)/src/mesa/glapi
HEADERS = \
eglconfig.h \
+ eglconfigutil.h \
eglcontext.h \
+ egldefines.h \
egldisplay.h \
egldriver.h \
eglglobals.h \
egllog.h \
eglhash.h \
+ eglmisc.h \
eglmode.h \
eglscreen.h \
- eglsurface.h
+ eglstring.h \
+ eglsurface.h \
+ eglx.h
SOURCES = \
eglapi.c \
eglconfig.c \
+ eglconfigutil.c \
eglcontext.c \
egldisplay.c \
egldriver.c \
eglglobals.c \
egllog.c \
eglhash.c \
+ eglmisc.c \
eglmode.c \
eglscreen.c \
- eglsurface.c
+ eglstring.c \
+ eglsurface.c \
+ eglx.c
OBJECTS = $(SOURCES:.c=.o)
+# Undefined for now
+LOCAL_CFLAGS = -D_EGL_PLATFORM_X=1
+
+LIBS = -lX11
+
+
.c.o:
- $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $< -o $@
+ $(CC) -c $(INCLUDE_DIRS) $(CFLAGS) $(LOCAL_CFLAGS) $< -o $@
@@ -48,7 +63,7 @@ library: $(TOP)/$(LIB_DIR)/libEGL.so
$(TOP)/$(LIB_DIR)/libEGL.so: $(OBJECTS)
$(MKLIB) -o EGL -linker '$(CC)' -ldflags '$(LDFLAGS)' \
-major 1 -minor 0 \
- -install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS)
+ -install $(TOP)/$(LIB_DIR) -ldl $(OBJECTS) $(LIBS)
@@ -59,9 +74,11 @@ clean:
depend: $(SOURCES) $(HEADERS)
@ echo "running $(MKDEP)"
+ @ rm -f depend
@ touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(DEFINES) $(INCLUDE_DIRS) \
- $(SOURCES) $(HEADERS) > /dev/null
+ $(SOURCES) $(HEADERS) > /dev/null 2>/dev/null
+
include depend
# DO NOT DELETE
diff --git a/src/egl/main/README.txt b/src/egl/main/README.txt
new file mode 100644
index 00000000000..b3d253dd133
--- /dev/null
+++ b/src/egl/main/README.txt
@@ -0,0 +1,71 @@
+
+
+Notes about the EGL library:
+
+
+The EGL code here basically consists of two things:
+
+1. An EGL API dispatcher. This directly routes all the eglFooBar() API
+ calls into driver-specific functions.
+
+2. Fallbacks for EGL API functions. A driver _could_ implement all the
+ EGL API calls from scratch. But in many cases, the fallbacks provided
+ in libEGL (such as eglChooseConfig()) will do the job.
+
+
+
+Bootstrapping:
+
+When the apps calls eglOpenDisplay() a device driver is selected and loaded
+(look for dlsym() or LoadLibrary() in egldriver.c).
+
+The driver's _eglMain() function is then called. This driver function
+allocates, initializes and returns a new _EGLDriver object (usually a
+subclass of that type).
+
+As part of initialization, the dispatch table in _EGLDriver->API must be
+populated with all the EGL entrypoints. Typically, _eglInitDriverFallbacks()
+can be used to plug in default/fallback functions. Some functions like
+driver->API.Initialize and driver->API.Terminate _must_ be implemented
+with driver-specific code (no default/fallback function is possible).
+
+
+A bit later, the app will call eglInitialize(). This will get routed
+to the driver->API.Initialize() function. Any additional driver
+initialization that wasn't done in _eglMain() should be done at this
+point. Typically, this will involve setting up visual configs, etc.
+
+
+
+Special Functions:
+
+Certain EGL functions _must_ be implemented by the driver. This includes:
+
+eglCreateContext
+eglCreateWindowSurface
+eglCreatePixmapSurface
+eglCreatePBufferSurface
+eglMakeCurrent
+eglSwapBuffers
+
+Most of the EGLConfig-related functions can be implemented with the
+defaults/fallbacks. Same thing for the eglGet/Query functions.
+
+
+
+
+Teardown:
+
+When eglTerminate() is called, the driver->API.Terminate() function is
+called. The driver should clean up after itself. eglTerminate() will
+then close/unload the driver (shared library).
+
+
+
+
+Subclassing:
+
+The internal libEGL data structures such as _EGLDisplay, _EGLContext,
+_EGLSurface, etc should be considered base classes from which drivers
+will derive subclasses.
+
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index bfa580e6c3f..9df938e1887 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -43,36 +43,63 @@
/**
- * NOTE: displayName is treated as a string in _eglChooseDriver()!!!
- * This will probably change!
- * See _eglChooseDriver() for details!
+ * This is typically the first EGL function that an application calls.
+ * We initialize our global vars and create a private _EGLDisplay object.
*/
-EGLDisplay APIENTRY
-eglGetDisplay(NativeDisplayType displayName)
+EGLDisplay EGLAPIENTRY
+eglGetDisplay(NativeDisplayType nativeDisplay)
{
_EGLDisplay *dpy;
_eglInitGlobals();
- dpy = _eglNewDisplay(displayName);
- if (dpy)
- return dpy->Handle;
- else
- return EGL_NO_DISPLAY;
+ dpy = _eglNewDisplay(nativeDisplay);
+ return _eglGetDisplayHandle(dpy);
}
-EGLBoolean APIENTRY
+/**
+ * This is typically the second EGL function that an application calls.
+ * Here we load/initialize the actual hardware driver.
+ */
+EGLBoolean EGLAPIENTRY
eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
+ EGLint major_int, minor_int;
+
if (dpy) {
- _EGLDriver *drv = _eglChooseDriver(dpy);
- if (drv)
- return drv->API.Initialize(drv, dpy, major, minor);
+ EGLBoolean retVal;
+ _EGLDisplay *dpyPriv = _eglLookupDisplay(dpy);
+ if (!dpyPriv) {
+ return EGL_FALSE;
+ }
+ dpyPriv->Driver = _eglOpenDriver(dpyPriv,
+ dpyPriv->DriverName,
+ dpyPriv->DriverArgs);
+ if (!dpyPriv->Driver) {
+ return EGL_FALSE;
+ }
+ /* Initialize the particular driver now */
+ retVal = dpyPriv->Driver->API.Initialize(dpyPriv->Driver, dpy,
+ &major_int, &minor_int);
+
+ dpyPriv->Driver->APImajor = major_int;
+ dpyPriv->Driver->APIminor = minor_int;
+ snprintf(dpyPriv->Driver->Version, sizeof(dpyPriv->Driver->Version),
+ "%d.%d (%s)", major_int, minor_int, dpyPriv->Driver->Name);
+
+ /* Update applications version of major and minor if not NULL */
+ if((major != NULL) && (minor != NULL))
+ {
+ *major = major_int;
+ *minor = minor_int;
+ }
+
+ return retVal;
}
return EGL_FALSE;
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglTerminate(EGLDisplay dpy)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -83,7 +110,7 @@ eglTerminate(EGLDisplay dpy)
}
-const char * APIENTRY
+const char * EGLAPIENTRY
eglQueryString(EGLDisplay dpy, EGLint name)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -94,7 +121,7 @@ eglQueryString(EGLDisplay dpy, EGLint name)
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -103,7 +130,7 @@ eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *nu
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -111,7 +138,7 @@ eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, E
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -119,7 +146,7 @@ eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *v
}
-EGLContext APIENTRY
+EGLContext EGLAPIENTRY
eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -127,7 +154,7 @@ eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -135,7 +162,7 @@ eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -143,7 +170,7 @@ eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -151,7 +178,7 @@ eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
}
-EGLSurface APIENTRY
+EGLSurface EGLAPIENTRY
eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -159,7 +186,7 @@ eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, NativeWindowType window
}
-EGLSurface APIENTRY
+EGLSurface EGLAPIENTRY
eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -167,7 +194,7 @@ eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap
}
-EGLSurface APIENTRY
+EGLSurface EGLAPIENTRY
eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -175,7 +202,7 @@ eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_l
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -183,7 +210,7 @@ eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -191,7 +218,7 @@ eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *va
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -199,7 +226,7 @@ eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint va
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -207,7 +234,7 @@ eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -215,7 +242,7 @@ eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglSwapInterval(EGLDisplay dpy, EGLint interval)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -223,7 +250,7 @@ eglSwapInterval(EGLDisplay dpy, EGLint interval)
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -231,7 +258,7 @@ eglSwapBuffers(EGLDisplay dpy, EGLSurface draw)
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -239,7 +266,7 @@ eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, NativePixmapType target)
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglWaitGL(void)
{
EGLDisplay dpy = eglGetCurrentDisplay();
@@ -252,7 +279,7 @@ eglWaitGL(void)
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglWaitNative(EGLint engine)
{
EGLDisplay dpy = eglGetCurrentDisplay();
@@ -265,40 +292,31 @@ eglWaitNative(EGLint engine)
}
-EGLDisplay APIENTRY
+EGLDisplay EGLAPIENTRY
eglGetCurrentDisplay(void)
{
_EGLDisplay *dpy = _eglGetCurrentDisplay();
- if (dpy)
- return dpy->Handle;
- else
- return EGL_NO_DISPLAY;
+ return _eglGetDisplayHandle(dpy);
}
-EGLContext APIENTRY
+EGLContext EGLAPIENTRY
eglGetCurrentContext(void)
{
_EGLContext *ctx = _eglGetCurrentContext();
- if (ctx)
- return ctx->Handle;
- else
- return EGL_NO_CONTEXT;
+ return _eglGetContextHandle(ctx);
}
-EGLSurface APIENTRY
+EGLSurface EGLAPIENTRY
eglGetCurrentSurface(EGLint readdraw)
{
_EGLSurface *s = _eglGetCurrentSurface(readdraw);
- if (s)
- return s->Handle;
- else
- return EGL_NO_SURFACE;
+ return _eglGetSurfaceHandle(s);
}
-EGLint APIENTRY
+EGLint EGLAPIENTRY
eglGetError(void)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
@@ -308,7 +326,7 @@ eglGetError(void)
}
-void (* APIENTRY eglGetProcAddress(const char *procname))()
+void (* EGLAPIENTRY eglGetProcAddress(const char *procname))()
{
typedef void (*genericFunc)();
struct name_function {
@@ -376,12 +394,15 @@ void (* APIENTRY eglGetProcAddress(const char *procname))()
return (genericFunc) egl_functions[i].function;
}
}
-#if 0
- /* XXX enable this code someday */
- return (genericFunc) _glapi_get_proc_address(procname);
-#else
+
+ /* now loop over drivers to query their procs */
+ for (i = 0; i < _eglGlobal.NumDrivers; i++) {
+ _EGLProc p = _eglGlobal.Drivers[i]->API.GetProcAddress(procname);
+ if (p)
+ return p;
+ }
+
return NULL;
-#endif
}
@@ -389,7 +410,7 @@ void (* APIENTRY eglGetProcAddress(const char *procname))()
* EGL_MESA_screen extension
*/
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
const EGLint *attrib_list, EGLModeMESA *modes,
EGLint modes_size, EGLint *num_modes)
@@ -402,7 +423,7 @@ eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen,
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -413,7 +434,7 @@ eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -424,7 +445,7 @@ eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint
}
-EGLBoolean APIENTRY
+EGLBoolean EGLAPIENTRY
eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask)
{
_EGLDriver *drv = _eglLookupDriver(dpy);
@@ -508,21 +529,42 @@ eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
#ifdef EGL_VERSION_1_2
+
+/**
+ * Specify the client API to use for subsequent calls including:
+ * eglCreateContext()
+ * eglGetCurrentContext()
+ * eglGetCurrentDisplay()
+ * eglGetCurrentSurface()
+ * eglMakeCurrent(when the ctx parameter is EGL NO CONTEXT)
+ * eglWaitClient()
+ * eglWaitNative()
+ * See section 3.7 "Rendering Context" in the EGL specification for details.
+ */
EGLBoolean
eglBindAPI(EGLenum api)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
switch (api) {
+#ifdef EGL_VERSION_1_4
+ case EGL_OPENGL_API:
+ if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_BIT) {
+ t->CurrentAPI = api;
+ return EGL_TRUE;
+ }
+ _eglError(EGL_BAD_PARAMETER, "eglBindAPI");
+ return EGL_FALSE;
+#endif
case EGL_OPENGL_ES_API:
- if (_eglGlobal.OpenGLESAPISupported) {
+ if (_eglGlobal.ClientAPIsMask & (EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT)) {
t->CurrentAPI = api;
return EGL_TRUE;
}
_eglError(EGL_BAD_PARAMETER, "eglBindAPI");
return EGL_FALSE;
case EGL_OPENVG_API:
- if (_eglGlobal.OpenVGAPISupported) {
+ if (_eglGlobal.ClientAPIsMask & EGL_OPENVG_BIT) {
t->CurrentAPI = api;
return EGL_TRUE;
}
@@ -535,6 +577,18 @@ eglBindAPI(EGLenum api)
}
+/**
+ * Return the last value set with eglBindAPI().
+ */
+EGLenum
+eglQueryAPI(void)
+{
+ /* returns one of EGL_OPENGL_API, EGL_OPENGL_ES_API or EGL_OPENVG_API */
+ _EGLThreadInfo *t = _eglGetCurrentThread();
+ return t->CurrentAPI;
+}
+
+
EGLSurface
eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
EGLClientBuffer buffer, EGLConfig config,
@@ -546,15 +600,6 @@ eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
}
-EGLenum
-eglQueryAPI(void)
-{
- /* returns one of EGL_OPENGL_ES_API or EGL_OPENVG_API */
- _EGLThreadInfo *t = _eglGetCurrentThread();
- return t->CurrentAPI;
-}
-
-
EGLBoolean
eglReleaseThread(void)
{
diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h
index 555aa5dd9ef..f6163a0c7a8 100644
--- a/src/egl/main/eglapi.h
+++ b/src/egl/main/eglapi.h
@@ -2,10 +2,15 @@
#define EGLAPI_INCLUDED
/**
- * Typedefs for all EGL API entrypoint functions.
+ * A generic function ptr type
*/
+typedef void (*_EGLProc)();
+/**
+ * Typedefs for all EGL API entrypoint functions.
+ */
+
/* driver funcs */
typedef EGLBoolean (*Initialize_t)(_EGLDriver *, EGLDisplay dpy, EGLint *major, EGLint *minor);
typedef EGLBoolean (*Terminate_t)(_EGLDriver *, EGLDisplay dpy);
@@ -39,6 +44,9 @@ typedef const char *(*QueryString_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint nam
typedef EGLBoolean (*WaitGL_t)(_EGLDriver *drv, EGLDisplay dpy);
typedef EGLBoolean (*WaitNative_t)(_EGLDriver *drv, EGLDisplay dpy, EGLint engine);
+typedef _EGLProc (*GetProcAddress_t)(const char *procname);
+
+
#ifdef EGL_MESA_screen_surface
typedef EGLBoolean (*ChooseModeMESA_t)(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes);
@@ -95,6 +103,7 @@ struct _egl_api
QueryString_t QueryString;
WaitGL_t WaitGL;
WaitNative_t WaitNative;
+ GetProcAddress_t GetProcAddress;
/* EGL_MESA_screen extension */
ChooseModeMESA_t ChooseModeMESA;
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index 2a62f95b542..b19988f49a9 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -17,48 +17,6 @@
#define MIN2(A, B) (((A) < (B)) ? (A) : (B))
-/**
- * Convert an _EGLConfig to a __GLcontextModes object.
- * NOTE: This routine may be incomplete - we're only making sure that
- * the fields needed by Mesa (for _mesa_create_context/framebuffer) are
- * set correctly.
- */
-void
-_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode)
-{
- memset(mode, 0, sizeof(*mode));
-
- mode->rgbMode = GL_TRUE; /* no color index */
- mode->colorIndexMode = GL_FALSE;
- mode->doubleBufferMode = GL_TRUE; /* always DB for now */
- mode->stereoMode = GL_FALSE;
-
- mode->redBits = GET_CONFIG_ATTRIB(config, EGL_RED_SIZE);
- mode->greenBits = GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE);
- mode->blueBits = GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE);
- mode->alphaBits = GET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE);
- mode->rgbBits = GET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE);
-
- /* no rgba masks - fix? */
-
- mode->depthBits = GET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE);
- mode->haveDepthBuffer = mode->depthBits > 0;
-
- mode->stencilBits = GET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE);
- mode->haveStencilBuffer = mode->stencilBits > 0;
-
- /* no accum */
-
- mode->level = GET_CONFIG_ATTRIB(config, EGL_LEVEL);
- mode->samples = GET_CONFIG_ATTRIB(config, EGL_SAMPLES);
- mode->sampleBuffers = GET_CONFIG_ATTRIB(config, EGL_SAMPLE_BUFFERS);
-
- /* surface type - not really needed */
- mode->visualType = GLX_TRUE_COLOR;
- mode->renderType = GLX_RGBA_BIT;
-}
-
-
void
_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val)
{
@@ -76,7 +34,7 @@ void
_eglInitConfig(_EGLConfig *config, EGLint id)
{
memset(config, 0, sizeof(*config));
- config->Handle = id;
+ config->Handle = (EGLConfig) 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);
@@ -85,9 +43,7 @@ _eglInitConfig(_EGLConfig *config, EGLint id)
_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_SCREEN_BIT_MESA | EGL_PBUFFER_BIT |
- EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
+ _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);
@@ -100,7 +56,19 @@ _eglInitConfig(_EGLConfig *config, EGLint id)
/**
+ * Return the public handle for an internal _EGLConfig.
+ * This is the inverse of _eglLookupConfig().
+ */
+EGLConfig
+_eglGetConfigHandle(_EGLConfig *config)
+{
+ return config ? config->Handle : 0;
+}
+
+
+/**
* Given an EGLConfig handle, return the corresponding _EGLConfig object.
+ * This is the inverse of _eglGetConfigHandle().
*/
_EGLConfig *
_eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config)
@@ -108,8 +76,8 @@ _eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config)
EGLint i;
_EGLDisplay *disp = _eglLookupDisplay(dpy);
for (i = 0; i < disp->NumConfigs; i++) {
- if (disp->Configs[i].Handle == config) {
- return disp->Configs + i;
+ if (disp->Configs[i]->Handle == config) {
+ return disp->Configs[i];
}
}
return NULL;
@@ -118,23 +86,32 @@ _eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config)
/**
* 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, const _EGLConfig *config)
+_eglAddConfig(_EGLDisplay *display, _EGLConfig *config)
{
- _EGLConfig *newConfigs;
+ _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;
- newConfigs = (_EGLConfig *) realloc(display->Configs,
- (n + 1) * sizeof(_EGLConfig));
+ /* realloc array of ptrs */
+ newConfigs = (_EGLConfig **) realloc(display->Configs,
+ (n + 1) * sizeof(_EGLConfig *));
if (newConfigs) {
display->Configs = newConfigs;
- display->Configs[n] = *config; /* copy struct */
- display->Configs[n].Handle = n;
+ display->Configs[n] = config;
display->NumConfigs++;
- return display->Configs + n;
+ return config;
}
else {
return NULL;
@@ -176,7 +153,7 @@ _eglParseConfigAttribs(_EGLConfig *config, const EGLint *attrib_list)
}
else if (attr == EGL_RENDERABLE_TYPE) {
EGLint renType = attrib_list[++i];
- if (renType & ~(EGL_OPENGL_ES_BIT | EGL_OPENVG_BIT)) {
+ if (renType & ~(EGL_OPENGL_ES_BIT | EGL_OPENGL_ES2_BIT | EGL_OPENVG_BIT)) {
_eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
return EGL_FALSE;
}
@@ -360,8 +337,8 @@ _eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list,
/* make array of pointers to qualifying configs */
for (i = count = 0; i < disp->NumConfigs && count < config_size; i++) {
- if (_eglConfigQualifies(disp->Configs + i, &criteria)) {
- configList[count++] = disp->Configs + i;
+ if (_eglConfigQualifies(disp->Configs[i], &criteria)) {
+ configList[count++] = disp->Configs[i];
}
}
@@ -369,8 +346,10 @@ _eglChooseConfig(_EGLDriver *drv, EGLDisplay dpy, const EGLint *attrib_list,
qsort(configList, count, sizeof(_EGLConfig *), _eglCompareConfigs);
/* copy config handles to output array */
- for (i = 0; i < count; i++) {
- configs[i] = configList[i]->Handle;
+ if (configs) {
+ for (i = 0; i < count; i++) {
+ configs[i] = configList[i]->Handle;
+ }
}
free(configList);
@@ -419,7 +398,7 @@ _eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs,
EGLint i;
*num_config = MIN2(disp->NumConfigs, config_size);
for (i = 0; i < *num_config; i++) {
- configs[i] = disp->Configs[i].Handle;
+ configs[i] = disp->Configs[i]->Handle;
}
}
else {
@@ -429,210 +408,3 @@ _eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs,
return EGL_TRUE;
}
-
-
-/**
- * Creates a set of \c __GLcontextModes that a driver will expose.
- *
- * A set of \c __GLcontextModes will be created based on the supplied
- * parameters. The number of modes processed will be 2 *
- * \c num_depth_stencil_bits * \c num_db_modes.
- *
- * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
- * \c db_modes, and \c visType into each \c __GLcontextModes element.
- * However, the meanings of \c fb_format and \c fb_type require further
- * explanation. The \c fb_format specifies which color components are in
- * each pixel and what the default order is. For example, \c GL_RGB specifies
- * that red, green, blue are available and red is in the "most significant"
- * position and blue is in the "least significant". The \c fb_type specifies
- * the bit sizes of each component and the actual ordering. For example, if
- * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
- * are the blue value, bits [10:5] are the green value, and bits [4:0] are
- * the red value.
- *
- * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either
- * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the
- * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
- * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as
- * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
- * still uses 32-bits.
- *
- * If in doubt, look at the tables used in the function.
- *
- * \param ptr_to_modes Pointer to a pointer to a linked list of
- * \c __GLcontextModes. Upon completion, a pointer to
- * the next element to be process will be stored here.
- * If the function fails and returns \c GL_FALSE, this
- * value will be unmodified, but some elements in the
- * linked list may be modified.
- * \param fb_format Format of the framebuffer. Currently only \c GL_RGB,
- * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
- * \param fb_type Type of the pixels in the framebuffer. Currently only
- * \c GL_UNSIGNED_SHORT_5_6_5,
- * \c GL_UNSIGNED_SHORT_5_6_5_REV,
- * \c GL_UNSIGNED_INT_8_8_8_8, and
- * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
- * \param depth_bits Array of depth buffer sizes to be exposed.
- * \param stencil_bits Array of stencil buffer sizes to be exposed.
- * \param num_depth_stencil_bits Number of entries in both \c depth_bits and
- * \c stencil_bits.
- * \param db_modes Array of buffer swap modes. If an element has a
- * value of \c GLX_NONE, then it represents a
- * single-buffered mode. Other valid values are
- * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
- * \c GLX_SWAP_UNDEFINED_OML. See the
- * GLX_OML_swap_method extension spec for more details.
- * \param num_db_modes Number of entries in \c db_modes.
- * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
- * \c GLX_DIRECT_COLOR.
- *
- * \returns
- * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only
- * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
- * \c fb_type).
- *
- * \todo
- * There is currently no way to support packed RGB modes (i.e., modes with
- * exactly 3 bytes per pixel) or floating-point modes. This could probably
- * be done by creating some new, private enums with clever names likes
- * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
- * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it.
- */
-GLboolean
-_eglFillInConfigs(_EGLConfig * configs,
- GLenum fb_format, GLenum fb_type,
- const uint8_t * depth_bits, const uint8_t * stencil_bits,
- unsigned num_depth_stencil_bits,
- const GLenum * db_modes, unsigned num_db_modes,
- int visType)
-{
- static const uint8_t bits_table[3][4] = {
- /* R G B A */
- { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
- { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
- { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
- };
-
- /* The following arrays are all indexed by the fb_type masked with 0x07.
- * Given the four supported fb_type values, this results in valid array
- * indices of 3, 4, 5, and 7.
- */
- static const uint32_t masks_table_rgb[8][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
- {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
- {0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000}, /* 8_8_8_8 */
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000} /* 8_8_8_8_REV */
- };
-
- static const uint32_t masks_table_rgba[8][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
- {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
- {0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF}, /* 8_8_8_8 */
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000}, /* 8_8_8_8_REV */
- };
-
- static const uint32_t masks_table_bgr[8][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
- {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
- {0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000}, /* 8_8_8_8 */
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000}, /* 8_8_8_8_REV */
- };
-
- static const uint32_t masks_table_bgra[8][4] = {
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
- {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
- {0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF}, /* 8_8_8_8 */
- {0x00000000, 0x00000000, 0x00000000, 0x00000000},
- {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000}, /* 8_8_8_8_REV */
- };
-
- static const uint8_t bytes_per_pixel[8] = {
- 0, 0, 0, 2, 2, 4, 0, 4
- };
-
- const uint8_t * bits;
- const uint32_t * masks;
- const int index = fb_type & 0x07;
- _EGLConfig *config;
- unsigned i;
- unsigned j;
- unsigned k;
-
- if ( bytes_per_pixel[index] == 0 ) {
- _eglLog(_EGL_INFO,
- "[%s:%u] Framebuffer type 0x%04x has 0 bytes per pixel.",
- __FUNCTION__, __LINE__, fb_type);
- return GL_FALSE;
- }
-
- /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
- * the _REV versions.
- *
- * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
- */
- switch ( fb_format ) {
- case GL_RGB:
- bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
- masks = masks_table_rgb[index];
- break;
-
- case GL_RGBA:
- bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
- masks = masks_table_rgba[index];
- break;
-
- case GL_BGR:
- bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
- masks = masks_table_bgr[index];
- break;
-
- case GL_BGRA:
- bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
- masks = masks_table_bgra[index];
- break;
-
- default:
- _eglLog(_EGL_WARNING,
- "[%s:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.",
- __FUNCTION__, __LINE__, fb_format);
- return GL_FALSE;
- }
-
- config = configs;
- for (k = 0; k < num_depth_stencil_bits; k++) {
- for (i = 0; i < num_db_modes; i++) {
- for (j = 0; j < 2; j++) {
- _eglSetConfigAttrib(config, EGL_RED_SIZE, bits[0]);
- _eglSetConfigAttrib(config, EGL_GREEN_SIZE, bits[1]);
- _eglSetConfigAttrib(config, EGL_BLUE_SIZE, bits[2]);
- _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, bits[3]);
- _eglSetConfigAttrib(config, EGL_BUFFER_SIZE,
- bits[0] + bits[1] + bits[2] + bits[3]);
-
- _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, stencil_bits[k]);
- _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, depth_bits[i]);
-
- _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_SCREEN_BIT_MESA |
- EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
-
- config++;
- }
- }
- }
- return GL_TRUE;
-}
diff --git a/src/egl/main/eglconfig.h b/src/egl/main/eglconfig.h
index 441b3f4d206..db1c4c10e08 100644
--- a/src/egl/main/eglconfig.h
+++ b/src/egl/main/eglconfig.h
@@ -3,10 +3,10 @@
#include "egltypedefs.h"
-#include "GL/internal/glcore.h"
+#include <GLES/gl.h>
-#define MAX_ATTRIBS 100
+#define MAX_ATTRIBS 128
#define FIRST_ATTRIB EGL_BUFFER_SIZE
@@ -17,7 +17,11 @@ struct _egl_config
};
-#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB] = VAL)
+#define SET_CONFIG_ATTRIB(CONF, ATTR, VAL) \
+ assert((ATTR) - FIRST_ATTRIB < MAX_ATTRIBS); \
+ ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB] = VAL)
+
+
#define GET_CONFIG_ATTRIB(CONF, ATTR) ((CONF)->Attrib[(ATTR) - FIRST_ATTRIB])
@@ -25,12 +29,16 @@ extern void
_eglInitConfig(_EGLConfig *config, EGLint id);
+extern EGLConfig
+_eglGetConfigHandle(_EGLConfig *config);
+
+
extern _EGLConfig *
_eglLookupConfig(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config);
extern _EGLConfig *
-_eglAddConfig(_EGLDisplay *display, const _EGLConfig *config);
+_eglAddConfig(_EGLDisplay *display, _EGLConfig *config);
extern EGLBoolean
@@ -52,16 +60,5 @@ _eglGetConfigs(_EGLDriver *drv, EGLDisplay dpy, EGLConfig *configs, EGLint confi
extern void
_eglSetConfigAttrib(_EGLConfig *config, EGLint attr, EGLint val);
-extern GLboolean
-_eglFillInConfigs( _EGLConfig *configs,
- GLenum fb_format, GLenum fb_type,
- const uint8_t * depth_bits, const uint8_t * stencil_bits,
- unsigned num_depth_stencil_bits,
- const GLenum * db_modes, unsigned num_db_modes,
- int visType );
-
-extern void
-_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode);
-
#endif /* EGLCONFIG_INCLUDED */
diff --git a/src/egl/main/eglconfigutil.c b/src/egl/main/eglconfigutil.c
new file mode 100644
index 00000000000..7061df691b2
--- /dev/null
+++ b/src/egl/main/eglconfigutil.c
@@ -0,0 +1,258 @@
+/**
+ * Extra utility functions related to EGL configs.
+ */
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "eglconfigutil.h"
+#include "egllog.h"
+
+
+/**
+ * Convert an _EGLConfig to a __GLcontextModes object.
+ * NOTE: This routine may be incomplete - we're only making sure that
+ * the fields needed by Mesa (for _mesa_create_context/framebuffer) are
+ * set correctly.
+ */
+void
+_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode)
+{
+ memset(mode, 0, sizeof(*mode));
+
+ mode->rgbMode = GL_TRUE; /* no color index */
+ mode->colorIndexMode = GL_FALSE;
+ mode->doubleBufferMode = GL_TRUE; /* always DB for now */
+ mode->stereoMode = GL_FALSE;
+
+ mode->redBits = GET_CONFIG_ATTRIB(config, EGL_RED_SIZE);
+ mode->greenBits = GET_CONFIG_ATTRIB(config, EGL_GREEN_SIZE);
+ mode->blueBits = GET_CONFIG_ATTRIB(config, EGL_BLUE_SIZE);
+ mode->alphaBits = GET_CONFIG_ATTRIB(config, EGL_ALPHA_SIZE);
+ mode->rgbBits = GET_CONFIG_ATTRIB(config, EGL_BUFFER_SIZE);
+
+ /* no rgba masks - fix? */
+
+ mode->depthBits = GET_CONFIG_ATTRIB(config, EGL_DEPTH_SIZE);
+ mode->haveDepthBuffer = mode->depthBits > 0;
+
+ mode->stencilBits = GET_CONFIG_ATTRIB(config, EGL_STENCIL_SIZE);
+ mode->haveStencilBuffer = mode->stencilBits > 0;
+
+ /* no accum */
+
+ mode->level = GET_CONFIG_ATTRIB(config, EGL_LEVEL);
+ mode->samples = GET_CONFIG_ATTRIB(config, EGL_SAMPLES);
+ mode->sampleBuffers = GET_CONFIG_ATTRIB(config, EGL_SAMPLE_BUFFERS);
+
+ /* surface type - not really needed */
+ mode->visualType = GLX_TRUE_COLOR;
+ mode->renderType = GLX_RGBA_BIT;
+}
+
+
+
+/**
+ * Creates a set of \c _EGLConfigs that a driver will expose.
+ *
+ * A set of \c __GLcontextModes will be created based on the supplied
+ * parameters. The number of modes processed will be 2 *
+ * \c num_depth_stencil_bits * \c num_db_modes.
+ *
+ * For the most part, data is just copied from \c depth_bits, \c stencil_bits,
+ * \c db_modes, and \c visType into each \c __GLcontextModes element.
+ * However, the meanings of \c fb_format and \c fb_type require further
+ * explanation. The \c fb_format specifies which color components are in
+ * each pixel and what the default order is. For example, \c GL_RGB specifies
+ * that red, green, blue are available and red is in the "most significant"
+ * position and blue is in the "least significant". The \c fb_type specifies
+ * the bit sizes of each component and the actual ordering. For example, if
+ * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11]
+ * are the blue value, bits [10:5] are the green value, and bits [4:0] are
+ * the red value.
+ *
+ * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either
+ * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the
+ * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or
+ * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as
+ * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8
+ * still uses 32-bits.
+ *
+ * If in doubt, look at the tables used in the function.
+ *
+ * \param configs the array of configs generated
+ * \param fb_format Format of the framebuffer. Currently only \c GL_RGB,
+ * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported.
+ * \param fb_type Type of the pixels in the framebuffer. Currently only
+ * \c GL_UNSIGNED_SHORT_5_6_5,
+ * \c GL_UNSIGNED_SHORT_5_6_5_REV,
+ * \c GL_UNSIGNED_INT_8_8_8_8, and
+ * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported.
+ * \param depth_bits Array of depth buffer sizes to be exposed.
+ * \param stencil_bits Array of stencil buffer sizes to be exposed.
+ * \param num_depth_stencil_bits Number of entries in both \c depth_bits and
+ * \c stencil_bits.
+ * \param db_modes Array of buffer swap modes. If an element has a
+ * value of \c GLX_NONE, then it represents a
+ * single-buffered mode. Other valid values are
+ * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and
+ * \c GLX_SWAP_UNDEFINED_OML. See the
+ * GLX_OML_swap_method extension spec for more details.
+ * \param num_db_modes Number of entries in \c db_modes.
+ * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or
+ * \c GLX_DIRECT_COLOR.
+ *
+ * \returns
+ * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only
+ * cause of failure is a bad parameter (i.e., unsupported \c fb_format or
+ * \c fb_type).
+ *
+ * \todo
+ * There is currently no way to support packed RGB modes (i.e., modes with
+ * exactly 3 bytes per pixel) or floating-point modes. This could probably
+ * be done by creating some new, private enums with clever names likes
+ * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32,
+ * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it.
+ */
+EGLBoolean
+_eglFillInConfigs(_EGLConfig * configs,
+ GLenum fb_format, GLenum fb_type,
+ const uint8_t * depth_bits, const uint8_t * stencil_bits,
+ unsigned num_depth_stencil_bits,
+ const GLenum * db_modes, unsigned num_db_modes,
+ int visType)
+{
+ static const uint8_t bits_table[3][4] = {
+ /* R G B A */
+ { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */
+ { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */
+ { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */
+ };
+
+ /* The following arrays are all indexed by the fb_type masked with 0x07.
+ * Given the four supported fb_type values, this results in valid array
+ * indices of 3, 4, 5, and 7.
+ */
+ static const uint32_t masks_table_rgb[8][4] = {
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
+ {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
+ {0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000}, /* 8_8_8_8 */
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000} /* 8_8_8_8_REV */
+ };
+
+ static const uint32_t masks_table_rgba[8][4] = {
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5 */
+ {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5_REV */
+ {0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF}, /* 8_8_8_8 */
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000}, /* 8_8_8_8_REV */
+ };
+
+ static const uint32_t masks_table_bgr[8][4] = {
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
+ {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
+ {0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000}, /* 8_8_8_8 */
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000}, /* 8_8_8_8_REV */
+ };
+
+ static const uint32_t masks_table_bgra[8][4] = {
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x0000001F, 0x000007E0, 0x0000F800, 0x00000000}, /* 5_6_5 */
+ {0x0000F800, 0x000007E0, 0x0000001F, 0x00000000}, /* 5_6_5_REV */
+ {0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF}, /* 8_8_8_8 */
+ {0x00000000, 0x00000000, 0x00000000, 0x00000000},
+ {0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000}, /* 8_8_8_8_REV */
+ };
+
+ static const uint8_t bytes_per_pixel[8] = {
+ 0, 0, 0, 2, 2, 4, 0, 4
+ };
+
+ const uint8_t * bits;
+ const uint32_t * masks;
+ const int index = fb_type & 0x07;
+ _EGLConfig *config;
+ unsigned i;
+ unsigned j;
+ unsigned k;
+
+ if ( bytes_per_pixel[index] == 0 ) {
+ _eglLog(_EGL_INFO,
+ "[%s:%u] Framebuffer type 0x%04x has 0 bytes per pixel.",
+ __FUNCTION__, __LINE__, fb_type);
+ return GL_FALSE;
+ }
+
+ /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and
+ * the _REV versions.
+ *
+ * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA.
+ */
+ switch ( fb_format ) {
+ case GL_RGB:
+ bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
+ masks = masks_table_rgb[index];
+ break;
+
+ case GL_RGBA:
+ bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
+ masks = masks_table_rgba[index];
+ break;
+
+#if 0
+ case GL_BGR:
+ bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[1];
+ masks = masks_table_bgr[index];
+ break;
+
+ case GL_BGRA:
+ bits = (bytes_per_pixel[index] == 2) ? bits_table[0] : bits_table[2];
+ masks = masks_table_bgra[index];
+ break;
+#endif
+
+ default:
+ _eglLog(_EGL_WARNING,
+ "[%s:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.",
+ __FUNCTION__, __LINE__, fb_format);
+ return GL_FALSE;
+ }
+
+ config = configs;
+ for (k = 0; k < num_depth_stencil_bits; k++) {
+ for (i = 0; i < num_db_modes; i++) {
+ for (j = 0; j < 2; j++) {
+ _eglSetConfigAttrib(config, EGL_RED_SIZE, bits[0]);
+ _eglSetConfigAttrib(config, EGL_GREEN_SIZE, bits[1]);
+ _eglSetConfigAttrib(config, EGL_BLUE_SIZE, bits[2]);
+ _eglSetConfigAttrib(config, EGL_ALPHA_SIZE, bits[3]);
+ _eglSetConfigAttrib(config, EGL_BUFFER_SIZE,
+ bits[0] + bits[1] + bits[2] + bits[3]);
+
+ _eglSetConfigAttrib(config, EGL_STENCIL_SIZE, stencil_bits[k]);
+ _eglSetConfigAttrib(config, EGL_DEPTH_SIZE, depth_bits[i]);
+
+ _eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_SCREEN_BIT_MESA |
+ EGL_PBUFFER_BIT | EGL_PIXMAP_BIT | EGL_WINDOW_BIT);
+
+ config++;
+ }
+ }
+ }
+ return GL_TRUE;
+}
+
diff --git a/src/egl/main/eglconfigutil.h b/src/egl/main/eglconfigutil.h
new file mode 100644
index 00000000000..c477b94737d
--- /dev/null
+++ b/src/egl/main/eglconfigutil.h
@@ -0,0 +1,26 @@
+
+#ifndef EGLCONFIGUTIL_INCLUDED
+#define EGLCONFIGUTIL_INCLUDED
+
+#include "eglconfig.h"
+#include "GL/internal/glcore.h"
+#if (!defined(WIN32) && !defined(_WIN32_WCE))
+#include "stdint.h"
+#endif
+
+
+extern void
+_eglConfigToContextModesRec(const _EGLConfig *config, __GLcontextModes *mode);
+
+
+extern EGLBoolean
+_eglFillInConfigs( _EGLConfig *configs,
+ EGLenum fb_format, EGLenum fb_type,
+ const uint8_t * depth_bits, const uint8_t * stencil_bits,
+ unsigned num_depth_stencil_bits,
+ const EGLenum * db_modes, unsigned num_db_modes,
+ int visType );
+
+
+
+#endif /* EGLCONFIGUTIL_INCLUDED */
diff --git a/src/egl/main/eglcontext.c b/src/egl/main/eglcontext.c
index 374c006dae7..461679db090 100644
--- a/src/egl/main/eglcontext.c
+++ b/src/egl/main/eglcontext.c
@@ -6,12 +6,12 @@
#include "egldisplay.h"
#include "egldriver.h"
#include "eglglobals.h"
-#include "eglhash.h"
#include "eglsurface.h"
/**
- * Initialize the given _EGLContext object to defaults.
+ * Initialize the given _EGLContext object to defaults and/or the values
+ * in the attrib_list.
*/
EGLBoolean
_eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
@@ -20,42 +20,54 @@ _eglInitContext(_EGLDriver *drv, EGLDisplay dpy, _EGLContext *ctx,
_EGLConfig *conf;
_EGLDisplay *display = _eglLookupDisplay(dpy);
EGLint i;
+ const EGLenum api = eglQueryAPI();
+
+ if (api == EGL_NONE) {
+ _eglError(EGL_BAD_MATCH, "eglCreateContext(no client API)");
+ return EGL_FALSE;
+ }
conf = _eglLookupConfig(drv, dpy, config);
if (!conf) {
- _eglError(EGL_BAD_CONFIG, "eglCreateContext");
+ _eglError(EGL_BAD_CONFIG, "_eglInitContext");
return EGL_FALSE;
}
+ memset(ctx, 0, sizeof(_EGLContext));
+
+ ctx->ClientVersion = 1; /* the default, per EGL spec */
+
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
switch (attrib_list[i]) {
- /* no attribs defined for now */
+ case EGL_CONTEXT_CLIENT_VERSION:
+ i++;
+ ctx->ClientVersion = attrib_list[i];
+ break;
default:
- _eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext");
- return EGL_NO_CONTEXT;
+ _eglError(EGL_BAD_ATTRIBUTE, "_eglInitContext");
+ return EGL_FALSE;
}
}
- memset(ctx, 0, sizeof(_EGLContext));
ctx->Display = display;
ctx->Config = conf;
ctx->DrawSurface = EGL_NO_SURFACE;
ctx->ReadSurface = EGL_NO_SURFACE;
+ ctx->ClientAPI = api;
return EGL_TRUE;
}
-/*
- * Assign an EGLContext handle to the _EGLContext object then put it into
- * the hash table.
+/**
+ * Save a new _EGLContext into the hash table.
*/
void
_eglSaveContext(_EGLContext *ctx)
{
- assert(ctx);
- ctx->Handle = _eglHashGenKey(_eglGlobal.Contexts);
- _eglHashInsert(_eglGlobal.Contexts, ctx->Handle, ctx);
+ /* no-op.
+ * Public EGLContext handle and private _EGLContext are the same.
+ */
}
@@ -65,19 +77,34 @@ _eglSaveContext(_EGLContext *ctx)
void
_eglRemoveContext(_EGLContext *ctx)
{
- _eglHashRemove(_eglGlobal.Contexts, ctx->Handle);
+ /* no-op.
+ * Public EGLContext handle and private _EGLContext are the same.
+ */
+}
+
+
+/**
+ * Return the public handle for the given private context ptr.
+ * This is the inverse of _eglLookupContext().
+ */
+EGLContext
+_eglGetContextHandle(_EGLContext *ctx)
+{
+ /* just a cast! */
+ return (EGLContext) ctx;
}
/**
* Return the _EGLContext object that corresponds to the given
* EGLContext handle.
+ * This is the inverse of _eglGetContextHandle().
*/
_EGLContext *
_eglLookupContext(EGLContext ctx)
{
- _EGLContext *c = (_EGLContext *) _eglHashLookup(_eglGlobal.Contexts, ctx);
- return c;
+ /* just a cast since EGLContext is just a void ptr */
+ return (_EGLContext *) ctx;
}
@@ -112,7 +139,7 @@ _eglCreateContext(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
}
_eglSaveContext(context);
- return context->Handle;
+ return (EGLContext) context;
#endif
return EGL_NO_CONTEXT;
}
@@ -126,7 +153,6 @@ _eglDestroyContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx)
{
_EGLContext *context = _eglLookupContext(ctx);
if (context) {
- _eglHashRemove(_eglGlobal.Contexts, ctx);
if (context->IsBound) {
context->DeletePending = EGL_TRUE;
}
@@ -163,8 +189,11 @@ _eglQueryContext(_EGLDriver *drv, EGLDisplay dpy, EGLContext ctx,
#ifdef EGL_VERSION_1_2
case EGL_CONTEXT_CLIENT_TYPE:
*value = c->ClientAPI;
- return EGL_FALSE;
+ return EGL_TRUE;
#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;
@@ -239,7 +268,7 @@ _eglMakeCurrent(_EGLDriver *drv, EGLDisplay dpy, EGLSurface d,
ctx = NULL;
}
/* really delete context now */
- drv->API.DestroyContext(drv, dpy, oldContext->Handle);
+ drv->API.DestroyContext(drv, dpy, _eglGetContextHandle(oldContext));
}
}
diff --git a/src/egl/main/eglcontext.h b/src/egl/main/eglcontext.h
index 82bfde151f3..34fee9c6376 100644
--- a/src/egl/main/eglcontext.h
+++ b/src/egl/main/eglcontext.h
@@ -11,8 +11,6 @@
*/
struct _egl_context
{
- EGLContext Handle; /* The public/opaque handle which names this object */
-
_EGLDisplay *Display; /* who do I belong to? */
_EGLConfig *Config;
@@ -22,9 +20,9 @@ struct _egl_context
EGLBoolean IsBound;
EGLBoolean DeletePending;
-#ifdef EGL_VERSION_1_2
- EGLint ClientAPI; /* Either EGL_OPENGL_ES_API or EGL_OPENVG_API */
-#endif /* EGL_VERSION_1_2 */
+
+ EGLint ClientAPI; /**< EGL_OPENGL_ES_API, EGL_OPENGL_API, EGL_OPENVG_API */
+ EGLint ClientVersion; /**< 1 = OpenGLES 1.x, 2 = OpenGLES 2.x */
};
@@ -41,6 +39,10 @@ extern void
_eglRemoveContext(_EGLContext *ctx);
+extern EGLContext
+_eglGetContextHandle(_EGLContext *ctx);
+
+
extern _EGLContext *
_eglLookupContext(EGLContext ctx);
diff --git a/src/egl/main/egldefines.h b/src/egl/main/egldefines.h
new file mode 100644
index 00000000000..8fc2301b795
--- /dev/null
+++ b/src/egl/main/egldefines.h
@@ -0,0 +1,45 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+
+/**
+ * Internal EGL defines
+ */
+
+
+#ifndef EGLDEFINES_INCLUDED
+#define EGLDEFINES_INCLUDED
+
+
+#define _EGL_MAX_EXTENSIONS_LEN 1000
+
+#define _EGL_VENDOR_STRING "Mesa Project"
+
+
+
+#endif /* EGLDEFINES_INCLUDED */
diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c
index 074a85bf26b..47a2323eafb 100644
--- a/src/egl/main/egldisplay.c
+++ b/src/egl/main/egldisplay.c
@@ -1,52 +1,88 @@
+
+/**
+ * Functions related to EGLDisplay.
+ */
+
+#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "eglcontext.h"
#include "egldisplay.h"
+#include "egldriver.h"
#include "eglglobals.h"
#include "eglhash.h"
-
-
-static char *
-my_strdup(const char *s)
-{
- int l = strlen(s);
- char *s2 = malloc(l + 1);
- strcpy(s2, s);
- return s2;
-}
+#include "eglstring.h"
/**
- * We're assuming that the NativeDisplayType parameter is actually
- * a string.
- * Return a new _EGLDisplay object for the given displayName
+ * Allocate a new _EGLDisplay object for the given nativeDisplay handle.
+ * We'll also try to determine the device driver name at this time.
+ *
+ * Note that nativeDisplay may be an X Display ptr, or a string.
*/
_EGLDisplay *
-_eglNewDisplay(NativeDisplayType displayName)
+_eglNewDisplay(NativeDisplayType nativeDisplay)
{
_EGLDisplay *dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
if (dpy) {
- dpy->Handle = _eglHashGenKey(_eglGlobal.Displays);
- _eglHashInsert(_eglGlobal.Displays, dpy->Handle, dpy);
- if (displayName)
- dpy->Name = my_strdup(displayName);
- else
- dpy->Name = NULL;
- dpy->Driver = NULL; /* this gets set later */
+ EGLuint key = _eglHashGenKey(_eglGlobal.Displays);
+
+ dpy->Handle = (EGLDisplay) key;
+ _eglHashInsert(_eglGlobal.Displays, key, dpy);
+
+ dpy->NativeDisplay = nativeDisplay;
+#if defined(_EGL_PLATFORM_X)
+ dpy->Xdpy = (Display *) nativeDisplay;
+#endif
+
+ dpy->DriverName = _eglChooseDriver(dpy);
+ if (!dpy->DriverName) {
+ free(dpy);
+ return NULL;
+ }
}
return dpy;
}
/**
+ * Return the public handle for an internal _EGLDisplay.
+ * This is the inverse of _eglLookupDisplay().
+ */
+EGLDisplay
+_eglGetDisplayHandle(_EGLDisplay *display)
+{
+ if (display)
+ return display->Handle;
+ else
+ return EGL_NO_DISPLAY;
+}
+
+
+/**
* Return the _EGLDisplay object that corresponds to the given public/
* opaque display handle.
+ * This is the inverse of _eglGetDisplayHandle().
*/
_EGLDisplay *
_eglLookupDisplay(EGLDisplay dpy)
{
- _EGLDisplay *d = (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, dpy);
- return d;
+ EGLuint key = (EGLuint) dpy;
+ if (!_eglGlobal.Displays)
+ return NULL;
+ return (_EGLDisplay *) _eglHashLookup(_eglGlobal.Displays, key);
+}
+
+
+void
+_eglSaveDisplay(_EGLDisplay *dpy)
+{
+ EGLuint key = _eglHashGenKey(_eglGlobal.Displays);
+ assert(dpy);
+ assert(!dpy->Handle);
+ dpy->Handle = (EGLDisplay) key;
+ assert(dpy->Handle);
+ _eglHashInsert(_eglGlobal.Displays, key, dpy);
}
@@ -61,11 +97,25 @@ _eglGetCurrentDisplay(void)
}
+/**
+ * Free all the data hanging of an _EGLDisplay object, but not
+ * the object itself.
+ */
void
_eglCleanupDisplay(_EGLDisplay *disp)
{
- /* XXX incomplete */
+ EGLint i;
+
+ for (i = 0; i < disp->NumConfigs; i++) {
+ free(disp->Configs[i]);
+ }
free(disp->Configs);
- free(disp->Name);
- /* driver deletes _EGLDisplay */
+ disp->Configs = NULL;
+
+ /* XXX incomplete */
+
+ free((void *) disp->DriverName);
+ disp->DriverName = NULL;
+
+ /* driver deletes the _EGLDisplay object */
}
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 1a03fdd4ad9..ff623ee1c66 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -1,22 +1,31 @@
#ifndef EGLDISPLAY_INCLUDED
#define EGLDISPLAY_INCLUDED
+#ifdef _EGL_PLATFORM_X
+#include <X11/Xlib.h>
+#endif
#include "egltypedefs.h"
struct _egl_display
{
+ EGLNativeDisplayType NativeDisplay;
EGLDisplay Handle;
- char *Name;
+ const char *DriverName;
+ const char *DriverArgs;
_EGLDriver *Driver;
EGLint NumScreens;
_EGLScreen **Screens; /* array [NumScreens] */
EGLint NumConfigs;
- _EGLConfig *Configs; /* array [NumConfigs] */
+ _EGLConfig **Configs; /* array [NumConfigs] of ptr to _EGLConfig */
+
+#ifdef _EGL_PLATFORM_X
+ Display *Xdpy;
+#endif
};
@@ -24,10 +33,18 @@ extern _EGLDisplay *
_eglNewDisplay(NativeDisplayType displayName);
+EGLDisplay
+_eglGetDisplayHandle(_EGLDisplay *display);
+
+
extern _EGLDisplay *
_eglLookupDisplay(EGLDisplay dpy);
+extern void
+_eglSaveDisplay(_EGLDisplay *dpy);
+
+
extern _EGLDisplay *
_eglGetCurrentDisplay(void);
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
index bda06dd827d..43b1f519034 100644
--- a/src/egl/main/egldriver.c
+++ b/src/egl/main/egldriver.c
@@ -1,112 +1,277 @@
+/**
+ * Functions for choosing and opening/loading device drivers.
+ */
+
+
#include <assert.h>
-#include <dlfcn.h>
-#include <stdio.h>
#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "eglconfig.h"
#include "eglcontext.h"
+#include "egldefines.h"
#include "egldisplay.h"
#include "egldriver.h"
#include "eglglobals.h"
#include "egllog.h"
+#include "eglmisc.h"
#include "eglmode.h"
#include "eglscreen.h"
+#include "eglstring.h"
#include "eglsurface.h"
+#if defined(_EGL_PLATFORM_X)
+#include <dlfcn.h>
+#include "eglx.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
+ static const char *SysFS = NULL;
+ 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
+ }
+
+#elif defined(_EGL_PLATFORM_X)
+ static const char *DefaultDriverName = ":0";
+ static const char *SysFS = "/sys/class";
+
+ typedef void * lib_handle;
+
+ static void *
+ open_library(const char *filename)
+ {
+ return dlopen(filename, RTLD_LAZY);
+ }
+
+ static void
+ close_library(void *lib)
+ {
+ dlclose(lib);
+ }
+
+#endif
+
+/**
+ * Given a card number, use sysfs to determine the DRI driver name.
+ */
+const char *
+_eglChooseDRMDriver(int card)
+{
+#if 0
+ return _eglstrdup("libEGLdri");
+#else
+ char path[2000], driverName[2000];
+ FILE *f;
+ int length;
+
+ snprintf(path, sizeof(path), "%s/drm/card%d/dri_library_name", SysFS, card);
+
+ f = fopen(path, "r");
+ if (!f)
+ return NULL;
-const char *DefaultDriverName = "demodriver";
+ fgets(driverName, sizeof(driverName), f);
+ fclose(f);
+ if ((length = strlen(driverName)) > 1) {
+ /* remove the trailing newline from sysfs */
+ driverName[length - 1] = '\0';
+ strncat(driverName, "_dri", sizeof(driverName));
+ return _eglstrdup(driverName);
+ }
+ else {
+ return NULL;
+ }
+#endif
+}
/**
- * Choose and open/init the hardware driver for the given EGLDisplay.
- * Previously, the EGLDisplay was created with _eglNewDisplay() where
- * we recorded the user's NativeDisplayType parameter.
+ * XXX this function is totally subject change!!!
+ *
+ *
+ * Determine/return the name of the driver to use for the given _EGLDisplay.
*
- * Now we'll use the NativeDisplayType value.
+ * Try to be clever and determine if nativeDisplay is an Xlib Display
+ * ptr or a string (naming a driver or screen number, etc).
*
- * Currently, the native display value is treated as a string.
* If the first character is ':' we interpret it as a screen or card index
* number (i.e. ":0" or ":1", etc)
* Else if the first character is '!' we interpret it as specific driver name
* (i.e. "!r200" or "!i830".
+ *
+ * Whatever follows ':' is copied and put into dpy->DriverArgs.
+ *
+ * The caller may free() the returned string.
*/
-_EGLDriver *
-_eglChooseDriver(EGLDisplay display)
+const char *
+_eglChooseDriver(_EGLDisplay *dpy)
{
- _EGLDisplay *dpy = _eglLookupDisplay(display);
- _EGLDriver *drv;
- const char *driverName = DefaultDriverName;
- const char *name;
+ /* Under Windows, the NativeDisplay is an HDC handle, therefore */
+ /* it can't be interpreted as a string or a pointer. */
+#if defined(_EGL_PLATFORM_WINDOWS)
+ const char *displayString = NULL;
+#else
+ const char *displayString = (const char *) dpy->NativeDisplay;
+#endif
+ const char *driverName = NULL;
- assert(dpy);
+ (void) DefaultDriverName;
- name = dpy->Name;
- if (!name) {
- /* use default */
+#if defined(_EGL_PLATFORM_X)
+ /* First, if the EGL_DRIVER env var is set, use that */
+ driverName = getenv("EGL_DRIVER");
+ if (driverName)
+ return _eglstrdup(driverName);
+#endif
+
+#if 0
+ if (!displayString) {
+ /* choose a default */
+ displayString = DefaultDriverName;
}
- else if (name[0] == ':' && (name[1] >= '0' && name[1] <= '9') && !name[2]) {
- /* XXX probe hardware here to determine which driver to open */
- driverName = "libEGLdri";
+#endif
+ /* extract default DriverArgs = whatever follows ':' */
+ if (displayString &&
+ (displayString[0] == '!' ||
+ displayString[0] == ':')) {
+ const char *args = strchr(displayString, ':');
+ if (args)
+ dpy->DriverArgs = _eglstrdup(args + 1);
}
- else if (name[0] == '!') {
- /* use specified driver name */
- driverName = name + 1;
+
+ /* determine driver name now */
+ if (displayString && displayString[0] == ':' &&
+ (displayString[1] >= '0' && displayString[1] <= '9') &&
+ !displayString[2]) {
+ int card = atoi(displayString + 1);
+ driverName = _eglChooseDRMDriver(card);
}
- else {
- /* Maybe display was returned by XOpenDisplay? */
- _eglLog(_EGL_FATAL, "eglChooseDriver() bad name");
+ else if (displayString && displayString[0] == '!') {
+ /* use user-specified driver name */
+ driverName = _eglstrdup(displayString + 1);
+ /* truncate driverName at ':' if present */
+ {
+ char *args = strchr(driverName, ':');
+ if (args) {
+ *args = 0;
+ }
+ }
+ }
+ else
+ {
+ /* NativeDisplay is not a string! */
+#if defined(_EGL_PLATFORM_X)
+ driverName = _xeglChooseDriver(dpy);
+#else
+ driverName = DefaultDriverName;
+#endif
}
- _eglLog(_EGL_INFO, "eglChooseDriver() choosing %s", driverName);
-
- drv = _eglOpenDriver(dpy, driverName);
- dpy->Driver = drv;
-
- return drv;
+ return driverName;
}
/**
* Open/load the named driver and call its bootstrap function: _eglMain().
+ * By the time this function is called, the dpy->DriverName should have
+ * been determined.
+ *
* \return new _EGLDriver object.
*/
_EGLDriver *
-_eglOpenDriver(_EGLDisplay *dpy, const char *driverName)
+_eglOpenDriver(_EGLDisplay *dpy, const char *driverName, const char *args)
{
_EGLDriver *drv;
_EGLMain_t mainFunc;
- void *lib;
+ lib_handle lib;
char driverFilename[1000];
+ assert(driverName);
+
+#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 */
+ sprintf(driverFilename, "%s.dll", driverName);
+ _eglLog(_EGL_DEBUG, "dlopen(%s)", driverFilename);
+ lib = open_library(driverFilename);
+ if (!lib) {
+ _eglLog(_EGL_WARNING, "Could not open %s",
+ driverFilename);
+ return NULL;
+ }
+ mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
+#endif
+#elif defined(_EGL_PLATFORM_X)
/* XXX also prepend a directory path??? */
sprintf(driverFilename, "%s.so", driverName);
-
_eglLog(_EGL_DEBUG, "dlopen(%s)", driverFilename);
- lib = dlopen(driverFilename, RTLD_NOW);
+ lib = open_library(driverFilename);
if (!lib) {
_eglLog(_EGL_WARNING, "Could not open %s (%s)",
driverFilename, dlerror());
return NULL;
}
-
mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
+#endif
+
if (!mainFunc) {
_eglLog(_EGL_WARNING, "_eglMain not found in %s", driverFilename);
- dlclose(lib);
+ close_library(lib);
return NULL;
}
- drv = mainFunc(dpy);
+ drv = mainFunc(dpy, args);
if (!drv) {
- dlclose(lib);
+ close_library(lib);
return NULL;
}
+
/* with a recurvise open you want the inner most handle */
- if (!drv->LibHandle)
+ if (!drv->LibHandle) {
drv->LibHandle = lib;
- else
- dlclose(lib);
+ }
+ else {
+ close_library(lib);
+ }
+
+ /* update the global notion of supported APIs */
+ _eglGlobal.ClientAPIsMask |= drv->ClientAPIsMask;
+
+ _eglSaveDriver(drv);
- drv->Display = dpy;
return drv;
}
@@ -117,19 +282,31 @@ _eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy)
void *handle = drv->LibHandle;
EGLBoolean b;
- _eglLog(_EGL_INFO, "Closing driver");
+ _eglLog(_EGL_DEBUG, "Closing %s", drv->Name);
/*
* XXX check for currently bound context/surfaces and delete them?
*/
b = drv->API.Terminate(drv, dpy);
- dlclose(handle);
+
+ close_library(handle);
+
return b;
}
/**
+ * Save the given driver pointer in the list of all known drivers.
+ */
+void
+_eglSaveDriver(_EGLDriver *drv)
+{
+ _eglGlobal.Drivers[ _eglGlobal.NumDrivers++ ] = drv;
+}
+
+
+/**
* Given a display handle, return the _EGLDriver for that display.
*/
_EGLDriver *
@@ -201,72 +378,48 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
}
+
/**
- * Examine the individual extension enable/disable flags and recompute
- * the driver's Extensions string.
+ * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc)
+ * are supported on the system by looking for standard library names.
*/
-static void
-_eglUpdateExtensionsString(_EGLDriver *drv)
-{
- drv->Extensions.String[0] = 0;
-
- if (drv->Extensions.MESA_screen_surface)
- strcat(drv->Extensions.String, "EGL_MESA_screen_surface ");
- if (drv->Extensions.MESA_copy_context)
- strcat(drv->Extensions.String, "EGL_MESA_copy_context ");
- assert(strlen(drv->Extensions.String) < MAX_EXTENSIONS_LEN);
-}
-
-
-
-const char *
-_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name)
+EGLint
+_eglFindAPIs(void)
{
- (void) drv;
- (void) dpy;
- switch (name) {
- case EGL_VENDOR:
- return "Mesa Project";
- case EGL_VERSION:
- return "1.0";
- case EGL_EXTENSIONS:
- _eglUpdateExtensionsString(drv);
- return drv->Extensions.String;
-#ifdef EGL_VERSION_1_2
- case EGL_CLIENT_APIS:
- /* XXX need to initialize somewhere */
- return drv->ClientAPIs;
+ EGLint mask = 0x0;
+ lib_handle lib;
+#if defined(_EGL_PLATFORM_WINDOWS)
+ /* XXX not sure about these names */
+ const char *es1_libname = "libGLESv1_CM.dll";
+ const char *es2_libname = "libGLESv2.dll";
+ const char *gl_libname = "OpenGL32.dll";
+ const char *vg_libname = "libOpenVG.dll";
+#elif defined(_EGL_PLATFORM_X)
+ const char *es1_libname = "libGLESv1_CM.so";
+ const char *es2_libname = "libGLESv2.so";
+ const char *gl_libname = "libGL.so";
+ const char *vg_libname = "libOpenVG.so";
#endif
- default:
- _eglError(EGL_BAD_PARAMETER, "eglQueryString");
- return NULL;
- }
-}
+ if ((lib = open_library(es1_libname))) {
+ close_library(lib);
+ mask |= EGL_OPENGL_ES_BIT;
+ }
-EGLBoolean
-_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy)
-{
- /* just a placeholder */
- (void) drv;
- (void) dpy;
- return EGL_TRUE;
-}
+ if ((lib = open_library(es2_libname))) {
+ close_library(lib);
+ mask |= EGL_OPENGL_ES2_BIT;
+ }
+ if ((lib = open_library(gl_libname))) {
+ close_library(lib);
+ mask |= EGL_OPENGL_BIT;
+ }
-EGLBoolean
-_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine)
-{
- /* just a placeholder */
- (void) drv;
- (void) dpy;
- switch (engine) {
- case EGL_CORE_NATIVE_ENGINE:
- break;
- default:
- _eglError(EGL_BAD_PARAMETER, "eglWaitNative(engine)");
- return EGL_FALSE;
+ if ((lib = open_library(vg_libname))) {
+ close_library(lib);
+ mask |= EGL_OPENVG_BIT;
}
- return EGL_TRUE;
+ return mask;
}
diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h
index 88526e973d1..4066c6ec1df 100644
--- a/src/egl/main/egldriver.h
+++ b/src/egl/main/egldriver.h
@@ -4,9 +4,7 @@
#include "egltypedefs.h"
#include "eglapi.h"
-
-/* should probably use a dynamic-length string, but this will do */
-#define MAX_EXTENSIONS_LEN 1000
+#include "egldefines.h"
/**
@@ -17,7 +15,7 @@ struct _egl_extensions
EGLBoolean MESA_screen_surface;
EGLBoolean MESA_copy_context;
- char String[MAX_EXTENSIONS_LEN];
+ char String[_EGL_MAX_EXTENSIONS_LEN];
};
@@ -26,37 +24,48 @@ struct _egl_extensions
*/
struct _egl_driver
{
- EGLBoolean Initialized; /* set by driver after initialized */
+ EGLBoolean Initialized; /**< set by driver after initialized */
+
+ void *LibHandle; /**< dlopen handle */
- void *LibHandle; /* dlopen handle */
+ const char *Name; /**< name of this driver */
- _EGLDisplay *Display;
+ int APImajor, APIminor; /**< as returned by eglInitialize() */
+ char Version[1000]; /**< initialized from APImajor/minor, Name */
- int ABIversion;
- int APImajor, APIminor; /* returned through eglInitialize */
- const char *ClientAPIs;
+ /** Bitmask of supported APIs (EGL_xx_BIT) set by the driver during init */
+ EGLint ClientAPIsMask;
- _EGLAPI API;
+ _EGLAPI API; /**< EGL API dispatch table */
_EGLExtensions Extensions;
+
+ int LargestPbuffer;
};
-extern _EGLDriver *_eglMain(_EGLDisplay *dpy);
+extern _EGLDriver *_eglMain(_EGLDisplay *dpy, const char *args);
-extern _EGLDriver *
-_eglChooseDriver(EGLDisplay dpy);
+extern const char *
+_eglChooseDRMDriver(int card);
+
+extern const char *
+_eglChooseDriver(_EGLDisplay *dpy);
extern _EGLDriver *
-_eglOpenDriver(_EGLDisplay *dpy, const char *driverName);
+_eglOpenDriver(_EGLDisplay *dpy, const char *driverName, const char *args);
extern EGLBoolean
_eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy);
+extern void
+_eglSaveDriver(_EGLDriver *drv);
+
+
extern _EGLDriver *
_eglLookupDriver(EGLDisplay d);
@@ -65,17 +74,8 @@ extern void
_eglInitDriverFallbacks(_EGLDriver *drv);
-extern const char *
-_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name);
-
-
-extern EGLBoolean
-_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy);
-
-
-extern EGLBoolean
-_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine);
-
+extern EGLint
+_eglFindAPIs(void);
#endif /* EGLDRIVER_INCLUDED */
diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c
index 608311d7494..b770e55dbdf 100644
--- a/src/egl/main/eglglobals.c
+++ b/src/egl/main/eglglobals.c
@@ -2,9 +2,10 @@
#include <stdlib.h>
#include "eglglobals.h"
-
-struct _egl_global _eglGlobal = { .Initialized = EGL_FALSE };
-
+struct _egl_global _eglGlobal =
+{
+ EGL_FALSE
+};
/**
* Init the fields in the _eglGlobal struct
@@ -15,13 +16,11 @@ _eglInitGlobals(void)
{
if (!_eglGlobal.Initialized) {
_eglGlobal.Displays = _eglNewHashTable();
- _eglGlobal.Contexts = _eglNewHashTable();
_eglGlobal.Surfaces = _eglNewHashTable();
_eglGlobal.FreeScreenHandle = 1;
_eglGlobal.Initialized = EGL_TRUE;
- _eglGlobal.OpenGLESAPISupported = EGL_TRUE;
- _eglGlobal.OpenVGAPISupported = EGL_FALSE;
+ _eglGlobal.ClientAPIsMask = 0x0;
/* XXX temporary */
_eglGlobal.ThreadInfo = _eglNewThreadInfo();
@@ -37,7 +36,6 @@ _eglDestroyGlobals(void)
{
/* XXX TODO walk over table entries, deleting each */
_eglDeleteHashTable(_eglGlobal.Displays);
- _eglDeleteHashTable(_eglGlobal.Contexts);
_eglDeleteHashTable(_eglGlobal.Surfaces);
}
@@ -52,7 +50,7 @@ _eglNewThreadInfo(void)
if (t) {
t->CurrentContext = EGL_NO_CONTEXT;
t->LastError = EGL_SUCCESS;
- t->CurrentAPI = EGL_NONE;
+ t->CurrentAPI = EGL_OPENGL_ES_API; /* default, per EGL spec */
}
return t;
}
diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h
index c16baa2d6bd..14d8ea487af 100644
--- a/src/egl/main/eglglobals.h
+++ b/src/egl/main/eglglobals.h
@@ -24,17 +24,20 @@ struct _egl_global
EGLBoolean Initialized;
_EGLHashtable *Displays;
- _EGLHashtable *Contexts;
_EGLHashtable *Surfaces;
EGLScreenMESA FreeScreenHandle;
- /* XXX these may be temporary */
- EGLBoolean OpenGLESAPISupported;
- EGLBoolean OpenVGAPISupported;
+ /* bitmaks of supported APIs (supported by _some_ driver) */
+ EGLint ClientAPIsMask;
+
+ char ClientAPIs[1000]; /**< updated by eglQueryString */
/* XXX temporary - should be thread-specific data (TSD) */
_EGLThreadInfo *ThreadInfo;
+
+ EGLint NumDrivers;
+ _EGLDriver *Drivers[10];
};
diff --git a/src/egl/main/egllog.c b/src/egl/main/egllog.c
index dc1daaa996a..1d7a0a388c6 100644
--- a/src/egl/main/egllog.c
+++ b/src/egl/main/egllog.c
@@ -1,5 +1,7 @@
/**
* Logging facility for debug/info messages.
+ * _EGL_FATAL messages are printed to stderr
+ * The EGL_LOG_LEVEL var controls the output of other warning/info/debug msgs.
*/
@@ -10,37 +12,41 @@
#include "egllog.h"
#define MAXSTRING 1000
-#define FALLBACK_LOG_LEVEL _EGL_DEBUG
-#define FALLBACK_LOG_LEVEL_STR "debug"
+#define FALLBACK_LOG_LEVEL _EGL_WARNING
+#define FALLBACK_LOG_LEVEL_STR "warning"
static EGLint ReportingLevel = -1;
static void
-log_level_initialize (void)
+log_level_initialize(void)
{
- char *log_env = getenv ("EGL_LOG_LEVEL");
+#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) {
+ else if (strcasecmp(log_env, "fatal") == 0) {
ReportingLevel = _EGL_FATAL;
}
- else if (strcasecmp (log_env, "warning") == 0) {
+ else if (strcasecmp(log_env, "warning") == 0) {
ReportingLevel = _EGL_WARNING;
}
- else if (strcasecmp (log_env, "info") == 0) {
+ else if (strcasecmp(log_env, "info") == 0) {
ReportingLevel = _EGL_INFO;
}
- else if (strcasecmp (log_env, "debug") == 0) {
+ else if (strcasecmp(log_env, "debug") == 0) {
ReportingLevel = _EGL_DEBUG;
}
else {
- fprintf (stderr, "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);
+ fprintf(stderr, "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;
}
}
@@ -59,7 +65,7 @@ _eglLog(EGLint level, const char *fmtStr, ...)
static int log_level_initialized = 0;
if (!log_level_initialized) {
- log_level_initialize ();
+ log_level_initialize();
log_level_initialized = 1;
}
@@ -85,7 +91,7 @@ _eglLog(EGLint level, const char *fmtStr, ...)
vsnprintf(msg, MAXSTRING, fmtStr, args);
va_end(args);
- fprintf(stderr, "EGL %s: %s\n", levelStr, msg);
+ fprintf(stderr, "libEGL %s: %s\n", levelStr, msg);
if (level == _EGL_FATAL) {
exit(1); /* or abort()? */
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
new file mode 100644
index 00000000000..b5bdc3ea4bf
--- /dev/null
+++ b/src/egl/main/eglmisc.c
@@ -0,0 +1,129 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * Small/misc EGL functions
+ */
+
+
+#include <assert.h>
+#include <string.h>
+#include "eglglobals.h"
+#include "eglmisc.h"
+
+
+/**
+ * Examine the individual extension enable/disable flags and recompute
+ * the driver's Extensions string.
+ */
+static void
+_eglUpdateExtensionsString(_EGLDriver *drv)
+{
+ drv->Extensions.String[0] = 0;
+
+ if (drv->Extensions.MESA_screen_surface)
+ strcat(drv->Extensions.String, "EGL_MESA_screen_surface ");
+ if (drv->Extensions.MESA_copy_context)
+ strcat(drv->Extensions.String, "EGL_MESA_copy_context ");
+ assert(strlen(drv->Extensions.String) < _EGL_MAX_EXTENSIONS_LEN);
+}
+
+
+static void
+_eglUpdateAPIsString(_EGLDriver *drv)
+{
+ _eglGlobal.ClientAPIs[0] = 0;
+
+ if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_BIT)
+ strcat(_eglGlobal.ClientAPIs, "OpenGL ");
+
+ if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_ES_BIT)
+ strcat(_eglGlobal.ClientAPIs, "OpenGL_ES ");
+
+ if (_eglGlobal.ClientAPIsMask & EGL_OPENGL_ES2_BIT)
+ strcat(_eglGlobal.ClientAPIs, "OpenGL_ES2 ");
+
+ if (_eglGlobal.ClientAPIsMask & EGL_OPENVG_BIT)
+ strcat(_eglGlobal.ClientAPIs, "OpenVG ");
+
+ assert(strlen(_eglGlobal.ClientAPIs) < sizeof(_eglGlobal.ClientAPIs));
+}
+
+
+
+const char *
+_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name)
+{
+ (void) drv;
+ (void) dpy;
+ switch (name) {
+ case EGL_VENDOR:
+ return _EGL_VENDOR_STRING;
+ case EGL_VERSION:
+ return drv->Version;
+ case EGL_EXTENSIONS:
+ _eglUpdateExtensionsString(drv);
+ return drv->Extensions.String;
+#ifdef EGL_VERSION_1_2
+ case EGL_CLIENT_APIS:
+ _eglUpdateAPIsString(drv);
+ return _eglGlobal.ClientAPIs;
+#endif
+ default:
+ _eglError(EGL_BAD_PARAMETER, "eglQueryString");
+ return NULL;
+ }
+}
+
+
+EGLBoolean
+_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy)
+{
+ /* just a placeholder */
+ (void) drv;
+ (void) dpy;
+ return EGL_TRUE;
+}
+
+
+EGLBoolean
+_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine)
+{
+ /* just a placeholder */
+ (void) drv;
+ (void) dpy;
+ switch (engine) {
+ case EGL_CORE_NATIVE_ENGINE:
+ break;
+ default:
+ _eglError(EGL_BAD_PARAMETER, "eglWaitNative(engine)");
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
+}
diff --git a/src/egl/main/eglmisc.h b/src/egl/main/eglmisc.h
new file mode 100644
index 00000000000..4e2a40ea991
--- /dev/null
+++ b/src/egl/main/eglmisc.h
@@ -0,0 +1,47 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+#ifndef EGLMISC_INCLUDED
+#define EGLMISC_INCLUDED
+
+#include "egldriver.h"
+
+
+extern const char *
+_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name);
+
+
+extern EGLBoolean
+_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy);
+
+
+extern EGLBoolean
+_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine);
+
+
+#endif /* EGLMISC_INCLUDED */
diff --git a/src/egl/main/eglmode.h b/src/egl/main/eglmode.h
index e70da857595..52d4875676d 100644
--- a/src/egl/main/eglmode.h
+++ b/src/egl/main/eglmode.h
@@ -4,6 +4,9 @@
#include "egltypedefs.h"
+#define EGL_NO_MODE_MESA 0
+
+
/**
* Data structure which corresponds to an EGLModeMESA.
*/
diff --git a/src/egl/main/eglstring.c b/src/egl/main/eglstring.c
new file mode 100644
index 00000000000..ba7406158c4
--- /dev/null
+++ b/src/egl/main/eglstring.c
@@ -0,0 +1,24 @@
+/**
+ * String utils.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include "eglstring.h"
+
+
+char *
+_eglstrdup(const char *s)
+{
+ if (s) {
+ int l = strlen(s);
+ char *s2 = malloc(l + 1);
+ if (s2)
+ strcpy(s2, s);
+ return s2;
+ }
+ return NULL;
+}
+
+
+
diff --git a/src/egl/main/eglstring.h b/src/egl/main/eglstring.h
new file mode 100644
index 00000000000..10468636e87
--- /dev/null
+++ b/src/egl/main/eglstring.h
@@ -0,0 +1,9 @@
+#ifndef EGLSTRING_INCLUDED
+#define EGLSTRING_INCLUDED
+
+
+extern char *
+_eglstrdup(const char *s);
+
+
+#endif /* EGLSTRING_INCLUDED */
diff --git a/src/egl/main/eglsurface.c b/src/egl/main/eglsurface.c
index 874f318e966..6905acac50b 100644
--- a/src/egl/main/eglsurface.c
+++ b/src/egl/main/eglsurface.c
@@ -8,6 +8,7 @@
#include <string.h>
#include "eglcontext.h"
#include "eglconfig.h"
+#include "egldriver.h"
#include "eglglobals.h"
#include "eglhash.h"
#include "egllog.h"
@@ -60,6 +61,12 @@ _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
return EGL_FALSE;
}
+ if ((GET_CONFIG_ATTRIB(conf, EGL_SURFACE_TYPE) & type) == 0) {
+ /* The config can't be used to create a surface of this type */
+ _eglError(EGL_BAD_CONFIG, func);
+ return EGL_FALSE;
+ }
+
/*
* Parse attribute list. Different kinds of surfaces support different
* attributes.
@@ -175,7 +182,7 @@ _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
}
}
- if (width <= 0 || height <= 0) {
+ if (width < 0 || height < 0) {
_eglError(EGL_BAD_ATTRIBUTE, func);
return EGL_FALSE;
}
@@ -207,25 +214,47 @@ _eglInitSurface(_EGLDriver *drv, EGLDisplay dpy,
void
_eglSaveSurface(_EGLSurface *surf)
{
+ EGLuint key = _eglHashGenKey(_eglGlobal.Surfaces);
assert(surf);
assert(!surf->Handle);
- surf->Handle = _eglHashGenKey(_eglGlobal.Contexts);
+ surf->Handle = (EGLSurface) key;
assert(surf->Handle);
- _eglHashInsert(_eglGlobal.Surfaces, surf->Handle, surf);
+ _eglHashInsert(_eglGlobal.Surfaces, key, surf);
}
void
_eglRemoveSurface(_EGLSurface *surf)
{
- _eglHashRemove(_eglGlobal.Surfaces, surf->Handle);
+ _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surf->Handle);
+}
+
+
+
+/**
+ * Return the public handle for an internal _EGLSurface.
+ * This is the inverse of _eglLookupSurface().
+ */
+EGLSurface
+_eglGetSurfaceHandle(_EGLSurface *surface)
+{
+ if (surface)
+ return surface->Handle;
+ else
+ return EGL_NO_SURFACE;
}
+/**
+ * Return the private _EGLSurface which corresponds to a public EGLSurface
+ * handle.
+ * This is the inverse of _eglGetSurfaceHandle().
+ */
_EGLSurface *
_eglLookupSurface(EGLSurface surf)
{
- _EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces, surf);
+ _EGLSurface *c = (_EGLSurface *) _eglHashLookup(_eglGlobal.Surfaces,
+ (EGLuint) surf);
return c;
}
@@ -254,12 +283,7 @@ _eglSwapBuffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
/* Basically just do error checking here. Drivers have to do the
* actual buffer swap.
*/
- _EGLContext *context = _eglGetCurrentContext();
_EGLSurface *surface = _eglLookupSurface(draw);
- if (context && context->DrawSurface != surface) {
- _eglError(EGL_BAD_SURFACE, "eglSwapBuffers");
- return EGL_FALSE;
- }
if (surface == NULL) {
_eglError(EGL_BAD_SURFACE, "eglSwapBuffers");
return EGL_FALSE;
@@ -297,7 +321,9 @@ _eglQuerySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
case EGL_CONFIG_ID:
*value = GET_CONFIG_ATTRIB(surface->Config, EGL_CONFIG_ID);
return EGL_TRUE;
- /*XXX case EGL_LARGEST_PBUFFER:*/
+ case EGL_LARGEST_PBUFFER:
+ *value = drv->LargestPbuffer;
+ return EGL_TRUE;
case EGL_SURFACE_TYPE:
*value = surface->Type;
return EGL_TRUE;
@@ -439,7 +465,7 @@ _eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
{
_EGLSurface *surf = _eglLookupSurface(surface);
if (surf) {
- _eglHashRemove(_eglGlobal.Surfaces, surface);
+ _eglHashRemove(_eglGlobal.Surfaces, (EGLuint) surface);
if (surf->IsBound) {
surf->DeletePending = EGL_TRUE;
}
@@ -459,7 +485,8 @@ _eglDestroySurface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
* Default fallback routine - drivers might override this.
*/
EGLBoolean
-_eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, EGLint attribute, EGLint value)
+_eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
+ EGLint attribute, EGLint value)
{
_EGLSurface *surface = _eglLookupSurface(surf);
@@ -481,18 +508,67 @@ _eglSurfaceAttrib(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf, EGLint attri
EGLBoolean
-_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+_eglBindTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
+ EGLint buffer)
{
- /* XXX unfinished */
- return EGL_FALSE;
+ /* Just do basic error checking and return success/fail.
+ * Drivers must implement the real stuff.
+ */
+ _EGLSurface *surface = _eglLookupSurface(surf);
+
+ if (!surface || surface->Type != EGL_PBUFFER_BIT) {
+ _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
+ return EGL_FALSE;
+ }
+
+ if (surface->TextureFormat == EGL_NO_TEXTURE) {
+ _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+ return EGL_FALSE;
+ }
+
+ if (buffer != EGL_BACK_BUFFER) {
+ _eglError(EGL_BAD_PARAMETER, "eglBindTexImage");
+ return EGL_FALSE;
+ }
+
+ surface->BoundToTexture = EGL_TRUE;
+
+ return EGL_TRUE;
}
EGLBoolean
-_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+_eglReleaseTexImage(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surf,
+ EGLint buffer)
{
- /* XXX unfinished */
- return EGL_FALSE;
+ /* Just do basic error checking and return success/fail.
+ * Drivers must implement the real stuff.
+ */
+ _EGLSurface *surface = _eglLookupSurface(surf);
+
+ if (!surface || surface->Type != EGL_PBUFFER_BIT) {
+ _eglError(EGL_BAD_SURFACE, "eglBindTexImage");
+ return EGL_FALSE;
+ }
+
+ if (surface->TextureFormat == EGL_NO_TEXTURE) {
+ _eglError(EGL_BAD_MATCH, "eglBindTexImage");
+ return EGL_FALSE;
+ }
+
+ if (buffer != EGL_BACK_BUFFER) {
+ _eglError(EGL_BAD_PARAMETER, "eglReleaseTexImage");
+ return EGL_FALSE;
+ }
+
+ if (!surface->BoundToTexture) {
+ _eglError(EGL_BAD_SURFACE, "eglReleaseTexImage");
+ return EGL_FALSE;
+ }
+
+ surface->BoundToTexture = EGL_FALSE;
+
+ return EGL_TRUE;
}
diff --git a/src/egl/main/eglsurface.h b/src/egl/main/eglsurface.h
index 79abeca0b2a..50f965b5cb7 100644
--- a/src/egl/main/eglsurface.h
+++ b/src/egl/main/eglsurface.h
@@ -16,6 +16,7 @@ struct _egl_surface
/* May need reference counting here */
EGLBoolean IsBound;
EGLBoolean DeletePending;
+ EGLBoolean BoundToTexture;
EGLint Type; /* one of EGL_WINDOW_BIT, EGL_PIXMAP_BIT or EGL_PBUFFER_BIT */
EGLint Width, Height;
@@ -51,6 +52,10 @@ extern void
_eglRemoveSurface(_EGLSurface *surf);
+extern EGLSurface
+_eglGetSurfaceHandle(_EGLSurface *surface);
+
+
extern _EGLSurface *
_eglLookupSurface(EGLSurface surf);
diff --git a/src/egl/main/egltypedefs.h b/src/egl/main/egltypedefs.h
index fa8cb496f8d..9fbc55352c2 100644
--- a/src/egl/main/egltypedefs.h
+++ b/src/egl/main/egltypedefs.h
@@ -1,8 +1,10 @@
#ifndef EGLTYPEDEFS_INCLUDED
#define EGLTYPEDEFS_INCLUDED
+#define EGL_EGLEXT_PROTOTYPES
-#include <GLES/egl.h>
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
typedef struct _egl_api _EGLAPI;
@@ -26,9 +28,7 @@ typedef struct _egl_surface _EGLSurface;
typedef struct _egl_thread_info _EGLThreadInfo;
-typedef void (*_EGLProc)();
-
-typedef _EGLDriver *(*_EGLMain_t)(_EGLDisplay *dpy);
+typedef _EGLDriver *(*_EGLMain_t)(_EGLDisplay *dpy, const char *args);
#endif /* EGLTYPEDEFS_INCLUDED */
diff --git a/src/egl/main/eglx.c b/src/egl/main/eglx.c
new file mode 100644
index 00000000000..50acc3a24f9
--- /dev/null
+++ b/src/egl/main/eglx.c
@@ -0,0 +1,100 @@
+/**************************************************************************
+ *
+ * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+
+/**
+ * X-specific EGL code.
+ *
+ * Any glue code needed to make EGL work with X is placed in this file.
+ */
+
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/Xlib.h>
+
+#include "egldriver.h"
+#include "egllog.h"
+#include "eglstring.h"
+#include "eglx.h"
+
+
+static const char *DefaultGLXDriver = "egl_glx";
+static const char *DefaultSoftDriver = "egl_softpipe";
+
+
+/**
+ * Given an X Display ptr (at dpy->Xdpy) try to determine the appropriate
+ * device driver. Return its name.
+ *
+ * This boils down to whether to use the egl_glx.so driver which will
+ * load a DRI driver or the egl_softpipe.so driver that'll do software
+ * rendering on Xlib.
+ */
+const char *
+_xeglChooseDriver(_EGLDisplay *dpy)
+{
+#ifdef _EGL_PLATFORM_X
+ _XPrivDisplay xdpy;
+ int screen;
+ const char *driverName;
+
+ assert(dpy);
+
+ if (!dpy->Xdpy) {
+ dpy->Xdpy = XOpenDisplay(NULL);
+ if (!dpy->Xdpy) {
+ /* can't open X display -> can't use X-based driver */
+ return NULL;
+ }
+ }
+ xdpy = (_XPrivDisplay) dpy->Xdpy;
+
+ assert(dpy->Xdpy);
+
+ screen = DefaultScreen(dpy->Xdpy);
+
+ /* See if we can choose a DRI/DRM driver */
+ driverName = _eglChooseDRMDriver(screen);
+ if (driverName) {
+ free((void *) driverName);
+ driverName = _eglstrdup(DefaultGLXDriver);
+ }
+ else {
+ driverName = _eglstrdup(DefaultSoftDriver);
+ }
+
+ _eglLog(_EGL_DEBUG, "_xeglChooseDriver: %s", driverName);
+
+ return driverName;
+#else
+ return NULL;
+#endif
+}
+
+
diff --git a/src/egl/main/eglx.h b/src/egl/main/eglx.h
new file mode 100644
index 00000000000..4323d558381
--- /dev/null
+++ b/src/egl/main/eglx.h
@@ -0,0 +1,12 @@
+#ifndef EGLX_INCLUDED
+#define EGLX_INCLUDED
+
+
+#include "egldisplay.h"
+
+
+extern const char *
+_xeglChooseDriver(_EGLDisplay *dpy);
+
+
+#endif /* EGLX_INCLUDED */