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

Commit c1a1a869 authored by Courtney Goeltzenleuchter's avatar Courtney Goeltzenleuchter Committed by Yiwei Zhang
Browse files

Allow native driver to be ANGLE

There are ANGLE specific behaviors that need to be followed whenever
the driver in use is ANGLE. This change removes those behaviors from
the ANGLE load path and allows them to be applied to the "native"
driver if it is ANGLE.

This change removes the ability to select different ANGLE back-ends.
E.g. debug property: "debug.angle.backend" no longer works.
Only Vulkan will be used. The other back-ends are not used or tested
on Android and would be unusable on a production device where ANGLE
is the one and only OpenGL driver.

Test: atest CtsAngleIntegrationHostTestCases
Bug: b/154237217
Change-Id: Ia792f63d8c7b9411056b9277ff4b37fa566335f5
(cherry picked from commit d1646cfd)
parent 09d2771d
Loading
Loading
Loading
Loading
+25 −64
Original line number Original line Diff line number Diff line
@@ -271,6 +271,12 @@ void* Loader::open(egl_connection_t* cnx)
    if (!hnd) {
    if (!hnd) {
        android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL,
        android::GraphicsEnv::getInstance().setDriverLoaded(android::GpuStatsInfo::Api::API_GL,
                                                            false, systemTime() - openTime);
                                                            false, systemTime() - openTime);
    } else {
        // init_angle_backend will check if loaded driver is ANGLE or not,
        // will set cnx->useAngle appropriately.
        // Do this here so that we use ANGLE path when driver is ANGLE (e.g. loaded as native),
        // not just loading ANGLE as option.
        init_angle_backend(hnd->dso[0], cnx);
    }
    }


    LOG_ALWAYS_FATAL_IF(!hnd,
    LOG_ALWAYS_FATAL_IF(!hnd,
@@ -311,11 +317,6 @@ void Loader::close(egl_connection_t* cnx)
    cnx->dso = nullptr;
    cnx->dso = nullptr;


    cnx->useAngle = false;
    cnx->useAngle = false;

    if (cnx->vendorEGL) {
        dlclose(cnx->vendorEGL);
        cnx->vendorEGL = nullptr;
    }
}
}


void Loader::init_api(void* dso,
void Loader::init_api(void* dso,
@@ -482,7 +483,7 @@ static void* load_system_driver(const char* kind, const char* suffix, const bool
    return dso;
    return dso;
}
}


static void* load_angle_from_namespace(const char* kind, android_namespace_t* ns) {
static void* load_angle(const char* kind, android_namespace_t* ns) {
    const android_dlextinfo dlextinfo = {
    const android_dlextinfo dlextinfo = {
            .flags = ANDROID_DLEXT_USE_NAMESPACE,
            .flags = ANDROID_DLEXT_USE_NAMESPACE,
            .library_namespace = ns,
            .library_namespace = ns,
@@ -502,61 +503,6 @@ static void* load_angle_from_namespace(const char* kind, android_namespace_t* ns
    return nullptr;
    return nullptr;
}
}


static void* load_angle(const char* kind, android_namespace_t* ns, egl_connection_t* cnx) {
    void* so = load_angle_from_namespace(kind, ns);

    if (so) {
        ALOGV("Loaded ANGLE %s library for '%s' (instead of native)", kind,
            android::GraphicsEnv::getInstance().getAngleAppName().c_str());
        cnx->useAngle = true;

        char prop[PROPERTY_VALUE_MAX];

        property_get("debug.hwui.renderer", prop, "UNSET");
        ALOGV("Skia's renderer set to %s", prop);

        EGLint angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
        property_get("debug.angle.backend", prop, "0");
        switch (atoi(prop)) {
            case 1:
                ALOGV("%s: Requesting OpenGLES back-end", __FUNCTION__);
                angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE;
                break;
            case 2:
                ALOGV("%s: Requesting Vulkan back-end", __FUNCTION__);
                angleBackendDefault = EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE;
                break;
            default:
                break;
        }

        cnx->angleBackend = angleBackendDefault;
        if (!cnx->vendorEGL && (cnx->angleBackend == EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE)) {
            // Find and load vendor libEGL for ANGLE's GL back-end to use.
            char prop[PROPERTY_VALUE_MAX + 1];
            for (auto key : HAL_SUBNAME_KEY_PROPERTIES) {
                if (property_get(key, prop, nullptr) <= 0) {
                    continue;
                }
                void* dso = load_system_driver("EGL", prop, true);
                if (dso) {
                    cnx->vendorEGL = dso;
                    break;
                }
            }
            if (!cnx->vendorEGL) {
                cnx->vendorEGL = load_system_driver("EGL", nullptr, true);
            }
        }
    } else {
        ALOGV("Loaded native %s library for '%s' (instead of ANGLE)", kind,
            android::GraphicsEnv::getInstance().getAngleAppName().c_str());
        cnx->useAngle = false;
    }

    return so;
}

static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
static void* load_updated_driver(const char* kind, android_namespace_t* ns) {
    ATRACE_CALL();
    ATRACE_CALL();
    const android_dlextinfo dlextinfo = {
    const android_dlextinfo dlextinfo = {
@@ -594,22 +540,37 @@ Loader::driver_t* Loader::attempt_to_load_angle(egl_connection_t* cnx) {
    driver_t* hnd = nullptr;
    driver_t* hnd = nullptr;


    // ANGLE doesn't ship with GLES library, and thus we skip GLES driver.
    // ANGLE doesn't ship with GLES library, and thus we skip GLES driver.
    void* dso = load_angle("EGL", ns, cnx);
    void* dso = load_angle("EGL", ns);
    if (dso) {
    if (dso) {
        initialize_api(dso, cnx, EGL);
        initialize_api(dso, cnx, EGL);
        hnd = new driver_t(dso);
        hnd = new driver_t(dso);


        dso = load_angle("GLESv1_CM", ns, cnx);
        dso = load_angle("GLESv1_CM", ns);
        initialize_api(dso, cnx, GLESv1_CM);
        initialize_api(dso, cnx, GLESv1_CM);
        hnd->set(dso, GLESv1_CM);
        hnd->set(dso, GLESv1_CM);


        dso = load_angle("GLESv2", ns, cnx);
        dso = load_angle("GLESv2", ns);
        initialize_api(dso, cnx, GLESv2);
        initialize_api(dso, cnx, GLESv2);
        hnd->set(dso, GLESv2);
        hnd->set(dso, GLESv2);
    }
    }
    return hnd;
    return hnd;
}
}


void Loader::init_angle_backend(void* dso, egl_connection_t* cnx) {
    void* eglCreateDeviceANGLE = nullptr;

    ALOGV("dso: %p", dso);
    eglCreateDeviceANGLE = dlsym(dso, "eglCreateDeviceANGLE");
    ALOGV("eglCreateDeviceANGLE: %p", eglCreateDeviceANGLE);
    if (eglCreateDeviceANGLE) {
        ALOGV("ANGLE GLES library in use");
        cnx->useAngle = true;
    } else {
        ALOGV("Native GLES library in use");
        cnx->useAngle = false;
    }
}

Loader::driver_t* Loader::attempt_to_load_updated_driver(egl_connection_t* cnx) {
Loader::driver_t* Loader::attempt_to_load_updated_driver(egl_connection_t* cnx) {
    ATRACE_CALL();
    ATRACE_CALL();
#ifndef __ANDROID_VNDK__
#ifndef __ANDROID_VNDK__
+1 −0
Original line number Original line Diff line number Diff line
@@ -60,6 +60,7 @@ private:
    driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix, const bool exact);
    driver_t* attempt_to_load_system_driver(egl_connection_t* cnx, const char* suffix, const bool exact);
    void unload_system_driver(egl_connection_t* cnx);
    void unload_system_driver(egl_connection_t* cnx);
    void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask);
    void initialize_api(void* dso, egl_connection_t* cnx, uint32_t mask);
    void init_angle_backend(void* dso, egl_connection_t* cnx);


    static __attribute__((noinline))
    static __attribute__((noinline))
    void init_api(void* dso,
    void init_api(void* dso,
+8 −44
Original line number Original line Diff line number Diff line
@@ -133,45 +133,6 @@ EGLDisplay egl_display_t::getFromNativeDisplay(EGLNativeDisplayType disp,
    return sDisplay[uintptr_t(disp)].getPlatformDisplay(disp, attrib_list);
    return sDisplay[uintptr_t(disp)].getPlatformDisplay(disp, attrib_list);
}
}


static bool addAnglePlatformAttributes(egl_connection_t* const cnx,
                                       std::vector<EGLAttrib>& attrs) {
    intptr_t vendorEGL = (intptr_t)cnx->vendorEGL;

    attrs.reserve(4 * 2);

    attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
    attrs.push_back(cnx->angleBackend);

    switch (cnx->angleBackend) {
        case EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE:
            ALOGV("%s: Requesting Vulkan ANGLE back-end", __FUNCTION__);
            char prop[PROPERTY_VALUE_MAX];
            property_get("debug.angle.validation", prop, "0");
            attrs.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE);
            attrs.push_back(atoi(prop));
            break;
        case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
            ALOGV("%s: Requesting Default ANGLE back-end", __FUNCTION__);
            break;
        case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
            ALOGV("%s: Requesting OpenGL ES ANGLE back-end", __FUNCTION__);
            // NOTE: This is only valid if the backend is OpenGL
            attrs.push_back(EGL_PLATFORM_ANGLE_EGL_HANDLE_ANGLE);
            attrs.push_back(vendorEGL);

            // Context virtualization is only available on GL back-end.
            // Needed to support threading with GL back-end
            attrs.push_back(EGL_PLATFORM_ANGLE_CONTEXT_VIRTUALIZATION_ANGLE);
            attrs.push_back(EGL_FALSE);
            break;
        default:
            ALOGE("%s: Requesting Unknown (%d) ANGLE back-end", __FUNCTION__, cnx->angleBackend);
            break;
    }

    return true;
}

static EGLDisplay getPlatformDisplayAngle(EGLNativeDisplayType display, egl_connection_t* const cnx,
static EGLDisplay getPlatformDisplayAngle(EGLNativeDisplayType display, egl_connection_t* const cnx,
                                          const EGLAttrib* attrib_list, EGLint* error) {
                                          const EGLAttrib* attrib_list, EGLint* error) {
    EGLDisplay dpy = EGL_NO_DISPLAY;
    EGLDisplay dpy = EGL_NO_DISPLAY;
@@ -186,11 +147,14 @@ static EGLDisplay getPlatformDisplayAngle(EGLNativeDisplayType display, egl_conn
            }
            }
        }
        }


        if (!addAnglePlatformAttributes(cnx, attrs)) {
        attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_ANGLE);
            ALOGE("eglGetDisplay(%p) failed: Mismatch display request", display);
        attrs.push_back(EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE);
            *error = EGL_BAD_PARAMETER;

            return EGL_NO_DISPLAY;
        char prop[PROPERTY_VALUE_MAX];
        }
        property_get("debug.angle.validation", prop, "0");
        attrs.push_back(EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE);
        attrs.push_back(atoi(prop));

        attrs.push_back(EGL_NONE);
        attrs.push_back(EGL_NONE);


        dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
        dpy = cnx->egl.eglGetPlatformDisplay(EGL_PLATFORM_ANGLE_ANGLE,
+6 −6
Original line number Original line Diff line number Diff line
@@ -721,7 +721,7 @@ EGLSurface eglCreateWindowSurfaceTmpl(egl_display_ptr dp, egl_connection_t* cnx,


    // NOTE: When using Vulkan backend, the Vulkan runtime makes all the
    // NOTE: When using Vulkan backend, the Vulkan runtime makes all the
    // native_window_* calls, so don't do them here.
    // native_window_* calls, so don't do them here.
    if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
    if (!cnx->useAngle) {
        int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
        int result = native_window_api_connect(window, NATIVE_WINDOW_API_EGL);
        if (result < 0) {
        if (result < 0) {
            ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
            ALOGE("eglCreateWindowSurface: native_window_api_connect (win=%p) "
@@ -740,14 +740,14 @@ EGLSurface eglCreateWindowSurfaceTmpl(egl_display_ptr dp, egl_connection_t* cnx,
    std::vector<AttrType> strippedAttribList;
    std::vector<AttrType> strippedAttribList;
    if (!processAttributes<AttrType>(dp, window, attrib_list, &colorSpace, &strippedAttribList)) {
    if (!processAttributes<AttrType>(dp, window, attrib_list, &colorSpace, &strippedAttribList)) {
        ALOGE("error invalid colorspace: %d", colorSpace);
        ALOGE("error invalid colorspace: %d", colorSpace);
        if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
        if (!cnx->useAngle) {
            native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
            native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
        }
        }
        return EGL_NO_SURFACE;
        return EGL_NO_SURFACE;
    }
    }
    attrib_list = strippedAttribList.data();
    attrib_list = strippedAttribList.data();


    if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
    if (!cnx->useAngle) {
        int err = native_window_set_buffers_format(window, format);
        int err = native_window_set_buffers_format(window, format);
        if (err != 0) {
        if (err != 0) {
            ALOGE("error setting native window pixel format: %s (%d)", strerror(-err), err);
            ALOGE("error setting native window pixel format: %s (%d)", strerror(-err), err);
@@ -779,7 +779,7 @@ EGLSurface eglCreateWindowSurfaceTmpl(egl_display_ptr dp, egl_connection_t* cnx,
    }
    }


    // EGLSurface creation failed
    // EGLSurface creation failed
    if (cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
    if (!cnx->useAngle) {
        native_window_set_buffers_format(window, 0);
        native_window_set_buffers_format(window, 0);
        native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
        native_window_api_disconnect(window, NATIVE_WINDOW_API_EGL);
    }
    }
@@ -1419,7 +1419,7 @@ EGLBoolean eglSwapBuffersWithDamageKHRImpl(EGLDisplay dpy, EGLSurface draw,
        }
        }
    }
    }


    if (s->cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
    if (!s->cnx->useAngle) {
        if (!sendSurfaceMetadata(s)) {
        if (!sendSurfaceMetadata(s)) {
            native_window_api_disconnect(s->getNativeWindow(), NATIVE_WINDOW_API_EGL);
            native_window_api_disconnect(s->getNativeWindow(), NATIVE_WINDOW_API_EGL);
            return setError(EGL_BAD_NATIVE_WINDOW, (EGLBoolean)EGL_FALSE);
            return setError(EGL_BAD_NATIVE_WINDOW, (EGLBoolean)EGL_FALSE);
@@ -1444,7 +1444,7 @@ EGLBoolean eglSwapBuffersWithDamageKHRImpl(EGLDisplay dpy, EGLSurface draw,
        androidRect.bottom = y;
        androidRect.bottom = y;
        androidRects.push_back(androidRect);
        androidRects.push_back(androidRect);
    }
    }
    if (s->cnx->angleBackend != EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE) {
    if (!s->cnx->useAngle) {
        native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(),
        native_window_set_surface_damage(s->getNativeWindow(), androidRects.data(),
                                         androidRects.size());
                                         androidRects.size());
    }
    }
+0 −2
Original line number Original line Diff line number Diff line
@@ -82,8 +82,6 @@ struct egl_connection_t {


    bool                systemDriverUnloaded;
    bool                systemDriverUnloaded;
    bool                useAngle;       // Was ANGLE successfully loaded
    bool                useAngle;       // Was ANGLE successfully loaded
    EGLint              angleBackend;
    void*               vendorEGL;
};
};
// clang-format on
// clang-format on