EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine) { _EGLContext *ctx = _eglGetCurrentContext(); _EGLDisplay *disp; _EGLDriver *drv; EGLBoolean ret; if (!ctx) RETURN_EGL_SUCCESS(NULL, EGL_TRUE); disp = ctx->Resource.Display; _eglLockMutex(&disp->Mutex); /* let bad current context imply bad current surface */ if (_eglGetContextHandle(ctx) == EGL_NO_CONTEXT || _eglGetSurfaceHandle(ctx->DrawSurface) == EGL_NO_SURFACE) RETURN_EGL_ERROR(disp, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); /* a valid current context implies an initialized current display */ assert(disp->Initialized); drv = disp->Driver; ret = drv->API.WaitNative(drv, disp, engine); RETURN_EGL_EVAL(disp, ret); }
/** * Match a display to a driver. The display is initialized unless test_only is * true. The matching is done by finding the first driver that can initialize * the display. */ _EGLDriver * _eglMatchDriver(_EGLDisplay *dpy, EGLBoolean test_only) { _EGLDriver *best_drv; assert(!dpy->Initialized); _eglLockMutex(&_eglModuleMutex); /* set options */ dpy->Options.TestOnly = test_only; dpy->Options.UseFallback = EGL_FALSE; best_drv = _eglMatchAndInitialize(dpy); if (!best_drv) { dpy->Options.UseFallback = EGL_TRUE; best_drv = _eglMatchAndInitialize(dpy); } _eglUnlockMutex(&_eglModuleMutex); if (best_drv) { _eglLog(_EGL_DEBUG, "the best driver is %s%s", best_drv->Name, (test_only) ? " (test only) " : ""); if (!test_only) { dpy->Driver = best_drv; dpy->Initialized = EGL_TRUE; } } return best_drv; }
EGLBoolean EGLAPIENTRY eglReleaseThread(void) { /* unbind current contexts */ if (!_eglIsCurrentThreadDummy()) { _EGLThreadInfo *t = _eglGetCurrentThread(); EGLint api_index = t->CurrentAPIIndex; EGLint i; for (i = 0; i < _EGL_API_NUM_APIS; i++) { _EGLContext *ctx = t->CurrentContexts[i]; if (ctx) { _EGLDisplay *disp = ctx->Resource.Display; _EGLDriver *drv; t->CurrentAPIIndex = i; _eglLockMutex(&disp->Mutex); drv = disp->Driver; (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL); _eglUnlockMutex(&disp->Mutex); } } t->CurrentAPIIndex = api_index; } _eglDestroyCurrentThread(); RETURN_EGL_SUCCESS(NULL, EGL_TRUE); }
/** * Log a message with message logger. * \param level one of _EGL_FATAL, _EGL_WARNING, _EGL_INFO, _EGL_DEBUG. */ void _eglLog(EGLint level, const char *fmtStr, ...) { va_list args; char msg[MAXSTRING]; int ret; /* one-time initialization; a little race here is fine */ if (!logging.initialized) _eglInitLogger(); if (level > logging.level || level < 0) return; _eglLockMutex(&logging.mutex); if (logging.logger) { va_start(args, fmtStr); ret = vsnprintf(msg, MAXSTRING, fmtStr, args); if (ret < 0 || ret >= MAXSTRING) strcpy(msg, "<message truncated>"); va_end(args); logging.logger(level, msg); logging.num_messages++; } _eglUnlockMutex(&logging.mutex); if (level == _EGL_FATAL) exit(1); /* or abort()? */ }
static boolean egl_g3d_st_manager_get_egl_image(struct st_manager *smapi, void *egl_image, struct st_egl_image *out) { struct egl_g3d_st_manager *gsmapi = egl_g3d_st_manager(smapi); EGLImageKHR handle = (EGLImageKHR) egl_image; _EGLImage *img; struct egl_g3d_image *gimg; /* this is called from state trackers */ _eglLockMutex(&gsmapi->display->Mutex); img = _eglLookupImage(handle, gsmapi->display); if (!img) { _eglUnlockMutex(&gsmapi->display->Mutex); return FALSE; } gimg = egl_g3d_image(img); out->texture = NULL; pipe_resource_reference(&out->texture, gimg->texture); out->level = gimg->level; out->layer = gimg->layer; _eglUnlockMutex(&gsmapi->display->Mutex); return TRUE; }
/** * Lookup and lock a display. */ static INLINE _EGLDisplay * _eglLockDisplay(EGLDisplay display) { _EGLDisplay *dpy = _eglLookupDisplay(display); if (dpy) _eglLockMutex(&dpy->Mutex); return dpy; }
/** * Return a new screen handle/ID. * NOTE: we never reuse these! */ static EGLScreenMESA _eglAllocScreenHandle(void) { EGLScreenMESA s; _eglLockMutex(&_eglNextScreenHandleMutex); s = _eglNextScreenHandle++; _eglUnlockMutex(&_eglNextScreenHandleMutex); return s; }
/** * Return a new screen handle/ID. * NOTE: we never reuse these! */ static EGLScreenMESA _eglAllocScreenHandle(void) { EGLScreenMESA s; _eglLockMutex(&_eglNextScreenHandleMutex); s = _eglNextScreenHandle; _eglNextScreenHandle += _EGL_SCREEN_MAX_MODES; _eglUnlockMutex(&_eglNextScreenHandleMutex); return s; }
/** * Link a display to itself and return the handle of the link. * The handle can be passed to client directly. */ EGLDisplay _eglLinkDisplay(_EGLDisplay *dpy) { _eglLockMutex(_eglGlobal.Mutex); dpy->Next = _eglGlobal.DisplayList; _eglGlobal.DisplayList = dpy; _eglUnlockMutex(_eglGlobal.Mutex); return (EGLDisplay) dpy; }
static INLINE void _eglFiniTSD(void) { _eglLockMutex(&_egl_TSDMutex); if (_egl_TSDInitialized) { _EGLThreadInfo *t = _eglGetTSD(); _egl_TSDInitialized = EGL_FALSE; if (t && _egl_FreeTSD) _egl_FreeTSD((void *) t); pthread_key_delete(_egl_TSD); } _eglUnlockMutex(&_egl_TSDMutex); }
/** * Return EGL_TRUE if the given handle is a valid handle to a display. */ EGLBoolean _eglCheckDisplayHandle(EGLDisplay dpy) { _EGLDisplay *cur; _eglLockMutex(_eglGlobal.Mutex); cur = _eglGlobal.DisplayList; while (cur) { if (cur == (_EGLDisplay *) dpy) break; cur = cur->Next; } _eglUnlockMutex(_eglGlobal.Mutex); return (cur != NULL); }
void _eglAddAtExitCall(void (*func)(void)) { if (func) { _eglLockMutex(_eglGlobal.Mutex); registered = EGL_TRUE; assert(_eglGlobal.NumAtExitCalls < ARRAY_SIZE(_eglGlobal.AtExitCalls)); _eglGlobal.AtExitCalls[_eglGlobal.NumAtExitCalls++] = func; _eglUnlockMutex(_eglGlobal.Mutex); } }
/** * Set the log reporting level. */ void _eglSetLogLevel(EGLint level) { switch (level) { case _EGL_FATAL: case _EGL_WARNING: case _EGL_INFO: case _EGL_DEBUG: _eglLockMutex(&logging.mutex); logging.level = level; _eglUnlockMutex(&logging.mutex); break; default: break; } }
void _eglAddAtExitCall(void (*func)(void)) { if (func) { static EGLBoolean registered = EGL_FALSE; _eglLockMutex(_eglGlobal.Mutex); if (!registered) { atexit(_eglAtExit); registered = EGL_TRUE; } assert(_eglGlobal.NumAtExitCalls < ARRAY_SIZE(_eglGlobal.AtExitCalls)); _eglGlobal.AtExitCalls[_eglGlobal.NumAtExitCalls++] = func; _eglUnlockMutex(_eglGlobal.Mutex); } }
/** * Find the display corresponding to the specified native display id in all * linked displays. */ _EGLDisplay * _eglFindDisplay(NativeDisplayType nativeDisplay) { _EGLDisplay *dpy; _eglLockMutex(_eglGlobal.Mutex); dpy = _eglGlobal.DisplayList; while (dpy) { if (dpy->NativeDisplay == nativeDisplay) { _eglUnlockMutex(_eglGlobal.Mutex); return dpy; } dpy = dpy->Next; } _eglUnlockMutex(_eglGlobal.Mutex); return NULL; }
static INLINE EGLBoolean _eglInitTSD(void (*dtor)(_EGLThreadInfo *)) { if (!_egl_TSDInitialized) { _eglLockMutex(&_egl_TSDMutex); /* check again after acquiring lock */ if (!_egl_TSDInitialized) { if (pthread_key_create(&_egl_TSD, (void (*)(void *)) dtor) != 0) { _eglUnlockMutex(&_egl_TSDMutex); return EGL_FALSE; } _egl_FreeTSD = dtor; _eglAddAtExitCall(_eglFiniTSD); _egl_TSDInitialized = EGL_TRUE; } _eglUnlockMutex(&_egl_TSDMutex); } return EGL_TRUE; }
/** * Set the function to be called when there is a message to log. * Note that the function will be called with an internal lock held. * Recursive logging is not allowed. */ void _eglSetLogProc(_EGLLogProc logger) { EGLint num_messages = 0; _eglLockMutex(&logging.mutex); if (logging.logger != logger) { logging.logger = logger; num_messages = logging.num_messages; logging.num_messages = 0; } _eglUnlockMutex(&logging.mutex); if (num_messages) _eglLog(_EGL_DEBUG, "New logger installed. " "Messages before the new logger might not be available."); }
/** * Unlink a linked display from itself. * Accessing an unlinked display should generate EGL_BAD_DISPLAY error. */ void _eglUnlinkDisplay(_EGLDisplay *dpy) { _EGLDisplay *prev; _eglLockMutex(_eglGlobal.Mutex); prev = _eglGlobal.DisplayList; if (prev != dpy) { while (prev) { if (prev->Next == dpy) break; prev = prev->Next; } assert(prev); prev->Next = dpy->Next; } else { _eglGlobal.DisplayList = dpy->Next; } _eglUnlockMutex(_eglGlobal.Mutex); }
/** * Find the display corresponding to the specified native display, or create a * new one. */ _EGLDisplay * _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->Platform == plat && dpy->PlatformDisplay == plat_dpy) break; dpy = dpy->Next; } /* create a new display */ if (!dpy) { dpy = calloc(1, sizeof(_EGLDisplay)); if (dpy) { _eglInitMutex(&dpy->Mutex); dpy->Platform = plat; dpy->PlatformDisplay = plat_dpy; /* add to the display list */ dpy->Next = _eglGlobal.DisplayList; _eglGlobal.DisplayList = dpy; } } _eglUnlockMutex(_eglGlobal.Mutex); return dpy; }
/** * Match a display to a driver. The display is initialized unless use_probe is * true. * * 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. */ _EGLDriver * _eglMatchDriver(_EGLDisplay *dpy, EGLBoolean use_probe) { _EGLModule *mod; _EGLDriver *best_drv = NULL; EGLint best_score = 0; EGLint major, minor, i; _eglLockMutex(&_eglModuleMutex); 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++; } } } _eglUnlockMutex(&_eglModuleMutex); 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 best_drv; }