summaryrefslogtreecommitdiffstats
path: root/src/egl
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl')
-rw-r--r--src/egl/drivers/dri2/Makefile6
-rw-r--r--src/egl/drivers/dri2/egl_dri2.c268
-rw-r--r--src/egl/drivers/glx/egl_glx.c16
-rw-r--r--src/egl/main/Makefile15
-rw-r--r--src/egl/main/SConscript3
-rw-r--r--src/egl/main/eglapi.c102
-rw-r--r--src/egl/main/eglarray.c180
-rw-r--r--src/egl/main/eglarray.h57
-rw-r--r--src/egl/main/eglconfig.c66
-rw-r--r--src/egl/main/egldisplay.c74
-rw-r--r--src/egl/main/egldisplay.h33
-rw-r--r--src/egl/main/egldriver.c496
-rw-r--r--src/egl/main/egldriver.h22
-rw-r--r--src/egl/main/eglglobals.c2
-rw-r--r--src/egl/main/eglglobals.h4
-rw-r--r--src/egl/main/eglmisc.c1
-rw-r--r--src/egl/main/eglmode.c7
-rw-r--r--src/egl/main/eglscreen.c50
-rw-r--r--src/egl/main/egltypedefs.h2
19 files changed, 953 insertions, 451 deletions
diff --git a/src/egl/drivers/dri2/Makefile b/src/egl/drivers/dri2/Makefile
index 4e760aec4c8..8a3c9b6a0aa 100644
--- a/src/egl/drivers/dri2/Makefile
+++ b/src/egl/drivers/dri2/Makefile
@@ -11,8 +11,10 @@ EGL_INCLUDES = \
-I$(TOP)/src/egl/main \
-I$(TOP)/src/mapi \
-DDEFAULT_DRIVER_DIR=\"$(DRI_DRIVER_SEARCH_DIR)\" \
- $(EGL_DRI2_CFLAGS)
+ $(XCB_DRI2_CFLAGS) \
+ $(LIBUDEV_CFLAGS) \
+ $(LIBDRM_CFLAGS)
-EGL_LIBS = $(EGL_DRI2_LIBS)
+EGL_LIBS = $(XCB_DRI2_LIBS) $(LIBUDEV_LIBS) $(LIBDRM_LIBS)
include ../Makefile.template
diff --git a/src/egl/drivers/dri2/egl_dri2.c b/src/egl/drivers/dri2/egl_dri2.c
index aa384cb1172..c6d79a64e8a 100644
--- a/src/egl/drivers/dri2/egl_dri2.c
+++ b/src/egl/drivers/dri2/egl_dri2.c
@@ -40,6 +40,12 @@
#include <xcb/dri2.h>
#include <xcb/xfixes.h>
#include <X11/Xlib-xcb.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef HAVE_LIBUDEV
+#include <libudev.h>
+#endif
#include <glapi/glapi.h>
#include "eglconfig.h"
@@ -79,7 +85,6 @@ struct dri2_egl_display
char *driver_name;
__DRIdri2LoaderExtension loader_extension;
- __DRIimageLookupExtension image_lookup_extension;
const __DRIextension *extensions[3];
};
@@ -117,6 +122,10 @@ struct dri2_egl_image
_EGL_DRIVER_STANDARD_TYPECASTS(dri2_egl)
_EGL_DRIVER_TYPECAST(dri2_egl_image, _EGLImage, obj)
+static const __DRIuseInvalidateExtension use_invalidate = {
+ { __DRI_USE_INVALIDATE, 1 }
+};
+
EGLint dri2_to_egl_attribute_map[] = {
0,
EGL_BUFFER_SIZE, /* __DRI_ATTRIB_BUFFER_SIZE */
@@ -381,6 +390,11 @@ dri2_lookup_egl_image(__DRIcontext *context, void *image, void *data)
return dri2_img->dri_image;
}
+static const __DRIimageLookupExtension image_lookup_extension = {
+ { __DRI_IMAGE_LOOKUP, 1 },
+ dri2_lookup_egl_image
+};
+
static __DRIbuffer *
dri2_get_buffers_with_format(__DRIdrawable * driDrawable,
int *width, int *height,
@@ -620,7 +634,7 @@ dri2_add_configs_for_visuals(struct dri2_egl_display *dri2_dpy,
xcb_depth_next(&d);
}
- if (!disp->NumConfigs) {
+ if (!_eglGetArraySize(disp->Configs)) {
_eglLog(_EGL_WARNING, "DRI2: failed to create any config");
return EGL_FALSE;
}
@@ -690,27 +704,63 @@ dri2_load_driver(_EGLDisplay *disp)
return EGL_TRUE;
}
-
-/**
- * Called via eglInitialize(), GLX_drv->API.Initialize().
- */
static EGLBoolean
-dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
- EGLint *major, EGLint *minor)
+dri2_create_screen(_EGLDisplay *disp)
{
const __DRIextension **extensions;
struct dri2_egl_display *dri2_dpy;
unsigned int api_mask;
+ dri2_dpy = disp->DriverData;
+ dri2_dpy->dri_screen =
+ dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
+ &dri2_dpy->driver_configs, dri2_dpy);
+
+ if (dri2_dpy->dri_screen == NULL) {
+ _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
+ return EGL_FALSE;
+ }
+
+ extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
+ if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
+ goto cleanup_dri_screen;
+
+ if (dri2_dpy->dri2->base.version >= 2)
+ api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
+ else
+ api_mask = __DRI_API_OPENGL;
+
+ disp->ClientAPIsMask = 0;
+ if (api_mask & (1 <<__DRI_API_OPENGL))
+ disp->ClientAPIsMask |= EGL_OPENGL_BIT;
+ if (api_mask & (1 <<__DRI_API_GLES))
+ disp->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
+ if (api_mask & (1 << __DRI_API_GLES2))
+ disp->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
+
+ return EGL_TRUE;
+
+ cleanup_dri_screen:
+ dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
+
+ return EGL_FALSE;
+}
+
+static EGLBoolean
+dri2_initialize_x11(_EGLDriver *drv, _EGLDisplay *disp,
+ EGLint *major, EGLint *minor)
+{
+ struct dri2_egl_display *dri2_dpy;
+
dri2_dpy = malloc(sizeof *dri2_dpy);
if (!dri2_dpy)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
disp->DriverData = (void *) dri2_dpy;
- if (disp->NativeDisplay == NULL) {
+ if (disp->PlatformDisplay == NULL) {
dri2_dpy->conn = xcb_connect(0, 0);
} else {
- dri2_dpy->conn = XGetXCBConnection(disp->NativeDisplay);
+ dri2_dpy->conn = XGetXCBConnection((Display *) disp->PlatformDisplay);
}
if (xcb_connection_has_error(dri2_dpy->conn)) {
@@ -754,39 +804,12 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
dri2_dpy->loader_extension.getBuffersWithFormat = NULL;
}
- dri2_dpy->image_lookup_extension.base.name = __DRI_IMAGE_LOOKUP;
- dri2_dpy->image_lookup_extension.base.version = 1;
- dri2_dpy->image_lookup_extension.lookupEGLImage = dri2_lookup_egl_image;
-
dri2_dpy->extensions[0] = &dri2_dpy->loader_extension.base;
- dri2_dpy->extensions[1] = &dri2_dpy->image_lookup_extension.base;
+ dri2_dpy->extensions[1] = &image_lookup_extension.base;
dri2_dpy->extensions[2] = NULL;
- dri2_dpy->dri_screen =
- dri2_dpy->dri2->createNewScreen(0, dri2_dpy->fd, dri2_dpy->extensions,
- &dri2_dpy->driver_configs, dri2_dpy);
-
- if (dri2_dpy->dri_screen == NULL) {
- _eglLog(_EGL_WARNING, "DRI2: failed to create dri screen");
+ if (!dri2_create_screen(disp))
goto cleanup_fd;
- }
-
- extensions = dri2_dpy->core->getExtensions(dri2_dpy->dri_screen);
- if (!dri2_bind_extensions(dri2_dpy, dri2_core_extensions, extensions))
- goto cleanup_dri_screen;
-
- if (dri2_dpy->dri2->base.version >= 2)
- api_mask = dri2_dpy->dri2->getAPIMask(dri2_dpy->dri_screen);
- else
- api_mask = __DRI_API_OPENGL;
-
- disp->ClientAPIsMask = 0;
- if (api_mask & (1 <<__DRI_API_OPENGL))
- disp->ClientAPIsMask |= EGL_OPENGL_BIT;
- if (api_mask & (1 <<__DRI_API_GLES))
- disp->ClientAPIsMask |= EGL_OPENGL_ES_BIT;
- if (api_mask & (1 << __DRI_API_GLES2))
- disp->ClientAPIsMask |= EGL_OPENGL_ES2_BIT;
if (dri2_dpy->conn) {
if (!dri2_add_configs_for_visuals(dri2_dpy, disp))
@@ -808,14 +831,13 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
cleanup_configs:
_eglCleanupDisplay(disp);
- cleanup_dri_screen:
dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
cleanup_fd:
close(dri2_dpy->fd);
cleanup_driver:
dlclose(dri2_dpy->driver);
cleanup_conn:
- if (disp->NativeDisplay == NULL)
+ if (disp->PlatformDisplay == NULL)
xcb_disconnect(dri2_dpy->conn);
cleanup_dpy:
free(dri2_dpy);
@@ -823,6 +845,168 @@ dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
return EGL_FALSE;
}
+#ifdef HAVE_LIBUDEV
+
+struct dri2_driver_map {
+ int vendor_id;
+ const char *driver;
+ const int *chip_ids;
+ int num_chips_ids;
+};
+
+const int i915_chip_ids[] = {
+ 0x3577, /* PCI_CHIP_I830_M */
+ 0x2562, /* PCI_CHIP_845_G */
+ 0x3582, /* PCI_CHIP_I855_GM */
+ 0x2572, /* PCI_CHIP_I865_G */
+ 0x2582, /* PCI_CHIP_I915_G */
+ 0x258a, /* PCI_CHIP_E7221_G */
+ 0x2592, /* PCI_CHIP_I915_GM */
+ 0x2772, /* PCI_CHIP_I945_G */
+ 0x27a2, /* PCI_CHIP_I945_GM */
+ 0x27ae, /* PCI_CHIP_I945_GME */
+ 0x29b2, /* PCI_CHIP_Q35_G */
+ 0x29c2, /* PCI_CHIP_G33_G */
+ 0x29d2, /* PCI_CHIP_Q33_G */
+};
+
+const int i965_chip_ids[] = {
+ 0x29a2, /* PCI_CHIP_I965_G */
+ 0x2992, /* PCI_CHIP_I965_Q */
+ 0x2982, /* PCI_CHIP_I965_G_1 */
+ 0x2972, /* PCI_CHIP_I946_GZ */
+ 0x2a02, /* PCI_CHIP_I965_GM */
+ 0x2a12, /* PCI_CHIP_I965_GME */
+ 0x2a42, /* PCI_CHIP_GM45_GM */
+ 0x2e02, /* PCI_CHIP_IGD_E_G */
+ 0x2e12, /* PCI_CHIP_Q45_G */
+ 0x2e22, /* PCI_CHIP_G45_G */
+ 0x2e32, /* PCI_CHIP_G41_G */
+};
+
+const struct dri2_driver_map driver_map[] = {
+ { 0x8086, "i915", i915_chip_ids, ARRAY_SIZE(i915_chip_ids) },
+ { 0x8086, "i965", i965_chip_ids, ARRAY_SIZE(i965_chip_ids) },
+};
+
+static char *
+dri2_get_driver_for_fd(int fd)
+{
+ struct udev *udev;
+ struct udev_device *device, *parent;
+ struct stat buf;
+ const char *pci_id;
+ char *driver = NULL;
+ int vendor_id, chip_id, i, j;
+
+ udev = udev_new();
+ if (fstat(fd, &buf) < 0) {
+ _eglLog(_EGL_WARNING, "EGL-DRI2: failed to stat fd %d", fd);
+ goto out;
+ }
+
+ device = udev_device_new_from_devnum(udev, 'c', buf.st_rdev);
+ if (device == NULL) {
+ _eglLog(_EGL_WARNING,
+ "EGL-DRI2: could not create udev device for fd %d", fd);
+ goto out;
+ }
+
+ parent = udev_device_get_parent(device);
+ if (parent == NULL) {
+ _eglLog(_EGL_WARNING, "DRI2: could not get parent device");
+ goto out;
+ }
+
+ pci_id = udev_device_get_property_value(parent, "PCI_ID");
+ if (pci_id == NULL || sscanf(pci_id, "%x:%x", &vendor_id, &chip_id) != 2) {
+ _eglLog(_EGL_WARNING, "EGL-DRI2: malformed or no PCI ID");
+ goto out;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(driver_map); i++) {
+ if (vendor_id != driver_map[i].vendor_id)
+ continue;
+ for (j = 0; j < driver_map[i].num_chips_ids; j++)
+ if (driver_map[i].chip_ids[j] == chip_id) {
+ driver = strdup(driver_map[i].driver);
+ _eglLog(_EGL_DEBUG, "pci id for %d: %04x:%04x, driver %s",
+ fd, vendor_id, chip_id, driver);
+ goto out;
+ }
+ }
+
+ out:
+ udev_device_unref(device);
+ udev_unref(udev);
+
+ return driver;
+}
+
+static EGLBoolean
+dri2_initialize_drm(_EGLDriver *drv, _EGLDisplay *disp,
+ EGLint *major, EGLint *minor)
+{
+ struct dri2_egl_display *dri2_dpy;
+
+ dri2_dpy = malloc(sizeof *dri2_dpy);
+ if (!dri2_dpy)
+ return _eglError(EGL_BAD_ALLOC, "eglInitialize");
+
+ disp->DriverData = (void *) dri2_dpy;
+ dri2_dpy->fd = (int) disp->PlatformDisplay;
+
+ dri2_dpy->driver_name = dri2_get_driver_for_fd(dri2_dpy->fd);
+ if (dri2_dpy->driver_name == NULL)
+ return _eglError(EGL_BAD_ALLOC, "DRI2: failed to get driver name");
+
+ if (!dri2_load_driver(disp))
+ goto cleanup_driver_name;
+
+ dri2_dpy->extensions[0] = &image_lookup_extension.base;
+ dri2_dpy->extensions[1] = &use_invalidate.base;
+ dri2_dpy->extensions[2] = NULL;
+
+ if (!dri2_create_screen(disp))
+ goto cleanup_driver;
+
+ disp->Extensions.KHR_image_base = EGL_TRUE;
+ disp->Extensions.KHR_gl_renderbuffer_image = EGL_TRUE;
+ disp->Extensions.KHR_gl_texture_2D_image = EGL_TRUE;
+
+ return EGL_TRUE;
+
+ cleanup_driver:
+ dlclose(dri2_dpy->driver);
+ cleanup_driver_name:
+ free(dri2_dpy->driver_name);
+
+ return EGL_FALSE;
+}
+
+#endif
+
+/**
+ * Called via eglInitialize(), GLX_drv->API.Initialize().
+ */
+static EGLBoolean
+dri2_initialize(_EGLDriver *drv, _EGLDisplay *disp,
+ EGLint *major, EGLint *minor)
+{
+ switch (disp->Platform) {
+ case _EGL_PLATFORM_X11:
+ return dri2_initialize_x11(drv, disp, major, minor);
+
+#ifdef HAVE_LIBUDEV
+ case _EGL_PLATFORM_DRM:
+ return dri2_initialize_drm(drv, disp, major, minor);
+#endif
+
+ default:
+ return EGL_FALSE;
+ }
+}
+
/**
* Called via eglTerminate(), drv->API.Terminate().
*/
@@ -837,7 +1021,7 @@ dri2_terminate(_EGLDriver *drv, _EGLDisplay *disp)
dri2_dpy->core->destroyScreen(dri2_dpy->dri_screen);
close(dri2_dpy->fd);
dlclose(dri2_dpy->driver);
- if (disp->NativeDisplay == NULL)
+ if (disp->PlatformDisplay == NULL)
xcb_disconnect(dri2_dpy->conn);
free(dri2_dpy);
disp->DriverData = NULL;
diff --git a/src/egl/drivers/glx/egl_glx.c b/src/egl/drivers/glx/egl_glx.c
index e08ef5f2228..b4a40d14377 100644
--- a/src/egl/drivers/glx/egl_glx.c
+++ b/src/egl/drivers/glx/egl_glx.c
@@ -498,11 +498,14 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
{
struct GLX_egl_display *GLX_dpy;
+ if (disp->Platform != _EGL_PLATFORM_X11)
+ return EGL_FALSE;
+
GLX_dpy = CALLOC_STRUCT(GLX_egl_display);
if (!GLX_dpy)
return _eglError(EGL_BAD_ALLOC, "eglInitialize");
- GLX_dpy->dpy = (Display *) disp->NativeDisplay;
+ GLX_dpy->dpy = (Display *) disp->PlatformDisplay;
if (!GLX_dpy->dpy) {
GLX_dpy->dpy = XOpenDisplay(NULL);
if (!GLX_dpy->dpy) {
@@ -514,7 +517,7 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
if (!glXQueryVersion(GLX_dpy->dpy, &GLX_dpy->glx_maj, &GLX_dpy->glx_min)) {
_eglLog(_EGL_WARNING, "GLX: glXQueryVersion failed");
- if (!disp->NativeDisplay)
+ if (!disp->PlatformDisplay)
XCloseDisplay(GLX_dpy->dpy);
free(GLX_dpy);
return EGL_FALSE;
@@ -524,9 +527,9 @@ GLX_eglInitialize(_EGLDriver *drv, _EGLDisplay *disp,
check_quirks(GLX_dpy, DefaultScreen(GLX_dpy->dpy));
create_configs(disp, GLX_dpy, DefaultScreen(GLX_dpy->dpy));
- if (!disp->NumConfigs) {
+ if (!_eglGetArraySize(disp->Configs)) {
_eglLog(_EGL_WARNING, "GLX: failed to create any config");
- if (!disp->NativeDisplay)
+ if (!disp->PlatformDisplay)
XCloseDisplay(GLX_dpy->dpy);
free(GLX_dpy);
return EGL_FALSE;
@@ -558,7 +561,7 @@ GLX_eglTerminate(_EGLDriver *drv, _EGLDisplay *disp)
if (GLX_dpy->fbconfigs)
XFree(GLX_dpy->fbconfigs);
- if (!disp->NativeDisplay)
+ if (!disp->PlatformDisplay)
XCloseDisplay(GLX_dpy->dpy);
free(GLX_dpy);
@@ -617,10 +620,11 @@ GLX_eglCreateContext(_EGLDriver *drv, _EGLDisplay *disp, _EGLConfig *conf,
static void
destroy_surface(_EGLDisplay *disp, _EGLSurface *surf)
{
+ struct GLX_egl_display *GLX_dpy = GLX_egl_display(disp);
struct GLX_egl_surface *GLX_surf = GLX_egl_surface(surf);
if (GLX_surf->destroy)
- GLX_surf->destroy(disp->NativeDisplay, GLX_surf->glx_drawable);
+ GLX_surf->destroy(GLX_dpy->dpy, GLX_surf->glx_drawable);
free(GLX_surf);
}
diff --git a/src/egl/main/Makefile b/src/egl/main/Makefile
index d9e9e4fcd6d..41d301fc140 100644
--- a/src/egl/main/Makefile
+++ b/src/egl/main/Makefile
@@ -30,6 +30,7 @@ HEADERS = \
SOURCES = \
eglapi.c \
+ eglarray.c \
eglconfig.c \
eglconfigutil.c \
eglcontext.c \
@@ -51,10 +52,20 @@ OBJECTS = $(SOURCES:.c=.o)
# use dl*() to load drivers
LOCAL_CFLAGS = -D_EGL_OS_UNIX=1
-EGL_DEFAULT_PLATFORM = $(firstword $(EGL_PLATFORMS))
+# translate --with-egl-platforms to _EGLPlatformType
+EGL_NATIVE_PLATFORM=_EGL_INVALID_PLATFORM
+ifeq ($(firstword $(EGL_PLATFORMS)),x11)
+EGL_NATIVE_PLATFORM=_EGL_PLATFORM_X11
+endif
+ifeq ($(firstword $(EGL_PLATFORMS)),kms)
+EGL_NATIVE_PLATFORM=_EGL_PLATFORM_DRM
+endif
+ifeq ($(firstword $(EGL_PLATFORMS)),fbdev)
+EGL_NATIVE_PLATFORM=_EGL_PLATFORM_FBDEV
+endif
LOCAL_CFLAGS += \
- -D_EGL_DEFAULT_PLATFORM=\"$(EGL_DEFAULT_PLATFORM)\" \
+ -D_EGL_NATIVE_PLATFORM=$(EGL_NATIVE_PLATFORM) \
-D_EGL_DRIVER_SEARCH_DIR=\"$(EGL_DRIVER_INSTALL_DIR)\"
.c.o:
diff --git a/src/egl/main/SConscript b/src/egl/main/SConscript
index a331c9711ec..3d7ae3a8e4e 100644
--- a/src/egl/main/SConscript
+++ b/src/egl/main/SConscript
@@ -9,7 +9,7 @@ if env['platform'] != 'winddk':
env = env.Clone()
env.Append(CPPDEFINES = [
- '_EGL_DEFAULT_DISPLAY=\\"gdi\\"',
+ '_EGL_NATIVE_PLATFORM=_EGL_PLATFORM_WINDOWS',
'_EGL_DRIVER_SEARCH_DIR=\\"\\"',
'_EGL_OS_WINDOWS',
'KHRONOS_DLL_EXPORTS',
@@ -21,6 +21,7 @@ if env['platform'] != 'winddk':
egl_sources = [
'eglapi.c',
+ 'eglarray.c',
'eglconfig.c',
'eglconfigutil.c',
'eglcontext.c',
diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c
index 9912043e06c..09271140b13 100644
--- a/src/egl/main/eglapi.c
+++ b/src/egl/main/eglapi.c
@@ -61,7 +61,6 @@
#include "eglcontext.h"
#include "egldisplay.h"
#include "egltypedefs.h"
-#include "eglglobals.h"
#include "eglcurrent.h"
#include "egldriver.h"
#include "eglsurface.h"
@@ -250,7 +249,8 @@ _eglUnlockDisplay(_EGLDisplay *dpy)
EGLDisplay EGLAPIENTRY
eglGetDisplay(EGLNativeDisplayType nativeDisplay)
{
- _EGLDisplay *dpy = _eglFindDisplay(nativeDisplay);
+ _EGLPlatformType plat = _eglGetNativePlatform();
+ _EGLDisplay *dpy = _eglFindDisplay(plat, (void *) nativeDisplay);
return _eglGetDisplayHandle(dpy);
}
@@ -263,46 +263,24 @@ EGLBoolean EGLAPIENTRY
eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
- EGLint major_int = 0, minor_int = 0;
if (!disp)
RETURN_EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE);
if (!disp->Initialized) {
- _EGLDriver *drv = disp->Driver;
-
- if (!drv) {
- _eglPreloadDrivers();
- drv = _eglMatchDriver(disp);
- /* Initialize the particular display now */
- if (drv && !drv->API.Initialize(drv, disp, &major_int, &minor_int))
- RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
- }
- if (!drv)
- /* Load and initialize the first default driver that works */
- drv = _eglLoadDefaultDriver(disp, &major_int, &minor_int);
- if (!drv)
- RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
-
- disp->APImajor = major_int;
- disp->APIminor = minor_int;
- _eglsnprintf(disp->Version, sizeof(disp->Version),
- "%d.%d (%s)", major_int, minor_int, drv->Name);
+ if (!_eglMatchDriver(disp, EGL_FALSE))
+ RETURN_EGL_ERROR(disp, EGL_NOT_INITIALIZED, EGL_FALSE);
+ _eglsnprintf(disp->Version, sizeof(disp->Version), "%d.%d (%s)",
+ disp->APImajor, disp->APIminor, disp->Driver->Name);
/* limit to APIs supported by core */
disp->ClientAPIsMask &= _EGL_API_ALL_BITS;
-
- disp->Driver = drv;
- disp->Initialized = EGL_TRUE;
- } else {
- major_int = disp->APImajor;
- minor_int = disp->APIminor;
}
/* Update applications version of major and minor if not NULL */
if ((major != NULL) && (minor != NULL)) {
- *major = major_int;
- *minor = minor_int;
+ *major = disp->APImajor;
+ *minor = disp->APIminor;
}
RETURN_EGL_SUCCESS(disp, EGL_TRUE);
@@ -491,6 +469,8 @@ eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config,
EGLSurface ret;
_EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
+ if (disp->Platform != _eglGetNativePlatform())
+ RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_WINDOW, EGL_NO_SURFACE);
surf = drv->API.CreateWindowSurface(drv, disp, conf, window, attrib_list);
ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
@@ -510,6 +490,8 @@ eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config,
EGLSurface ret;
_EGL_CHECK_CONFIG(disp, conf, EGL_NO_SURFACE, drv);
+ if (disp->Platform != _eglGetNativePlatform())
+ RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_NO_SURFACE);
surf = drv->API.CreatePixmapSurface(drv, disp, conf, pixmap, attrib_list);
ret = (surf) ? _eglLinkSurface(surf, disp) : EGL_NO_SURFACE;
@@ -667,6 +649,8 @@ eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
EGLBoolean ret;
_EGL_CHECK_SURFACE(disp, surf, EGL_FALSE, drv);
+ if (disp->Platform != _eglGetNativePlatform())
+ RETURN_EGL_ERROR(disp, EGL_BAD_NATIVE_PIXMAP, EGL_FALSE);
ret = drv->API.CopyBuffers(drv, disp, surf, target);
RETURN_EGL_EVAL(disp, ret);
@@ -836,6 +820,9 @@ eglGetProcAddress(const char *procname)
{ "eglQueryScreenModeMESA", (_EGLProc) eglQueryScreenModeMESA },
{ "eglQueryModeStringMESA", (_EGLProc) eglQueryModeStringMESA },
#endif /* EGL_MESA_screen_surface */
+#ifdef EGL_MESA_drm_display
+ { "eglGetDRMDisplayMESA", (_EGLProc) eglGetDRMDisplayMESA },
+#endif
#ifdef EGL_KHR_image_base
{ "eglCreateImageKHR", (_EGLProc) eglCreateImageKHR },
{ "eglDestroyImageKHR", (_EGLProc) eglDestroyImageKHR },
@@ -860,18 +847,8 @@ eglGetProcAddress(const char *procname)
}
}
}
- if (ret)
- RETURN_EGL_SUCCESS(NULL, ret);
-
- _eglPreloadDrivers();
-
- /* now loop over drivers to query their procs */
- for (i = 0; i < _eglGlobal.NumDrivers; i++) {
- _EGLDriver *drv = _eglGlobal.Drivers[i];
- ret = drv->API.GetProcAddress(drv, procname);
- if (ret)
- break;
- }
+ if (!ret)
+ ret = _eglGetDriverProc(procname);
RETURN_EGL_SUCCESS(NULL, ret);
}
@@ -955,7 +932,7 @@ eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest,
}
-EGLBoolean
+EGLBoolean EGLAPIENTRY
eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
EGLint max_screens, EGLint *num_screens)
{
@@ -970,7 +947,7 @@ eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens,
}
-EGLSurface
+EGLSurface EGLAPIENTRY
eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
const EGLint *attrib_list)
{
@@ -989,7 +966,7 @@ eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config,
}
-EGLBoolean
+EGLBoolean EGLAPIENTRY
eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen,
EGLSurface surface, EGLModeMESA mode)
{
@@ -1012,7 +989,7 @@ eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen,
}
-EGLBoolean
+EGLBoolean EGLAPIENTRY
eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
@@ -1027,7 +1004,7 @@ eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y)
}
-EGLBoolean
+EGLBoolean EGLAPIENTRY
eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
EGLint attribute, EGLint *value)
{
@@ -1043,7 +1020,7 @@ eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen,
}
-EGLBoolean
+EGLBoolean EGLAPIENTRY
eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
EGLSurface *surface)
{
@@ -1062,7 +1039,7 @@ eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen,
}
-EGLBoolean
+EGLBoolean EGLAPIENTRY
eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
@@ -1080,7 +1057,7 @@ eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode)
}
-const char *
+const char * EGLAPIENTRY
eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
@@ -1098,6 +1075,17 @@ eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
#endif /* EGL_MESA_screen_surface */
+#ifdef EGL_MESA_drm_display
+
+EGLDisplay EGLAPIENTRY
+eglGetDRMDisplayMESA(int fd)
+{
+ _EGLDisplay *dpy = _eglFindDisplay(_EGL_PLATFORM_DRM, (void *) fd);
+ return _eglGetDisplayHandle(dpy);
+}
+
+#endif /* EGL_MESA_drm_display */
+
/**
** EGL 1.2
**/
@@ -1116,7 +1104,7 @@ eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode)
* eglWaitNative()
* See section 3.7 "Rendering Context" in the EGL specification for details.
*/
-EGLBoolean
+EGLBoolean EGLAPIENTRY
eglBindAPI(EGLenum api)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
@@ -1136,7 +1124,7 @@ eglBindAPI(EGLenum api)
/**
* Return the last value set with eglBindAPI().
*/
-EGLenum
+EGLenum EGLAPIENTRY
eglQueryAPI(void)
{
_EGLThreadInfo *t = _eglGetCurrentThread();
@@ -1149,7 +1137,7 @@ eglQueryAPI(void)
}
-EGLSurface
+EGLSurface EGLAPIENTRY
eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
EGLClientBuffer buffer, EGLConfig config,
const EGLint *attrib_list)
@@ -1170,7 +1158,7 @@ eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype,
}
-EGLBoolean
+EGLBoolean EGLAPIENTRY
eglReleaseThread(void)
{
/* unbind current contexts */
@@ -1209,7 +1197,7 @@ eglReleaseThread(void)
#ifdef EGL_KHR_image_base
-EGLImageKHR
+EGLImageKHR EGLAPIENTRY
eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
EGLClientBuffer buffer, const EGLint *attr_list)
{
@@ -1231,7 +1219,7 @@ eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target,
}
-EGLBoolean
+EGLBoolean EGLAPIENTRY
eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
{
_EGLDisplay *disp = _eglLockDisplay(dpy);
@@ -1255,7 +1243,7 @@ eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image)
#ifdef EGL_NOK_swap_region
-EGLBoolean
+EGLBoolean EGLAPIENTRY
eglSwapBuffersRegionNOK(EGLDisplay dpy, EGLSurface surface,
EGLint numRects, const EGLint *rects)
{
diff --git a/src/egl/main/eglarray.c b/src/egl/main/eglarray.c
new file mode 100644
index 00000000000..d686fa162d5
--- /dev/null
+++ b/src/egl/main/eglarray.c
@@ -0,0 +1,180 @@
+#include <stdlib.h>
+#include <string.h>
+
+#include "egllog.h"
+#include "eglarray.h"
+
+
+/**
+ * Grow the size of the array.
+ */
+static EGLBoolean
+_eglGrowArray(_EGLArray *array)
+{
+ EGLint new_size;
+ void **elems;
+
+ new_size = array->MaxSize;
+ while (new_size <= array->Size)
+ new_size *= 2;
+
+ elems = realloc(array->Elements, new_size * sizeof(array->Elements[0]));
+ if (!elems) {
+ _eglLog(_EGL_DEBUG, "failed to grow %s array to %d",
+ array->Name, new_size);
+ return EGL_FALSE;
+ }
+
+ array->Elements = elems;
+ array->MaxSize = new_size;
+
+ return EGL_TRUE;
+}
+
+
+/**
+ * Create an array.
+ */
+_EGLArray *
+_eglCreateArray(const char *name, EGLint init_size)
+{
+ _EGLArray *array;
+
+ array = calloc(1, sizeof(*array));
+ if (array) {
+ array->Name = name;
+ array->MaxSize = (init_size > 0) ? init_size : 1;
+ if (!_eglGrowArray(array)) {
+ free(array);
+ array = NULL;
+ }
+ }
+
+ return array;
+}
+
+
+/**
+ * Destroy an array, optionally free the data.
+ */
+void
+_eglDestroyArray(_EGLArray *array, void (*free_cb)(void *))
+{
+ if (free_cb) {
+ EGLint i;
+ for (i = 0; i < array->Size; i++)
+ free_cb(array->Elements[i]);
+ }
+ free(array->Elements);
+ free(array);
+}
+
+
+/**
+ * Append a element to an array.
+ */
+void
+_eglAppendArray(_EGLArray *array, void *elem)
+{
+ if (array->Size >= array->MaxSize && !_eglGrowArray(array))
+ return;
+
+ array->Elements[array->Size++] = elem;
+}
+
+
+/**
+ * Erase an element from an array.
+ */
+void
+_eglEraseArray(_EGLArray *array, EGLint i, void (*free_cb)(void *))
+{
+ if (free_cb)
+ free_cb(array->Elements[i]);
+ if (i < array->Size - 1) {
+ memmove(&array->Elements[i], &array->Elements[i + 1],
+ (array->Size - i - 1) * sizeof(array->Elements[0]));
+ }
+ array->Size--;
+}
+
+
+/**
+ * Find in an array for the given element.
+ */
+void *
+_eglFindArray(_EGLArray *array, void *elem)
+{
+ EGLint i;
+
+ if (!array)
+ return NULL;
+
+ for (i = 0; i < array->Size; i++)
+ if (array->Elements[i] == elem)
+ return elem;
+ return NULL;
+}
+
+
+/**
+ * Filter an array and return the filtered data. The returned data pointer
+ * should be freed.
+ */
+void **
+_eglFilterArray(_EGLArray *array, EGLint *size,
+ _EGLArrayForEach filter, void *filter_data)
+{
+ void **data;
+ EGLint count = 0, i;
+
+ if (!array) {
+ *size = 0;
+ return malloc(0);
+ }
+
+ data = malloc(array->Size * sizeof(array->Elements[0]));
+ if (!data)
+ return NULL;
+
+ if (filter) {
+ for (i = 0; i < array->Size; i++) {
+ if (filter(array->Elements[i], filter_data))
+ data[count++] = array->Elements[i];
+ }
+ }
+ else {
+ memcpy(data, array->Elements, array->Size * sizeof(array->Elements[0]));
+ }
+
+ *size = count;
+
+ return data;
+}
+
+
+/**
+ * Flatten an array by converting array elements into another form and store
+ * them in a buffer.
+ */
+EGLint
+_eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
+ _EGLArrayForEach flatten)
+{
+ EGLint i, count;
+
+ if (!array)
+ return 0;
+
+ count = array->Size;
+ if (buffer) {
+ /* do not exceed buffer size */
+ if (count > size)
+ count = size;
+ for (i = 0; i < count; i++)
+ flatten(array->Elements[i],
+ (void *) ((char *) buffer + elem_size * i));
+ }
+
+ return count;
+}
diff --git a/src/egl/main/eglarray.h b/src/egl/main/eglarray.h
new file mode 100644
index 00000000000..fe92efc11ee
--- /dev/null
+++ b/src/egl/main/eglarray.h
@@ -0,0 +1,57 @@
+#ifndef EGLARRAY_INCLUDED
+#define EGLARRAY_INCLUDED
+
+
+#include "egltypedefs.h"
+
+
+typedef EGLBoolean (*_EGLArrayForEach)(void *elem, void *foreach_data);
+
+
+struct _egl_array {
+ const char *Name;
+ EGLint MaxSize;
+
+ void **Elements;
+ EGLint Size;
+};
+
+
+extern _EGLArray *
+_eglCreateArray(const char *name, EGLint init_size);
+
+
+PUBLIC void
+_eglDestroyArray(_EGLArray *array, void (*free_cb)(void *));
+
+
+extern void
+_eglAppendArray(_EGLArray *array, void *elem);
+
+
+extern void
+_eglEraseArray(_EGLArray *array, EGLint i, void (*free_cb)(void *));
+
+
+void *
+_eglFindArray(_EGLArray *array, void *elem);
+
+
+void **
+_eglFilterArray(_EGLArray *array, EGLint *size,
+ _EGLArrayForEach filter, void *filter_data);
+
+
+EGLint
+_eglFlattenArray(_EGLArray *array, void *buffer, EGLint elem_size, EGLint size,
+ _EGLArrayForEach flatten);
+
+
+static INLINE EGLint
+_eglGetArraySize(_EGLArray *array)
+{
+ return (array) ? array->Size : 0;
+}
+
+
+#endif /* EGLARRAY_INCLUDED */
diff --git a/src/egl/main/eglconfig.c b/src/egl/main/eglconfig.c
index fa947d76887..a9af3200976 100644
--- a/src/egl/main/eglconfig.c
+++ b/src/egl/main/eglconfig.c
@@ -50,26 +50,17 @@ _eglInitConfig(_EGLConfig *config, _EGLDisplay *dpy, EGLint id)
EGLConfig
_eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf)
{
- _EGLConfig **configs;
-
/* sanity check */
assert(GET_CONFIG_ATTRIB(conf, EGL_CONFIG_ID) > 0);
- configs = dpy->Configs;
- if (dpy->NumConfigs >= dpy->MaxConfigs) {
- EGLint new_size = dpy->MaxConfigs + 16;
- assert(dpy->NumConfigs < new_size);
-
- configs = realloc(dpy->Configs, new_size * sizeof(dpy->Configs[0]));
- if (!configs)
+ if (!dpy->Configs) {
+ dpy->Configs = _eglCreateArray("Config", 16);
+ if (!dpy->Configs)
return (EGLConfig) NULL;
-
- dpy->Configs = configs;
- dpy->MaxConfigs = new_size;
}
conf->Display = dpy;
- dpy->Configs[dpy->NumConfigs++] = conf;
+ _eglAppendArray(dpy->Configs, (void *) conf);
return (EGLConfig) conf;
}
@@ -78,17 +69,13 @@ _eglAddConfig(_EGLDisplay *dpy, _EGLConfig *conf)
EGLBoolean
_eglCheckConfigHandle(EGLConfig config, _EGLDisplay *dpy)
{
- EGLint num_configs = (dpy) ? dpy->NumConfigs : 0;
- EGLint i;
+ _EGLConfig *conf;
- for (i = 0; i < num_configs; i++) {
- _EGLConfig *conf = dpy->Configs[i];
- if (conf == (_EGLConfig *) config) {
- assert(conf->Display == dpy);
- break;
- }
- }
- return (i < num_configs);
+ conf = (_EGLConfig *) _eglFindArray(dpy->Configs, (void *) config);
+ if (conf)
+ assert(conf->Display == dpy);
+
+ return (conf != NULL);
}
@@ -776,19 +763,11 @@ _eglChooseConfig(_EGLDriver *drv, _EGLDisplay *disp, const EGLint *attrib_list,
if (!_eglParseConfigAttribList(&criteria, attrib_list))
return _eglError(EGL_BAD_ATTRIBUTE, "eglChooseConfig");
- /* allocate array of config pointers */
- configList = (_EGLConfig **)
- malloc(disp->NumConfigs * sizeof(_EGLConfig *));
+ configList = (_EGLConfig **) _eglFilterArray(disp->Configs, &count,
+ (_EGLArrayForEach) _eglMatchConfig, (void *) &criteria);
if (!configList)
return _eglError(EGL_BAD_ALLOC, "eglChooseConfig(out of memory)");
- /* perform selection of configs */
- count = 0;
- for (i = 0; i < disp->NumConfigs; i++) {
- if (_eglMatchConfig(disp->Configs[i], &criteria))
- configList[count++] = disp->Configs[i];
- }
-
/* perform sorting of configs */
if (configs && count) {
_eglSortConfigs((const _EGLConfig **) configList, count,
@@ -823,6 +802,15 @@ _eglGetConfigAttrib(_EGLDriver *drv, _EGLDisplay *dpy, _EGLConfig *conf,
}
+static EGLBoolean
+_eglFlattenConfig(void *elem, void *buffer)
+{
+ _EGLConfig *conf = (_EGLConfig *) elem;
+ EGLConfig *handle = (EGLConfig *) buffer;
+ *handle = _eglGetConfigHandle(conf);
+ return EGL_TRUE;
+}
+
/**
* Fallback for eglGetConfigs.
*/
@@ -833,16 +821,8 @@ _eglGetConfigs(_EGLDriver *drv, _EGLDisplay *disp, EGLConfig *configs,
if (!num_config)
return _eglError(EGL_BAD_PARAMETER, "eglGetConfigs");
- if (configs) {
- EGLint i;
- *num_config = MIN2(disp->NumConfigs, config_size);
- for (i = 0; i < *num_config; i++)
- configs[i] = _eglGetConfigHandle(disp->Configs[i]);
- }
- else {
- /* just return total number of supported configs */
- *num_config = disp->NumConfigs;
- }
+ *num_config = _eglFlattenArray(disp->Configs, (void *) configs,
+ sizeof(configs[0]), config_size, _eglFlattenConfig);
return EGL_TRUE;
}
diff --git a/src/egl/main/egldisplay.c b/src/egl/main/egldisplay.c
index 5dc5fd9719a..31ff090484c 100644
--- a/src/egl/main/egldisplay.c
+++ b/src/egl/main/egldisplay.c
@@ -15,6 +15,62 @@
/**
+ * Return the native platform by parsing EGL_PLATFORM.
+ */
+static _EGLPlatformType
+_eglGetNativePlatformFromEnv(void)
+{
+ /* map --with-egl-platforms names to platform types */
+ static const struct {
+ _EGLPlatformType platform;
+ const char *name;
+ } egl_platforms[_EGL_NUM_PLATFORMS] = {
+ { _EGL_PLATFORM_WINDOWS, "gdi" },
+ { _EGL_PLATFORM_X11, "x11" },
+ { _EGL_PLATFORM_DRM, "kms" },
+ { _EGL_PLATFORM_FBDEV, "fbdev" }
+ };
+ _EGLPlatformType plat = _EGL_INVALID_PLATFORM;
+ const char *plat_name;
+ EGLint i;
+
+ plat_name = getenv("EGL_PLATFORM");
+ /* try deprecated env variable */
+ if (!plat_name || !plat_name[0])
+ plat_name = getenv("EGL_DISPLAY");
+ if (!plat_name || !plat_name[0])
+ return _EGL_INVALID_PLATFORM;
+
+ for (i = 0; i < _EGL_NUM_PLATFORMS; i++) {
+ if (strcmp(egl_platforms[i].name, plat_name) == 0) {
+ plat = egl_platforms[i].platform;
+ break;
+ }
+ }
+
+ return plat;
+}
+
+
+/**
+ * Return the native platform. It is the platform of the EGL native types.
+ */
+_EGLPlatformType
+_eglGetNativePlatform(void)
+{
+ static _EGLPlatformType native_platform = _EGL_INVALID_PLATFORM;
+
+ if (native_platform == _EGL_INVALID_PLATFORM) {
+ native_platform = _eglGetNativePlatformFromEnv();
+ if (native_platform == _EGL_INVALID_PLATFORM)
+ native_platform = _EGL_NATIVE_PLATFORM;
+ }
+
+ return native_platform;
+}
+
+
+/**
* Finish display management.
*/
void
@@ -49,16 +105,19 @@ _eglFiniDisplay(void)
* new one.
*/
_EGLDisplay *
-_eglFindDisplay(EGLNativeDisplayType nativeDisplay)
+_eglFindDisplay(_EGLPlatformType plat, void *plat_dpy)
{
_EGLDisplay *dpy;
+ if (plat == _EGL_INVALID_PLATFORM)
+ return NULL;
+
_eglLockMutex(_eglGlobal.Mutex);
/* search the display list first */
dpy = _eglGlobal.DisplayList;
while (dpy) {
- if (dpy->NativeDisplay == nativeDisplay)
+ if (dpy->Platform == plat && dpy->PlatformDisplay == plat_dpy)
break;
dpy = dpy->Next;
}
@@ -68,7 +127,8 @@ _eglFindDisplay(EGLNativeDisplayType nativeDisplay)
dpy = (_EGLDisplay *) calloc(1, sizeof(_EGLDisplay));
if (dpy) {
_eglInitMutex(&dpy->Mutex);
- dpy->NativeDisplay = nativeDisplay;
+ dpy->Platform = plat;
+ dpy->PlatformDisplay = plat_dpy;
/* add to the display list */
dpy->Next = _eglGlobal.DisplayList;
@@ -119,15 +179,9 @@ _eglReleaseDisplayResources(_EGLDriver *drv, _EGLDisplay *display)
void
_eglCleanupDisplay(_EGLDisplay *disp)
{
- EGLint i;
-
if (disp->Configs) {
- for (i = 0; i < disp->NumConfigs; i++)
- free(disp->Configs[i]);
- free(disp->Configs);
+ _eglDestroyArray(disp->Configs, free);
disp->Configs = NULL;
- disp->NumConfigs = 0;
- disp->MaxConfigs = 0;
}
/* XXX incomplete */
diff --git a/src/egl/main/egldisplay.h b/src/egl/main/egldisplay.h
index 42e305f91ac..0b2f26a4c07 100644
--- a/src/egl/main/egldisplay.h
+++ b/src/egl/main/egldisplay.h
@@ -5,6 +5,19 @@
#include "egltypedefs.h"
#include "egldefines.h"
#include "eglmutex.h"
+#include "eglarray.h"
+
+
+enum _egl_platform_type {
+ _EGL_PLATFORM_WINDOWS,
+ _EGL_PLATFORM_X11,
+ _EGL_PLATFORM_DRM,
+ _EGL_PLATFORM_FBDEV,
+
+ _EGL_NUM_PLATFORMS,
+ _EGL_INVALID_PLATFORM = -1
+};
+typedef enum _egl_platform_type _EGLPlatformType;
enum _egl_resource_type {
@@ -39,6 +52,7 @@ struct _egl_extensions
{
EGLBoolean MESA_screen_surface;
EGLBoolean MESA_copy_context;
+ EGLBoolean MESA_drm_display;
EGLBoolean KHR_image_base;
EGLBoolean KHR_image_pixmap;
EGLBoolean KHR_vg_parent_image;
@@ -53,14 +67,15 @@ struct _egl_extensions
};
-struct _egl_display
+struct _egl_display
{
/* used to link displays */
_EGLDisplay *Next;
_EGLMutex Mutex;
- EGLNativeDisplayType NativeDisplay;
+ _EGLPlatformType Platform;
+ void *PlatformDisplay;
EGLBoolean Initialized; /**< True if the display is initialized */
_EGLDriver *Driver;
@@ -75,24 +90,24 @@ struct _egl_display
_EGLExtensions Extensions;
- EGLint NumScreens;
- _EGLScreen **Screens; /* array [NumScreens] */
-
- EGLint MaxConfigs;
- EGLint NumConfigs;
- _EGLConfig **Configs; /* array [NumConfigs] of ptr to _EGLConfig */
+ _EGLArray *Screens;
+ _EGLArray *Configs;
/* lists of resources */
_EGLResource *ResourceLists[_EGL_NUM_RESOURCES];
};
+extern _EGLPlatformType
+_eglGetNativePlatform(void);
+
+
extern void
_eglFiniDisplay(void);
extern _EGLDisplay *
-_eglFindDisplay(EGLNativeDisplayType displayName);
+_eglFindDisplay(_EGLPlatformType plat, void *plat_dpy);
PUBLIC void
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
index f56214472e9..1e3d7d24aa7 100644
--- a/src/egl/main/egldriver.c
+++ b/src/egl/main/egldriver.c
@@ -22,6 +22,7 @@
#include "eglstring.h"
#include "eglsurface.h"
#include "eglimage.h"
+#include "eglmutex.h"
#if defined(_EGL_OS_UNIX)
#include <dlfcn.h>
@@ -31,17 +32,22 @@
#endif
+typedef struct _egl_module {
+ char *Path;
+ void *Handle;
+ _EGLDriver *Driver;
+} _EGLModule;
+
+static _EGL_DECLARE_MUTEX(_eglModuleMutex);
+static _EGLArray *_eglModules;
+
+
/**
* Wrappers for dlopen/dlclose()
*/
#if defined(_EGL_OS_WINDOWS)
-/* XXX Need to decide how to do dynamic name lookup on Windows */
-static const char *DefaultDriverNames[] = {
- "egl_gdi_swrast"
-};
-
typedef HMODULE lib_handle;
static HMODULE
@@ -67,11 +73,6 @@ library_suffix(void)
#elif defined(_EGL_OS_UNIX)
-static const char *DefaultDriverNames[] = {
- "egl_dri2",
- "egl_glx"
-};
-
typedef void * lib_handle;
static void *
@@ -97,13 +98,6 @@ library_suffix(void)
#endif
-#define NUM_PROBE_CACHE_SLOTS 8
-static struct {
- EGLint keys[NUM_PROBE_CACHE_SLOTS];
- const void *values[NUM_PROBE_CACHE_SLOTS];
-} _eglProbeCache;
-
-
/**
* Open the named driver and find its bootstrap function: _eglMain().
*/
@@ -163,85 +157,106 @@ _eglOpenLibrary(const char *driverPath, lib_handle *handle)
/**
- * Load the named driver.
+ * Load a module and create the driver object.
*/
-static _EGLDriver *
-_eglLoadDriver(const char *path, const char *args)
+static EGLBoolean
+_eglLoadModule(_EGLModule *mod)
{
_EGLMain_t mainFunc;
lib_handle lib;
- _EGLDriver *drv = NULL;
+ _EGLDriver *drv;
- mainFunc = _eglOpenLibrary(path, &lib);
+ mainFunc = _eglOpenLibrary(mod->Path, &lib);
if (!mainFunc)
- return NULL;
+ return EGL_FALSE;
- drv = mainFunc(args);
+ drv = mainFunc(NULL);
if (!drv) {
if (lib)
close_library(lib);
- return NULL;
+ return EGL_FALSE;
}
if (!drv->Name) {
- _eglLog(_EGL_WARNING, "Driver loaded from %s has no name", path);
+ _eglLog(_EGL_WARNING, "Driver loaded from %s has no name", mod->Path);
drv->Name = "UNNAMED";
}
- drv->Path = _eglstrdup(path);
- drv->Args = (args) ? _eglstrdup(args) : NULL;
- if (!drv->Path || (args && !drv->Args)) {
- if (drv->Path)
- free((char *) drv->Path);
- if (drv->Args)
- free((char *) drv->Args);
- drv->Unload(drv);
- if (lib)
- close_library(lib);
- return NULL;
- }
+ mod->Handle = (void *) lib;
+ mod->Driver = drv;
+
+ return EGL_TRUE;
+}
- drv->LibHandle = lib;
- return drv;
+/**
+ * Unload a module.
+ */
+static void
+_eglUnloadModule(_EGLModule *mod)
+{
+ /* destroy the driver */
+ if (mod->Driver && mod->Driver->Unload)
+ mod->Driver->Unload(mod->Driver);
+ if (mod->Handle)
+ close_library(mod->Handle);
+
+ mod->Driver = NULL;
+ mod->Handle = NULL;
}
/**
- * Match a display to a preloaded driver.
- *
- * The matching is done by finding the driver with the highest score.
+ * Add a module to the module array.
*/
-_EGLDriver *
-_eglMatchDriver(_EGLDisplay *dpy)
+static _EGLModule *
+_eglAddModule(const char *path)
{
- _EGLDriver *best_drv = NULL;
- EGLint best_score = -1, i;
+ _EGLModule *mod;
+ EGLint i;
- /*
- * this function is called after preloading and the drivers never change
- * after preloading.
- */
- for (i = 0; i < _eglGlobal.NumDrivers; i++) {
- _EGLDriver *drv = _eglGlobal.Drivers[i];
- EGLint score;
-
- score = (drv->Probe) ? drv->Probe(drv, dpy) : 0;
- if (score > best_score) {
- if (best_drv) {
- _eglLog(_EGL_DEBUG, "driver %s has higher score than %s",
- drv->Name, best_drv->Name);
- }
+ if (!_eglModules) {
+ _eglModules = _eglCreateArray("Module", 8);
+ if (!_eglModules)
+ return NULL;
+ }
- best_drv = drv;
- best_score = score;
- /* perfect match */
- if (score >= 100)
- break;
+ /* find duplicates */
+ for (i = 0; i < _eglModules->Size; i++) {
+ mod = _eglModules->Elements[i];
+ if (strcmp(mod->Path, path) == 0)
+ return mod;
+ }
+
+ /* allocate a new one */
+ mod = calloc(1, sizeof(*mod));
+ if (mod) {
+ mod->Path = _eglstrdup(path);
+ if (!mod->Path) {
+ free(mod);
+ mod = NULL;
}
}
+ if (mod) {
+ _eglAppendArray(_eglModules, (void *) mod);
+ _eglLog(_EGL_DEBUG, "added %s to module array", mod->Path);
+ }
- return best_drv;
+ return mod;
+}
+
+
+/**
+ * Free a module.
+ */
+static void
+_eglFreeModule(void *module)
+{
+ _EGLModule *mod = (_EGLModule *) module;
+
+ _eglUnloadModule(mod);
+ free(mod->Path);
+ free(mod);
}
@@ -252,7 +267,6 @@ _eglMatchDriver(_EGLDisplay *dpy)
static EGLBoolean
_eglLoaderFile(const char *dir, size_t len, void *loader_data)
{
- _EGLDriver *drv;
char path[1024];
const char *filename = (const char *) loader_data;
size_t flen = strlen(filename);
@@ -268,9 +282,7 @@ _eglLoaderFile(const char *dir, size_t len, void *loader_data)
len += flen;
path[len] = '\0';
- if (library_suffix() == NULL || strstr(path, library_suffix()))
- drv = _eglLoadDriver(path, NULL);
- else {
+ if (library_suffix()) {
const char *suffix = library_suffix();
size_t slen = strlen(suffix);
const char *p;
@@ -278,19 +290,23 @@ _eglLoaderFile(const char *dir, size_t len, void *loader_data)
p = filename + flen - slen;
need_suffix = (p < filename || strcmp(p, suffix) != 0);
- if (need_suffix && len + slen + 1 <= sizeof(path)) {
+ if (need_suffix) {
+ /* overflow */
+ if (len + slen + 1 > sizeof(path))
+ return EGL_TRUE;
strcpy(path + len, suffix);
- drv = _eglLoadDriver(path, NULL);
- } else {
- drv = NULL;
}
}
- if (!drv)
+
+#if defined(_EGL_OS_UNIX)
+ /* check if the file exists */
+ if (access(path, F_OK))
return EGL_TRUE;
+#endif
- /* remember the driver and stop */
- _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
- return EGL_FALSE;
+ _eglAddModule(path);
+
+ return EGL_TRUE;
}
@@ -326,7 +342,6 @@ _eglLoaderPattern(const char *dir, size_t len, void *loader_data)
suffix_len = (suffix) ? strlen(suffix) : 0;
while ((dirent = readdir(dirp))) {
- _EGLDriver *drv;
size_t dirent_len = strlen(dirent->d_name);
const char *p;
@@ -340,12 +355,10 @@ _eglLoaderPattern(const char *dir, size_t len, void *loader_data)
continue;
}
- /* make a full path and load the driver */
+ /* make a full path and add it to the module array */
if (len + dirent_len + 1 <= sizeof(path)) {
strcpy(path + len, dirent->d_name);
- drv = _eglLoadDriver(path, NULL);
- if (drv)
- _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv;
+ _eglAddModule(path);
}
}
@@ -360,19 +373,17 @@ _eglLoaderPattern(const char *dir, size_t len, void *loader_data)
/**
- * Run the preload function on each driver directory and return the number of
- * drivers loaded.
+ * Run the callback function on each driver directory.
*
* The process may end prematurely if the callback function returns false.
*/
-static EGLint
+static void
_eglPreloadForEach(const char *search_path,
EGLBoolean (*loader)(const char *, size_t, void *),
void *loader_data)
{
const char *cur, *next;
size_t len;
- EGLint num_drivers = _eglGlobal.NumDrivers;
cur = search_path;
while (cur) {
@@ -384,8 +395,6 @@ _eglPreloadForEach(const char *search_path,
cur = (next) ? next + 1 : NULL;
}
-
- return (_eglGlobal.NumDrivers - num_drivers);
}
@@ -430,12 +439,12 @@ _eglGetSearchPath(void)
/**
- * Preload a user driver.
+ * Add the user driver to the module array.
*
- * A user driver can be specified by EGL_DRIVER.
+ * The user driver is specified by EGL_DRIVER.
*/
-static EGLBoolean
-_eglPreloadUserDriver(void)
+static void
+_eglAddUserDriver(void)
{
const char *search_path = _eglGetSearchPath();
char *env;
@@ -451,132 +460,206 @@ _eglPreloadUserDriver(void)
}
}
#endif /* _EGL_OS_UNIX */
- if (!env)
- return EGL_FALSE;
+ if (env)
+ _eglPreloadForEach(search_path, _eglLoaderFile, (void *) env);
+}
- if (!_eglPreloadForEach(search_path, _eglLoaderFile, (void *) env)) {
- _eglLog(_EGL_WARNING, "EGL_DRIVER is set to an invalid driver");
- return EGL_FALSE;
- }
- return EGL_TRUE;
+/**
+ * Add default drivers to the module array.
+ */
+static void
+_eglAddDefaultDrivers(void)
+{
+ const char *search_path = _eglGetSearchPath();
+ EGLint i;
+#if defined(_EGL_OS_WINDOWS)
+ const char *DefaultDriverNames[] = {
+ "egl_gallium"
+ };
+#elif defined(_EGL_OS_UNIX)
+ const char *DefaultDriverNames[] = {
+ "egl_gallium",
+ "egl_dri2",
+ "egl_glx"
+ };
+#endif
+
+ for (i = 0; i < ARRAY_SIZE(DefaultDriverNames); i++) {
+ void *name = (void *) DefaultDriverNames[i];
+ _eglPreloadForEach(search_path, _eglLoaderFile, name);
+ }
}
/**
- * Preload platform drivers.
- *
- * Platform drivers are a set of drivers that support a certain window system.
- * The window system may be specified by EGL_PLATFORM.
- *
- * FIXME This makes libEGL a memory hog if an user driver is not specified and
- * there are many platform drivers.
+ * Add drivers to the module array. Drivers will be loaded as they are matched
+ * to displays.
*/
static EGLBoolean
-_eglPreloadPlatformDrivers(void)
+_eglAddDrivers(void)
{
- const char *dpy;
- char prefix[32];
- int ret;
-
- dpy = getenv("EGL_PLATFORM");
- /* try deprecated env variable */
- if (!dpy || !dpy[0])
- dpy = getenv("EGL_DISPLAY");
- if (!dpy || !dpy[0])
- dpy = _EGL_DEFAULT_PLATFORM;
- if (!dpy || !dpy[0])
- return EGL_FALSE;
+ if (_eglModules)
+ return EGL_TRUE;
- ret = _eglsnprintf(prefix, sizeof(prefix), "egl_%s_", dpy);
- if (ret < 0 || ret >= sizeof(prefix))
- return EGL_FALSE;
+ /* the order here decides the priorities of the drivers */
+ _eglAddUserDriver();
+ _eglAddDefaultDrivers();
+ _eglPreloadForEach(_eglGetSearchPath(), _eglLoaderPattern, (void *) "egl_");
- return (_eglPreloadForEach(_eglGetSearchPath(),
- _eglLoaderPattern, (void *) prefix) > 0);
+ return (_eglModules != NULL);
}
/**
- * Preload drivers.
+ * Match a display to a driver. The display is initialized unless use_probe is
+ * true.
*
- * This function loads the driver modules and creates the corresponding
- * _EGLDriver objects.
+ * The matching is done by finding the first driver that can initialize the
+ * display, or when use_probe is true, the driver with highest score.
*/
-EGLBoolean
-_eglPreloadDrivers(void)
+_EGLDriver *
+_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean use_probe)
{
- EGLBoolean loaded;
+ _EGLModule *mod;
+ _EGLDriver *best_drv = NULL;
+ EGLint best_score = 0;
+ EGLint major, minor, i;
- /* protect the preloading process */
- _eglLockMutex(_eglGlobal.Mutex);
+ _eglLockMutex(&_eglModuleMutex);
- /* already preloaded */
- if (_eglGlobal.NumDrivers) {
- _eglUnlockMutex(_eglGlobal.Mutex);
- return EGL_TRUE;
+ if (!_eglAddDrivers()) {
+ _eglUnlockMutex(&_eglModuleMutex);
+ return EGL_FALSE;
+ }
+
+ /* match the loaded modules */
+ for (i = 0; i < _eglModules->Size; i++) {
+ mod = (_EGLModule *) _eglModules->Elements[i];
+ if (!mod->Driver)
+ break;
+
+ if (use_probe) {
+ EGLint score = (mod->Driver->Probe) ?
+ mod->Driver->Probe(mod->Driver, dpy) : 1;
+ if (score > best_score) {
+ best_drv = mod->Driver;
+ best_score = score;
+ }
+ }
+ else {
+ if (mod->Driver->API.Initialize(mod->Driver, dpy, &major, &minor)) {
+ best_drv = mod->Driver;
+ best_score = 100;
+ }
+ }
+ /* perfect match */
+ if (best_score >= 100)
+ break;
+ }
+
+ /* load more modules */
+ if (!best_drv) {
+ EGLint first_unloaded = i;
+
+ while (i < _eglModules->Size) {
+ mod = (_EGLModule *) _eglModules->Elements[i];
+ assert(!mod->Driver);
+
+ if (!_eglLoadModule(mod)) {
+ /* remove invalid modules */
+ _eglEraseArray(_eglModules, i, _eglFreeModule);
+ continue;
+ }
+
+ if (use_probe) {
+ best_score = (mod->Driver->Probe) ?
+ mod->Driver->Probe(mod->Driver, dpy) : 1;
+ }
+ else {
+ if (mod->Driver->API.Initialize(mod->Driver, dpy, &major, &minor))
+ best_score = 100;
+ }
+
+ if (best_score > 0) {
+ best_drv = mod->Driver;
+ /* loaded modules come before unloaded ones */
+ if (first_unloaded != i) {
+ void *tmp = _eglModules->Elements[i];
+ _eglModules->Elements[i] =
+ _eglModules->Elements[first_unloaded];
+ _eglModules->Elements[first_unloaded] = tmp;
+ }
+ break;
+ }
+ else {
+ _eglUnloadModule(mod);
+ i++;
+ }
+ }
}
- loaded = (_eglPreloadUserDriver() ||
- _eglPreloadPlatformDrivers());
+ _eglUnlockMutex(&_eglModuleMutex);
- _eglUnlockMutex(_eglGlobal.Mutex);
+ if (best_drv) {
+ _eglLog(_EGL_DEBUG, "the best driver is %s (score %d)",
+ best_drv->Name, best_score);
+ if (!use_probe) {
+ dpy->Driver = best_drv;
+ dpy->Initialized = EGL_TRUE;
+ dpy->APImajor = major;
+ dpy->APIminor = minor;
+ }
+ }
- return loaded;
+ return best_drv;
}
-/**
- * Unload preloaded drivers.
- */
-void
-_eglUnloadDrivers(void)
+
+__eglMustCastToProperFunctionPointerType
+_eglGetDriverProc(const char *procname)
{
EGLint i;
+ _EGLProc proc = NULL;
+
+ if (!_eglModules) {
+ /* load the driver for the default display */
+ EGLDisplay egldpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ _EGLDisplay *dpy = _eglLookupDisplay(egldpy);
+ if (!dpy || !_eglMatchDriver(dpy, EGL_TRUE))
+ return NULL;
+ }
- /* this is called at atexit time */
- for (i = 0; i < _eglGlobal.NumDrivers; i++) {
- _EGLDriver *drv = _eglGlobal.Drivers[i];
- lib_handle handle = drv->LibHandle;
-
- if (drv->Path)
- free((char *) drv->Path);
- if (drv->Args)
- free((char *) drv->Args);
-
- /* destroy driver */
- if (drv->Unload)
- drv->Unload(drv);
-
- if (handle)
- close_library(handle);
- _eglGlobal.Drivers[i] = NULL;
+ for (i = 0; i < _eglModules->Size; i++) {
+ _EGLModule *mod = (_EGLModule *) _eglModules->Elements[i];
+
+ if (!mod->Driver)
+ break;
+ proc = mod->Driver->API.GetProcAddress(mod->Driver, procname);
+ if (proc)
+ break;
}
- _eglGlobal.NumDrivers = 0;
+ return proc;
}
-_EGLDriver *
-_eglLoadDefaultDriver(EGLDisplay dpy, EGLint *major, EGLint *minor)
-{
- _EGLDriver *drv = NULL;
- int i;
-
- _eglLockMutex(_eglGlobal.Mutex);
- for (i = 0; i < ARRAY_SIZE(DefaultDriverNames); i++) {
- _eglPreloadForEach(_eglGetSearchPath(),
- _eglLoaderFile, (void *) DefaultDriverNames[i]);
- if (_eglGlobal.NumDrivers == 0)
- continue;
- drv = _eglGlobal.Drivers[0];
- if (drv->API.Initialize(drv, dpy, major, minor))
- break;
- _eglUnloadDrivers();
- }
-
- _eglUnlockMutex(_eglGlobal.Mutex);
-
- return _eglGlobal.NumDrivers > 0 ? drv : NULL;
+/**
+ * Unload all drivers.
+ */
+void
+_eglUnloadDrivers(void)
+{
+ /* this is called at atexit time */
+ if (_eglModules) {
+#if defined(_EGL_OS_UNIX)
+ _eglDestroyArray(_eglModules, _eglFreeModule);
+#elif defined(_EGL_OS_WINDOWS)
+ /* XXX Windows unloads DLLs before atexit */
+ _eglDestroyArray(_eglModules, NULL);
+#endif
+ _eglModules = NULL;
+ }
}
@@ -656,44 +739,3 @@ _eglSearchPathForEach(EGLBoolean (*callback)(const char *, size_t, void *),
const char *search_path = _eglGetSearchPath();
_eglPreloadForEach(search_path, callback, callback_data);
}
-
-
-/**
- * Set the probe cache at the given key.
- *
- * A key, instead of a _EGLDriver, is used to allow the probe cache to be share
- * by multiple drivers.
- */
-void
-_eglSetProbeCache(EGLint key, const void *val)
-{
- EGLint idx;
-
- for (idx = 0; idx < NUM_PROBE_CACHE_SLOTS; idx++) {
- if (!_eglProbeCache.keys[idx] || _eglProbeCache.keys[idx] == key)
- break;
- }
- assert(key > 0);
- assert(idx < NUM_PROBE_CACHE_SLOTS);
-
- _eglProbeCache.keys[idx] = key;
- _eglProbeCache.values[idx] = val;
-}
-
-
-/**
- * Return the probe cache at the given key.
- */
-const void *
-_eglGetProbeCache(EGLint key)
-{
- EGLint idx;
-
- for (idx = 0; idx < NUM_PROBE_CACHE_SLOTS; idx++) {
- if (!_eglProbeCache.keys[idx] || _eglProbeCache.keys[idx] == key)
- break;
- }
-
- return (idx < NUM_PROBE_CACHE_SLOTS && _eglProbeCache.keys[idx] == key) ?
- _eglProbeCache.values[idx] : NULL;
-}
diff --git a/src/egl/main/egldriver.h b/src/egl/main/egldriver.h
index 8b34c43b924..c618feb6b02 100644
--- a/src/egl/main/egldriver.h
+++ b/src/egl/main/egldriver.h
@@ -41,10 +41,6 @@ typedef _EGLDriver *(*_EGLMain_t)(const char *args);
*/
struct _egl_driver
{
- void *LibHandle; /**< dlopen handle */
- const char *Path; /**< path to this driver */
- const char *Args; /**< args to load this driver */
-
const char *Name; /**< name of this driver */
/**
@@ -73,21 +69,17 @@ _eglMain(const char *args);
extern _EGLDriver *
-_eglMatchDriver(_EGLDisplay *dpy);
+_eglMatchDriver(_EGLDisplay *dpy, EGLBoolean probe_only);
-extern EGLBoolean
-_eglPreloadDrivers(void);
+extern __eglMustCastToProperFunctionPointerType
+_eglGetDriverProc(const char *procname);
extern void
_eglUnloadDrivers(void);
-extern _EGLDriver *
-_eglLoadDefaultDriver(EGLDisplay dpy, EGLint *major, EGLint *minor);
-
-
PUBLIC void
_eglInitDriverFallbacks(_EGLDriver *drv);
@@ -97,12 +89,4 @@ _eglSearchPathForEach(EGLBoolean (*callback)(const char *, size_t, void *),
void *callback_data);
-PUBLIC void
-_eglSetProbeCache(EGLint key, const void *val);
-
-
-PUBLIC const void *
-_eglGetProbeCache(EGLint key);
-
-
#endif /* EGLDRIVER_INCLUDED */
diff --git a/src/egl/main/eglglobals.c b/src/egl/main/eglglobals.c
index e63819e08a2..725a25eca63 100644
--- a/src/egl/main/eglglobals.c
+++ b/src/egl/main/eglglobals.c
@@ -12,8 +12,6 @@ struct _egl_global _eglGlobal =
&_eglGlobalMutex, /* Mutex */
NULL, /* DisplayList */
1, /* FreeScreenHandle */
- 0, /* NumDrivers */
- { NULL }, /* Drivers */
2, /* NumAtExitCalls */
{
/* default AtExitCalls, called in reverse order */
diff --git a/src/egl/main/eglglobals.h b/src/egl/main/eglglobals.h
index 43688980208..e8bf5416e2a 100644
--- a/src/egl/main/eglglobals.h
+++ b/src/egl/main/eglglobals.h
@@ -18,10 +18,6 @@ struct _egl_global
EGLScreenMESA FreeScreenHandle;
- /* these never change after preloading */
- EGLint NumDrivers;
- _EGLDriver *Drivers[10];
-
EGLint NumAtExitCalls;
void (*AtExitCalls[10])(void);
};
diff --git a/src/egl/main/eglmisc.c b/src/egl/main/eglmisc.c
index 4652969659b..281138c7523 100644
--- a/src/egl/main/eglmisc.c
+++ b/src/egl/main/eglmisc.c
@@ -84,6 +84,7 @@ _eglUpdateExtensionsString(_EGLDisplay *dpy)
_EGL_CHECK_EXTENSION(MESA_screen_surface);
_EGL_CHECK_EXTENSION(MESA_copy_context);
+ _EGL_CHECK_EXTENSION(MESA_drm_display);
_EGL_CHECK_EXTENSION(KHR_image_base);
_EGL_CHECK_EXTENSION(KHR_image_pixmap);
diff --git a/src/egl/main/eglmode.c b/src/egl/main/eglmode.c
index 66446c0495d..859e9318b4a 100644
--- a/src/egl/main/eglmode.c
+++ b/src/egl/main/eglmode.c
@@ -22,9 +22,12 @@ _eglLookupMode(EGLModeMESA mode, _EGLDisplay *disp)
{
EGLint scrnum;
+ if (!disp->Screens)
+ return NULL;
+
/* loop over all screens on the display */
- for (scrnum = 0; scrnum < disp->NumScreens; scrnum++) {
- const _EGLScreen *scrn = disp->Screens[scrnum];
+ for (scrnum = 0; scrnum < disp->Screens->Size; scrnum++) {
+ const _EGLScreen *scrn = disp->Screens->Elements[scrnum];
EGLint i;
/* search list of modes for handle */
for (i = 0; i < scrn->NumModes; i++) {
diff --git a/src/egl/main/eglscreen.c b/src/egl/main/eglscreen.c
index c47afd6abda..8f96fd935c7 100644
--- a/src/egl/main/eglscreen.c
+++ b/src/egl/main/eglscreen.c
@@ -62,9 +62,13 @@ _eglLookupScreen(EGLScreenMESA screen, _EGLDisplay *display)
{
EGLint i;
- for (i = 0; i < display->NumScreens; i++) {
- if (display->Screens[i]->Handle == screen)
- return display->Screens[i];
+ if (!display->Screens)
+ return NULL;
+
+ for (i = 0; i < display->Screens->Size; i++) {
+ _EGLScreen *scr = (_EGLScreen *) display->Screens->Elements[i];
+ if (scr->Handle == screen)
+ return scr;
}
return NULL;
}
@@ -76,40 +80,36 @@ _eglLookupScreen(EGLScreenMESA screen, _EGLDisplay *display)
void
_eglAddScreen(_EGLDisplay *display, _EGLScreen *screen)
{
- EGLint n;
-
assert(display);
assert(screen);
+ if (!display->Screens) {
+ display->Screens = _eglCreateArray("Screen", 4);
+ if (!display->Screens)
+ return;
+ }
screen->Handle = _eglAllocScreenHandle();
- n = display->NumScreens;
- display->Screens = realloc(display->Screens, (n+1) * sizeof(_EGLScreen *));
- display->Screens[n] = screen;
- display->NumScreens++;
+ _eglAppendArray(display->Screens, (void *) screen);
}
+static EGLBoolean
+_eglFlattenScreen(void *elem, void *buffer)
+{
+ _EGLScreen *scr = (_EGLScreen *) elem;
+ EGLScreenMESA *handle = (EGLScreenMESA *) buffer;
+ *handle = scr->Handle;
+ return EGL_TRUE;
+}
+
+
EGLBoolean
_eglGetScreensMESA(_EGLDriver *drv, _EGLDisplay *display, EGLScreenMESA *screens,
EGLint max_screens, EGLint *num_screens)
{
- EGLint n;
-
- if (display->NumScreens > max_screens) {
- n = max_screens;
- }
- else {
- n = display->NumScreens;
- }
-
- if (screens) {
- EGLint i;
- for (i = 0; i < n; i++)
- screens[i] = display->Screens[i]->Handle;
- }
- if (num_screens)
- *num_screens = n;
+ *num_screens = _eglFlattenArray(display->Screens, (void *) screens,
+ sizeof(screens[0]), max_screens, _eglFlattenScreen);
return EGL_TRUE;
}
diff --git a/src/egl/main/egltypedefs.h b/src/egl/main/egltypedefs.h
index 166b133909e..0e29e9aa47e 100644
--- a/src/egl/main/egltypedefs.h
+++ b/src/egl/main/egltypedefs.h
@@ -10,6 +10,8 @@
typedef struct _egl_api _EGLAPI;
+typedef struct _egl_array _EGLArray;
+
typedef struct _egl_config _EGLConfig;
typedef struct _egl_context _EGLContext;