summaryrefslogtreecommitdiffstats
path: root/src/egl/main
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl/main')
-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
16 files changed, 713 insertions, 401 deletions
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;