Add support for background blurs

Bug: 141640413
Fixes: 146384234
Test: adb shell setprop debug.sf.disableBlurs 1
Test: adb shell setprop debug.sf.gaussianBlur 0
Test: adb shell setprop ro.surface_flinger.supports_background_blur 1
Test: ./SurfaceFlinger_test --gtest_filter=Layer*Tests/Layer*Test.SetBackgroundBlur*
Test: ./librenderengine_test --gtest_filter=*BlurBackground*"
Test: atest SurfaceFlinger_test:SurfaceInterceptorTest#InterceptBackgroundBlurRadiusUpdateWorks
Change-Id: I5194c910fe7062f33e70943867012539e6c6626a
diff --git a/libs/renderengine/gl/GLFramebuffer.cpp b/libs/renderengine/gl/GLFramebuffer.cpp
index 5fbb5ba..091eac9 100644
--- a/libs/renderengine/gl/GLFramebuffer.cpp
+++ b/libs/renderengine/gl/GLFramebuffer.cpp
@@ -20,8 +20,8 @@
 
 #include <GLES/gl.h>
 #include <GLES/glext.h>
-#include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
+#include <GLES3/gl3.h>
 #include <gui/DebugEGLImageTracker.h>
 #include <nativebase/nativebase.h>
 #include <utils/Trace.h>
@@ -32,14 +32,23 @@
 namespace gl {
 
 GLFramebuffer::GLFramebuffer(GLESRenderEngine& engine)
+      : GLFramebuffer(engine, false /* multiTarget */) {}
+
+GLFramebuffer::GLFramebuffer(GLESRenderEngine& engine, bool multiTarget)
       : mEngine(engine), mEGLDisplay(engine.getEGLDisplay()), mEGLImage(EGL_NO_IMAGE_KHR) {
     glGenTextures(1, &mTextureName);
+    if (multiTarget) {
+        glGenTextures(1, &mSecondaryTextureName);
+    }
     glGenFramebuffers(1, &mFramebufferName);
 }
 
 GLFramebuffer::~GLFramebuffer() {
     glDeleteFramebuffers(1, &mFramebufferName);
     glDeleteTextures(1, &mTextureName);
+    if (mSecondaryTextureName != -1) {
+        glDeleteTextures(1, &mSecondaryTextureName);
+    }
 }
 
 bool GLFramebuffer::setNativeWindowBuffer(ANativeWindowBuffer* nativeBuffer, bool isProtected,
@@ -68,6 +77,55 @@
     return true;
 }
 
+void GLFramebuffer::allocateBuffers(uint32_t width, uint32_t height) {
+    ATRACE_CALL();
+
+    glBindTexture(GL_TEXTURE_2D, mTextureName);
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
+
+    const bool multiTarget = mSecondaryTextureName != -1;
+    if (multiTarget) {
+        glBindTexture(GL_TEXTURE_2D, mSecondaryTextureName);
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, nullptr);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
+        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
+    }
+
+    mBufferHeight = height;
+    mBufferWidth = width;
+    mEngine.checkErrors("Allocating Fbo texture");
+
+    bind();
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mTextureName, 0);
+    if (multiTarget) {
+        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D,
+                               mSecondaryTextureName, 0);
+        GLenum buffers[] = {GL_COLOR_ATTACHMENT0_EXT, GL_COLOR_ATTACHMENT1_EXT};
+        glDrawBuffers(2, buffers);
+    }
+    mStatus = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    unbind();
+    glBindTexture(GL_TEXTURE_2D, 0);
+
+    if (mStatus != GL_FRAMEBUFFER_COMPLETE) {
+        ALOGE("Frame buffer is not complete. Error %d", mStatus);
+    }
+}
+
+void GLFramebuffer::bind() const {
+    glBindFramebuffer(GL_FRAMEBUFFER, mFramebufferName);
+}
+
+void GLFramebuffer::unbind() const {
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+}
+
 } // namespace gl
 } // namespace renderengine
 } // namespace android