gfxstream: stream_renderer_snapshot(..) + stream_renderer_restore(..)

This is designed to match the API added in crrev.com/c/4853266.
The issue with the prior one is it assumes an aemu::snapshot
C++ object is passed through, which would be difficult to get
working with crosvm or upstream QEMU.

Passing through a C-string to a directory is simpler and more
portable.

In addition, since the API is only used with the testing layer,
GFXSTREAM_ENABLE_HOST_SNAPSHOT is added.  This is because the
code assumes a newer AEMU, and the versioning on that is still
TBD.  In production, STREAM_RENDERER_FLAGS_VULKAN_SNAPSHOTS will
always be true likely, so the runtime flag doesn't add much value.

BUG=324440526
TEST=End2EndTests pass

Change-Id: I71686603d8293781733fc5eb5fd936e46871baf7
diff --git a/host/virtio-gpu-gfxstream-renderer.cpp b/host/virtio-gpu-gfxstream-renderer.cpp
index 2d8acd1..1d9706d 100644
--- a/host/virtio-gpu-gfxstream-renderer.cpp
+++ b/host/virtio-gpu-gfxstream-renderer.cpp
@@ -45,6 +45,10 @@
 #include "virtgpu_gfxstream_protocol.h"
 #include "vk_util.h"
 
+#ifdef GFXSTREAM_ENABLE_HOST_VK_SNAPSHOT
+#include "aemu/base/files/StdioStream.h"
+#endif
+
 extern "C" {
 #include "drm_fourcc.h"
 #include "gfxstream/virtio-gpu-gfxstream-renderer-unstable.h"
@@ -1977,6 +1981,52 @@
     return sRenderer()->vulkanInfo(res_handle, vulkan_info);
 }
 
+VG_EXPORT int stream_renderer_snapshot(const char* dir) {
+#ifdef GFXSTREAM_ENABLE_HOST_VK_SNAPSHOT
+    std::string dirString(dir);
+
+    std::string snapshotFileName = dirString + "snapshot.bin";
+
+    std::unique_ptr<android::base::StdioStream> stream(new android::base::StdioStream(
+        fopen(snapshotFileName.c_str(), "wb"), android::base::StdioStream::kOwner));
+
+    android_getOpenglesRenderer()->pauseAllPreSave();
+    android::snapshot::SnapshotSaveStream saveStream{
+        .stream = stream.get(),
+    };
+
+    android_getOpenglesRenderer()->save(saveStream.stream, saveStream.textureSaver);
+    return 0;
+#else
+    stream_renderer_error("Snapshot save requested without support.");
+    return -EINVAL;
+#endif
+}
+
+VG_EXPORT int stream_renderer_restore(const char* dir) {
+#ifdef GFXSTREAM_ENABLE_HOST_VK_SNAPSHOT
+    std::string dirString(dir);
+    std::string snapshotFileName = dirString + "snapshot.bin";
+
+    std::unique_ptr<android::base::StdioStream> stream(new android::base::StdioStream(
+        fopen(snapshotFileName.c_str(), "rb"), android::base::StdioStream::kOwner));
+
+    android::snapshot::SnapshotLoadStream loadStream{
+        .stream = stream.get(),
+    };
+
+    android_getOpenglesRenderer()->load(loadStream.stream, loadStream.textureLoader);
+
+    // In end2end tests, we don't really do snapshot save for render threads.
+    // We will need to resume all render threads without waiting for snapshot.
+    android_getOpenglesRenderer()->resumeAll(false);
+    return 0;
+#else
+    stream_renderer_error("Snapshot save requested without support.");
+    return -EINVAL;
+#endif
+}
+
 static const GoldfishPipeServiceOps goldfish_pipe_service_ops = {
     // guest_open()
     [](GoldfishHwPipe* hwPipe) -> GoldfishHostPipe* {
@@ -2108,7 +2158,6 @@
     android::base::setEnvironmentVariable("ANDROID_EMU_HEADLESS", "1");
     bool enableVk = (renderer_flags & STREAM_RENDERER_FLAGS_USE_VK_BIT);
     bool enableGles = (renderer_flags & STREAM_RENDERER_FLAGS_USE_GLES_BIT);
-    bool enableVkSnapshot = (renderer_flags & STREAM_RENDERER_FLAGS_VULKAN_SNAPSHOTS);
 
     bool egl2eglByEnv = android::base::getEnvironmentVariable("ANDROID_EGL_ON_EGL") == "1";
     bool egl2eglByFlag = renderer_flags & STREAM_RENDERER_FLAGS_USE_EGL_BIT;
@@ -2157,7 +2206,6 @@
     feature_set_enabled_override(kFeature_NativeTextureDecompression, false);
     feature_set_enabled_override(kFeature_GLDirectMem, false);
     feature_set_enabled_override(kFeature_Vulkan, enableVk);
-    feature_set_enabled_override(kFeature_VulkanSnapshots, enableVkSnapshot);
     feature_set_enabled_override(kFeature_VulkanNullOptionalStrings, true);
     feature_set_enabled_override(kFeature_VulkanShaderFloat16Int8, true);
     feature_set_enabled_override(kFeature_HostComposition, true);
@@ -2172,6 +2220,10 @@
     feature_set_enabled_override(kFeature_ExternalBlob, useExternalBlob);
     feature_set_enabled_override(kFeature_SystemBlob, useSystemBlob);
 
+    if (android::base::getEnvironmentVariable("ANDROID_GFXSTREAM_CAPTURE_VK_SNAPSHOT") == "1") {
+        feature_set_enabled_override(kFeature_VulkanSnapshots, true);
+    }
+
     android::featurecontrol::productFeatureOverride();
 
     if (useVulkanNativeSwapchain && !enableVk) {