Cache edge extension shader

Bug: 322036393
Test: N/A
Flag: com.android.graphics.libgui.flags.edge_extension_shader
Change-Id: Idd44d0970e6a4e65888ba7122db97611e1bf22ac
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 9bc2c48..776b74a 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -97,6 +97,7 @@
     bool cacheImageDimmedLayers = true;
     bool cacheClippedLayers = true;
     bool cacheShadowLayers = true;
+    bool cacheEdgeExtension = true;
     bool cachePIPImageLayers = true;
     bool cacheTransparentImageDimmedLayers = true;
     bool cacheClippedDimmedImageLayers = true;
diff --git a/libs/renderengine/skia/Cache.cpp b/libs/renderengine/skia/Cache.cpp
index 59b0656..57041ee 100644
--- a/libs/renderengine/skia/Cache.cpp
+++ b/libs/renderengine/skia/Cache.cpp
@@ -27,6 +27,8 @@
 #include "ui/Rect.h"
 #include "utils/Timers.h"
 
+#include <com_android_graphics_libgui_flags.h>
+
 namespace android::renderengine::skia {
 
 namespace {
@@ -619,6 +621,32 @@
     }
 }
 
+static void drawEdgeExtensionLayers(SkiaRenderEngine* renderengine, const DisplaySettings& display,
+                                    const std::shared_ptr<ExternalTexture>& dstTexture,
+                                    const std::shared_ptr<ExternalTexture>& srcTexture) {
+    const Rect& displayRect = display.physicalDisplay;
+    // Make the layer
+    LayerSettings layer{
+            // Make the layer bigger than the texture
+            .geometry = Geometry{.boundaries = FloatRect(0, 0, displayRect.width(),
+                                                         displayRect.height())},
+            .source = PixelSource{.buffer =
+                                          Buffer{
+                                                  .buffer = srcTexture,
+                                                  .isOpaque = 1,
+                                          }},
+            // The type of effect does not affect the shader's uniforms, but the layer must have a
+            // valid EdgeExtensionEffect to apply the shader
+            .edgeExtensionEffect =
+                    EdgeExtensionEffect(true /* left */, false, false, true /* bottom */),
+    };
+    for (float alpha : {0.5, 0.0, 1.0}) {
+        layer.alpha = alpha;
+        auto layers = std::vector<LayerSettings>{layer};
+        renderengine->drawLayers(display, layers, dstTexture, base::unique_fd());
+    }
+}
+
 //
 // The collection of shaders cached here were found by using perfetto to record shader compiles
 // during actions that involve RenderEngine, logging the layer settings, and the shader code
@@ -761,6 +789,12 @@
                 // Draw layers for b/185569240.
                 drawClippedLayers(renderengine, display, dstTexture, texture);
             }
+
+            if (com::android::graphics::libgui::flags::edge_extension_shader() &&
+                config.cacheEdgeExtension) {
+                drawEdgeExtensionLayers(renderengine, display, dstTexture, texture);
+                drawEdgeExtensionLayers(renderengine, p3Display, dstTexture, texture);
+            }
         }
 
         if (config.cachePIPImageLayers) {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index e13c74f..aecc256 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1006,6 +1006,8 @@
             // which we maintain for backwards compatibility.
             config.cacheUltraHDR =
                     base::GetBoolProperty("ro.surface_flinger.prime_shader_cache.ultrahdr"s, false);
+            config.cacheEdgeExtension =
+                    base::GetBoolProperty("debug.sf.edge_extension_shader"s, true);
             return getRenderEngine().primeCache(config);
         });