surfaceflinger: prime shader cache for P3 conversion

Bug: 77287550
Test: no shader compilation when WCG apps start
Change-Id: I45cdefc97c5e9060269060e33d79b40304cfdbbf
diff --git a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
index 90404fa..0048000 100644
--- a/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/GLES20RenderEngine.cpp
@@ -112,7 +112,10 @@
 using ui::Dataspace;
 
 GLES20RenderEngine::GLES20RenderEngine(uint32_t featureFlags)
-      : mVpWidth(0), mVpHeight(0), mPlatformHasWideColor((featureFlags & WIDE_COLOR_SUPPORT) != 0) {
+      : RenderEngine(featureFlags),
+        mVpWidth(0),
+        mVpHeight(0),
+        mPlatformHasWideColor((featureFlags & WIDE_COLOR_SUPPORT) != 0) {
     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &mMaxTextureSize);
     glGetIntegerv(GL_MAX_VIEWPORT_DIMS, mMaxViewportDims);
 
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.cpp b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
index 5b61db9..796901a 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.cpp
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.cpp
@@ -14,10 +14,13 @@
  * limitations under the License.
  */
 
+#define ATRACE_TAG ATRACE_TAG_GRAPHICS
+
 #include <GLES2/gl2.h>
 #include <GLES2/gl2ext.h>
 
 #include <utils/String8.h>
+#include <utils/Trace.h>
 
 #include "Description.h"
 #include "Program.h"
@@ -75,15 +78,11 @@
 
 ANDROID_SINGLETON_STATIC_INSTANCE(ProgramCache)
 
-ProgramCache::ProgramCache() {
-    // Until surfaceflinger has a dependable blob cache on the filesystem,
-    // generate shaders on initialization so as to avoid jank.
-    primeCache();
-}
+ProgramCache::ProgramCache() {}
 
 ProgramCache::~ProgramCache() {}
 
-void ProgramCache::primeCache() {
+void ProgramCache::primeCache(bool hasWideColor) {
     uint32_t shaderCount = 0;
     uint32_t keyMask = Key::BLEND_MASK | Key::OPACITY_MASK | Key::ALPHA_MASK | Key::TEXTURE_MASK;
     // Prime the cache for all combinations of the above masks,
@@ -104,6 +103,27 @@
             shaderCount++;
         }
     }
+
+    // Prime for sRGB->P3 conversion
+    if (hasWideColor) {
+        Key shaderKey;
+        shaderKey.set(Key::BLEND_MASK | Key::TEXTURE_MASK | Key::OUTPUT_TRANSFORM_MATRIX_MASK |
+                              Key::INPUT_TF_MASK | Key::OUTPUT_TF_MASK,
+                      Key::BLEND_PREMULT | Key::TEXTURE_EXT | Key::OUTPUT_TRANSFORM_MATRIX_ON |
+                              Key::INPUT_TF_SRGB | Key::OUTPUT_TF_SRGB);
+        for (int i = 0; i < 4; i++) {
+            shaderKey.set(Key::OPACITY_MASK,
+                          (i & 1) ? Key::OPACITY_OPAQUE : Key::OPACITY_TRANSLUCENT);
+            shaderKey.set(Key::ALPHA_MASK, (i & 2) ? Key::ALPHA_LT_ONE : Key::ALPHA_EQ_ONE);
+            Program* program = mCache.valueFor(shaderKey);
+            if (program == nullptr) {
+                program = generateProgram(shaderKey);
+                mCache.add(shaderKey, program);
+                shaderCount++;
+            }
+        }
+    }
+
     nsecs_t timeAfter = systemTime();
     float compileTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
     ALOGD("shader cache generated - %u shaders in %f ms\n", shaderCount, compileTimeMs);
@@ -631,6 +651,8 @@
 }
 
 Program* ProgramCache::generateProgram(const Key& needs) {
+    ATRACE_CALL();
+
     // vertex shader
     String8 vs = generateVertexShader(needs);
 
@@ -654,8 +676,8 @@
         mCache.add(needs, program);
         time += systemTime();
 
-        // ALOGD(">>> generated new program: needs=%08X, time=%u ms (%d programs)",
-        //        needs.mNeeds, uint32_t(ns2ms(time)), mCache.size());
+        ALOGV(">>> generated new program: needs=%08X, time=%u ms (%zu programs)", needs.mKey,
+              uint32_t(ns2ms(time)), mCache.size());
     }
 
     // here we have a suitable program for this description
diff --git a/services/surfaceflinger/RenderEngine/ProgramCache.h b/services/surfaceflinger/RenderEngine/ProgramCache.h
index 864bc3f..983e7ba 100644
--- a/services/surfaceflinger/RenderEngine/ProgramCache.h
+++ b/services/surfaceflinger/RenderEngine/ProgramCache.h
@@ -160,13 +160,14 @@
     ProgramCache();
     ~ProgramCache();
 
+    // Generate shaders to populate the cache
+    void primeCache(bool hasWideColor);
+
     // useProgram lookup a suitable program in the cache or generates one
     // if none can be found.
     void useProgram(const Description& description);
 
 private:
-    // Generate shaders to populate the cache
-    void primeCache();
     // compute a cache Key from a Description
     static Key computeKey(const Description& description);
     // Generate EOTF based from Key.
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.cpp b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
index 4c878ae..b392d28 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.cpp
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.cpp
@@ -150,8 +150,11 @@
     }
 }
 
-RenderEngine::RenderEngine()
-      : mEGLDisplay(EGL_NO_DISPLAY), mEGLConfig(nullptr), mEGLContext(EGL_NO_CONTEXT) {}
+RenderEngine::RenderEngine(uint32_t featureFlags)
+      : mEGLDisplay(EGL_NO_DISPLAY),
+        mEGLConfig(nullptr),
+        mEGLContext(EGL_NO_CONTEXT),
+        mFeatureFlags(featureFlags) {}
 
 RenderEngine::~RenderEngine() {
     eglMakeCurrent(mEGLDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -582,9 +585,7 @@
 }
 
 void RenderEngine::primeCache() const {
-    // Getting the ProgramCache instance causes it to prime its shader cache,
-    // which is performed in its constructor
-    ProgramCache::getInstance();
+    ProgramCache::getInstance().primeCache(mFeatureFlags & WIDE_COLOR_SUPPORT);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/RenderEngine/RenderEngine.h b/services/surfaceflinger/RenderEngine/RenderEngine.h
index a14acaa..1196216 100644
--- a/services/surfaceflinger/RenderEngine/RenderEngine.h
+++ b/services/surfaceflinger/RenderEngine/RenderEngine.h
@@ -172,7 +172,9 @@
     static bool overrideUseContextPriorityFromConfig(bool useContextPriority);
 
 protected:
-    RenderEngine();
+    RenderEngine(uint32_t featureFlags);
+
+    const uint32_t mFeatureFlags;
 
 public:
     virtual ~RenderEngine() = 0;