diff options
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/renderengine/Android.bp | 2 | ||||
| -rw-r--r-- | libs/renderengine/gl/GLESRenderEngine.cpp | 9 | ||||
| -rw-r--r-- | libs/renderengine/gl/GLESRenderEngine.h | 2 | ||||
| -rw-r--r-- | libs/renderengine/gl/filters/BlurFilter.cpp | 16 | ||||
| -rw-r--r-- | libs/renderengine/gl/filters/BlurFilter.h | 2 | ||||
| -rw-r--r-- | libs/renderengine/gl/filters/KawaseBlurFilter.cpp | 139 | ||||
| -rw-r--r-- | libs/renderengine/gl/filters/KawaseBlurFilter.h (renamed from libs/renderengine/gl/filters/LensBlurFilter.h) | 39 | ||||
| -rw-r--r-- | libs/renderengine/gl/filters/LensBlurFilter.cpp | 225 |
8 files changed, 175 insertions, 259 deletions
diff --git a/libs/renderengine/Android.bp b/libs/renderengine/Android.bp index 4c7b629197..3d77059b9d 100644 --- a/libs/renderengine/Android.bp +++ b/libs/renderengine/Android.bp @@ -59,7 +59,7 @@ filegroup { "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 69003fb86f..e523836c59 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 @@ std::unique_ptr<GLESRenderEngine> GLESRenderEngine::create(const RenderEngineCre // 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 @@ GLESRenderEngine::GLESRenderEngine(const RenderEngineCreationArgs& args, EGLDisp 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 4fc457f904..ebf78fe6c8 100644 --- a/libs/renderengine/gl/GLESRenderEngine.h +++ b/libs/renderengine/gl/GLESRenderEngine.h @@ -262,7 +262,7 @@ private: 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 48c256065c..f8b0a7a891 100644 --- a/libs/renderengine/gl/filters/BlurFilter.cpp +++ b/libs/renderengine/gl/filters/BlurFilter.cpp @@ -71,8 +71,18 @@ status_t BlurFilter::setAsDrawTarget(const DisplaySettings& display, uint32_t ra } 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 @@ void BlurFilter::drawMesh(GLuint uv, GLuint position) { 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 6889939518..67b3895262 100644 --- a/libs/renderengine/gl/filters/BlurFilter.h +++ b/libs/renderengine/gl/filters/BlurFilter.h @@ -33,7 +33,7 @@ public: 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 0000000000..fc26bccc52 --- /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/LensBlurFilter.h b/libs/renderengine/gl/filters/KawaseBlurFilter.h index 1620c5a556..ec81f81229 100644 --- a/libs/renderengine/gl/filters/LensBlurFilter.h +++ b/libs/renderengine/gl/filters/KawaseBlurFilter.h @@ -1,5 +1,5 @@ /* - * Copyright 2019 The Android Open Source Project + * 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. @@ -28,38 +28,27 @@ namespace android { namespace renderengine { namespace gl { -class LensBlurFilter : public BlurFilter { +class KawaseBlurFilter : public BlurFilter { public: - explicit LensBlurFilter(GLESRenderEngine& engine); + static constexpr uint32_t kMaxPasses = 8; + + explicit KawaseBlurFilter(GLESRenderEngine& engine); status_t prepare() override; void allocateTextures() override; private: - string getFragmentShader(bool forComposition) const; - - // Intermediate render pass - GLFramebuffer mVerticalDiagonalPassFbo; + string getFragmentShader() const; + void blit(GLFramebuffer& read, GLFramebuffer& draw) const; - // Vertical/diagonal pass and its uniforms - GenericProgram mVerticalDiagonalProgram; - GLuint mVDPosLoc; - GLuint mVDUvLoc; - GLuint mVDTexture0Loc; - GLuint mVDSizeLoc; - GLuint mVDRadiusLoc; - GLuint mVDNumSamplesLoc; + GLFramebuffer mFbo; - // Blur composition pass and its uniforms - GenericProgram mCombinedProgram; - GLuint mCPosLoc; - GLuint mCUvLoc; - GLuint mCTexture0Loc; - GLuint mCTexture1Loc; - GLuint mCSizeLoc; - GLuint mCRadiusLoc; - GLuint mCNumSamplesLoc; + GenericProgram mProgram; + GLuint mPosLoc; + GLuint mUvLoc; + GLuint mTextureLoc; + GLuint mOffsetLoc; }; } // namespace gl } // namespace renderengine -} // namespace android
\ No newline at end of file +} // namespace android diff --git a/libs/renderengine/gl/filters/LensBlurFilter.cpp b/libs/renderengine/gl/filters/LensBlurFilter.cpp deleted file mode 100644 index fb29fbb48b..0000000000 --- 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 |