aboutsummaryrefslogtreecommitdiffstats
path: root/src/egl/main/egldriver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/egl/main/egldriver.c')
-rw-r--r--src/egl/main/egldriver.c363
1 files changed, 258 insertions, 105 deletions
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
index bda06dd827d..43b1f519034 100644
--- a/src/egl/main/egldriver.c
+++ b/src/egl/main/egldriver.c
@@ -1,112 +1,277 @@
+/**
+ * Functions for choosing and opening/loading device drivers.
+ */
+
+
#include <assert.h>
-#include <dlfcn.h>
-#include <stdio.h>
#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
#include "eglconfig.h"
#include "eglcontext.h"
+#include "egldefines.h"
#include "egldisplay.h"
#include "egldriver.h"
#include "eglglobals.h"
#include "egllog.h"
+#include "eglmisc.h"
#include "eglmode.h"
#include "eglscreen.h"
+#include "eglstring.h"
#include "eglsurface.h"
+#if defined(_EGL_PLATFORM_X)
+#include <dlfcn.h>
+#include "eglx.h"
+#elif defined(_EGL_PLATFORM_WINDOWS)
+/* Use static linking on Windows for now */
+#define WINDOWS_STATIC_LINK
+#endif
+
+/**
+ * Wrappers for dlopen/dlclose()
+ */
+#if defined(_EGL_PLATFORM_WINDOWS)
+#ifdef WINDOWS_STATIC_LINK
+ static const char *DefaultDriverName = "Windows EGL Static Library";
+#else
+ /* XXX Need to decide how to do dynamic name lookup on Windows */
+ static const char *DefaultDriverName = "TBD";
+#endif
+ static const char *SysFS = NULL;
+ typedef HMODULE lib_handle;
+
+ static HMODULE
+ open_library(const char *filename)
+ {
+#ifdef WINDOWS_STATIC_LINK
+ return 0;
+#else
+ return LoadLibrary(filename);
+#endif
+ }
+
+ static void
+ close_library(HMODULE lib)
+ {
+#ifdef WINDOWS_STATIC_LINK
+#else
+ FreeLibrary(lib);
+#endif
+ }
+
+#elif defined(_EGL_PLATFORM_X)
+ static const char *DefaultDriverName = ":0";
+ static const char *SysFS = "/sys/class";
+
+ typedef void * lib_handle;
+
+ static void *
+ open_library(const char *filename)
+ {
+ return dlopen(filename, RTLD_LAZY);
+ }
+
+ static void
+ close_library(void *lib)
+ {
+ dlclose(lib);
+ }
+
+#endif
+
+/**
+ * Given a card number, use sysfs to determine the DRI driver name.
+ */
+const char *
+_eglChooseDRMDriver(int card)
+{
+#if 0
+ return _eglstrdup("libEGLdri");
+#else
+ char path[2000], driverName[2000];
+ FILE *f;
+ int length;
+
+ snprintf(path, sizeof(path), "%s/drm/card%d/dri_library_name", SysFS, card);
+
+ f = fopen(path, "r");
+ if (!f)
+ return NULL;
-const char *DefaultDriverName = "demodriver";
+ fgets(driverName, sizeof(driverName), f);
+ fclose(f);
+ if ((length = strlen(driverName)) > 1) {
+ /* remove the trailing newline from sysfs */
+ driverName[length - 1] = '\0';
+ strncat(driverName, "_dri", sizeof(driverName));
+ return _eglstrdup(driverName);
+ }
+ else {
+ return NULL;
+ }
+#endif
+}
/**
- * Choose and open/init the hardware driver for the given EGLDisplay.
- * Previously, the EGLDisplay was created with _eglNewDisplay() where
- * we recorded the user's NativeDisplayType parameter.
+ * XXX this function is totally subject change!!!
+ *
+ *
+ * Determine/return the name of the driver to use for the given _EGLDisplay.
*
- * Now we'll use the NativeDisplayType value.
+ * Try to be clever and determine if nativeDisplay is an Xlib Display
+ * ptr or a string (naming a driver or screen number, etc).
*
- * Currently, the native display value is treated as a string.
* If the first character is ':' we interpret it as a screen or card index
* number (i.e. ":0" or ":1", etc)
* Else if the first character is '!' we interpret it as specific driver name
* (i.e. "!r200" or "!i830".
+ *
+ * Whatever follows ':' is copied and put into dpy->DriverArgs.
+ *
+ * The caller may free() the returned string.
*/
-_EGLDriver *
-_eglChooseDriver(EGLDisplay display)
+const char *
+_eglChooseDriver(_EGLDisplay *dpy)
{
- _EGLDisplay *dpy = _eglLookupDisplay(display);
- _EGLDriver *drv;
- const char *driverName = DefaultDriverName;
- const char *name;
+ /* Under Windows, the NativeDisplay is an HDC handle, therefore */
+ /* it can't be interpreted as a string or a pointer. */
+#if defined(_EGL_PLATFORM_WINDOWS)
+ const char *displayString = NULL;
+#else
+ const char *displayString = (const char *) dpy->NativeDisplay;
+#endif
+ const char *driverName = NULL;
- assert(dpy);
+ (void) DefaultDriverName;
- name = dpy->Name;
- if (!name) {
- /* use default */
+#if defined(_EGL_PLATFORM_X)
+ /* First, if the EGL_DRIVER env var is set, use that */
+ driverName = getenv("EGL_DRIVER");
+ if (driverName)
+ return _eglstrdup(driverName);
+#endif
+
+#if 0
+ if (!displayString) {
+ /* choose a default */
+ displayString = DefaultDriverName;
}
- else if (name[0] == ':' && (name[1] >= '0' && name[1] <= '9') && !name[2]) {
- /* XXX probe hardware here to determine which driver to open */
- driverName = "libEGLdri";
+#endif
+ /* extract default DriverArgs = whatever follows ':' */
+ if (displayString &&
+ (displayString[0] == '!' ||
+ displayString[0] == ':')) {
+ const char *args = strchr(displayString, ':');
+ if (args)
+ dpy->DriverArgs = _eglstrdup(args + 1);
}
- else if (name[0] == '!') {
- /* use specified driver name */
- driverName = name + 1;
+
+ /* determine driver name now */
+ if (displayString && displayString[0] == ':' &&
+ (displayString[1] >= '0' && displayString[1] <= '9') &&
+ !displayString[2]) {
+ int card = atoi(displayString + 1);
+ driverName = _eglChooseDRMDriver(card);
}
- else {
- /* Maybe display was returned by XOpenDisplay? */
- _eglLog(_EGL_FATAL, "eglChooseDriver() bad name");
+ else if (displayString && displayString[0] == '!') {
+ /* use user-specified driver name */
+ driverName = _eglstrdup(displayString + 1);
+ /* truncate driverName at ':' if present */
+ {
+ char *args = strchr(driverName, ':');
+ if (args) {
+ *args = 0;
+ }
+ }
+ }
+ else
+ {
+ /* NativeDisplay is not a string! */
+#if defined(_EGL_PLATFORM_X)
+ driverName = _xeglChooseDriver(dpy);
+#else
+ driverName = DefaultDriverName;
+#endif
}
- _eglLog(_EGL_INFO, "eglChooseDriver() choosing %s", driverName);
-
- drv = _eglOpenDriver(dpy, driverName);
- dpy->Driver = drv;
-
- return drv;
+ return driverName;
}
/**
* Open/load the named driver and call its bootstrap function: _eglMain().
+ * By the time this function is called, the dpy->DriverName should have
+ * been determined.
+ *
* \return new _EGLDriver object.
*/
_EGLDriver *
-_eglOpenDriver(_EGLDisplay *dpy, const char *driverName)
+_eglOpenDriver(_EGLDisplay *dpy, const char *driverName, const char *args)
{
_EGLDriver *drv;
_EGLMain_t mainFunc;
- void *lib;
+ lib_handle lib;
char driverFilename[1000];
+ assert(driverName);
+
+#if defined(_EGL_PLATFORM_WINDOWS)
+/* Use static linking on Windows for now */
+#ifdef WINDOWS_STATIC_LINK
+ lib = 0;
+ mainFunc = (_EGLMain_t)_eglMain;
+#else
+ /* XXX untested */
+ sprintf(driverFilename, "%s.dll", driverName);
+ _eglLog(_EGL_DEBUG, "dlopen(%s)", driverFilename);
+ lib = open_library(driverFilename);
+ if (!lib) {
+ _eglLog(_EGL_WARNING, "Could not open %s",
+ driverFilename);
+ return NULL;
+ }
+ mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain");
+#endif
+#elif defined(_EGL_PLATFORM_X)
/* XXX also prepend a directory path??? */
sprintf(driverFilename, "%s.so", driverName);
-
_eglLog(_EGL_DEBUG, "dlopen(%s)", driverFilename);
- lib = dlopen(driverFilename, RTLD_NOW);
+ lib = open_library(driverFilename);
if (!lib) {
_eglLog(_EGL_WARNING, "Could not open %s (%s)",
driverFilename, dlerror());
return NULL;
}
-
mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
+#endif
+
if (!mainFunc) {
_eglLog(_EGL_WARNING, "_eglMain not found in %s", driverFilename);
- dlclose(lib);
+ close_library(lib);
return NULL;
}
- drv = mainFunc(dpy);
+ drv = mainFunc(dpy, args);
if (!drv) {
- dlclose(lib);
+ close_library(lib);
return NULL;
}
+
/* with a recurvise open you want the inner most handle */
- if (!drv->LibHandle)
+ if (!drv->LibHandle) {
drv->LibHandle = lib;
- else
- dlclose(lib);
+ }
+ else {
+ close_library(lib);
+ }
+
+ /* update the global notion of supported APIs */
+ _eglGlobal.ClientAPIsMask |= drv->ClientAPIsMask;
+
+ _eglSaveDriver(drv);
- drv->Display = dpy;
return drv;
}
@@ -117,19 +282,31 @@ _eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy)
void *handle = drv->LibHandle;
EGLBoolean b;
- _eglLog(_EGL_INFO, "Closing driver");
+ _eglLog(_EGL_DEBUG, "Closing %s", drv->Name);
/*
* XXX check for currently bound context/surfaces and delete them?
*/
b = drv->API.Terminate(drv, dpy);
- dlclose(handle);
+
+ close_library(handle);
+
return b;
}
/**
+ * Save the given driver pointer in the list of all known drivers.
+ */
+void
+_eglSaveDriver(_EGLDriver *drv)
+{
+ _eglGlobal.Drivers[ _eglGlobal.NumDrivers++ ] = drv;
+}
+
+
+/**
* Given a display handle, return the _EGLDriver for that display.
*/
_EGLDriver *
@@ -201,72 +378,48 @@ _eglInitDriverFallbacks(_EGLDriver *drv)
}
+
/**
- * Examine the individual extension enable/disable flags and recompute
- * the driver's Extensions string.
+ * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc)
+ * are supported on the system by looking for standard library names.
*/
-static void
-_eglUpdateExtensionsString(_EGLDriver *drv)
-{
- drv->Extensions.String[0] = 0;
-
- if (drv->Extensions.MESA_screen_surface)
- strcat(drv->Extensions.String, "EGL_MESA_screen_surface ");
- if (drv->Extensions.MESA_copy_context)
- strcat(drv->Extensions.String, "EGL_MESA_copy_context ");
- assert(strlen(drv->Extensions.String) < MAX_EXTENSIONS_LEN);
-}
-
-
-
-const char *
-_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name)
+EGLint
+_eglFindAPIs(void)
{
- (void) drv;
- (void) dpy;
- switch (name) {
- case EGL_VENDOR:
- return "Mesa Project";
- case EGL_VERSION:
- return "1.0";
- case EGL_EXTENSIONS:
- _eglUpdateExtensionsString(drv);
- return drv->Extensions.String;
-#ifdef EGL_VERSION_1_2
- case EGL_CLIENT_APIS:
- /* XXX need to initialize somewhere */
- return drv->ClientAPIs;
+ EGLint mask = 0x0;
+ lib_handle lib;
+#if defined(_EGL_PLATFORM_WINDOWS)
+ /* XXX not sure about these names */
+ const char *es1_libname = "libGLESv1_CM.dll";
+ const char *es2_libname = "libGLESv2.dll";
+ const char *gl_libname = "OpenGL32.dll";
+ const char *vg_libname = "libOpenVG.dll";
+#elif defined(_EGL_PLATFORM_X)
+ const char *es1_libname = "libGLESv1_CM.so";
+ const char *es2_libname = "libGLESv2.so";
+ const char *gl_libname = "libGL.so";
+ const char *vg_libname = "libOpenVG.so";
#endif
- default:
- _eglError(EGL_BAD_PARAMETER, "eglQueryString");
- return NULL;
- }
-}
+ if ((lib = open_library(es1_libname))) {
+ close_library(lib);
+ mask |= EGL_OPENGL_ES_BIT;
+ }
-EGLBoolean
-_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy)
-{
- /* just a placeholder */
- (void) drv;
- (void) dpy;
- return EGL_TRUE;
-}
+ if ((lib = open_library(es2_libname))) {
+ close_library(lib);
+ mask |= EGL_OPENGL_ES2_BIT;
+ }
+ if ((lib = open_library(gl_libname))) {
+ close_library(lib);
+ mask |= EGL_OPENGL_BIT;
+ }
-EGLBoolean
-_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine)
-{
- /* just a placeholder */
- (void) drv;
- (void) dpy;
- switch (engine) {
- case EGL_CORE_NATIVE_ENGINE:
- break;
- default:
- _eglError(EGL_BAD_PARAMETER, "eglWaitNative(engine)");
- return EGL_FALSE;
+ if ((lib = open_library(vg_libname))) {
+ close_library(lib);
+ mask |= EGL_OPENVG_BIT;
}
- return EGL_TRUE;
+ return mask;
}