Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ca8dce91 authored by Yiwei Zhang's avatar Yiwei Zhang
Browse files

opengl: fix a race condition when unloading gl driver

Previously, EGL apis call clearError() at the first place including those core
apis which initialize the driver. Calling clearError() before the driver has
been loaded is basically a no-op.

Later the driver unloading mechanism was added to support Angle and updatable
driver with EGL/GL driver still preloaded in Zygote. However, calling
clearError() on another thread races with the driver unloading process. So this
change moves the clearError() calls after the driver has been successfully
unloaded and reloaded, so that the initial core apis will be protected by the
driver loading lock in the loader.

For those non-core apis, they could still be incorrectly called before calling
any of those core apis on another thread when the driver unloading and reloading
is still on going. Since this scenario is supposed to error out anyway, so the
apps need to use EGL apis correctly by themselves.

Bug: 140072978
Test: CtsAngleDeveloperOptionHostTest
Change-Id: Ica5b19edc0dfb0a0910f56c1442eaff63f76b35a
Merged-In: Ica5b19edc0dfb0a0910f56c1442eaff63f76b35a
parent 766c08dc
Loading
Loading
Loading
Loading
+7 −12
Original line number Original line Diff line number Diff line
@@ -40,7 +40,6 @@ static inline void clearError() {


EGLDisplay eglGetDisplay(EGLNativeDisplayType display) {
EGLDisplay eglGetDisplay(EGLNativeDisplayType display) {
    ATRACE_CALL();
    ATRACE_CALL();
    clearError();


    if (egl_init_drivers() == EGL_FALSE) {
    if (egl_init_drivers() == EGL_FALSE) {
        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
@@ -48,6 +47,7 @@ EGLDisplay eglGetDisplay(EGLNativeDisplayType display) {


    // Call down the chain, which usually points directly to the impl
    // Call down the chain, which usually points directly to the impl
    // but may also be routed through layers
    // but may also be routed through layers
    clearError();
    egl_connection_t* const cnx = &gEGLImpl;
    egl_connection_t* const cnx = &gEGLImpl;
    return cnx->platform.eglGetDisplay(display);
    return cnx->platform.eglGetDisplay(display);
}
}
@@ -55,7 +55,6 @@ EGLDisplay eglGetDisplay(EGLNativeDisplayType display) {
EGLDisplay eglGetPlatformDisplay(EGLenum platform, EGLNativeDisplayType display,
EGLDisplay eglGetPlatformDisplay(EGLenum platform, EGLNativeDisplayType display,
                                 const EGLAttrib* attrib_list) {
                                 const EGLAttrib* attrib_list) {
    ATRACE_CALL();
    ATRACE_CALL();
    clearError();


    if (egl_init_drivers() == EGL_FALSE) {
    if (egl_init_drivers() == EGL_FALSE) {
        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
        return setError(EGL_BAD_PARAMETER, EGL_NO_DISPLAY);
@@ -63,6 +62,7 @@ EGLDisplay eglGetPlatformDisplay(EGLenum platform, EGLNativeDisplayType display,


    // Call down the chain, which usually points directly to the impl
    // Call down the chain, which usually points directly to the impl
    // but may also be routed through layers
    // but may also be routed through layers
    clearError();
    egl_connection_t* const cnx = &gEGLImpl;
    egl_connection_t* const cnx = &gEGLImpl;
    return cnx->platform.eglGetPlatformDisplay(platform, display, attrib_list);
    return cnx->platform.eglGetPlatformDisplay(platform, display, attrib_list);
}
}
@@ -239,13 +239,12 @@ __eglMustCastToProperFunctionPointerType eglGetProcAddress(const char* procname)
    // in which case we must make sure we've initialized ourselves, this
    // in which case we must make sure we've initialized ourselves, this
    // happens the first time egl_get_display() is called.
    // happens the first time egl_get_display() is called.


    clearError();

    if (egl_init_drivers() == EGL_FALSE) {
    if (egl_init_drivers() == EGL_FALSE) {
        setError(EGL_BAD_PARAMETER, NULL);
        setError(EGL_BAD_PARAMETER, NULL);
        return nullptr;
        return nullptr;
    }
    }


    clearError();
    egl_connection_t* const cnx = &gEGLImpl;
    egl_connection_t* const cnx = &gEGLImpl;
    return cnx->platform.eglGetProcAddress(procname);
    return cnx->platform.eglGetProcAddress(procname);
}
}
@@ -324,23 +323,21 @@ EGLBoolean eglWaitClient(void) {
}
}


EGLBoolean eglBindAPI(EGLenum api) {
EGLBoolean eglBindAPI(EGLenum api) {
    clearError();

    if (egl_init_drivers() == EGL_FALSE) {
    if (egl_init_drivers() == EGL_FALSE) {
        return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
        return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
    }
    }


    clearError();
    egl_connection_t* const cnx = &gEGLImpl;
    egl_connection_t* const cnx = &gEGLImpl;
    return cnx->platform.eglBindAPI(api);
    return cnx->platform.eglBindAPI(api);
}
}


EGLenum eglQueryAPI(void) {
EGLenum eglQueryAPI(void) {
    clearError();

    if (egl_init_drivers() == EGL_FALSE) {
    if (egl_init_drivers() == EGL_FALSE) {
        return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
        return setError(EGL_BAD_PARAMETER, (EGLBoolean)EGL_FALSE);
    }
    }


    clearError();
    egl_connection_t* const cnx = &gEGLImpl;
    egl_connection_t* const cnx = &gEGLImpl;
    return cnx->platform.eglQueryAPI();
    return cnx->platform.eglQueryAPI();
}
}
@@ -595,23 +592,21 @@ EGLClientBuffer eglGetNativeClientBufferANDROID(const AHardwareBuffer* buffer) {
}
}


EGLuint64NV eglGetSystemTimeFrequencyNV() {
EGLuint64NV eglGetSystemTimeFrequencyNV() {
    clearError();

    if (egl_init_drivers() == EGL_FALSE) {
    if (egl_init_drivers() == EGL_FALSE) {
        return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
        return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
    }
    }


    clearError();
    egl_connection_t* const cnx = &gEGLImpl;
    egl_connection_t* const cnx = &gEGLImpl;
    return cnx->platform.eglGetSystemTimeFrequencyNV();
    return cnx->platform.eglGetSystemTimeFrequencyNV();
}
}


EGLuint64NV eglGetSystemTimeNV() {
EGLuint64NV eglGetSystemTimeNV() {
    clearError();

    if (egl_init_drivers() == EGL_FALSE) {
    if (egl_init_drivers() == EGL_FALSE) {
        return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
        return setError(EGL_BAD_PARAMETER, (EGLuint64NV)EGL_FALSE);
    }
    }


    clearError();
    egl_connection_t* const cnx = &gEGLImpl;
    egl_connection_t* const cnx = &gEGLImpl;
    return cnx->platform.eglGetSystemTimeNV();
    return cnx->platform.eglGetSystemTimeNV();
}
}