From 655f4654675e601a9482e40d8e50156c965b8934 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 17 Feb 2010 17:30:44 +0800 Subject: [PATCH] egl: Always lock a display before using it. This gives a simple access control to the display. It is potentially slow, but a finer grained mutex can always be used in the future. The benefit of this simple approach is that drivers need not to worry about thread-safety. --- src/egl/main/eglapi.c | 125 +++++++++++++++++++++++++++--------------- src/egl/main/eglapi.h | 1 + 2 files changed, 81 insertions(+), 45 deletions(-) diff --git a/src/egl/main/eglapi.c b/src/egl/main/eglapi.c index d5e69a6e25c..2de1ac33184 100644 --- a/src/egl/main/eglapi.c +++ b/src/egl/main/eglapi.c @@ -71,9 +71,13 @@ /** * Macros to help return an API entrypoint. + * + * These macros will unlock the display and record the error code. */ #define _EGL_ERROR(disp, err, ret) \ ({ \ + if (disp) \ + _eglUnlockDisplay(disp); \ /* EGL error codes are non-zero */ \ if (err) \ _eglError(err, __FUNCTION__); \ @@ -206,6 +210,29 @@ _eglCheckMode(_EGLDisplay *disp, _EGLMode *m, const char *msg) #endif /* EGL_MESA_screen_surface */ +/** + * Lookup and lock a display. + */ +static INLINE _EGLDisplay * +_eglLockDisplay(EGLDisplay display) +{ + _EGLDisplay *dpy = _eglLookupDisplay(display); + if (dpy) + _eglLockMutex(&dpy->Mutex); + return dpy; +} + + +/** + * Unlock a display. + */ +static INLINE void +_eglUnlockDisplay(_EGLDisplay *dpy) +{ + _eglUnlockMutex(&dpy->Mutex); +} + + /** * This is typically the first EGL function that an application calls. * It associates a private _EGLDisplay object to the native display. @@ -225,7 +252,7 @@ eglGetDisplay(EGLNativeDisplayType nativeDisplay) EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); EGLint major_int, minor_int; if (!disp) @@ -273,7 +300,7 @@ eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor) EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); if (!disp) return _EGL_ERROR(NULL, EGL_BAD_DISPLAY, EGL_FALSE); @@ -293,7 +320,7 @@ eglTerminate(EGLDisplay dpy) const char * EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLDriver *drv; const char *ret; @@ -308,7 +335,7 @@ EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLDriver *drv; EGLBoolean ret; @@ -323,7 +350,7 @@ EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLDriver *drv; EGLBoolean ret; @@ -339,7 +366,7 @@ EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); _EGLDriver *drv; EGLBoolean ret; @@ -355,7 +382,7 @@ EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); _EGLContext *share = _eglLookupContext(share_list, disp); _EGLDriver *drv; @@ -376,7 +403,7 @@ eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_list, EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLContext *context = _eglLookupContext(ctx, disp); _EGLDriver *drv; EGLBoolean ret; @@ -393,7 +420,7 @@ EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLContext *context = _eglLookupContext(ctx, disp); _EGLSurface *draw_surf = _eglLookupSurface(draw, disp); _EGLSurface *read_surf = _eglLookupSurface(read, disp); @@ -429,7 +456,7 @@ EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLContext *context = _eglLookupContext(ctx, disp); _EGLDriver *drv; EGLBoolean ret; @@ -445,7 +472,7 @@ EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType window, const EGLint *attrib_list) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); _EGLDriver *drv; _EGLSurface *surf; @@ -464,7 +491,7 @@ EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); _EGLDriver *drv; _EGLSurface *surf; @@ -483,7 +510,7 @@ EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); _EGLDriver *drv; _EGLSurface *surf; @@ -501,7 +528,7 @@ eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); _EGLDriver *drv; EGLBoolean ret; @@ -517,7 +544,7 @@ EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); _EGLDriver *drv; EGLBoolean ret; @@ -532,7 +559,7 @@ EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); _EGLDriver *drv; EGLBoolean ret; @@ -547,7 +574,7 @@ eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); _EGLDriver *drv; EGLBoolean ret; @@ -562,7 +589,7 @@ eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); _EGLDriver *drv; EGLBoolean ret; @@ -577,7 +604,7 @@ eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer) EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLContext *ctx = _eglGetCurrentContext(); _EGLSurface *surf; _EGLDriver *drv; @@ -602,7 +629,7 @@ EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) { _EGLContext *ctx = _eglGetCurrentContext(); - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); _EGLDriver *drv; EGLBoolean ret; @@ -622,7 +649,7 @@ eglSwapBuffers(EGLDisplay dpy, EGLSurface surface) EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLSurface *surf = _eglLookupSurface(surface, disp); _EGLDriver *drv; EGLBoolean ret; @@ -644,18 +671,20 @@ eglWaitClient(void) if (!ctx) return _EGL_SUCCESS(NULL, EGL_TRUE); - /* let bad current context imply bad current surface */ - if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface)) - return _EGL_ERROR(NULL, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); disp = ctx->Resource.Display; + _eglLockMutex(&disp->Mutex); + + /* let bad current context imply bad current surface */ + if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface)) + 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.WaitClient(drv, disp, ctx); - return _EGL_EVAL(NULL, ret); + return _EGL_EVAL(disp, ret); } @@ -692,18 +721,19 @@ eglWaitNative(EGLint engine) if (!ctx) return _EGL_SUCCESS(NULL, EGL_TRUE); + disp = ctx->Resource.Display; + _eglLockMutex(&disp->Mutex); + /* let bad current context imply bad current surface */ if (!_eglIsContextLinked(ctx) || !_eglIsSurfaceLinked(ctx->DrawSurface)) - return _EGL_ERROR(NULL, EGL_BAD_CURRENT_SURFACE, EGL_FALSE); - - disp = ctx->Resource.Display; + 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(NULL, ret); + return _EGL_EVAL(disp, ret); } @@ -844,7 +874,7 @@ eglChooseModeMESA(EGLDisplay dpy, EGLScreenMESA screen, const EGLint *attrib_list, EGLModeMESA *modes, EGLint modes_size, EGLint *num_modes) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLScreen *scrn = _eglLookupScreen(screen, disp); _EGLDriver *drv; EGLBoolean ret; @@ -861,7 +891,7 @@ EGLBoolean EGLAPIENTRY eglGetModesMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *modes, EGLint mode_size, EGLint *num_mode) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLScreen *scrn = _eglLookupScreen(screen, disp); _EGLDriver *drv; EGLBoolean ret; @@ -877,7 +907,7 @@ EGLBoolean EGLAPIENTRY eglGetModeAttribMESA(EGLDisplay dpy, EGLModeMESA mode, EGLint attribute, EGLint *value) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLMode *m = _eglLookupMode(mode, disp); _EGLDriver *drv; EGLBoolean ret; @@ -893,7 +923,7 @@ EGLBoolean EGLAPIENTRY eglCopyContextMESA(EGLDisplay dpy, EGLContext source, EGLContext dest, EGLint mask) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLContext *source_context = _eglLookupContext(source, disp); _EGLContext *dest_context = _eglLookupContext(dest, disp); _EGLDriver *drv; @@ -914,7 +944,7 @@ EGLBoolean eglGetScreensMESA(EGLDisplay dpy, EGLScreenMESA *screens, EGLint max_screens, EGLint *num_screens) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLDriver *drv; EGLBoolean ret; @@ -929,7 +959,7 @@ EGLSurface eglCreateScreenSurfaceMESA(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); _EGLDriver *drv; _EGLSurface *surf; @@ -948,7 +978,7 @@ EGLBoolean eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLSurface surface, EGLModeMESA mode) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp); _EGLSurface *surf = _eglLookupSurface(surface, disp); _EGLMode *m = _eglLookupMode(mode, disp); @@ -970,7 +1000,7 @@ eglShowScreenSurfaceMESA(EGLDisplay dpy, EGLint screen, EGLBoolean eglScreenPositionMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint x, EGLint y) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLScreen *scrn = _eglLookupScreen(screen, disp); _EGLDriver *drv; EGLBoolean ret; @@ -986,7 +1016,7 @@ EGLBoolean eglQueryScreenMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLint attribute, EGLint *value) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLScreen *scrn = _eglLookupScreen(screen, disp); _EGLDriver *drv; EGLBoolean ret; @@ -1002,7 +1032,7 @@ EGLBoolean eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLSurface *surface) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp); _EGLDriver *drv; _EGLSurface *surf; @@ -1020,7 +1050,7 @@ eglQueryScreenSurfaceMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLBoolean eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLScreen *scrn = _eglLookupScreen((EGLScreenMESA) screen, disp); _EGLDriver *drv; _EGLMode *m; @@ -1038,7 +1068,7 @@ eglQueryScreenModeMESA(EGLDisplay dpy, EGLScreenMESA screen, EGLModeMESA *mode) const char * eglQueryModeStringMESA(EGLDisplay dpy, EGLModeMESA mode) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLMode *m = _eglLookupMode(mode, disp); _EGLDriver *drv; const char *ret; @@ -1109,7 +1139,7 @@ eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLConfig *conf = _eglLookupConfig(config, disp); _EGLDriver *drv; _EGLSurface *surf; @@ -1138,9 +1168,14 @@ eglReleaseThread(void) _EGLContext *ctx = t->CurrentContexts[i]; if (ctx) { _EGLDisplay *disp = ctx->Resource.Display; - _EGLDriver *drv = disp->Driver; + _EGLDriver *drv; + t->CurrentAPIIndex = i; + + _eglLockMutex(&disp->Mutex); + drv = disp->Driver; (void) drv->API.MakeCurrent(drv, disp, NULL, NULL, NULL); + _eglUnlockMutex(&disp->Mutex); } } @@ -1163,7 +1198,7 @@ EGLImageKHR eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLint *attr_list) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLContext *context = _eglLookupContext(ctx, disp); _EGLDriver *drv; _EGLImage *img; @@ -1184,7 +1219,7 @@ eglCreateImageKHR(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLBoolean eglDestroyImageKHR(EGLDisplay dpy, EGLImageKHR image) { - _EGLDisplay *disp = _eglLookupDisplay(dpy); + _EGLDisplay *disp = _eglLockDisplay(dpy); _EGLImage *img = _eglLookupImage(image, disp); _EGLDriver *drv; EGLBoolean ret; diff --git a/src/egl/main/eglapi.h b/src/egl/main/eglapi.h index c3676ec56a1..3e2ba8dd415 100644 --- a/src/egl/main/eglapi.h +++ b/src/egl/main/eglapi.h @@ -45,6 +45,7 @@ typedef const char *(*QueryString_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint n typedef EGLBoolean (*WaitClient_t)(_EGLDriver *drv, _EGLDisplay *dpy, _EGLContext *ctx); typedef EGLBoolean (*WaitNative_t)(_EGLDriver *drv, _EGLDisplay *dpy, EGLint engine); +/* this function may be called from multiple threads at the same time */ typedef _EGLProc (*GetProcAddress_t)(_EGLDriver *drv, const char *procname); -- 2.30.2