1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2017 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include <mutex> 9cb93a386Sopenharmony_ci 10cb93a386Sopenharmony_ci#include <android/asset_manager.h> 11cb93a386Sopenharmony_ci#include <android/asset_manager_jni.h> 12cb93a386Sopenharmony_ci#include <jni.h> 13cb93a386Sopenharmony_ci#include <sys/stat.h> 14cb93a386Sopenharmony_ci 15cb93a386Sopenharmony_ci#include "include/core/SkStream.h" 16cb93a386Sopenharmony_ci#include "include/private/SkTo.h" 17cb93a386Sopenharmony_ci#include "tools/ResourceFactory.h" 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci#include "tools/skqp/src/skqp.h" 20cb93a386Sopenharmony_ci 21cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 22cb93a386Sopenharmony_ciextern "C" { 23cb93a386Sopenharmony_ciJNIEXPORT void JNICALL Java_org_skia_skqp_SkQP_nInit(JNIEnv*, jobject, jobject, jstring); 24cb93a386Sopenharmony_ciJNIEXPORT jlong JNICALL Java_org_skia_skqp_SkQP_nExecuteGM(JNIEnv*, jobject, jint, jint); 25cb93a386Sopenharmony_ciJNIEXPORT jobjectArray JNICALL Java_org_skia_skqp_SkQP_nExecuteUnitTest(JNIEnv*, jobject, jint); 26cb93a386Sopenharmony_ciJNIEXPORT void JNICALL Java_org_skia_skqp_SkQP_nMakeReport(JNIEnv*, jobject); 27cb93a386Sopenharmony_ci} // extern "C" 28cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 29cb93a386Sopenharmony_ci 30cb93a386Sopenharmony_cistatic AAssetManager* gAAssetManager = nullptr; 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_cistatic sk_sp<SkData> open_asset_data(const char* path) { 33cb93a386Sopenharmony_ci sk_sp<SkData> data; 34cb93a386Sopenharmony_ci if (gAAssetManager) { 35cb93a386Sopenharmony_ci if (AAsset* asset = AAssetManager_open(gAAssetManager, path, AASSET_MODE_STREAMING)) { 36cb93a386Sopenharmony_ci if (size_t size = SkToSizeT(AAsset_getLength(asset))) { 37cb93a386Sopenharmony_ci data = SkData::MakeUninitialized(size); 38cb93a386Sopenharmony_ci int ret = AAsset_read(asset, data->writable_data(), size); 39cb93a386Sopenharmony_ci if (ret != SkToInt(size)) { 40cb93a386Sopenharmony_ci SkDebugf("ERROR: AAsset_read != AAsset_getLength (%s)\n", path); 41cb93a386Sopenharmony_ci } 42cb93a386Sopenharmony_ci } 43cb93a386Sopenharmony_ci AAsset_close(asset); 44cb93a386Sopenharmony_ci } 45cb93a386Sopenharmony_ci } 46cb93a386Sopenharmony_ci return data; 47cb93a386Sopenharmony_ci} 48cb93a386Sopenharmony_ci 49cb93a386Sopenharmony_cinamespace { 50cb93a386Sopenharmony_cistruct AndroidAssetManager : public SkQPAssetManager { 51cb93a386Sopenharmony_ci sk_sp<SkData> open(const char* path) override { return open_asset_data(path); } 52cb93a386Sopenharmony_ci}; 53cb93a386Sopenharmony_ci} 54cb93a386Sopenharmony_ci 55cb93a386Sopenharmony_ci// TODO(halcanary): Should not have global variables; SkQP Java object should 56cb93a386Sopenharmony_ci// own pointers and manage concurency. 57cb93a386Sopenharmony_cistatic AndroidAssetManager gAndroidAssetManager; 58cb93a386Sopenharmony_cistatic std::mutex gMutex; 59cb93a386Sopenharmony_cistatic SkQP gSkQP; 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci#define jassert(env, cond, ret) do { if (!(cond)) { \ 62cb93a386Sopenharmony_ci (env)->ThrowNew((env)->FindClass("java/lang/Exception"), \ 63cb93a386Sopenharmony_ci __FILE__ ": assert(" #cond ") failed."); \ 64cb93a386Sopenharmony_ci return ret; } } while (0) 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_cistatic void set_string_array_element(JNIEnv* env, jobjectArray a, const char* s, unsigned i) { 67cb93a386Sopenharmony_ci jstring jstr = env->NewStringUTF(s); 68cb93a386Sopenharmony_ci jassert(env, jstr != nullptr,); 69cb93a386Sopenharmony_ci env->SetObjectArrayElement(a, (jsize)i, jstr); 70cb93a386Sopenharmony_ci env->DeleteLocalRef(jstr); 71cb93a386Sopenharmony_ci} 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_cisk_sp<SkData> get_resource(const char* resource) { 76cb93a386Sopenharmony_ci return open_asset_data((std::string("resources/") + resource).c_str()); 77cb93a386Sopenharmony_ci} 78cb93a386Sopenharmony_ci 79cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_citemplate <typename T, typename F> 82cb93a386Sopenharmony_cijobjectArray to_java_string_array(JNIEnv* env, 83cb93a386Sopenharmony_ci const std::vector<T>& array, 84cb93a386Sopenharmony_ci F toString) { 85cb93a386Sopenharmony_ci jclass stringClass = env->FindClass("java/lang/String"); 86cb93a386Sopenharmony_ci jassert(env, stringClass, nullptr); 87cb93a386Sopenharmony_ci jobjectArray jarray = env->NewObjectArray((jint)array.size(), stringClass, nullptr); 88cb93a386Sopenharmony_ci jassert(env, jarray != nullptr, nullptr); 89cb93a386Sopenharmony_ci for (unsigned i = 0; i < array.size(); ++i) { 90cb93a386Sopenharmony_ci set_string_array_element(env, jarray, std::string(toString(array[i])).c_str(), i); 91cb93a386Sopenharmony_ci } 92cb93a386Sopenharmony_ci return jarray; 93cb93a386Sopenharmony_ci} 94cb93a386Sopenharmony_ci 95cb93a386Sopenharmony_cistatic std::string to_string(JNIEnv* env, jstring jString) { 96cb93a386Sopenharmony_ci const char* utf8String = env->GetStringUTFChars(jString, nullptr); 97cb93a386Sopenharmony_ci jassert(env, utf8String && utf8String[0], ""); 98cb93a386Sopenharmony_ci std::string sString(utf8String); 99cb93a386Sopenharmony_ci env->ReleaseStringUTFChars(jString, utf8String); 100cb93a386Sopenharmony_ci return sString; 101cb93a386Sopenharmony_ci} 102cb93a386Sopenharmony_ci 103cb93a386Sopenharmony_civoid Java_org_skia_skqp_SkQP_nInit(JNIEnv* env, jobject object, jobject assetManager, 104cb93a386Sopenharmony_ci jstring dataDir) { 105cb93a386Sopenharmony_ci jclass SkQP_class = env->GetObjectClass(object); 106cb93a386Sopenharmony_ci 107cb93a386Sopenharmony_ci // tools/Resources 108cb93a386Sopenharmony_ci gResourceFactory = &get_resource; 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci std::string reportDirectory = to_string(env, dataDir); 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci jassert(env, assetManager,); 113cb93a386Sopenharmony_ci // This global must be set before using AndroidAssetManager 114cb93a386Sopenharmony_ci gAAssetManager = AAssetManager_fromJava(env, assetManager); 115cb93a386Sopenharmony_ci jassert(env, gAAssetManager,); 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_ci std::lock_guard<std::mutex> lock(gMutex); 118cb93a386Sopenharmony_ci gSkQP.init(&gAndroidAssetManager, nullptr, reportDirectory.c_str()); 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci auto backends = gSkQP.getSupportedBackends(); 121cb93a386Sopenharmony_ci jassert(env, backends.size() > 0,); 122cb93a386Sopenharmony_ci auto gms = gSkQP.getGMs(); 123cb93a386Sopenharmony_ci jassert(env, gms.size() > 0,); 124cb93a386Sopenharmony_ci auto unitTests = gSkQP.getUnitTests(); 125cb93a386Sopenharmony_ci jassert(env, unitTests.size() > 0,); 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_ci constexpr char kStringArrayType[] = "[Ljava/lang/String;"; 128cb93a386Sopenharmony_ci env->SetObjectField(object, env->GetFieldID(SkQP_class, "mBackends", kStringArrayType), 129cb93a386Sopenharmony_ci to_java_string_array(env, backends, SkQP::GetBackendName)); 130cb93a386Sopenharmony_ci env->SetObjectField(object, env->GetFieldID(SkQP_class, "mUnitTests", kStringArrayType), 131cb93a386Sopenharmony_ci to_java_string_array(env, unitTests, SkQP::GetUnitTestName)); 132cb93a386Sopenharmony_ci env->SetObjectField(object, env->GetFieldID(SkQP_class, "mGMs", kStringArrayType), 133cb93a386Sopenharmony_ci to_java_string_array(env, gms, SkQP::GetGMName)); 134cb93a386Sopenharmony_ci} 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_cijlong Java_org_skia_skqp_SkQP_nExecuteGM(JNIEnv* env, 137cb93a386Sopenharmony_ci jobject object, 138cb93a386Sopenharmony_ci jint gmIndex, 139cb93a386Sopenharmony_ci jint backendIndex) { 140cb93a386Sopenharmony_ci SkQP::RenderOutcome outcome; 141cb93a386Sopenharmony_ci std::string except; 142cb93a386Sopenharmony_ci { 143cb93a386Sopenharmony_ci std::lock_guard<std::mutex> lock(gMutex); 144cb93a386Sopenharmony_ci jassert(env, backendIndex < (jint)gSkQP.getSupportedBackends().size(), -1); 145cb93a386Sopenharmony_ci jassert(env, gmIndex < (jint)gSkQP.getGMs().size(), -1); 146cb93a386Sopenharmony_ci SkQP::SkiaBackend backend = gSkQP.getSupportedBackends()[backendIndex]; 147cb93a386Sopenharmony_ci SkQP::GMFactory gm = gSkQP.getGMs()[gmIndex]; 148cb93a386Sopenharmony_ci std::tie(outcome, except) = gSkQP.evaluateGM(backend, gm); 149cb93a386Sopenharmony_ci } 150cb93a386Sopenharmony_ci 151cb93a386Sopenharmony_ci if (!except.empty()) { 152cb93a386Sopenharmony_ci (void)env->ThrowNew(env->FindClass("org/skia/skqp/SkQPException"), except.c_str()); 153cb93a386Sopenharmony_ci } 154cb93a386Sopenharmony_ci return (jlong)outcome.fTotalError; 155cb93a386Sopenharmony_ci} 156cb93a386Sopenharmony_ci 157cb93a386Sopenharmony_cijobjectArray Java_org_skia_skqp_SkQP_nExecuteUnitTest(JNIEnv* env, 158cb93a386Sopenharmony_ci jobject object, 159cb93a386Sopenharmony_ci jint index) { 160cb93a386Sopenharmony_ci std::vector<std::string> errors; 161cb93a386Sopenharmony_ci { 162cb93a386Sopenharmony_ci jassert(env, index < (jint)gSkQP.getUnitTests().size(), nullptr); 163cb93a386Sopenharmony_ci std::lock_guard<std::mutex> lock(gMutex); 164cb93a386Sopenharmony_ci errors = gSkQP.executeTest(gSkQP.getUnitTests()[index]); 165cb93a386Sopenharmony_ci } 166cb93a386Sopenharmony_ci if (errors.size() == 0) { 167cb93a386Sopenharmony_ci return nullptr; 168cb93a386Sopenharmony_ci } 169cb93a386Sopenharmony_ci jclass stringClass = env->FindClass("java/lang/String"); 170cb93a386Sopenharmony_ci jassert(env, stringClass, nullptr); 171cb93a386Sopenharmony_ci jobjectArray array = env->NewObjectArray(errors.size(), stringClass, nullptr); 172cb93a386Sopenharmony_ci for (unsigned i = 0; i < errors.size(); ++i) { 173cb93a386Sopenharmony_ci set_string_array_element(env, array, errors[i].c_str(), i); 174cb93a386Sopenharmony_ci } 175cb93a386Sopenharmony_ci return (jobjectArray)env->NewGlobalRef(array); 176cb93a386Sopenharmony_ci} 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_civoid Java_org_skia_skqp_SkQP_nMakeReport(JNIEnv*, jobject) { 179cb93a386Sopenharmony_ci std::lock_guard<std::mutex> lock(gMutex); 180cb93a386Sopenharmony_ci gSkQP.makeReport(); 181cb93a386Sopenharmony_ci} 182cb93a386Sopenharmony_ci 183cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////// 184cb93a386Sopenharmony_ci 185