Blur shader polish

Overall performance optimizations, including float precision tweaks,
and mipmapping for better antialiasing.

Test: visual
Test: systrace
Test: SurfaceFlinger_test
Bug: 141640413
Change-Id: Ic4e6ac9ccea236c561416f000a2287f2867c71a3
diff --git a/libs/renderengine/gl/filters/BlurFilter.cpp b/libs/renderengine/gl/filters/BlurFilter.cpp
index a554687..a18a999 100644
--- a/libs/renderengine/gl/filters/BlurFilter.cpp
+++ b/libs/renderengine/gl/filters/BlurFilter.cpp
@@ -42,9 +42,20 @@
     ATRACE_NAME("BlurFilter::setAsDrawTarget");
 
     if (!mTexturesAllocated) {
-        const uint32_t fboWidth = floorf(display.physicalDisplay.width() * kFboScale);
-        const uint32_t fboHeight = floorf(display.physicalDisplay.height() * kFboScale);
-        mCompositionFbo.allocateBuffers(fboWidth, fboHeight);
+        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);
         allocateTextures();
         mTexturesAllocated = true;
diff --git a/libs/renderengine/gl/filters/BlurFilter.h b/libs/renderengine/gl/filters/BlurFilter.h
index 2b5ea58..e265b51 100644
--- a/libs/renderengine/gl/filters/BlurFilter.h
+++ b/libs/renderengine/gl/filters/BlurFilter.h
@@ -30,7 +30,7 @@
 class BlurFilter {
 public:
     // Downsample FBO to improve performance
-    static constexpr float kFboScale = 0.35f;
+    static constexpr float kFboScale = 0.25f;
 
     explicit BlurFilter(GLESRenderEngine& engine);
     virtual ~BlurFilter(){};
@@ -54,6 +54,8 @@
     GLFramebuffer mCompositionFbo;
     // Frame buffer holding the blur result.
     GLFramebuffer mBlurredFbo;
+    uint32_t mDisplayWidth;
+    uint32_t mDisplayHeight;
 
 private:
     bool mTexturesAllocated = false;
diff --git a/libs/renderengine/gl/filters/GaussianBlurFilter.cpp b/libs/renderengine/gl/filters/GaussianBlurFilter.cpp
index b1ad72c..f5ba02a 100644
--- a/libs/renderengine/gl/filters/GaussianBlurFilter.cpp
+++ b/libs/renderengine/gl/filters/GaussianBlurFilter.cpp
@@ -77,12 +77,14 @@
     // set uniforms
     auto width = mVerticalPassFbo.getBufferWidth();
     auto height = mVerticalPassFbo.getBufferHeight();
+    auto radiusF = fmax(1.0f, radius * kFboScale);
     glViewport(0, 0, width, height);
     glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D, mCompositionFbo.getTextureName());
+    glGenerateMipmap(GL_TEXTURE_2D);
     glUniform1i(mVTextureLoc, 0);
     glUniform2f(mVSizeLoc, width, height);
-    glUniform1f(mVRadiusLoc, radius * kFboScale);
+    glUniform1f(mVRadiusLoc, radiusF);
     mEngine.checkErrors("Setting vertical-diagonal pass uniforms");
 
     drawMesh(mVUvLoc, mVPosLoc);
@@ -96,7 +98,7 @@
     glBindTexture(GL_TEXTURE_2D, mVerticalPassFbo.getTextureName());
     glUniform1i(mHTextureLoc, 0);
     glUniform2f(mHSizeLoc, width, height);
-    glUniform1f(mHRadiusLoc, radius * kFboScale);
+    glUniform1f(mHRadiusLoc, radiusF);
     mEngine.checkErrors("Setting vertical pass uniforms");
 
     drawMesh(mHUvLoc, mHPosLoc);
@@ -122,8 +124,7 @@
         uniform vec2 uSize;
         uniform float uRadius;
 
-        in mediump vec2 vUV;
-
+        mediump in vec2 vUV;
         out vec4 fragColor;
 
         #define PI 3.14159265359
@@ -131,7 +132,7 @@
         #define MU 0.0
         #define A 1.0 / (THETA * sqrt(2.0 * PI))
         #define K 1.0 / (2.0 * THETA * THETA)
-        #define MAX_SAMPLES 12
+        #define MAX_SAMPLES 10
 
         float gaussianBellCurve(float x) {
             float tmp = (x - MU);
@@ -139,14 +140,14 @@
         }
 
         vec3 gaussianBlur(sampler2D texture, mediump vec2 uv, float size,
-                          vec2 direction, float radius) {
+                          mediump vec2 direction, float radius) {
             float totalWeight = 0.0;
             vec3 blurred = vec3(0.);
-            int samples = min(int(floor(radius / 2.0)), MAX_SAMPLES);
+            int samples = min(int(ceil(radius / 2.0)), MAX_SAMPLES);
             float inc = radius / (size * 2.0);
 
             for (int i = -samples; i <= samples; i++) {
-                float normalized = (float(i) / float(samples));
+                float normalized = float(i) / float(samples);
                 float weight = gaussianBellCurve(normalized);
                 float radInc = inc * normalized;
                 blurred += weight * (texture(texture, uv + radInc * direction)).rgb;;
@@ -162,7 +163,7 @@
             #else
             vec3 color = gaussianBlur(uTexture, vUV, uSize.y, vec2(0.0, 1.0), uRadius);
             #endif
-            fragColor = vec4(color.r, color.g, color.b, texture(uTexture, vUV).a);
+            fragColor = vec4(color, 1.0);
         }
 
     )SHADER";
diff --git a/libs/renderengine/gl/filters/LensBlurFilter.cpp b/libs/renderengine/gl/filters/LensBlurFilter.cpp
index 386bd91..799deac 100644
--- a/libs/renderengine/gl/filters/LensBlurFilter.cpp
+++ b/libs/renderengine/gl/filters/LensBlurFilter.cpp
@@ -86,12 +86,14 @@
     // set uniforms
     auto width = mVerticalDiagonalPassFbo.getBufferWidth();
     auto height = mVerticalDiagonalPassFbo.getBufferHeight();
+    auto radiusF = fmax(1.0f, radius * kFboScale);
     glViewport(0, 0, width, height);
     glActiveTexture(GL_TEXTURE0);
     glBindTexture(GL_TEXTURE_2D, mCompositionFbo.getTextureName());
+    glGenerateMipmap(GL_TEXTURE_2D);
     glUniform1i(mVDTexture0Loc, 0);
-    glUniform2f(mVDSizeLoc, width, height);
-    glUniform1f(mVDRadiusLoc, radius * kFboScale);
+    glUniform2f(mVDSizeLoc, mDisplayWidth, mDisplayHeight);
+    glUniform1f(mVDRadiusLoc, radiusF);
     glUniform1i(mVDNumSamplesLoc, kNumSamples);
     mEngine.checkErrors("Setting vertical-diagonal pass uniforms");
 
@@ -108,8 +110,8 @@
     glActiveTexture(GL_TEXTURE1);
     glBindTexture(GL_TEXTURE_2D, mVerticalDiagonalPassFbo.getSecondaryTextureName());
     glUniform1i(mCTexture1Loc, 1);
-    glUniform2f(mCSizeLoc, width, height);
-    glUniform1f(mCRadiusLoc, radius * kFboScale);
+    glUniform2f(mCSizeLoc, mDisplayWidth, mDisplayHeight);
+    glUniform1f(mCRadiusLoc, radiusF);
     glUniform1i(mCNumSamplesLoc, kNumSamples);
     mEngine.checkErrors("Setting vertical pass uniforms");
 
@@ -134,7 +136,6 @@
     shader += R"SHADER(
         precision lowp float;
 
-        #define BOKEH_ANGLE 0.0
         #define PI 3.14159265359
 
         uniform sampler2D uTexture0;
@@ -142,7 +143,7 @@
         uniform float uRadius;
         uniform int uNumSamples;
 
-        in mediump vec2 vUV;
+        mediump in vec2 vUV;
 
         #if DIRECTION == 0
         layout(location = 0) out vec4 fragColor0;
@@ -152,61 +153,55 @@
         out vec4 fragColor;
         #endif
 
-        vec4 blur(const sampler2D tex, in vec2 uv, const vec2 direction, float radius,
-                  in int samples, float intensity) {
-            vec4 finalColor = vec4(vec3(0.0), 1.0);
-            float blurAmount = 0.0;
+        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);
-                vec4 color = texture(tex, uv + direction * delta);
+                vec3 color = texture(tex, uv + direction * delta).rgb;
                 color.rgb *= intensity;
-                color *= color.a;
-                blurAmount += color.a;
                 finalColor += color;
             }
 
-            return finalColor / blurAmount;
+            return finalColor / float(samples);
         }
 
-        vec4 blur(const sampler2D tex, in vec2 uv, const vec2 direction, float radius,
-                  in int 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) {
-            float coc = texture(texture, uv).a;
-
             // Vertical Blur
-            vec2 blurDirV = (coc / resolution.xy) * vec2(cos(BOKEH_ANGLE + PI / 2.0),
-                sin(BOKEH_ANGLE + PI / 2.0));
-            vec3 colorV = blur(texture, uv, blurDirV, radius, samples).rgb * coc;
+            vec2 blurDirV = 1.0 / resolution.xy * verticalMult;
+            vec3 colorV = blur(texture, uv, blurDirV, radius, samples);
 
             // Diagonal Blur
-            vec2 blurDirD = (coc / resolution.xy) * vec2(cos(BOKEH_ANGLE - PI / 6.0),
-                sin(BOKEH_ANGLE - PI / 6.0));
-            vec3 colorD = blur(texture, uv, blurDirD, radius, samples).rgb * coc;
+            vec2 blurDirD = 1.0 / resolution.xy * diagonalMult;
+            vec3 colorD = blur(texture, uv, blurDirD, radius, samples);
 
             vec4 composed[2];
-            composed[0] = vec4(colorV, coc);
+            composed[0] = vec4(colorV, 1.0);
             // added * 0.5, to remap
-            composed[1] = vec4((colorD + colorV) * 0.5, coc);
+            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) {
-            float coc1 = texture(texture0, uv).a;
-            float coc2 = texture(texture1, uv).a;
+            vec2 blurDirection1 = 1.0 / resolution.xy * diagonalMult;
+            vec3 color1 = blur(texture0, uv, blurDirection1, radius, samples);
 
-            vec2 blurDirection1 = coc1 / resolution.xy * vec2(cos(BOKEH_ANGLE - PI / 6.0), sin(BOKEH_ANGLE - PI / 6.0));
-            vec3 color1 = blur(texture0, uv, blurDirection1, radius, samples).rgb * coc1;
-
-            vec2 blurDirection2 = coc2 / resolution.xy * vec2(cos(BOKEH_ANGLE - 5.0 * PI / 6.0), sin(BOKEH_ANGLE - 5.0 * PI / 6.0));
-            vec3 color2 = blur(texture1, uv, blurDirection2, radius, samples, 2.0).rgb * coc2;
+            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);
         }