#include #include #include #include #include "eglconfig.h" #include "eglcontext.h" #include "egldisplay.h" #include "egldriver.h" #include "eglglobals.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]) { printf("EGL: Use driver for screen: %s\n", name); /* XXX probe hardware here to determine which driver to open */ driverName = "libEGLdri"; } else if (name[0] == '!') { /* use specified driver name */ driverName = name + 1; printf("EGL: Use driver named %s\n", driverName); } else { /* Maybe display was returned by XOpenDisplay? */ printf("EGL: can't parse display pointer\n"); } 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); lib = dlopen(driverFilename, RTLD_NOW); if (!lib) { fprintf(stderr, "EGLdebug: Error opening %s: %s\n", driverFilename, dlerror()); return NULL; } mainFunc = (_EGLMain_t) dlsym(lib, "_eglMain"); if (!mainFunc) { fprintf(stderr, "_eglMain not found in %s", (char *) 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; fprintf(stderr, "EGL debug: Closing driver\n"); /* * XXX check for currently bound context/surfaces and delete them? */ b = drv->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->Initialize = NULL; drv->Terminate = NULL; drv->GetConfigs = _eglGetConfigs; drv->ChooseConfig = _eglChooseConfig; drv->GetConfigAttrib = _eglGetConfigAttrib; drv->CreateContext = _eglCreateContext; drv->DestroyContext = _eglDestroyContext; drv->MakeCurrent = _eglMakeCurrent; drv->QueryContext = _eglQueryContext; drv->CreateWindowSurface = _eglCreateWindowSurface; drv->CreatePixmapSurface = _eglCreatePixmapSurface; drv->CreatePbufferSurface = _eglCreatePbufferSurface; drv->DestroySurface = _eglDestroySurface; drv->QuerySurface = _eglQuerySurface; drv->SurfaceAttrib = _eglSurfaceAttrib; drv->BindTexImage = _eglBindTexImage; drv->ReleaseTexImage = _eglReleaseTexImage; drv->SwapInterval = _eglSwapInterval; drv->SwapBuffers = _eglSwapBuffers; drv->CopyBuffers = _eglCopyBuffers; drv->QueryString = _eglQueryString; drv->WaitGL = _eglWaitGL; drv->WaitNative = _eglWaitNative; /* EGL_MESA_screen */ drv->ChooseModeMESA = _eglChooseModeMESA; drv->GetModesMESA = _eglGetModesMESA; drv->GetModeAttribMESA = _eglGetModeAttribMESA; drv->GetScreensMESA = _eglGetScreensMESA; drv->CreateScreenSurfaceMESA = _eglCreateScreenSurfaceMESA; drv->ShowSurfaceMESA = _eglShowSurfaceMESA; drv->ScreenPositionMESA = _eglScreenPositionMESA; drv->QueryScreenMESA = _eglQueryScreenMESA; drv->QueryScreenSurfaceMESA = _eglQueryScreenSurfaceMESA; drv->QueryScreenModeMESA = _eglQueryScreenModeMESA; drv->QueryModeStringMESA = _eglQueryModeStringMESA; } /** * Examine the individual extension enable/disable flags and recompute * the driver's Extensions string. */ static void UpdateExtensionsString(_EGLDriver *drv) { drv->Extensions[0] = 0; if (drv->MESA_screen_surface) strcat(drv->Extensions, "EGL_MESA_screen_surface "); if (drv->MESA_copy_context) strcat(drv->Extensions, "EGL_MESA_copy_context "); assert(strlen(drv->Extensions) < 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: UpdateExtensionsString(drv); return drv->Extensions; 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; (void) engine; return EGL_TRUE; }