diff options
Diffstat (limited to 'src/egl')
-rw-r--r-- | src/egl/drivers/dri2/Makefile | 6 | ||||
-rw-r--r-- | src/egl/drivers/dri2/egl_dri2.c | 268 | ||||
-rw-r--r-- | src/egl/drivers/glx/egl_glx.c | 16 | ||||
-rw-r--r-- | src/egl/main/Makefile | 15 | ||||
-rw-r--r-- | src/egl/main/SConscript | 3 | ||||
-rw-r--r-- | src/egl/main/eglapi.c | 102 | ||||
-rw-r--r-- | src/egl/main/eglarray.c | 180 | ||||
-rw-r--r-- | src/egl/main/eglarray.h | 57 | ||||
-rw-r--r-- | src/egl/main/eglconfig.c | 66 | ||||
-rw-r--r-- | src/egl/main/egldisplay.c | 74 | ||||
-rw-r--r-- | src/egl/main/egldisplay.h | 33 | ||||
-rw-r--r-- | src/egl/main/egldriver.c | 496 | ||||
-rw-r--r-- | src/egl/main/egldriver.h | 22 | ||||
-rw-r--r-- | src/egl/main/eglglobals.c | 2 | ||||
-rw-r--r-- | src/egl/main/eglglobals.h | 4 | ||||
-rw-r--r-- | src/egl/main/eglmisc.c | 1 | ||||
-rw-r--r-- | src/egl/main/eglmode.c | 7 | ||||
-rw-r--r-- | src/egl/main/eglscreen.c | 50 | ||||
-rw-r--r-- | src/egl/main/egltypedefs.h | 2 |
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; |