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

Commit da4cf3be authored by Alec Mouri's avatar Alec Mouri
Browse files

Add output fb cache to renderengine

On some devices this can shave off multiple milliseconds.

Bug: 123107664
Test: manual tests, systrace
Change-Id: If29b1753f899fec03852fb1ddaaa1a245f68424b
parent 77b510f1
Loading
Loading
Loading
Loading
+4 −3
Original line number Original line Diff line number Diff line
@@ -24,15 +24,16 @@
namespace android {
namespace android {
namespace renderengine {
namespace renderengine {


std::unique_ptr<impl::RenderEngine> RenderEngine::create(int hwcFormat, uint32_t featureFlags) {
std::unique_ptr<impl::RenderEngine> RenderEngine::create(int hwcFormat, uint32_t featureFlags,
                                                         uint32_t imageCacheSize) {
    char prop[PROPERTY_VALUE_MAX];
    char prop[PROPERTY_VALUE_MAX];
    property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "gles");
    property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, "gles");
    if (strcmp(prop, "gles") == 0) {
    if (strcmp(prop, "gles") == 0) {
        ALOGD("RenderEngine GLES Backend");
        ALOGD("RenderEngine GLES Backend");
        return renderengine::gl::GLESRenderEngine::create(hwcFormat, featureFlags);
        return renderengine::gl::GLESRenderEngine::create(hwcFormat, featureFlags, imageCacheSize);
    }
    }
    ALOGE("UNKNOWN BackendType: %s, create GLES RenderEngine.", prop);
    ALOGE("UNKNOWN BackendType: %s, create GLES RenderEngine.", prop);
    return renderengine::gl::GLESRenderEngine::create(hwcFormat, featureFlags);
    return renderengine::gl::GLESRenderEngine::create(hwcFormat, featureFlags, imageCacheSize);
}
}


RenderEngine::~RenderEngine() = default;
RenderEngine::~RenderEngine() = default;
+37 −3
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@
#include <sync/sync.h>
#include <sync/sync.h>
#include <ui/ColorSpace.h>
#include <ui/ColorSpace.h>
#include <ui/DebugUtils.h>
#include <ui/DebugUtils.h>
#include <ui/GraphicBuffer.h>
#include <ui/Rect.h>
#include <ui/Rect.h>
#include <ui/Region.h>
#include <ui/Region.h>
#include <utils/KeyedVector.h>
#include <utils/KeyedVector.h>
@@ -225,7 +226,8 @@ static status_t selectEGLConfig(EGLDisplay display, EGLint format, EGLint render
    return err;
    return err;
}
}


std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(int hwcFormat, uint32_t featureFlags) {
std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(int hwcFormat, uint32_t featureFlags,
                                                           uint32_t imageCacheSize) {
    // initialize EGL for the default display
    // initialize EGL for the default display
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    if (!eglInitialize(display, nullptr, nullptr)) {
    if (!eglInitialize(display, nullptr, nullptr)) {
@@ -295,7 +297,8 @@ std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(int hwcFormat, uint32
        case GLES_VERSION_2_0:
        case GLES_VERSION_2_0:
        case GLES_VERSION_3_0:
        case GLES_VERSION_3_0:
            engine = std::make_unique<GLESRenderEngine>(featureFlags, display, config, ctxt, dummy,
            engine = std::make_unique<GLESRenderEngine>(featureFlags, display, config, ctxt, dummy,
                                                        protectedContext, protectedDummy);
                                                        protectedContext, protectedDummy,
                                                        imageCacheSize);
            break;
            break;
    }
    }


@@ -351,7 +354,7 @@ EGLConfig GLESRenderEngine::chooseEglConfig(EGLDisplay display, int format, bool


GLESRenderEngine::GLESRenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config,
GLESRenderEngine::GLESRenderEngine(uint32_t featureFlags, EGLDisplay display, EGLConfig config,
                                   EGLContext ctxt, EGLSurface dummy, EGLContext protectedContext,
                                   EGLContext ctxt, EGLSurface dummy, EGLContext protectedContext,
                                   EGLSurface protectedDummy)
                                   EGLSurface protectedDummy, uint32_t imageCacheSize)
      : renderengine::impl::RenderEngine(featureFlags),
      : renderengine::impl::RenderEngine(featureFlags),
        mEGLDisplay(display),
        mEGLDisplay(display),
        mEGLConfig(config),
        mEGLConfig(config),
@@ -361,6 +364,7 @@ GLESRenderEngine::GLESRenderEngine(uint32_t featureFlags, EGLDisplay display, EG
        mProtectedDummySurface(protectedDummy),
        mProtectedDummySurface(protectedDummy),
        mVpWidth(0),
        mVpWidth(0),
        mVpHeight(0),
        mVpHeight(0),
        mFramebufferImageCacheSize(imageCacheSize),
        mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) {
        mUseColorManagement(featureFlags & USE_COLOR_MANAGEMENT) {
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
    glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
    glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
@@ -428,6 +432,10 @@ GLESRenderEngine::GLESRenderEngine(uint32_t featureFlags, EGLDisplay display, EG
}
}


GLESRenderEngine::~GLESRenderEngine() {
GLESRenderEngine::~GLESRenderEngine() {
    for (const auto& image : mFramebufferImageCache) {
        eglDestroyImageKHR(mEGLDisplay, image.second);
    }
    mFramebufferImageCache.clear();
    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    eglTerminate(mEGLDisplay);
    eglTerminate(mEGLDisplay);
}
}
@@ -785,6 +793,32 @@ bool GLESRenderEngine::useProtectedContext(bool useProtectedContext) {
    }
    }
    return success;
    return success;
}
}
EGLImageKHR GLESRenderEngine::createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer,
                                                             bool isProtected) {
    sp<GraphicBuffer> graphicBuffer = GraphicBuffer::from(nativeBuffer);
    uint32_t bufferId = graphicBuffer->getId();
    for (const auto& image : mFramebufferImageCache) {
        if (image.first == bufferId) {
            return image.second;
        }
    }
    EGLint attributes[] = {
            isProtected ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
            isProtected ? EGL_TRUE : EGL_NONE,
            EGL_NONE,
    };
    EGLImageKHR image = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
                                          nativeBuffer, attributes);
    if (image != EGL_NO_IMAGE_KHR) {
        if (mFramebufferImageCache.size() >= mFramebufferImageCacheSize) {
            EGLImageKHR expired = mFramebufferImageCache.front().second;
            mFramebufferImageCache.pop_front();
            eglDestroyImageKHR(mEGLDisplay, expired);
        }
        mFramebufferImageCache.push_back({bufferId, image});
    }
    return image;
}


status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
                                      const std::vector<LayerSettings>& layers,
                                      const std::vector<LayerSettings>& layers,
+14 −3
Original line number Original line Diff line number Diff line
@@ -21,16 +21,17 @@
#include <stdint.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/types.h>
#include <condition_variable>
#include <condition_variable>
#include <deque>
#include <mutex>
#include <mutex>
#include <queue>
#include <queue>
#include <thread>
#include <thread>
#include <unordered_map>


#include <EGL/egl.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2.h>
#include <renderengine/RenderEngine.h>
#include <renderengine/RenderEngine.h>
#include <renderengine/private/Description.h>
#include <renderengine/private/Description.h>
#include <unordered_map>


#define EGL_NO_CONFIG ((EGLConfig)0)
#define EGL_NO_CONFIG ((EGLConfig)0)


@@ -47,12 +48,14 @@ class GLImage;


class GLESRenderEngine : public impl::RenderEngine {
class GLESRenderEngine : public impl::RenderEngine {
public:
public:
    static std::unique_ptr<GLESRenderEngine> create(int hwcFormat, uint32_t featureFlags);
    static std::unique_ptr<GLESRenderEngine> create(int hwcFormat, uint32_t featureFlags,
                                                    uint32_t imageCacheSize);
    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);
    static EGLConfig chooseEglConfig(EGLDisplay display, int format, bool logConfig);


    GLESRenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
    GLESRenderEngine(uint32_t featureFlags, // See RenderEngine::FeatureFlag
                     EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy,
                     EGLDisplay display, EGLConfig config, EGLContext ctxt, EGLSurface dummy,
                     EGLContext protectedContext, EGLSurface protectedDummy);
                     EGLContext protectedContext, EGLSurface protectedDummy,
                     uint32_t imageCacheSize);
    ~GLESRenderEngine() override;
    ~GLESRenderEngine() override;


    std::unique_ptr<Framebuffer> createFramebuffer() override;
    std::unique_ptr<Framebuffer> createFramebuffer() override;
@@ -87,6 +90,8 @@ public:
    // internal to RenderEngine
    // internal to RenderEngine
    EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
    EGLDisplay getEGLDisplay() const { return mEGLDisplay; }
    EGLConfig getEGLConfig() const { return mEGLConfig; }
    EGLConfig getEGLConfig() const { return mEGLConfig; }
    // Creates an output image for rendering to
    EGLImageKHR createFramebufferImageIfNeeded(ANativeWindowBuffer* nativeBuffer, bool isProtected);


protected:
protected:
    Framebuffer* getFramebufferForDrawing() override;
    Framebuffer* getFramebufferForDrawing() override;
@@ -176,6 +181,12 @@ private:
    // If set to true, then enables tracing flush() and finish() to systrace.
    // If set to true, then enables tracing flush() and finish() to systrace.
    bool mTraceGpuCompletion = false;
    bool mTraceGpuCompletion = false;
    int32_t mFboHeight = 0;
    int32_t mFboHeight = 0;
    // Maximum size of mFramebufferImageCache. If more images would be cached, then (approximately)
    // the last recently used buffer should be kicked out.
    uint32_t mFramebufferImageCacheSize = 0;

    // Cache of output images, keyed by corresponding GraphicBuffer ID.
    std::deque<std::pair<uint64_t, EGLImageKHR>> mFramebufferImageCache;


    // Current dataspace of layer being rendered
    // Current dataspace of layer being rendered
    ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN;
    ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN;
+3 −11
Original line number Original line Diff line number Diff line
@@ -30,8 +30,8 @@ namespace android {
namespace renderengine {
namespace renderengine {
namespace gl {
namespace gl {


GLFramebuffer::GLFramebuffer(const GLESRenderEngine& engine)
GLFramebuffer::GLFramebuffer(GLESRenderEngine& engine)
      : mEGLDisplay(engine.getEGLDisplay()), mEGLImage(EGL_NO_IMAGE_KHR) {
      : mEngine(engine), mEGLDisplay(engine.getEGLDisplay()), mEGLImage(EGL_NO_IMAGE_KHR) {
    glGenTextures(1, &mTextureName);
    glGenTextures(1, &mTextureName);
    glGenFramebuffers(1, &mFramebufferName);
    glGenFramebuffers(1, &mFramebufferName);
}
}
@@ -39,26 +39,18 @@ GLFramebuffer::GLFramebuffer(const GLESRenderEngine& engine)
GLFramebuffer::~GLFramebuffer() {
GLFramebuffer::~GLFramebuffer() {
    glDeleteFramebuffers(1, &mFramebufferName);
    glDeleteFramebuffers(1, &mFramebufferName);
    glDeleteTextures(1, &mTextureName);
    glDeleteTextures(1, &mTextureName);
    eglDestroyImageKHR(mEGLDisplay, mEGLImage);
}
}


bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected) {
bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected) {
    ATRACE_CALL();
    ATRACE_CALL();
    if (mEGLImage != EGL_NO_IMAGE_KHR) {
    if (mEGLImage != EGL_NO_IMAGE_KHR) {
        eglDestroyImageKHR(mEGLDisplay, mEGLImage);
        mEGLImage = EGL_NO_IMAGE_KHR;
        mEGLImage = EGL_NO_IMAGE_KHR;
        mBufferWidth = 0;
        mBufferWidth = 0;
        mBufferHeight = 0;
        mBufferHeight = 0;
    }
    }


    if (nativeBuffer) {
    if (nativeBuffer) {
        EGLint attributes[] = {
        mEGLImage = mEngine.createFramebufferImageIfNeeded(nativeBuffer, isProtected);
                isProtected ? EGL_PROTECTED_CONTENT_EXT : EGL_NONE,
                isProtected ? EGL_TRUE : EGL_NONE,
                EGL_NONE,
        };
        mEGLImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
                                      nativeBuffer, attributes);
        if (mEGLImage == EGL_NO_IMAGE_KHR) {
        if (mEGLImage == EGL_NO_IMAGE_KHR) {
            return false;
            return false;
        }
        }
+2 −1
Original line number Original line Diff line number Diff line
@@ -32,7 +32,7 @@ class GLESRenderEngine;


class GLFramebuffer : public renderengine::Framebuffer {
class GLFramebuffer : public renderengine::Framebuffer {
public:
public:
    explicit GLFramebuffer(const GLESRenderEngine& engine);
    explicit GLFramebuffer(GLESRenderEngine& engine);
    ~GLFramebuffer() override;
    ~GLFramebuffer() override;


    bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected) override;
    bool setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected) override;
@@ -43,6 +43,7 @@ public:
    int32_t getBufferWidth() const { return mBufferWidth; }
    int32_t getBufferWidth() const { return mBufferWidth; }


private:
private:
    GLESRenderEngine& mEngine;
    EGLDisplay mEGLDisplay;
    EGLDisplay mEGLDisplay;
    EGLImageKHR mEGLImage;
    EGLImageKHR mEGLImage;
    uint32_t mTextureName, mFramebufferName;
    uint32_t mTextureName, mFramebufferName;
Loading