SkQP: ResourceFactory

Change-Id: Ic57a86ec115e3ace52615c0b8e9a22a915988850
Reviewed-on: https://skia-review.googlesource.com/101320
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Commit-Queue: Hal Canary <halcanary@google.com>
diff --git a/BUILD.gn b/BUILD.gn
index 841ff1e..9eb4022 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -1832,6 +1832,7 @@
       deps = [
         ":skia",
         ":skqp_lib",
+        ":tool_utils",
       ]
       libs = [ "android" ]
     }
diff --git a/platform_tools/android/apps/skqp/src/main/assets/.gitignore b/platform_tools/android/apps/skqp/src/main/assets/.gitignore
index 0dddfcb..036d7bb 100644
--- a/platform_tools/android/apps/skqp/src/main/assets/.gitignore
+++ b/platform_tools/android/apps/skqp/src/main/assets/.gitignore
@@ -1,3 +1,4 @@
 /gmkb
 /skqp
 /files.txt
+/resources
diff --git a/tools/ResourceFactory.h b/tools/ResourceFactory.h
new file mode 100644
index 0000000..7e89017
--- /dev/null
+++ b/tools/ResourceFactory.h
@@ -0,0 +1,14 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+#ifndef ResourceFactory_DEFINED
+#define ResourceFactory_DEFINED
+
+#include <SkData.h>
+
+extern sk_sp<SkData> (*gResourceFactory)(const char*);
+
+#endif  // ResourceFactory_DEFINED
diff --git a/tools/Resources.cpp b/tools/Resources.cpp
index 9d54026..002d411 100644
--- a/tools/Resources.cpp
+++ b/tools/Resources.cpp
@@ -42,8 +42,17 @@
 }
 
 #ifdef SK_EMBED_RESOURCES
+
+#include "ResourceFactory.h"
+
+sk_sp<SkData> (*gResourceFactory)(const char*) = nullptr;
+
 extern BinaryAsset gResources[];
+
 sk_sp<SkData> GetResourceAsData(const char* resource) {
+    if (gResourceFactory) {
+        return gResourceFactory(resource);
+    }
     for (const BinaryAsset* ptr = gResources; ptr->name; ++ptr) {
         if (0 == strcmp(resource, ptr->name)) {
             return SkData::MakeWithoutCopy(ptr->data, ptr->len);
diff --git a/tools/skqp/README.md b/tools/skqp/README.md
index 51b0e27..bf41b25 100644
--- a/tools/skqp/README.md
+++ b/tools/skqp/README.md
@@ -38,6 +38,7 @@
         python tools/git-sync-deps
         python tools/skqp/generate_gn_args out/skqp-arm "$ANDROID_NDK" arm
         bin/gn gen out/skqp-arm
+        python tools/skqp/setup_resources . out/skqp-arm
 
 6.  Build, install, and run.
 
@@ -68,6 +69,7 @@
 
 2.  Build the SkQP program, load files on the device, and run skqp:
 
+        rm -f out/skqp-arm/gen/binary_resources.cpp
         ninja -C out/skqp-arm skqp
         python tools/skqp/run_skqp_exe out/skqp-arm
 
diff --git a/tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp b/tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp
index 7864fc4..2203888 100644
--- a/tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp
+++ b/tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp
@@ -13,10 +13,12 @@
 #include <jni.h>
 #include <sys/stat.h>
 
-#include "gm_runner.h"
-#include "gm_knowledge.h"
-#include "skqp_asset_manager.h"
+#include "ResourceFactory.h"
+#include "SkOSPath.h"
 #include "SkStream.h"
+#include "gm_knowledge.h"
+#include "gm_runner.h"
+#include "skqp_asset_manager.h"
 
 ////////////////////////////////////////////////////////////////////////////////
 extern "C" {
@@ -108,6 +110,25 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+sk_sp<SkData> get_resource(const char* resource) {
+    AAssetManager* mgr = gAssetManager.fMgr;
+    if (!mgr) {
+        return nullptr;
+    }
+    SkString path = SkOSPath::Join("resources", resource);
+    AAsset* asset = AAssetManager_open(mgr, path.c_str(), AASSET_MODE_STREAMING);
+    if (!asset) {
+        return nullptr;
+    }
+    size_t size = SkToSizeT(AAsset_getLength(asset));
+    sk_sp<SkData> data = SkData::MakeUninitialized(size);
+    (void)AAsset_read(asset, data->writable_data(), size);
+    AAsset_close(asset);
+    return data;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 template <typename T, typename F>
 jobjectArray to_java_string_array(JNIEnv* env,
                                   const std::vector<T>& array,
@@ -131,6 +152,7 @@
     gm_runner::InitSkia(experimentalMode ? gm_runner::Mode::kExperimentalMode
                                          : gm_runner::Mode::kCompatibilityTestMode,
                         &gAssetManager);
+    gResourceFactory = &get_resource;
 
     const char* dataDirString = env->GetStringUTFChars(dataDir, nullptr);
     jassert(env, dataDirString && dataDirString[0]);
diff --git a/tools/skqp/setup_resources b/tools/skqp/setup_resources
new file mode 100755
index 0000000..45b9b70
--- /dev/null
+++ b/tools/skqp/setup_resources
@@ -0,0 +1,29 @@
+#! /usr/bin/env python
+
+# Copyright 2018 Google Inc.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import os
+import shutil
+import sys
+
+if __name__ == '__main__':
+    if len(sys.argv) != 3 or not os.path.isdir(sys.argv[1]) or not os.path.isdir(sys.argv[2]):
+        sys.stderr.write('Usage\n  %s SKIA_DIR BUILD_DIR\n\n' % sys.argv[0])
+        sys.exit(1)
+    skia = sys.argv[1]
+    gen = os.path.join(sys.argv[2], 'gen')
+    if not os.path.isdir(gen):
+        os.mkdir(gen)
+    with open(os.path.join(gen, 'binary_resources.cpp'), 'w') as o:
+        o.write('#include "BinaryAsset.h"\n'
+                'BinaryAsset gResources[] = { {nullptr, nullptr, 0} };\n')
+    dst = os.path.join(skia, 'platform_tools', 'android', 'apps', 'skqp',
+                       'src', 'main', 'assets', 'resources')
+    if os.path.isdir(dst) and not os.path.islink(dst):
+        shutil.rmtree(dst)
+    elif os.path.exists(dst):
+        os.remove(dst)
+    shutil.copytree(os.path.join(skia, 'resources'), dst)
+