aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/skqp/jni
diff options
context:
space:
mode:
authorGravatar Hal Canary <halcanary@google.com>2017-12-12 09:42:14 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-12-18 18:58:52 +0000
commit28f89389f026379aad6f90254ba37f4d37272bcb (patch)
tree7736d9a3fdd88d628bb070bc5348096d3e363a9a /tools/skqp/jni
parent37155d476cd727329d985b75ecedbefe380a0f23 (diff)
SkQP: add junit app
Change-Id: Ic32eaec6cce1509f07e7cf610717d3b12d335c89 Reviewed-on: https://skia-review.googlesource.com/83921 Reviewed-by: Hal Canary <halcanary@google.com> Commit-Queue: Hal Canary <halcanary@google.com>
Diffstat (limited to 'tools/skqp/jni')
-rw-r--r--tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp195
1 files changed, 195 insertions, 0 deletions
diff --git a/tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp b/tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp
new file mode 100644
index 0000000000..9c9c9dfa10
--- /dev/null
+++ b/tools/skqp/jni/org_skia_skqp_SkQPRunner.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright 2017 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include <mutex>
+#include <vector>
+
+#include <jni.h>
+#include <android/asset_manager.h>
+#include <android/asset_manager_jni.h>
+
+#include "gm_runner.h"
+#include "skqp_asset_manager.h"
+#include "SkStream.h"
+
+////////////////////////////////////////////////////////////////////////////////
+extern "C" {
+JNIEXPORT void JNICALL Java_org_skia_skqp_SkQPRunner_nInit(JNIEnv*, jobject, jobject, jstring);
+JNIEXPORT jfloat JNICALL Java_org_skia_skqp_SkQPRunner_nExecuteGM(JNIEnv*, jobject, jint, jint);
+JNIEXPORT jobjectArray JNICALL Java_org_skia_skqp_SkQPRunner_nExecuteUnitTest(JNIEnv*, jobject,
+ jint);
+} // extern "C"
+////////////////////////////////////////////////////////////////////////////////
+
+namespace {
+struct AndroidAssetManager : public skqp::AssetManager {
+ AAssetManager* fMgr = nullptr;
+ std::unique_ptr<SkStreamAsset> open(const char* path) override {
+ struct AAStrm : public SkStreamAsset {
+ AAssetManager* fMgr;
+ std::string fPath;
+ AAsset* fAsset;
+ AAStrm(AAssetManager* m, std::string p, AAsset* a)
+ : fMgr(m), fPath(std::move(p)), fAsset(a) {}
+ ~AAStrm() override { AAsset_close(fAsset); }
+ size_t read(void* buffer, size_t size) override {
+ size_t r = SkTMin(size, SkToSizeT(AAsset_getRemainingLength(fAsset)));
+ if (buffer) {
+ return SkToSizeT(AAsset_read(fAsset, buffer, r));
+ } else {
+ this->move(SkTo<long>(r));
+ return r;
+ }
+ }
+ size_t getLength() const override { return SkToSizeT(AAsset_getLength(fAsset)); }
+ size_t peek(void* buffer, size_t size) const override {
+ size_t r = const_cast<AAStrm*>(this)->read(buffer, size);
+ const_cast<AAStrm*>(this)->move(-(long)r);
+ return r;
+ }
+ bool isAtEnd() const override { return 0 == AAsset_getRemainingLength(fAsset); }
+ bool rewind() override { return this->seek(0); }
+ size_t getPosition() const override {
+ return SkToSizeT(AAsset_seek(fAsset, 0, SEEK_CUR));
+ }
+ bool seek(size_t position) override {
+ return -1 != AAsset_seek(fAsset, SkTo<off_t>(position), SEEK_SET);
+ }
+ bool move(long offset) override {
+ return -1 != AAsset_seek(fAsset, SkTo<off_t>(offset), SEEK_CUR);
+ }
+ SkStreamAsset* onDuplicate() const override {
+ AAsset* dupAsset = AndroidAssetManager::OpenAsset(fMgr, fPath.c_str());
+ return dupAsset ? new AAStrm(fMgr, fPath, dupAsset) : nullptr;
+ }
+ SkStreamAsset* onFork() const override {
+ SkStreamAsset* dup = this->onDuplicate();
+ if (dup) { (void)dup->seek(this->getPosition()); }
+ return dup;
+ }
+ };
+ AAsset* asset = AndroidAssetManager::OpenAsset(fMgr, path);
+ return asset ? std::unique_ptr<SkStreamAsset>(new AAStrm(fMgr, std::string(path), asset))
+ : nullptr;
+ }
+ static AAsset* OpenAsset(AAssetManager* mgr, const char* path) {
+ std::string fullPath = std::string("gmkb/") + path;
+ return mgr ? AAssetManager_open(mgr, fullPath.c_str(), AASSET_MODE_STREAMING) : nullptr;
+ }
+};
+}
+
+static void set_string_array_element(JNIEnv* env, jobjectArray a, const char* s, unsigned i) {
+ jstring jstr = env->NewStringUTF(s);
+ env->SetObjectArrayElement(a, (jsize)i, jstr);
+ env->DeleteLocalRef(jstr);
+}
+
+#define jassert(env, cond) do { if (!(cond)) { \
+ (env)->ThrowNew((env)->FindClass("java/lang/Exception"), \
+ __FILE__ ": assert(" #cond ") failed."); } } while (0)
+
+////////////////////////////////////////////////////////////////////////////////
+
+static std::mutex gMutex;
+static std::vector<gm_runner::SkiaBackend> gBackends;
+static std::vector<gm_runner::GMFactory> gGMs;
+static std::vector<gm_runner::UnitTest> gUnitTests;
+static AndroidAssetManager gAssetManager;
+static std::string gReportDirectory;
+static jclass gStringClass = nullptr;
+
+////////////////////////////////////////////////////////////////////////////////
+
+template <typename T, typename F>
+jobjectArray to_java_string_array(JNIEnv* env,
+ const std::vector<T>& array,
+ F toString) {
+ jobjectArray jarray = env->NewObjectArray((jint)array.size(), gStringClass, nullptr);
+ for (unsigned i = 0; i < array.size(); ++i) {
+ set_string_array_element(env, jarray, std::string(toString(array[i])).c_str(), i);
+ }
+ return jarray;
+}
+
+void Java_org_skia_skqp_SkQPRunner_nInit(JNIEnv* env, jobject object, jobject assetManager,
+ jstring dataDir) {
+ jclass clazz = env->GetObjectClass(object);
+ jassert(env, assetManager);
+
+ gm_runner::InitSkia();
+
+ std::lock_guard<std::mutex> lock(gMutex);
+ gAssetManager.fMgr = AAssetManager_fromJava(env, assetManager);
+ jassert(env, gAssetManager.fMgr);
+
+ const char* dataDirString = env->GetStringUTFChars(dataDir, nullptr);
+ gReportDirectory = dataDirString;
+ env->ReleaseStringUTFChars(dataDir, dataDirString);
+
+ gBackends = gm_runner::GetSupportedBackends();
+ gGMs = gm_runner::GetGMFactories(&gAssetManager);
+ gUnitTests = gm_runner::GetUnitTests();
+ gStringClass = env->FindClass("java/lang/String");
+
+ constexpr char stringArrayType[] = "[Ljava/lang/String;";
+ env->SetObjectField(object, env->GetFieldID(clazz, "mBackends", stringArrayType),
+ to_java_string_array(env, gBackends, gm_runner::GetBackendName));
+ env->SetObjectField(object, env->GetFieldID(clazz, "mUnitTests", stringArrayType),
+ to_java_string_array(env, gUnitTests, gm_runner::GetUnitTestName));
+ env->SetObjectField(object, env->GetFieldID(clazz, "mGMs", stringArrayType),
+ to_java_string_array(env, gGMs, gm_runner::GetGMName));
+}
+
+jfloat Java_org_skia_skqp_SkQPRunner_nExecuteGM(JNIEnv* env,
+ jobject object,
+ jint gmIndex,
+ jint backendIndex) {
+ jassert(env, gmIndex < (jint)gGMs.size());
+ jassert(env, backendIndex < (jint)gBackends.size());
+ gm_runner::GMFactory gm;
+ gm_runner::SkiaBackend backend;
+ std::string reportDirectoryPath;
+ {
+ std::lock_guard<std::mutex> lock(gMutex);
+ backend = gBackends[backendIndex];
+ gm = gGMs[gmIndex];
+ reportDirectoryPath = gReportDirectory;
+ }
+ float result;
+ gm_runner::Error error;
+ std::tie(result, error) = gm_runner::EvaluateGM(backend, gm, &gAssetManager,
+ reportDirectoryPath.c_str());
+ if (error != gm_runner::Error::None) {
+ (void)env->ThrowNew(env->FindClass("org/skia/skqp/SkQPException"),
+ gm_runner::GetErrorString(error));
+ }
+ return result;
+}
+
+jobjectArray Java_org_skia_skqp_SkQPRunner_nExecuteUnitTest(JNIEnv* env,
+ jobject object,
+ jint index) {
+ jassert(env, index < (jint)gUnitTests.size());
+ gm_runner::UnitTest test;
+ {
+ std::lock_guard<std::mutex> lock(gMutex);
+ test = gUnitTests[index];
+ }
+ std::vector<std::string> errors = gm_runner::ExecuteTest(test);
+ if (errors.size() == 0) {
+ return nullptr;
+ }
+ jobjectArray array = env->NewObjectArray(errors.size(), gStringClass, nullptr);
+ for (unsigned i = 0; i < errors.size(); ++i) {
+ set_string_array_element(env, array, errors[i].c_str(), i);
+ }
+ return (jobjectArray)env->NewGlobalRef(array);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+