summaryrefslogtreecommitdiff
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.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c
new file mode 100644
index 0000000000..bda06dd827
--- /dev/null
+++ b/src/egl/main/egldriver.c
@@ -0,0 +1,272 @@
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+#include "eglconfig.h"
+#include "eglcontext.h"
+#include "egldisplay.h"
+#include "egldriver.h"
+#include "eglglobals.h"
+#include "egllog.h"
+#include "eglmode.h"
+#include "eglscreen.h"
+#include "eglsurface.h"
+
+
+const char *DefaultDriverName = "demodriver";
+
+
+/**
+ * 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.
+ *
+ * Now we'll use the NativeDisplayType value.
+ *
+ * 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".
+ */
+_EGLDriver *
+_eglChooseDriver(EGLDisplay display)
+{
+ _EGLDisplay *dpy = _eglLookupDisplay(display);
+ _EGLDriver *drv;
+ const char *driverName = DefaultDriverName;
+ const char *name;
+
+ assert(dpy);
+
+ name = dpy->Name;
+ if (!name) {
+ /* use default */
+ }
+ else if (name[0] == ':' && (name[1] >= '0' && name[1] <= '9') && !name[2]) {
+ /* XXX probe hardware here to determine which driver to open */
+ driverName = "libEGLdri";
+ }
+ else if (name[0] == '!') {
+ /* use specified driver name */
+ driverName = name + 1;
+ }
+ else {
+ /* Maybe display was returned by XOpenDisplay? */
+ _eglLog(_EGL_FATAL, "eglChooseDriver() bad name");
+ }
+
+ _eglLog(_EGL_INFO, "eglChooseDriver() choosing %s", driverName);
+
+ drv = _eglOpenDriver(dpy, driverName);
+ dpy->Driver = drv;
+
+ return drv;
+}
+
+
+/**
+ * Open/load the named driver and call its bootstrap function: _eglMain().
+ * \return new _EGLDriver object.
+ */
+_EGLDriver *
+_eglOpenDriver(_EGLDisplay *dpy, const char *driverName)
+{
+ _EGLDriver *drv;
+ _EGLMain_t mainFunc;
+ void *lib;
+ char driverFilename[1000];
+
+ /* XXX also prepend a directory path??? */
+ sprintf(driverFilename, "%s.so", driverName);
+
+ _eglLog(_EGL_DEBUG, "dlopen(%s)", driverFilename);
+ lib = dlopen(driverFilename, RTLD_NOW);
+ if (!lib) {
+ _eglLog(_EGL_WARNING, "Could not open %s (%s)",
+ driverFilename, dlerror());
+ return NULL;
+ }
+
+ mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain");
+ if (!mainFunc) {
+ _eglLog(_EGL_WARNING, "_eglMain not found in %s", driverFilename);
+ dlclose(lib);
+ return NULL;
+ }
+
+ drv = mainFunc(dpy);
+ if (!drv) {
+ dlclose(lib);
+ return NULL;
+ }
+ /* with a recurvise open you want the inner most handle */
+ if (!drv->LibHandle)
+ drv->LibHandle = lib;
+ else
+ dlclose(lib);
+
+ drv->Display = dpy;
+ return drv;
+}
+
+
+EGLBoolean
+_eglCloseDriver(_EGLDriver *drv, EGLDisplay dpy)
+{
+ void *handle = drv->LibHandle;
+ EGLBoolean b;
+
+ _eglLog(_EGL_INFO, "Closing driver");
+
+ /*
+ * XXX check for currently bound context/surfaces and delete them?
+ */
+
+ b = drv->API.Terminate(drv, dpy);
+ dlclose(handle);
+ return b;
+}
+
+
+/**
+ * Given a display handle, return the _EGLDriver for that display.
+ */
+_EGLDriver *
+_eglLookupDriver(EGLDisplay dpy)
+{
+ _EGLDisplay *d = _eglLookupDisplay(dpy);
+ if (d)
+ return d->Driver;
+ else
+ return NULL;
+}
+
+
+/**
+ * Plug all the available fallback routines into the given driver's
+ * dispatch table.
+ */
+void
+_eglInitDriverFallbacks(_EGLDriver *drv)
+{
+ /* If a pointer is set to NULL, then the device driver _really_ has
+ * to implement it.
+ */
+ drv->API.Initialize = NULL;
+ drv->API.Terminate = NULL;
+
+ drv->API.GetConfigs = _eglGetConfigs;
+ drv->API.ChooseConfig = _eglChooseConfig;
+ drv->API.GetConfigAttrib = _eglGetConfigAttrib;
+
+ drv->API.CreateContext = _eglCreateContext;
+ drv->API.DestroyContext = _eglDestroyContext;
+ drv->API.MakeCurrent = _eglMakeCurrent;
+ drv->API.QueryContext = _eglQueryContext;
+
+ drv->API.CreateWindowSurface = _eglCreateWindowSurface;
+ drv->API.CreatePixmapSurface = _eglCreatePixmapSurface;
+ drv->API.CreatePbufferSurface = _eglCreatePbufferSurface;
+ drv->API.DestroySurface = _eglDestroySurface;
+ drv->API.QuerySurface = _eglQuerySurface;
+ drv->API.SurfaceAttrib = _eglSurfaceAttrib;
+ drv->API.BindTexImage = _eglBindTexImage;
+ drv->API.ReleaseTexImage = _eglReleaseTexImage;
+ drv->API.SwapInterval = _eglSwapInterval;
+ drv->API.SwapBuffers = _eglSwapBuffers;
+ drv->API.CopyBuffers = _eglCopyBuffers;
+
+ drv->API.QueryString = _eglQueryString;
+ drv->API.WaitGL = _eglWaitGL;
+ drv->API.WaitNative = _eglWaitNative;
+
+#ifdef EGL_MESA_screen_surface
+ drv->API.ChooseModeMESA = _eglChooseModeMESA;
+ drv->API.GetModesMESA = _eglGetModesMESA;
+ drv->API.GetModeAttribMESA = _eglGetModeAttribMESA;
+ drv->API.GetScreensMESA = _eglGetScreensMESA;
+ drv->API.CreateScreenSurfaceMESA = _eglCreateScreenSurfaceMESA;
+ drv->API.ShowScreenSurfaceMESA = _eglShowScreenSurfaceMESA;
+ drv->API.ScreenPositionMESA = _eglScreenPositionMESA;
+ drv->API.QueryScreenMESA = _eglQueryScreenMESA;
+ drv->API.QueryScreenSurfaceMESA = _eglQueryScreenSurfaceMESA;
+ drv->API.QueryScreenModeMESA = _eglQueryScreenModeMESA;
+ drv->API.QueryModeStringMESA = _eglQueryModeStringMESA;
+#endif /* EGL_MESA_screen_surface */
+
+#ifdef EGL_VERSION_1_2
+ drv->API.CreatePbufferFromClientBuffer = _eglCreatePbufferFromClientBuffer;
+#endif /* EGL_VERSION_1_2 */
+}
+
+
+/**
+ * Examine the individual extension enable/disable flags and recompute
+ * the driver's Extensions string.
+ */
+static void
+_eglUpdateExtensionsString(_EGLDriver *drv)
+{
+ drv->Extensions.String[0] = 0;
+
+ if (drv->Extensions.MESA_screen_surface)
+ strcat(drv->Extensions.String, "EGL_MESA_screen_surface ");
+ if (drv->Extensions.MESA_copy_context)
+ strcat(drv->Extensions.String, "EGL_MESA_copy_context ");
+ assert(strlen(drv->Extensions.String) < MAX_EXTENSIONS_LEN);
+}
+
+
+
+const char *
+_eglQueryString(_EGLDriver *drv, EGLDisplay dpy, EGLint name)
+{
+ (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;
+#endif
+ default:
+ _eglError(EGL_BAD_PARAMETER, "eglQueryString");
+ return NULL;
+ }
+}
+
+
+EGLBoolean
+_eglWaitGL(_EGLDriver *drv, EGLDisplay dpy)
+{
+ /* just a placeholder */
+ (void) drv;
+ (void) dpy;
+ return EGL_TRUE;
+}
+
+
+EGLBoolean
+_eglWaitNative(_EGLDriver *drv, EGLDisplay dpy, EGLint engine)
+{
+ /* just a placeholder */
+ (void) drv;
+ (void) dpy;
+ switch (engine) {
+ case EGL_CORE_NATIVE_ENGINE:
+ break;
+ default:
+ _eglError(EGL_BAD_PARAMETER, "eglWaitNative(engine)");
+ return EGL_FALSE;
+ }
+
+ return EGL_TRUE;
+}