vulkan_renderengine: Check for support first

The vulkan_renderengine flag allows us to switch some users to using
Vulkan as part of the trunk stable process. But not all devices support
Vulkan.

Move canSupportSkiaVkRenderEngine into the RenderEngine header, so it
can be used by SurfaceFlinger. When the vulkan_renderengine flag is set,
check for support before choosing Vulkan. Do *not* log an error, since
this is specified broadly, so it is expected that the flag will be set
for devices that do not have support.

This introduces an extra call to initVulkanInterface, so log the amount
of time it takes. On my device, the first call is only ~17ms, so this
seems fine. The next call is much faster, ~4ms. The next call is not
interestingly different, possibly because the first call was already
made.

Bug: 293371537
Bug: 325619183
Test: atest librenderengine_test
Test: manual
Change-Id: Iba66e67347c69b95dc9c05ca838fa1391ef4ab81
diff --git a/libs/renderengine/include/renderengine/RenderEngine.h b/libs/renderengine/include/renderengine/RenderEngine.h
index 7047358..de05268 100644
--- a/libs/renderengine/include/renderengine/RenderEngine.h
+++ b/libs/renderengine/include/renderengine/RenderEngine.h
@@ -104,6 +104,8 @@
 
     static std::unique_ptr<RenderEngine> create(const RenderEngineCreationArgs& args);
 
+    static bool canSupport(GraphicsApi);
+
     virtual ~RenderEngine() = 0;
 
     // ----- BEGIN DEPRECATED INTERFACE -----
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.cpp b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
index bff12ce..b43ab6c 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.cpp
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.cpp
@@ -287,6 +287,7 @@
     CHECK_NONNULL(vk##F)
 
 VulkanInterface initVulkanInterface(bool protectedContent = false) {
+    const nsecs_t timeBefore = systemTime();
     VulkanInterface interface;
 
     VK_GET_PROC(EnumerateInstanceVersion);
@@ -598,7 +599,9 @@
     interface.isProtected = protectedContent;
     // funcs already initialized
 
-    ALOGD("%s: Success init Vulkan interface", __func__);
+    const nsecs_t timeAfter = systemTime();
+    const float initTimeMs = static_cast<float>(timeAfter - timeBefore) / 1.0E6;
+    ALOGD("%s: Success init Vulkan interface in %f ms", __func__, initTimeMs);
     return interface;
 }
 
@@ -654,17 +657,25 @@
     }
 }
 
+bool RenderEngine::canSupport(GraphicsApi graphicsApi) {
+    switch (graphicsApi) {
+        case GraphicsApi::GL:
+            return true;
+        case GraphicsApi::VK: {
+            if (!sVulkanInterface.initialized) {
+                sVulkanInterface = initVulkanInterface(false /* no protected content */);
+                ALOGD("%s: initialized == %s.", __func__,
+                      sVulkanInterface.initialized ? "true" : "false");
+            }
+            return sVulkanInterface.initialized;
+        }
+    }
+}
+
 namespace skia {
 
 using base::StringAppendF;
 
-bool SkiaVkRenderEngine::canSupportSkiaVkRenderEngine() {
-    VulkanInterface temp = initVulkanInterface(false /* no protected content */);
-    ALOGD("SkiaVkRenderEngine::canSupportSkiaVkRenderEngine(): initialized == %s.",
-          temp.initialized ? "true" : "false");
-    return temp.initialized;
-}
-
 std::unique_ptr<SkiaVkRenderEngine> SkiaVkRenderEngine::create(
         const RenderEngineCreationArgs& args) {
     std::unique_ptr<SkiaVkRenderEngine> engine(new SkiaVkRenderEngine(args));
diff --git a/libs/renderengine/skia/SkiaVkRenderEngine.h b/libs/renderengine/skia/SkiaVkRenderEngine.h
index 2e0cf45..52bc500 100644
--- a/libs/renderengine/skia/SkiaVkRenderEngine.h
+++ b/libs/renderengine/skia/SkiaVkRenderEngine.h
@@ -27,8 +27,6 @@
 
 class SkiaVkRenderEngine : public SkiaRenderEngine {
 public:
-    // Returns false if Vulkan implementation can't support SkiaVkRenderEngine.
-    static bool canSupportSkiaVkRenderEngine();
     static std::unique_ptr<SkiaVkRenderEngine> create(const RenderEngineCreationArgs& args);
     ~SkiaVkRenderEngine() override;
 
diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp
index 4c18704..7b8eb84 100644
--- a/libs/renderengine/tests/RenderEngineTest.cpp
+++ b/libs/renderengine/tests/RenderEngineTest.cpp
@@ -107,7 +107,7 @@
 
     virtual std::string name() = 0;
     virtual renderengine::RenderEngine::GraphicsApi graphicsApi() = 0;
-    virtual bool apiSupported() = 0;
+    bool apiSupported() { return renderengine::RenderEngine::canSupport(graphicsApi()); }
     std::unique_ptr<renderengine::RenderEngine> createRenderEngine() {
         renderengine::RenderEngineCreationArgs reCreationArgs =
                 renderengine::RenderEngineCreationArgs::Builder()
@@ -131,10 +131,6 @@
     renderengine::RenderEngine::GraphicsApi graphicsApi() override {
         return renderengine::RenderEngine::GraphicsApi::VK;
     }
-
-    bool apiSupported() override {
-        return skia::SkiaVkRenderEngine::canSupportSkiaVkRenderEngine();
-    }
 };
 
 class SkiaGLESRenderEngineFactory : public RenderEngineFactory {
@@ -144,8 +140,6 @@
     renderengine::RenderEngine::GraphicsApi graphicsApi() {
         return renderengine::RenderEngine::GraphicsApi::GL;
     }
-
-    bool apiSupported() override { return true; }
 };
 
 class RenderEngineTest : public ::testing::TestWithParam<std::shared_ptr<RenderEngineFactory>> {
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 5bb5508..edba50b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -816,9 +816,10 @@
         builder.setThreaded(renderengine::RenderEngine::Threaded::YES)
                 .setGraphicsApi(renderengine::RenderEngine::GraphicsApi::VK);
     } else {
-        builder.setGraphicsApi(FlagManager::getInstance().vulkan_renderengine()
-                                       ? renderengine::RenderEngine::GraphicsApi::VK
-                                       : renderengine::RenderEngine::GraphicsApi::GL);
+        const auto kVulkan = renderengine::RenderEngine::GraphicsApi::VK;
+        const bool useVulkan = FlagManager::getInstance().vulkan_renderengine() &&
+                renderengine::RenderEngine::canSupport(kVulkan);
+        builder.setGraphicsApi(useVulkan ? kVulkan : renderengine::RenderEngine::GraphicsApi::GL);
     }
 }