X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fegl%2Fmain%2Fegldriver.c;h=2f42e64fbe00ef1849a7104569ef453a26c05960;hb=a7d15d2ae3a6b0cbf6770ae50eff58ec2dd506e1;hp=018b06d3bea77022566413aa47e14fef8f6441f0;hpb=49d402e275cdaf46de8db5a475dfe00509141195;p=mesa.git diff --git a/src/egl/main/egldriver.c b/src/egl/main/egldriver.c index 018b06d3bea..987b4b333ea 100644 --- a/src/egl/main/egldriver.c +++ b/src/egl/main/egldriver.c @@ -1,3 +1,33 @@ +/************************************************************************** + * + * Copyright 2008 VMware, Inc. + * Copyright 2009-2010 Chia-I Wu + * Copyright 2010-2011 LunarG, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + /** * Functions for choosing and opening/loading device drivers. */ @@ -7,477 +37,55 @@ #include #include #include -#include "eglconfig.h" -#include "eglcontext.h" +#include "c11/threads.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 -#endif - - -/** - * Wrappers for dlopen/dlclose() - */ -#if defined(_EGL_PLATFORM_WINDOWS) - - -/* XXX Need to decide how to do dynamic name lookup on Windows */ -static const char DefaultDriverName[] = "TBD"; - -typedef HMODULE lib_handle; - -static HMODULE -open_library(const char *filename) -{ - return LoadLibrary(filename); -} - -static void -close_library(HMODULE lib) -{ - FreeLibrary(lib); -} - - -#elif defined(_EGL_PLATFORM_X) - - -static const char DefaultDriverName[] = "egl_softpipe"; - -typedef void * lib_handle; - -static void * -open_library(const char *filename) -{ - return dlopen(filename, RTLD_LAZY); -} - -static void -close_library(void *lib) -{ - dlclose(lib); -} - -#else /* _EGL_PLATFORM_NO_OS */ - -static const char DefaultDriverName[] = "builtin"; - -typedef void *lib_handle; - -static INLINE void * -open_library(const char *filename) -{ - return (void *) filename; -} - -static INLINE void -close_library(void *lib) -{ -} - - -#endif - - -/** - * Choose a driver for a given display. - * The caller may free() the returned strings. - */ -static char * -_eglChooseDriver(_EGLDisplay *dpy, char **argsRet) -{ - char *path = NULL; - const char *args = NULL; - const char *suffix = NULL; - const char *p; - - path = getenv("EGL_DRIVER"); - if (path) - path = _eglstrdup(path); - -#if defined(_EGL_PLATFORM_X) - if (!path && dpy && dpy->NativeDisplay) { - /* assume (wrongly!) that the native display is a display string */ - path = _eglSplitDisplayString((const char *) dpy->NativeDisplay, &args); - } - suffix = "so"; -#elif defined(_EGL_PLATFORM_WINDOWS) - suffix = "dll"; -#else /* _EGL_PLATFORM_NO_OS */ - if (path) { - /* force the use of the default driver */ - _eglLog(_EGL_DEBUG, "ignore EGL_DRIVER"); - free(path); - path = NULL; - } - suffix = NULL; -#endif - - if (!path) - path = _eglstrdup(DefaultDriverName); - - /* append suffix if there isn't */ - p = strrchr(path, '.'); - if (!p && suffix) { - size_t len = strlen(path); - char *tmp = malloc(len + strlen(suffix) + 2); - if (tmp) { - memcpy(tmp, path, len); - tmp[len++] = '.'; - tmp[len] = '\0'; - strcat(tmp + len, suffix); - - free(path); - path = tmp; - } - } - - if (argsRet) - *argsRet = (args) ? _eglstrdup(args) : NULL; - - return path; -} - - -/** - * Open the named driver and find its bootstrap function: _eglMain(). - */ -static _EGLMain_t -_eglOpenLibrary(const char *driverPath, lib_handle *handle) -{ - lib_handle lib; - _EGLMain_t mainFunc = NULL; - const char *error = "unknown error"; - - assert(driverPath); - - _eglLog(_EGL_DEBUG, "dlopen(%s)", driverPath); - lib = open_library(driverPath); - -#if defined(_EGL_PLATFORM_WINDOWS) - /* XXX untested */ - if (lib) - mainFunc = (_EGLMain_t) GetProcAddress(lib, "_eglMain"); -#elif defined(_EGL_PLATFORM_X) - if (lib) { - mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain"); - if (!mainFunc) - error = dlerror(); - } - else { - error = dlerror(); - } -#else /* _EGL_PLATFORM_NO_OS */ - /* must be the default driver name */ - if (strcmp(driverPath, DefaultDriverName) == 0) - mainFunc = (_EGLMain_t) _eglMain; - else - error = "not builtin driver"; -#endif - - if (!lib) { - _eglLog(_EGL_WARNING, "Could not open driver %s (%s)", - driverPath, error); - if (!getenv("EGL_DRIVER")) - _eglLog(_EGL_WARNING, - "The driver can be overridden by setting EGL_DRIVER"); - return NULL; - } - - if (!mainFunc) { - _eglLog(_EGL_WARNING, "_eglMain not found in %s (%s)", - driverPath, error); - if (lib) - close_library(lib); - return NULL; - } - - *handle = lib; - return mainFunc; -} - - -/** - * Load the named driver. The path and args passed will be - * owned by the driver and freed. - */ -static _EGLDriver * -_eglLoadDriver(char *path, char *args) -{ - _EGLMain_t mainFunc; - lib_handle lib; - _EGLDriver *drv = NULL; - - mainFunc = _eglOpenLibrary(path, &lib); - if (!mainFunc) - return NULL; - - drv = mainFunc(args); - if (!drv) { - if (lib) - close_library(lib); - return NULL; - } - - if (!drv->Name) { - _eglLog(_EGL_WARNING, "Driver loaded from %s has no name", path); - drv->Name = "UNNAMED"; - } - drv->Path = path; - drv->Args = args; - drv->LibHandle = lib; - - return drv; -} +#include "util/debug.h" +extern const _EGLDriver _eglDriver; /** - * Match a display to a preloaded driver. + * Initialize the display using the driver's function. + * If the initialisation fails, try again using only software rendering. */ -static _EGLDriver * -_eglMatchDriver(_EGLDisplay *dpy) +bool +_eglInitializeDisplay(_EGLDisplay *disp) { - _EGLDriver *defaultDriver = NULL; - EGLint i; + assert(!disp->Initialized); - for (i = 0; i < _eglGlobal.NumDrivers; i++) { - _EGLDriver *drv = _eglGlobal.Drivers[i]; + /* set options */ + disp->Options.ForceSoftware = + env_var_as_boolean("LIBGL_ALWAYS_SOFTWARE", false); + if (disp->Options.ForceSoftware) + _eglLog(_EGL_DEBUG, "Found 'LIBGL_ALWAYS_SOFTWARE' set, will use a CPU renderer"); - /* display specifies a driver */ - if (dpy->DriverName) { - if (strcmp(dpy->DriverName, drv->Name) == 0) - return drv; - } - else if (drv->Probe) { - if (drv->Probe(drv, dpy)) - return drv; - } - else { - if (!defaultDriver) - defaultDriver = drv; - } + if (_eglDriver.Initialize(disp)) { + disp->Driver = &_eglDriver; + disp->Initialized = EGL_TRUE; + return true; } - return defaultDriver; -} - - -/** - * Load a driver and save it. - */ -const char * -_eglPreloadDriver(_EGLDisplay *dpy) -{ - char *path, *args; - _EGLDriver *drv; - EGLint i; - - path = _eglChooseDriver(dpy, &args); - if (!path) - return NULL; - - for (i = 0; i < _eglGlobal.NumDrivers; i++) { - drv = _eglGlobal.Drivers[i]; - if (strcmp(drv->Path, path) == 0) { - _eglLog(_EGL_DEBUG, "Driver %s is already preloaded", - drv->Name); - free(path); - if (args) - free(args); - return drv->Name; - } - } + if (disp->Options.ForceSoftware) + return false; - drv = _eglLoadDriver(path, args); - if (!drv) - return NULL; + disp->Options.ForceSoftware = EGL_TRUE; + if (!_eglDriver.Initialize(disp)) + return false; - _eglGlobal.Drivers[_eglGlobal.NumDrivers++] = drv; - - return drv->Name; -} - - -/** - * Open a preloaded driver. - */ -_EGLDriver * -_eglOpenDriver(_EGLDisplay *dpy) -{ - _EGLDriver *drv = _eglMatchDriver(dpy); - return drv; -} - - -/** - * Close a preloaded driver. - */ -EGLBoolean -_eglCloseDriver(_EGLDriver *drv, _EGLDisplay *dpy) -{ - return EGL_TRUE; + disp->Driver = &_eglDriver; + disp->Initialized = EGL_TRUE; + return true; } - -/** - * Unload preloaded drivers. - */ -void -_eglUnloadDrivers(void) +__eglMustCastToProperFunctionPointerType +_eglGetDriverProc(const char *procname) { - EGLint i; - 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; - } - - _eglGlobal.NumDrivers = 0; -} - - -/** - * 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.WaitClient = _eglWaitClient; - 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 */ -} - - - -/** - * Try to determine which EGL APIs (OpenGL, OpenGL ES, OpenVG, etc) - * are supported on the system by looking for standard library names. - */ -EGLint -_eglFindAPIs(void) -{ - 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"; -#else /* _EGL_PLATFORM_NO_OS */ - const char *es1_libname = NULL; - const char *es2_libname = NULL; - const char *gl_libname = NULL; - const char *vg_libname = NULL; -#endif - - if ((lib = open_library(es1_libname))) { - close_library(lib); - mask |= EGL_OPENGL_ES_BIT; - } - - 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; - } - - if ((lib = open_library(vg_libname))) { - close_library(lib); - mask |= EGL_OPENVG_BIT; - } + if (_eglDriver.GetProcAddress) + return _eglDriver.GetProcAddress(procname); - return mask; + return NULL; }