Kawase blur filter

For better performance and more stable large radius.
Also removing LensFilter given that performance was not
good enough for real time effects.

Test: visual (on Kawase and Gaussian)
Bug: 148614710
Change-Id: I81fd2cce030dafb8d87a7c65606632ac1ecfa113
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp
index 4c7b629..3d77059 100644
--- a/libs/renderengine/Android.bp
+++ b/libs/renderengine/Android.bp
@@ -59,7 +59,7 @@
         "gl/Program.cpp",
         "gl/ProgramCache.cpp",
         "gl/filters/BlurFilter.cpp",
-        "gl/filters/LensBlurFilter.cpp",
+        "gl/filters/KawaseBlurFilter.cpp",
         "gl/filters/GaussianBlurFilter.cpp",
         "gl/filters/GenericProgram.cpp",
     ],
diff --git a/libs/renderengine/gl/GLESRenderEngine.cpp b/libs/renderengine/gl/GLESRenderEngine.cpp
index 69003fb..e523836 100644
--- a/libs/renderengine/gl/GLESRenderEngine.cpp
+++ b/libs/renderengine/gl/GLESRenderEngine.cpp
@@ -51,7 +51,7 @@
 #include "ProgramCache.h"
 #include "filters/BlurFilter.h"
 #include "filters/GaussianBlurFilter.h"
-#include "filters/LensBlurFilter.h"
+#include "filters/KawaseBlurFilter.h"
 
 extern "C" EGLAPI const char* eglQueryStringImplementationANDROID(EGLDisplay dpy, EGLint name);
 
@@ -285,6 +285,9 @@
     // now figure out what version of GL did we actually get
     GlesVersion version = parseGlesVersion(extensions.getVersion());
 
+    LOG_ALWAYS_FATAL_IF(args.supportsBackgroundBlur && version < GLES_VERSION_3_0,
+        "Blurs require OpenGL ES 3.0. Please unset ro.surface_flinger.supports_background_blur");
+
     // initialize the renderer while GL is current
     std::unique_ptr<GLESRenderEngine> engine;
     switch (version) {
@@ -428,11 +431,11 @@
 
     if (args.supportsBackgroundBlur) {
         char isGaussian[PROPERTY_VALUE_MAX];
-        property_get("debug.sf.gaussianBlur", isGaussian, "1");
+        property_get("debug.sf.gaussianBlur", isGaussian, "0");
         if (atoi(isGaussian)) {
             mBlurFilter = new GaussianBlurFilter(*this);
         } else {
-            mBlurFilter = new LensBlurFilter(*this);
+            mBlurFilter = new KawaseBlurFilter(*this);
         }
         checkErrors("BlurFilter creation");
     }
diff --git a/libs/renderengine/gl/GLESRenderEngine.h b/libs/renderengine/gl/GLESRenderEngine.h
index 4fc457f..ebf78fe 100644
--- a/libs/renderengine/gl/GLESRenderEngine.h
+++ b/libs/renderengine/gl/GLESRenderEngine.h
@@ -262,7 +262,7 @@
     friend class GLFramebuffer;
     friend class BlurFilter;
     friend class GaussianBlurFilter;
-    friend class LensBlurFilter;
+    friend class KawaseBlurFilter;
     friend class GenericProgram;
     std::unique_ptr<FlushTracer> mFlushTracer;
     std::unique_ptr<ImageManager> mImageManager = std::make_unique<ImageManager>(this);
diff --git a/libs/renderengine/gl/filters/BlurFilter.cpp b/libs/renderengine/gl/filters/BlurFilter.cpp
index 48c2560..f8b0a7a 100644
--- a/libs/renderengine/gl/filters/BlurFilter.cpp
+++ b/libs/renderengine/gl/filters/BlurFilter.cpp
@@ -71,8 +71,18 @@
 }
 
 void BlurFilter::drawMesh(GLuint uv, GLuint position) {
-    GLfloat positions[] = {-1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, 1.0f, -1.0f};
-    GLfloat texCoords[] = {0.0, 0.0, 0.0, 1.0f, 1.0f, 1.0f, 1.0f, 0};
+    static constexpr auto size = 2.0f;
+    static constexpr auto translation = 1.0f;
+    GLfloat positions[] = {
+        translation-size, -translation-size,
+        translation-size, -translation+size,
+        translation+size, -translation+size
+    };
+    GLfloat texCoords[] = {
+        0.0f, 0.0f-translation,
+        0.0f, size-translation,
+        size, size-translation
+    };
 
     // set attributes
     glEnableVertexAttribArray(uv);
@@ -82,7 +92,7 @@
                           positions);
 
     // draw mesh
-    glDrawArrays(GL_TRIANGLE_FAN, 0 /* first */, 4 /* count */);
+    glDrawArrays(GL_TRIANGLES, 0 /* first */, 3 /* count */);
     mEngine.checkErrors("Drawing blur mesh");
 }
 
diff --git a/libs/renderengine/gl/filters/BlurFilter.h b/libs/renderengine/gl/filters/BlurFilter.h
index 6889939..67b3895 100644
--- a/libs/renderengine/gl/filters/BlurFilter.h
+++ b/libs/renderengine/gl/filters/BlurFilter.h
@@ -33,7 +33,7 @@
     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;
+    static constexpr float kMaxCrossFadeRadius = 30.0f;
 
     explicit BlurFilter(GLESRenderEngine& engine);
     virtual ~BlurFilter(){};
diff --git a/libs/renderengine/gl/filters/KawaseBlurFilter.cpp b/libs/renderengine/gl/filters/KawaseBlurFilter.cpp
new file mode 100644
index 0000000..fc26bcc
--- /dev/null
+++ b/libs/renderengine/gl/filters/KawaseBlurFilter.cpp
@@ -0,0 +1,139 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
+#include "KawaseBlurFilter.h"
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <GLES3/gl3.h>
+#include <GLES3/gl3ext.h>
+#include <ui/GraphicTypes.h>
+
+#include <utils/Trace.h>
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+KawaseBlurFilter::KawaseBlurFilter(GLESRenderEngine& engine)
+      : BlurFilter(engine), mFbo(engine), mProgram(engine) {
+    mProgram.compile(getVertexShader(), getFragmentShader());
+    mPosLoc = mProgram.getAttributeLocation("aPosition");
+    mUvLoc = mProgram.getAttributeLocation("aUV");
+    mTextureLoc = mProgram.getUniformLocation("uTexture");
+    mOffsetLoc = mProgram.getUniformLocation("uOffset");
+}
+
+void KawaseBlurFilter::allocateTextures() {
+    mFbo.allocateBuffers(mBlurredFbo.getBufferWidth(), mBlurredFbo.getBufferHeight());
+}
+
+status_t KawaseBlurFilter::prepare() {
+    ATRACE_NAME("KawaseBlurFilter::prepare");
+
+    if (mFbo.getStatus() != GL_FRAMEBUFFER_COMPLETE) {
+        ALOGE("Invalid FBO");
+        return mFbo.getStatus();
+    }
+    if (!mProgram.isValid()) {
+        ALOGE("Invalid shader");
+        return GL_INVALID_OPERATION;
+    }
+
+    blit(mCompositionFbo, mBlurredFbo);
+
+    // Kawase is an approximation of Gaussian, but it behaves differently from it.
+    // A radius transformation is required for approximating them, and also to introduce
+    // non-integer steps, necessary to smoothly interpolate large radii.
+    auto radius = mRadius / 6.0f;
+
+    // Calculate how many passes we'll do, based on the radius.
+    // Too many passes will make the operation expensive.
+    auto passes = min(kMaxPasses, (uint32_t)ceil(radius));
+
+    // We'll ping pong between our textures, to accumulate the result of various offsets.
+    mProgram.useProgram();
+    GLFramebuffer* draw = &mFbo;
+    GLFramebuffer* read = &mBlurredFbo;
+    float stepX = radius / (float)mCompositionFbo.getBufferWidth() / (float)passes;
+    float stepY = radius / (float)mCompositionFbo.getBufferHeight() / (float)passes;
+    glActiveTexture(GL_TEXTURE0);
+    glUniform1i(mTextureLoc, 0);
+    for (auto i = 0; i < passes; i++) {
+        ATRACE_NAME("KawaseBlurFilter::renderPass");
+        draw->bind();
+
+        glViewport(0, 0, draw->getBufferWidth(), draw->getBufferHeight());
+        glBindTexture(GL_TEXTURE_2D, read->getTextureName());
+        glUniform2f(mOffsetLoc, stepX * i, stepY * i);
+        mEngine.checkErrors("Setting uniforms");
+
+        drawMesh(mUvLoc, mPosLoc);
+
+        // Swap buffers for next iteration
+        auto tmp = draw;
+        draw = read;
+        read = tmp;
+    }
+
+    // Copy texture, given that we're expected to end on mBlurredFbo.
+    if (draw == &mBlurredFbo) {
+        blit(mFbo, mBlurredFbo);
+    }
+
+    // Cleanup
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+    return NO_ERROR;
+}
+
+string KawaseBlurFilter::getFragmentShader() const {
+    return R"SHADER(#version 310 es
+        precision mediump float;
+
+        uniform sampler2D uTexture;
+        highp uniform vec2 uOffset;
+
+        highp in vec2 vUV;
+        out vec4 fragColor;
+
+        vec4 kawaseBlur() {
+            return (texture(uTexture, vec2(-1.0, 1.0) * uOffset + vUV, 0.0)
+                    + texture(uTexture, uOffset + vUV, 0.0)
+                    + texture(uTexture, vec2(1.0, -1.0) * uOffset + vUV, 0.0)
+                    + texture(uTexture, vec2(-1.0) * uOffset + vUV, 0.0))
+                * 0.25;
+        }
+
+        void main() {
+            fragColor = kawaseBlur();
+        }
+    )SHADER";
+}
+
+void KawaseBlurFilter::blit(GLFramebuffer& read, GLFramebuffer& draw) const {
+    read.bindAsReadBuffer();
+    draw.bindAsDrawBuffer();
+    glBlitFramebuffer(0, 0, read.getBufferWidth(), read.getBufferHeight(), 0, 0,
+                      draw.getBufferWidth(), draw.getBufferHeight(), GL_COLOR_BUFFER_BIT,
+                      GL_LINEAR);
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
+} // namespace gl
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/gl/filters/KawaseBlurFilter.h b/libs/renderengine/gl/filters/KawaseBlurFilter.h
new file mode 100644
index 0000000..ec81f81
--- /dev/null
+++ b/libs/renderengine/gl/filters/KawaseBlurFilter.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2020 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.
+ */
+
+#pragma once
+
+#include <ui/GraphicTypes.h>
+#include "../GLESRenderEngine.h"
+#include "../GLFramebuffer.h"
+#include "BlurFilter.h"
+#include "GenericProgram.h"
+
+using namespace std;
+
+namespace android {
+namespace renderengine {
+namespace gl {
+
+class KawaseBlurFilter : public BlurFilter {
+public:
+    static constexpr uint32_t kMaxPasses = 8;
+
+    explicit KawaseBlurFilter(GLESRenderEngine& engine);
+    status_t prepare() override;
+    void allocateTextures() override;
+
+private:
+    string getFragmentShader() const;
+    void blit(GLFramebuffer& read, GLFramebuffer& draw) const;
+
+    GLFramebuffer mFbo;
+
+    GenericProgram mProgram;
+    GLuint mPosLoc;
+    GLuint mUvLoc;
+    GLuint mTextureLoc;
+    GLuint mOffsetLoc;
+};
+
+} // namespace gl
+} // namespace renderengine
+} // namespace android
diff --git a/libs/renderengine/gl/filters/LensBlurFilter.cpp b/libs/renderengine/gl/filters/LensBlurFilter.cpp
deleted file mode 100644
index fb29fbb..0000000
--- a/libs/renderengine/gl/filters/LensBlurFilter.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include "LensBlurFilter.h"
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <GLES3/gl3.h>
-#include <GLES3/gl3ext.h>
-#include <ui/GraphicTypes.h>
-#include <cstdint>
-
-#include <utils/Trace.h>
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-// Number of blur samples in shader (for loop)
-static constexpr auto kNumSamples = 12;
-
-LensBlurFilter::LensBlurFilter(GLESRenderEngine& engine)
-      : BlurFilter(engine),
-        mVerticalDiagonalPassFbo(engine, true /* multiTarget */),
-        mVerticalDiagonalProgram(engine),
-        mCombinedProgram(engine) {
-    mVerticalDiagonalProgram.compile(getVertexShader(), getFragmentShader(false));
-    mCombinedProgram.compile(getVertexShader(), getFragmentShader(true));
-
-    mVDPosLoc = mVerticalDiagonalProgram.getAttributeLocation("aPosition");
-    mVDUvLoc = mVerticalDiagonalProgram.getAttributeLocation("aUV");
-    mVDTexture0Loc = mVerticalDiagonalProgram.getUniformLocation("uTexture0");
-    mVDSizeLoc = mVerticalDiagonalProgram.getUniformLocation("uSize");
-    mVDRadiusLoc = mVerticalDiagonalProgram.getUniformLocation("uRadius");
-    mVDNumSamplesLoc = mVerticalDiagonalProgram.getUniformLocation("uNumSamples");
-
-    mCPosLoc = mCombinedProgram.getAttributeLocation("aPosition");
-    mCUvLoc = mCombinedProgram.getAttributeLocation("aUV");
-    mCTexture0Loc = mCombinedProgram.getUniformLocation("uTexture0");
-    mCTexture1Loc = mCombinedProgram.getUniformLocation("uTexture1");
-    mCSizeLoc = mCombinedProgram.getUniformLocation("uSize");
-    mCRadiusLoc = mCombinedProgram.getUniformLocation("uRadius");
-    mCNumSamplesLoc = mCombinedProgram.getUniformLocation("uNumSamples");
-}
-
-void LensBlurFilter::allocateTextures() {
-    mVerticalDiagonalPassFbo.allocateBuffers(mBlurredFbo.getBufferWidth(),
-                                             mBlurredFbo.getBufferHeight());
-}
-
-status_t LensBlurFilter::prepare() {
-    ATRACE_NAME("LensBlurFilter::prepare");
-
-    if (mVerticalDiagonalPassFbo.getStatus() != GL_FRAMEBUFFER_COMPLETE) {
-        ALOGE("Invalid vertical-diagonal FBO");
-        return mVerticalDiagonalPassFbo.getStatus();
-    }
-    if (!mVerticalDiagonalProgram.isValid()) {
-        ALOGE("Invalid vertical-diagonal shader");
-        return GL_INVALID_OPERATION;
-    }
-    if (!mCombinedProgram.isValid()) {
-        ALOGE("Invalid blur shader");
-        return GL_INVALID_OPERATION;
-    }
-
-    // First, we'll apply the vertical/diagonal pass, that receives the flattened background layers,
-    // and writes the output to two textures (vertical and diagonal.)
-    mVerticalDiagonalPassFbo.bind();
-    mVerticalDiagonalProgram.useProgram();
-
-    // set uniforms
-    auto width = mVerticalDiagonalPassFbo.getBufferWidth();
-    auto height = mVerticalDiagonalPassFbo.getBufferHeight();
-    auto radiusF = fmax(1.0f, mRadius * kFboScale);
-    glViewport(0, 0, width, height);
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, mCompositionFbo.getTextureName());
-    glUniform1i(mVDTexture0Loc, 0);
-    glUniform2f(mVDSizeLoc, mDisplayWidth, mDisplayHeight);
-    glUniform1f(mVDRadiusLoc, radiusF);
-    glUniform1i(mVDNumSamplesLoc, kNumSamples);
-    mEngine.checkErrors("Setting vertical-diagonal pass uniforms");
-
-    drawMesh(mVDUvLoc, mVDPosLoc);
-
-    // Now we'll combine the multi render pass into a blurred image
-    mBlurredFbo.bind();
-    mCombinedProgram.useProgram();
-
-    // set uniforms
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, mVerticalDiagonalPassFbo.getTextureName());
-    glUniform1i(mCTexture0Loc, 0);
-    glActiveTexture(GL_TEXTURE1);
-    glBindTexture(GL_TEXTURE_2D, mVerticalDiagonalPassFbo.getSecondaryTextureName());
-    glUniform1i(mCTexture1Loc, 1);
-    glUniform2f(mCSizeLoc, mDisplayWidth, mDisplayHeight);
-    glUniform1f(mCRadiusLoc, radiusF);
-    glUniform1i(mCNumSamplesLoc, kNumSamples);
-    mEngine.checkErrors("Setting vertical pass uniforms");
-
-    drawMesh(mCUvLoc, mCPosLoc);
-
-    // reset active texture
-    mBlurredFbo.unbind();
-    glActiveTexture(GL_TEXTURE1);
-    glBindTexture(GL_TEXTURE_2D, 0);
-    glActiveTexture(GL_TEXTURE0);
-    glBindTexture(GL_TEXTURE_2D, 0);
-
-    // unbind program
-    glUseProgram(0);
-
-    return NO_ERROR;
-}
-
-string LensBlurFilter::getFragmentShader(bool forComposition) const {
-    string shader = "#version 310 es\n#define DIRECTION ";
-    shader += (forComposition ? "1" : "0");
-    shader += R"SHADER(
-        precision mediump float;
-        #define PI 3.14159265359
-
-        uniform sampler2D uTexture0;
-        uniform vec2 uSize;
-        uniform float uRadius;
-        uniform int uNumSamples;
-
-        highp in vec2 vUV;
-
-        #if DIRECTION == 0
-        layout(location = 0) out vec4 fragColor0;
-        layout(location = 1) out vec4 fragColor1;
-        #else
-        uniform sampler2D uTexture1;
-        out vec4 fragColor;
-        #endif
-
-        const vec2 verticalMult = vec2(cos(PI / 2.0), sin(PI / 2.0));
-        const vec2 diagonalMult = vec2(cos(-PI / 6.0), sin(-PI / 6.0));
-        const vec2 diagonal2Mult = vec2(cos(-5.0 * PI / 6.0), sin(-5.0 * PI / 6.0));
-
-        vec3 blur(const sampler2D tex, vec2 uv, const vec2 direction, float radius,
-                  int samples, float intensity) {
-            vec3 finalColor = vec3(0.0);
-            uv += direction * 0.5;
-
-            for (int i = 0; i < samples; i++){
-                float delta = radius * float(i) / float(samples);
-                vec3 color = texture(tex, uv + direction * delta).rgb;
-                color.rgb *= intensity;
-                finalColor += color;
-            }
-
-            return finalColor / float(samples);
-        }
-
-        vec3 blur(const sampler2D tex, vec2 uv, const vec2 direction, float radius,
-                  int samples) {
-            return blur(tex, uv, direction, radius, samples, 1.0);
-        }
-
-        vec4[2] verticalDiagonalLensBlur (vec2 uv, sampler2D texture, vec2 resolution,
-                                          float radius, int samples) {
-            // Vertical Blur
-            vec2 blurDirV = 1.0 / resolution.xy * verticalMult;
-            vec3 colorV = blur(texture, uv, blurDirV, radius, samples);
-
-            // Diagonal Blur
-            vec2 blurDirD = 1.0 / resolution.xy * diagonalMult;
-            vec3 colorD = blur(texture, uv, blurDirD, radius, samples);
-
-            vec4 composed[2];
-            composed[0] = vec4(colorV, 1.0);
-            // added * 0.5, to remap
-            composed[1] = vec4((colorD + colorV) * 0.5, 1.0);
-
-            return composed;
-        }
-
-        vec4 rhombiLensBlur (vec2 uv, sampler2D texture0, sampler2D texture1, vec2 resolution,
-                             float radius, int samples) {
-            vec2 blurDirection1 = 1.0 / resolution.xy * diagonalMult;
-            vec3 color1 = blur(texture0, uv, blurDirection1, radius, samples);
-
-            vec2 blurDirection2 = 1.0 / resolution.xy * diagonal2Mult;
-            vec3 color2 = blur(texture1, uv, blurDirection2, radius, samples, 2.0);
-
-            return vec4((color1 + color2) * 0.33, 1.0);
-        }
-
-        void main() {
-            #if DIRECTION == 0
-            // First pass: outputs two textures
-            vec4 colorOut[] = verticalDiagonalLensBlur(vUV, uTexture0, uSize, uRadius, uNumSamples);
-            fragColor0 = colorOut[0];
-            fragColor1 = colorOut[1];
-            #else
-            // Second pass: combines both textures into a blurred one.
-            fragColor = rhombiLensBlur(vUV, uTexture0, uTexture1, uSize, uRadius, uNumSamples);
-            #endif
-        }
-
-    )SHADER";
-    return shader;
-}
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
diff --git a/libs/renderengine/gl/filters/LensBlurFilter.h b/libs/renderengine/gl/filters/LensBlurFilter.h
deleted file mode 100644
index 1620c5a..0000000
--- a/libs/renderengine/gl/filters/LensBlurFilter.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright 2019 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.
- */
-
-#pragma once
-
-#include <ui/GraphicTypes.h>
-#include "../GLESRenderEngine.h"
-#include "../GLFramebuffer.h"
-#include "BlurFilter.h"
-#include "GenericProgram.h"
-
-using namespace std;
-
-namespace android {
-namespace renderengine {
-namespace gl {
-
-class LensBlurFilter : public BlurFilter {
-public:
-    explicit LensBlurFilter(GLESRenderEngine& engine);
-    status_t prepare() override;
-    void allocateTextures() override;
-
-private:
-    string getFragmentShader(bool forComposition) const;
-
-    // Intermediate render pass
-    GLFramebuffer mVerticalDiagonalPassFbo;
-
-    // Vertical/diagonal pass and its uniforms
-    GenericProgram mVerticalDiagonalProgram;
-    GLuint mVDPosLoc;
-    GLuint mVDUvLoc;
-    GLuint mVDTexture0Loc;
-    GLuint mVDSizeLoc;
-    GLuint mVDRadiusLoc;
-    GLuint mVDNumSamplesLoc;
-
-    // Blur composition pass and its uniforms
-    GenericProgram mCombinedProgram;
-    GLuint mCPosLoc;
-    GLuint mCUvLoc;
-    GLuint mCTexture0Loc;
-    GLuint mCTexture1Loc;
-    GLuint mCSizeLoc;
-    GLuint mCRadiusLoc;
-    GLuint mCNumSamplesLoc;
-};
-
-} // namespace gl
-} // namespace renderengine
-} // namespace android
\ No newline at end of file