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

Commit a5e9f1b0 authored by Peiyong Lin's avatar Peiyong Lin
Browse files

[RenderEngine] Make use of EGL_KHR_surfaceless_context.

Per
https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_surfaceless_context.txt,
when EGL_KHR_surfaceless_context is present, we can make the context current
without specifying draw and read surface, thus we no longer need to create a
1x1 buffer surface.

BUG: 35315015
Test: Build, flash, boot.
Change-Id: Ia5f19cf0f9561bb660708b5a2ae0187593422210
parent b49bb915
Loading
Loading
Loading
Loading
+54 −38
Original line number Diff line number Diff line
@@ -240,60 +240,29 @@ std::unique_ptr<GLES20RenderEngine> GLES20RenderEngine::create(int hwcFormat,
        config = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
    }

    EGLint renderableType = 0;
    if (config == EGL_NO_CONFIG) {
        renderableType = EGL_OPENGL_ES2_BIT;
    } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
        LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
    }
    EGLint contextClientVersion = 0;
    if (renderableType & EGL_OPENGL_ES2_BIT) {
        contextClientVersion = 2;
    } else if (renderableType & EGL_OPENGL_ES_BIT) {
        contextClientVersion = 1;
    } else {
        LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
    }

    std::vector<EGLint> contextAttributes;
    contextAttributes.reserve(6);
    contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
    contextAttributes.push_back(contextClientVersion);
    bool useContextPriority = extensions.hasContextPriority() &&
            (featureFlags & RenderEngine::USE_HIGH_PRIORITY_CONTEXT);
    if (useContextPriority) {
        contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
        contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
    }
    contextAttributes.push_back(EGL_NONE);

    EGLContext ctxt = eglCreateContext(display, config, nullptr, contextAttributes.data());
    EGLContext ctxt = createEglContext(display, config, EGL_NO_CONTEXT, useContextPriority);

    // if can't create a GL context, we can only abort.
    LOG_ALWAYS_FATAL_IF(ctxt == EGL_NO_CONTEXT, "EGLContext creation failed");

    // now figure out what version of GL did we actually get
    // NOTE: a dummy surface is not needed if KHR_create_context is supported
    // TODO(alecmouri): don't create this surface if EGL_KHR_surfaceless_context
    // is supported.

    EGLConfig dummyConfig = config;
    if (dummyConfig == EGL_NO_CONFIG) {
        dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
    }
    EGLint attribs[] = {EGL_WIDTH, 1, EGL_HEIGHT, 1, EGL_NONE, EGL_NONE};
    EGLSurface dummy = eglCreatePbufferSurface(display, dummyConfig, attribs);
    EGLSurface dummy = EGL_NO_SURFACE;
    if (!extensions.hasSurfacelessContext()) {
        dummy = createDummyEglPbufferSurface(display, config, hwcFormat);
        LOG_ALWAYS_FATAL_IF(dummy == EGL_NO_SURFACE, "can't create dummy pbuffer");
    }

    EGLBoolean success = eglMakeCurrent(display, dummy, dummy, ctxt);
    LOG_ALWAYS_FATAL_IF(!success, "can't make dummy pbuffer current");

    extensions.initWithGLStrings(glGetString(GL_VENDOR), glGetString(GL_RENDERER),
                                 glGetString(GL_VERSION), glGetString(GL_EXTENSIONS));

    // now figure out what version of GL did we actually get
    GlesVersion version = parseGlesVersion(extensions.getVersion());

    // initialize the renderer while GL is current

    std::unique_ptr<GLES20RenderEngine> engine;
    switch (version) {
        case GLES_VERSION_1_0:
@@ -908,6 +877,53 @@ GLES20RenderEngine::GlesVersion GLES20RenderEngine::parseGlesVersion(const char*
    return GLES_VERSION_1_0;
}

EGLContext GLES20RenderEngine::createEglContext(EGLDisplay display, EGLConfig config,
                                                EGLContext shareContext, bool useContextPriority) {
    EGLint renderableType = 0;
    if (config == EGL_NO_CONFIG) {
        renderableType = EGL_OPENGL_ES2_BIT;
    } else if (!eglGetConfigAttrib(display, config, EGL_RENDERABLE_TYPE, &renderableType)) {
        LOG_ALWAYS_FATAL("can't query EGLConfig RENDERABLE_TYPE");
    }
    EGLint contextClientVersion = 0;
    if (renderableType & EGL_OPENGL_ES2_BIT) {
        contextClientVersion = 2;
    } else if (renderableType & EGL_OPENGL_ES_BIT) {
        contextClientVersion = 1;
    } else {
        LOG_ALWAYS_FATAL("no supported EGL_RENDERABLE_TYPEs");
    }

    std::vector<EGLint> contextAttributes;
    contextAttributes.reserve(5);
    contextAttributes.push_back(EGL_CONTEXT_CLIENT_VERSION);
    contextAttributes.push_back(contextClientVersion);
    if (useContextPriority) {
        contextAttributes.push_back(EGL_CONTEXT_PRIORITY_LEVEL_IMG);
        contextAttributes.push_back(EGL_CONTEXT_PRIORITY_HIGH_IMG);
    }
    contextAttributes.push_back(EGL_NONE);

    return eglCreateContext(display, config, shareContext, contextAttributes.data());
}

EGLSurface GLES20RenderEngine::createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
                                                            int hwcFormat) {
    EGLConfig dummyConfig = config;
    if (dummyConfig == EGL_NO_CONFIG) {
        dummyConfig = chooseEglConfig(display, hwcFormat, /*logConfig*/ true);
    }
    std::vector<EGLint> attributes;
    attributes.reserve(5);
    attributes.push_back(EGL_WIDTH);
    attributes.push_back(1);
    attributes.push_back(EGL_HEIGHT);
    attributes.push_back(1);
    attributes.push_back(EGL_NONE);

    return eglCreatePbufferSurface(display, dummyConfig, attributes.data());
}

bool GLES20RenderEngine::isHdrDataSpace(const Dataspace dataSpace) const {
    const Dataspace standard = static_cast<Dataspace>(dataSpace & Dataspace::STANDARD_MASK);
    const Dataspace transfer = static_cast<Dataspace>(dataSpace & Dataspace::TRANSFER_MASK);
+4 −0
Original line number Diff line number Diff line
@@ -112,6 +112,10 @@ private:
    };

    static GlesVersion parseGlesVersion(const char* str);
    static EGLContext createEglContext(EGLDisplay display, EGLConfig config,
                                       EGLContext shareContext, bool useContextPriority);
    static EGLSurface createDummyEglPbufferSurface(EGLDisplay display, EGLConfig config,
                                                   int hwcFormat);

    // A data space is considered HDR data space if it has BT2020 color space
    // with PQ or HLG transfer function.
+3 −0
Original line number Diff line number Diff line
@@ -112,6 +112,9 @@ void GLExtensions::initWithEGLStrings(char const* eglVersion, char const* eglExt
    if (extensionSet.hasExtension("EGL_IMG_context_priority")) {
        mHasContextPriority = true;
    }
    if (extensionSet.hasExtension("EGL_KHR_surfaceless_context")) {
        mHasSurfacelessContext = true;
    }
}

char const* GLExtensions::getEGLVersion() const {
+25 −22
Original line number Diff line number Diff line
@@ -32,6 +32,30 @@ namespace renderengine {
namespace gl {

class GLExtensions : public Singleton<GLExtensions> {
public:
    bool hasNoConfigContext() const { return mHasNoConfigContext; }
    bool hasNativeFenceSync() const { return mHasNativeFenceSync; }
    bool hasFenceSync() const { return mHasFenceSync; }
    bool hasWaitSync() const { return mHasWaitSync; }
    bool hasProtectedContent() const { return mHasProtectedContent; }
    bool hasContextPriority() const { return mHasContextPriority; }
    bool hasSurfacelessContext() const { return mHasSurfacelessContext; }

    void initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version,
                           GLubyte const* extensions);
    char const* getVendor() const;
    char const* getRenderer() const;
    char const* getVersion() const;
    char const* getExtensions() const;

    void initWithEGLStrings(char const* eglVersion, char const* eglExtensions);
    char const* getEGLVersion() const;
    char const* getEGLExtensions() const;

protected:
    GLExtensions() = default;

private:
    friend class Singleton<GLExtensions>;

    bool mHasNoConfigContext = false;
@@ -40,6 +64,7 @@ class GLExtensions : public Singleton<GLExtensions> {
    bool mHasWaitSync = false;
    bool mHasProtectedContent = false;
    bool mHasContextPriority = false;
    bool mHasSurfacelessContext = false;

    String8 mVendor;
    String8 mRenderer;
@@ -51,28 +76,6 @@ class GLExtensions : public Singleton<GLExtensions> {

    GLExtensions(const GLExtensions&);
    GLExtensions& operator=(const GLExtensions&);

protected:
    GLExtensions() = default;

public:
    bool hasNoConfigContext() const { return mHasNoConfigContext; }
    bool hasNativeFenceSync() const { return mHasNativeFenceSync; }
    bool hasFenceSync() const { return mHasFenceSync; }
    bool hasWaitSync() const { return mHasWaitSync; }
    bool hasProtectedContent() const { return mHasProtectedContent; }
    bool hasContextPriority() const { return mHasContextPriority; }

    void initWithGLStrings(GLubyte const* vendor, GLubyte const* renderer, GLubyte const* version,
                           GLubyte const* extensions);
    char const* getVendor() const;
    char const* getRenderer() const;
    char const* getVersion() const;
    char const* getExtensions() const;

    void initWithEGLStrings(char const* eglVersion, char const* eglExtensions);
    char const* getEGLVersion() const;
    char const* getEGLExtensions() const;
};

} // namespace gl