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 Original line Diff line number Diff line
@@ -1003,7 +1003,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
        setViewportAndProjection(display.physicalDisplay, display.clip);
        setViewportAndProjection(display.physicalDisplay, display.clip);
    } else {
    } else {
        setViewportAndProjection(display.physicalDisplay, display.clip);
        setViewportAndProjection(display.physicalDisplay, display.clip);
        auto status = mBlurFilter->setAsDrawTarget(display);
        auto status = mBlurFilter->setAsDrawTarget(display, blurLayer->backgroundBlurRadius);
        if (status != NO_ERROR) {
        if (status != NO_ERROR) {
            ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).",
            ALOGE("Failed to prepare blur filter! Aborting GPU composition for buffer (%p).",
                  buffer->handle);
                  buffer->handle);
@@ -1037,7 +1037,7 @@ status_t GLESRenderEngine::drawLayers(const DisplaySettings& display,
                        .build();
                        .build();
    for (auto const layer : layers) {
    for (auto const layer : layers) {
        if (blurLayer == layer) {
        if (blurLayer == layer) {
            auto status = mBlurFilter->prepare(layer->backgroundBlurRadius);
            auto status = mBlurFilter->prepare();
            if (status != NO_ERROR) {
            if (status != NO_ERROR) {
                ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).",
                ALOGE("Failed to render blur effect! Aborting GPU composition for buffer (%p).",
                      buffer->handle);
                      buffer->handle);
+8 −0
Original line number Original line Diff line number Diff line
@@ -122,6 +122,14 @@ void GLFramebuffer::bind() const {
    glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
    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 {
void GLFramebuffer::unbind() const {
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
}
}
+2 −0
Original line number Original line Diff line number Diff line
@@ -48,6 +48,8 @@ public:
    int32_t getBufferWidth() const { return mBufferWidth; }
    int32_t getBufferWidth() const { return mBufferWidth; }
    GLenum getStatus() const { return mStatus; }
    GLenum getStatus() const { return mStatus; }
    void bind() const;
    void bind() const;
    void bindAsReadBuffer() const;
    void bindAsDrawBuffer() const;
    void unbind() const;
    void unbind() const;


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


BlurFilter::BlurFilter(GLESRenderEngine& engine)
BlurFilter::BlurFilter(GLESRenderEngine& engine)
      : mEngine(engine), mCompositionFbo(engine), mBlurredFbo(engine), mSimpleProgram(engine) {
      : mEngine(engine), mCompositionFbo(engine), mBlurredFbo(engine), mMixProgram(engine) {
    mSimpleProgram.compile(getVertexShader(), getSimpleFragShader());
    mMixProgram.compile(getVertexShader(), getMixFragShader());
    mSPosLoc = mSimpleProgram.getAttributeLocation("aPosition");
    mMPosLoc = mMixProgram.getAttributeLocation("aPosition");
    mSUvLoc = mSimpleProgram.getAttributeLocation("aUV");
    mMUvLoc = mMixProgram.getAttributeLocation("aUV");
    mSTextureLoc = mSimpleProgram.getUniformLocation("uTexture");
    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");
    ATRACE_NAME("BlurFilter::setAsDrawTarget");
    mRadius = radius;


    if (!mTexturesAllocated) {
    if (!mTexturesAllocated) {
        mDisplayWidth = display.physicalDisplay.width();
        mDisplayWidth = display.physicalDisplay.width();
        mDisplayHeight = display.physicalDisplay.height();
        mDisplayHeight = display.physicalDisplay.height();
        mCompositionFbo.allocateBuffers(mDisplayWidth, mDisplayHeight);
        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 fboWidth = floorf(mDisplayWidth * kFboScale);
        const uint32_t fboHeight = floorf(mDisplayHeight * kFboScale);
        const uint32_t fboHeight = floorf(mDisplayHeight * kFboScale);
        mBlurredFbo.allocateBuffers(fboWidth, fboHeight);
        mBlurredFbo.allocateBuffers(fboWidth, fboHeight);
@@ -94,27 +89,41 @@ void BlurFilter::drawMesh(GLuint uv, GLuint position) {
status_t BlurFilter::render() {
status_t BlurFilter::render() {
    ATRACE_NAME("BlurFilter::render");
    ATRACE_NAME("BlurFilter::render");


    // Now let's scale our blur up
    // Now let's scale our blur up. It will be interpolated with the larger composited
    mSimpleProgram.useProgram();
    // 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);
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, mBlurredFbo.getTextureName());
    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");
    mEngine.checkErrors("Setting final pass uniforms");


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


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


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


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


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


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


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


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


        void main() {
        void main() {
            fragColor = texture(uTexture, vUV);
            vec4 blurred = texture(uTexture, vUV);
            vec4 composition = texture(uCompositionTexture, vUV);
            fragColor = mix(composition, blurred, uMix);
        }
        }
    )SHADER";
    )SHADER";
    return shader;
    return shader;
+13 −7
Original line number Original line Diff line number Diff line
@@ -31,22 +31,25 @@ class BlurFilter {
public:
public:
    // Downsample FBO to improve performance
    // Downsample FBO to improve performance
    static constexpr float kFboScale = 0.25f;
    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);
    explicit BlurFilter(GLESRenderEngine& engine);
    virtual ~BlurFilter(){};
    virtual ~BlurFilter(){};


    // Set up render targets, redirecting output to offscreen texture.
    // 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.
    // Allocate any textures needed for the filter.
    virtual void allocateTextures() = 0;
    virtual void allocateTextures() = 0;
    // Execute blur passes, rendering to offscreen texture.
    // 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).
    // Render blur to the bound framebuffer (screen).
    status_t render();
    status_t render();


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


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


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


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


} // namespace gl
} // namespace gl
Loading