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

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

[RenderEngine] Make BindNativeBufferAsFramebuffer more generic.

BindNativeBufferAsFramebuffer is a helper class that manages resource of an EGL
image for screenshot capturing. However, as a public API it ties to GLES. This
patch abstracts framebuffer out as Framebuffer and uses it instead of EGL
image. As a result, we can move the most of the implementation of
bindNativeBufferAsFrameBuffer and unbindNativeBufferAsFrameBuffer to
GLFramebuffer so that it manages its own resources, and move the rest of the
implementation to GLES20RenderEngine and get rid off two virtual functions.

Minor: Clean up some coding style.

BUG: 112585051
Test: Build, flash, boot and run some display validation
Change-Id: I787625089f8959cc273d4756baa7135cb004ed2d
parent 52ea8133
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ filegroup {
    srcs: [
        "gl/GLES20RenderEngine.cpp",
        "gl/GLExtensions.cpp",
        "gl/GLFramebuffer.cpp",
        "gl/GLImage.cpp",
        "gl/GLSurface.cpp",
        "gl/Program.cpp",
+0 −39
Original line number Diff line number Diff line
@@ -354,45 +354,6 @@ void RenderEngine::dump(String8& result) {
    result.appendFormat("%s\n", extensions.getExtensions());
}

void RenderEngine::bindNativeBufferAsFrameBuffer(
        ANativeWindowBuffer* buffer,
        renderengine::BindNativeBufferAsFramebuffer* bindHelper) {
    bindHelper->mImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID,
                                           buffer, nullptr);
    if (bindHelper->mImage == EGL_NO_IMAGE_KHR) {
        bindHelper->mStatus = NO_MEMORY;
        return;
    }

    uint32_t glStatus;
    bindImageAsFramebuffer(bindHelper->mImage, &bindHelper->mTexName, &bindHelper->mFbName,
                           &glStatus);

    ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES, "glCheckFramebufferStatusOES error %d",
             glStatus);

    bindHelper->mStatus = glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
}

void RenderEngine::unbindNativeBufferAsFrameBuffer(
        renderengine::BindNativeBufferAsFramebuffer* bindHelper) {
    if (bindHelper->mImage == EGL_NO_IMAGE_KHR) {
        return;
    }

    // back to main framebuffer
    unbindFramebuffer(bindHelper->mTexName, bindHelper->mFbName);
    eglDestroyImageKHR(mEGLDisplay, bindHelper->mImage);

    // Workaround for b/77935566 to force the EGL driver to release the
    // screenshot buffer
    setScissor(0, 0, 0, 0);
    clearWithColor(0.0, 0.0, 0.0, 0.0);
    disableScissor();
}

// ---------------------------------------------------------------------------

static status_t selectConfigForAttribute(EGLDisplay dpy, EGLint const* attrs, EGLint attribute,
                                         EGLint wanted, EGLConfig* outConfig) {
    EGLint numConfigs = -1, n = 0;
+45 −29
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include <utils/String8.h>
#include <utils/Trace.h>
#include "GLExtensions.h"
#include "GLFramebuffer.h"
#include "GLImage.h"
#include "GLSurface.h"
#include "Program.h"
@@ -154,6 +155,10 @@ GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags)

GLES20RenderEngine::~GLES20RenderEngine() {}

std::unique_ptr<Framebuffer> GLES20RenderEngine::createFramebuffer() {
    return std::make_unique<GLFramebuffer>(*this);
}

std::unique_ptr<Surface> GLES20RenderEngine::createSurface() {
    return std::make_unique<GLSurface>(*this);
}
@@ -197,8 +202,47 @@ void GLES20RenderEngine::bindExternalTextureImage(uint32_t texName,

    glBindTexture(target, texName);
    if (glImage.getEGLImage() != EGL_NO_IMAGE_KHR) {
        glEGLImageTargetTexture2DOES(target, static_cast<GLeglImageOES>(glImage.getEGLImage()));
        glEGLImageTargetTexture2DOES(target,
                                     static_cast<GLeglImageOES>(glImage.getEGLImage()));
    }
}

status_t GLES20RenderEngine::bindFrameBuffer(Framebuffer* framebuffer) {
    GLFramebuffer* glFramebuffer = static_cast<GLFramebuffer*>(framebuffer);
    EGLImageKHR eglImage = glFramebuffer->getEGLImage();
    uint32_t textureName = glFramebuffer->getTextureName();
    uint32_t framebufferName = glFramebuffer->getFramebufferName();

    // Bind the texture and turn our EGLImage into a texture
    glBindTexture(GL_TEXTURE_2D, textureName);
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)eglImage);

    // Bind the Framebuffer to render into
    glBindFramebuffer(GL_FRAMEBUFFER, framebufferName);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
                           GL_TEXTURE_2D, textureName, 0);

    mRenderToFbo = true;

    uint32_t glStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);

    ALOGE_IF(glStatus != GL_FRAMEBUFFER_COMPLETE_OES,
             "glCheckFramebufferStatusOES error %d", glStatus);

    return glStatus == GL_FRAMEBUFFER_COMPLETE_OES ? NO_ERROR : BAD_VALUE;
}

void GLES20RenderEngine::unbindFrameBuffer(Framebuffer* /* framebuffer */) {
    mRenderToFbo = false;

    // back to main framebuffer
    glBindFramebuffer(GL_FRAMEBUFFER, 0);

    // Workaround for b/77935566 to force the EGL driver to release the
    // screenshot buffer
    setScissor(0, 0, 0, 0);
    clearWithColor(0.0, 0.0, 0.0, 0.0);
    disableScissor();
}

void GLES20RenderEngine::setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
@@ -304,34 +348,6 @@ void GLES20RenderEngine::disableBlending() {
    glDisable(GL_BLEND);
}

void GLES20RenderEngine::bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName,
                                                uint32_t* fbName, uint32_t* status) {
    GLuint tname, name;
    // turn our EGLImage into a texture
    glGenTextures(1, &tname);
    glBindTexture(GL_TEXTURE_2D, tname);
    glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)image);

    // create a Framebuffer Object to render into
    glGenFramebuffers(1, &name);
    glBindFramebuffer(GL_FRAMEBUFFER, name);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tname, 0);

    *status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    *texName = tname;
    *fbName = name;

    mRenderToFbo = true;
}

void GLES20RenderEngine::unbindFramebuffer(uint32_t texName, uint32_t fbName) {
    mRenderToFbo = false;

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glDeleteFramebuffers(1, &fbName);
    glDeleteTextures(1, &texName);
}

void GLES20RenderEngine::setupFillWithColor(float r, float g, float b, float a) {
    mState.setPremultipliedAlpha(true);
    mState.setOpaque(false);
+42 −52
Original line number Diff line number Diff line
@@ -39,32 +39,13 @@ class GLImage;
class GLSurface;

class GLES20RenderEngine : public impl::RenderEngine {
    GLuint mProtectedTexName;
    GLint mMaxViewportDims[2];
    GLint mMaxTextureSize;
    GLuint mVpWidth;
    GLuint mVpHeight;

    struct Group {
        GLuint texture;
        GLuint fbo;
        GLuint width;
        GLuint height;
        mat4 colorTransform;
    };

    Description mState;

    virtual void bindImageAsFramebuffer(EGLImageKHR image, uint32_t* texName, uint32_t* fbName,
                                        uint32_t* status);
    virtual void unbindFramebuffer(uint32_t texName, uint32_t fbName);

public:
    GLES20RenderEngine(uint32_t featureFlags); // See RenderEngine::FeatureFlag
    virtual ~GLES20RenderEngine();
    ~GLES20RenderEngine() override;

    std::unique_ptr<renderengine::Surface> createSurface() override;
    std::unique_ptr<renderengine::Image> createImage() override;
    std::unique_ptr<Framebuffer> createFramebuffer() override;
    std::unique_ptr<Surface> createSurface() override;
    std::unique_ptr<Image> createImage() override;

    void primeCache() const override;

@@ -72,14 +53,15 @@ public:
    bool setCurrentSurface(const Surface& surface) override;
    void resetCurrentSurface() override;

    void bindExternalTextureImage(uint32_t texName, const renderengine::Image& image) override;

    void bindExternalTextureImage(uint32_t texName, const Image& image) override;
    status_t bindFrameBuffer(Framebuffer* framebuffer) override;
    void unbindFrameBuffer(Framebuffer* framebuffer) override;

protected:
    virtual void dump(String8& result);
    virtual void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
                                          ui::Transform::orientation_flags rotation);
    virtual void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
    void dump(String8& result) override;
    void setViewportAndProjection(size_t vpw, size_t vph, Rect sourceCrop,
                                  ui::Transform::orientation_flags rotation) override;
    void setupLayerBlending(bool premultipliedAlpha, bool opaque, bool disableTexture,
                            const half4& color) override;

    // Color management related functions and state
@@ -88,27 +70,31 @@ protected:
    void setOutputDataSpace(ui::Dataspace dataspace) override;
    void setDisplayMaxLuminance(const float maxLuminance) override;

    virtual void setupLayerTexturing(const Texture& texture);
    virtual void setupLayerBlackedOut();
    virtual void setupFillWithColor(float r, float g, float b, float a);
    virtual void setupColorTransform(const mat4& colorTransform);
    virtual void disableTexturing();
    virtual void disableBlending();
    void setupLayerTexturing(const Texture& texture) override;
    void setupLayerBlackedOut() override;
    void setupFillWithColor(float r, float g, float b, float a) override;
    void setupColorTransform(const mat4& colorTransform) override;
    void disableTexturing() override;
    void disableBlending() override;

    virtual void drawMesh(const Mesh& mesh);
    void drawMesh(const Mesh& mesh) override;

    virtual size_t getMaxTextureSize() const;
    virtual size_t getMaxViewportDims() const;
    size_t getMaxTextureSize() const override;
    size_t getMaxViewportDims() const override;

    // Current dataspace of layer being rendered
    ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN;
private:
    // A data space is considered HDR data space if it has BT2020 color space
    // with PQ or HLG transfer function.
    bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
    bool needsXYZTransformMatrix() const;

    // Current output dataspace of the render engine
    ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN;
    GLuint mProtectedTexName;
    GLint mMaxViewportDims[2];
    GLint mMaxTextureSize;
    GLuint mVpWidth;
    GLuint mVpHeight;
    Description mState;

    // Whether device supports color management, currently color management
    // supports sRGB, DisplayP3 color spaces.
    const bool mUseColorManagement = false;
    mat4 mSrgbToDisplayP3;
    mat4 mDisplayP3ToSrgb;
    mat3 mSrgbToXyz;
@@ -118,13 +104,17 @@ protected:
    mat4 mXyzToDisplayP3;
    mat4 mXyzToBt2020;

private:
    // A data space is considered HDR data space if it has BT2020 color space
    // with PQ or HLG transfer function.
    bool isHdrDataSpace(const ui::Dataspace dataSpace) const;
    bool needsXYZTransformMatrix() const;

    bool mRenderToFbo = false;

    // Current dataspace of layer being rendered
    ui::Dataspace mDataSpace = ui::Dataspace::UNKNOWN;

    // Current output dataspace of the render engine
    ui::Dataspace mOutputDataSpace = ui::Dataspace::UNKNOWN;

    // Whether device supports color management, currently color management
    // supports sRGB, DisplayP3 color spaces.
    const bool mUseColorManagement = false;
};

}  // namespace gl
+61 −0
Original line number Diff line number Diff line
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "GLFramebuffer.h"

#include <GLES/gl.h>
#include <GLES/glext.h>
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include "GLES20RenderEngine.h"

namespace android {
namespace renderengine {
namespace gl {

GLFramebuffer::GLFramebuffer(const GLES20RenderEngine& engine)
        : mEGLDisplay(engine.getEGLDisplay()),
          mEGLImage(EGL_NO_IMAGE_KHR) {
    glGenTextures(1, &mTextureName);
    glGenFramebuffers(1, &mFramebufferName);
}

GLFramebuffer::~GLFramebuffer() {
    glDeleteFramebuffers(1, &mFramebufferName);
    glDeleteTextures(1, &mTextureName);
    eglDestroyImageKHR(mEGLDisplay, mEGLImage);
}

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

    if (nativeBuffer) {
        mEGLImage = eglCreateImageKHR(mEGLDisplay, EGL_NO_CONTEXT,
                                      EGL_NATIVE_BUFFER_ANDROID,
                                      nativeBuffer, nullptr);
        if (mEGLImage == EGL_NO_IMAGE_KHR) {
            return false;
        }
    }
    return true;
}

}  // namespace gl
}  // namespace renderengine
}  // namespace android
Loading