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

Commit 5e18e873 authored by Lucas Dupin's avatar Lucas Dupin Committed by Android (Google) Code Review
Browse files

Merge "Blur shader performance optimizations"

parents 365f4423 f82ed8f8
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -1003,7 +1003,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
        setViewportAndProjection(display.physicalDisplay, display.clip);
    } else {
        setViewportAndProjection(display.physicalDisplay, display.clip);
        auto status = mBlurFilter->setAsDrawTarget(display);
        auto status = mBlurFilter->setAsDrawTarget(display, blurLayer->backgroundBlurRadius);
        if (status != NO_ERROR) {
            ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).",
                  buffer->handle);
@@ -1037,7 +1037,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
                        .build();
    for (auto const layer : layers) {
        if (blurLayer == layer) {
            auto status = mBlurFilter->prepare(layer->backgroundBlurRadius);
            auto status = mBlurFilter->prepare();
            if (status != NO_ERROR) {
                ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).",
                      buffer->handle);
+8 −0
Original line number Diff line number Diff line
@@ -122,6 +122,14 @@ void GLFramebuffer::bind() const {
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
}

void GLFramebuffer::bindAsReadBuffer() const {
    glBindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferName);
}

void GLFramebuffer::bindAsDrawBuffer() const {
    glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferName);
}

void GLFramebuffer::unbind() const {
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
+2 −0
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@ public:
    int32_t getBufferWidth() const { return mBufferWidth; }
    GLenum getStatus() const { return mStatus; }
    void bind() const;
    void bindAsReadBuffer() const;
    void bindAsDrawBuffer() const;
    void unbind() const;

private:
+38 −25
Original line number Diff line number Diff line
@@ -31,29 +31,24 @@ namespace renderengine {
namespace gl {

BlurFilter::BlurFilter(GLESRenderEngine& engine)
      : mEngine(engine), mCompositionFbo(engine), mBlurredFbo(engine), mSimpleProgram(engine) {
    mSimpleProgram.compile(getVertexShader(), getSimpleFragShader());
    mSPosLoc = mSimpleProgram.getAttributeLocation("aPosition");
    mSUvLoc = mSimpleProgram.getAttributeLocation("aUV");
    mSTextureLoc = mSimpleProgram.getUniformLocation("uTexture");
      : mEngine(engine), mCompositionFbo(engine), mBlurredFbo(engine), mMixProgram(engine) {
    mMixProgram.compile(getVertexShader(), getMixFragShader());
    mMPosLoc = mMixProgram.getAttributeLocation("aPosition");
    mMUvLoc = mMixProgram.getAttributeLocation("aUV");
    mMTextureLoc = mMixProgram.getUniformLocation("uTexture");
    mMCompositionTextureLoc = mMixProgram.getUniformLocation("uCompositionTexture");
    mMMixLoc = mMixProgram.getUniformLocation("uMix");
}

status_t BlurFilter::setAsDrawTarget(const DisplaySettings& display) {
status_t BlurFilter::setAsDrawTarget(const DisplaySettings& display, uint32_t radius) {
    ATRACE_NAME("BlurFilter::setAsDrawTarget");
    mRadius = radius;

    if (!mTexturesAllocated) {
        mDisplayWidth = display.physicalDisplay.width();
        mDisplayHeight = display.physicalDisplay.height();
        mCompositionFbo.allocateBuffers(mDisplayWidth, mDisplayHeight);

        // Let's use mimap filtering on the offscreen composition texture,
        // this will drastically improve overall shader quality.
        glBindTexture(GL_TEXTURE_2D, mCompositionFbo.getTextureName());
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 3);
        glBindTexture(GL_TEXTURE_2D, 0);

        const uint32_t fboWidth = floorf(mDisplayWidth * kFboScale);
        const uint32_t fboHeight = floorf(mDisplayHeight * kFboScale);
        mBlurredFbo.allocateBuffers(fboWidth, fboHeight);
@@ -94,27 +89,41 @@ void BlurFilter::drawMesh(GLuint uv, GLuint position) {
status_t BlurFilter::render() {
    ATRACE_NAME("BlurFilter::render");

    // Now let's scale our blur up
    mSimpleProgram.useProgram();
    // Now let's scale our blur up. It will be interpolated with the larger composited
    // texture for the first frames, to hide downscaling artifacts.
    GLfloat mix = fmin(1.0, mRadius / kMaxCrossFadeRadius);
    if (mix >= 1) {
        mBlurredFbo.bindAsReadBuffer();
        glBlitFramebuffer(0, 0, mBlurredFbo.getBufferWidth(), mBlurredFbo.getBufferHeight(), 0, 0,
                          mDisplayWidth, mDisplayHeight, GL_COLOR_BUFFER_BIT, GL_LINEAR);
        glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
        return NO_ERROR;
    }

    mMixProgram.useProgram();
    glUniform1f(mMMixLoc, mix);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, mBlurredFbo.getTextureName());
    glUniform1i(mSTextureLoc, 0);
    glUniform1i(mMTextureLoc, 0);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, mCompositionFbo.getTextureName());
    glUniform1i(mMCompositionTextureLoc, 1);
    mEngine.checkErrors("Setting final pass uniforms");

    drawMesh(mSUvLoc, mSPosLoc);
    drawMesh(mMUvLoc, mMPosLoc);

    glUseProgram(0);
    glActiveTexture(GL_TEXTURE0);
    return NO_ERROR;
}

string BlurFilter::getVertexShader() const {
    return R"SHADER(
        #version 310 es
        precision lowp float;

        in vec2 aPosition;
        in mediump vec2 aUV;
        out mediump vec2 vUV;
        in highp vec2 aUV;
        out highp vec2 vUV;

        void main() {
            vUV = aUV;
@@ -123,18 +132,22 @@ string BlurFilter::getVertexShader() const {
    )SHADER";
}

string BlurFilter::getSimpleFragShader() const {
string BlurFilter::getMixFragShader() const {
    string shader = R"SHADER(
        #version 310 es
        precision lowp float;
        precision mediump float;

        in mediump vec2 vUV;
        in highp vec2 vUV;
        out vec4 fragColor;

        uniform sampler2D uCompositionTexture;
        uniform sampler2D uTexture;
        uniform float uMix;

        void main() {
            fragColor = texture(uTexture, vUV);
            vec4 blurred = texture(uTexture, vUV);
            vec4 composition = texture(uCompositionTexture, vUV);
            fragColor = mix(composition, blurred, uMix);
        }
    )SHADER";
    return shader;
+13 −7
Original line number Diff line number Diff line
@@ -31,22 +31,25 @@ class BlurFilter {
public:
    // Downsample FBO to improve performance
    static constexpr float kFboScale = 0.25f;
    // To avoid downscaling artifacts, we interpolate the blurred fbo with the full composited
    // image, up to this radius.
    static constexpr float kMaxCrossFadeRadius = 15.0f;

    explicit BlurFilter(GLESRenderEngine& engine);
    virtual ~BlurFilter(){};

    // Set up render targets, redirecting output to offscreen texture.
    status_t setAsDrawTarget(const DisplaySettings&);
    status_t setAsDrawTarget(const DisplaySettings&, uint32_t radius);
    // Allocate any textures needed for the filter.
    virtual void allocateTextures() = 0;
    // Execute blur passes, rendering to offscreen texture.
    virtual status_t prepare(uint32_t radius) = 0;
    virtual status_t prepare() = 0;
    // Render blur to the bound framebuffer (screen).
    status_t render();

protected:
    uint32_t mRadius;
    void drawMesh(GLuint uv, GLuint position);
    string getSimpleFragShader() const;
    string getVertexShader() const;

    GLESRenderEngine& mEngine;
@@ -58,12 +61,15 @@ protected:
    uint32_t mDisplayHeight;

private:
    string getMixFragShader() const;
    bool mTexturesAllocated = false;

    GenericProgram mSimpleProgram;
    GLuint mSPosLoc;
    GLuint mSUvLoc;
    GLuint mSTextureLoc;
    GenericProgram mMixProgram;
    GLuint mMPosLoc;
    GLuint mMUvLoc;
    GLuint mMMixLoc;
    GLuint mMTextureLoc;
    GLuint mMCompositionTextureLoc;
};

} // namespace gl
Loading