1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2021 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 <android/log.h>
9cb93a386Sopenharmony_ci#include <jni.h>
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#include "include/core/SkM44.h"
12cb93a386Sopenharmony_ci#include "include/effects/SkRuntimeEffect.h"
13cb93a386Sopenharmony_ci#include "modules/androidkit/src/Utils.h"
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_cinamespace {
16cb93a386Sopenharmony_ci
17cb93a386Sopenharmony_cistatic jlong ShaderBuilder_Create(JNIEnv* env, jobject, jstring jsksl) {
18cb93a386Sopenharmony_ci    auto [eff,err] = SkRuntimeEffect::MakeForShader(
19cb93a386Sopenharmony_ci                         SkString(androidkit::utils::CString(env, jsksl)));
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_ci    if (!eff) {
22cb93a386Sopenharmony_ci        // TODO: throw exception?
23cb93a386Sopenharmony_ci        __android_log_print(ANDROID_LOG_ERROR, "AndroidKit", "Failed to compile shader: %s\n",
24cb93a386Sopenharmony_ci                            err.c_str());
25cb93a386Sopenharmony_ci        return 0;
26cb93a386Sopenharmony_ci    }
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_ci    return reinterpret_cast<jlong>(new SkRuntimeShaderBuilder(std::move(eff)));
29cb93a386Sopenharmony_ci}
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_cistatic void ShaderBuilder_Release(JNIEnv* env, jobject, jlong native_instance) {
32cb93a386Sopenharmony_ci    if (auto* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(native_instance)) {
33cb93a386Sopenharmony_ci        delete builder;
34cb93a386Sopenharmony_ci    }
35cb93a386Sopenharmony_ci}
36cb93a386Sopenharmony_ci
37cb93a386Sopenharmony_cistatic void ShaderBuilder_SetUniformFloat(JNIEnv* env, jobject, jlong native_instance, jstring jname, float val) {
38cb93a386Sopenharmony_ci    if (auto* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(native_instance)) {
39cb93a386Sopenharmony_ci        builder->uniform(androidkit::utils::CString(env, jname)) = val;
40cb93a386Sopenharmony_ci    }
41cb93a386Sopenharmony_ci}
42cb93a386Sopenharmony_ci
43cb93a386Sopenharmony_cistatic void ShaderBuilder_SetUniformFloat3(JNIEnv* env, jobject, jlong native_instance, jstring jname, float valX, float valY, float valZ) {
44cb93a386Sopenharmony_ci    if (auto* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(native_instance)) {
45cb93a386Sopenharmony_ci        builder->uniform(androidkit::utils::CString(env, jname)) = SkV3{valX, valY, valZ};
46cb93a386Sopenharmony_ci    }
47cb93a386Sopenharmony_ci}
48cb93a386Sopenharmony_ci
49cb93a386Sopenharmony_cistatic void ShaderBuilder_SetUniformMatrix(JNIEnv* env, jobject, jlong native_instance, jstring jname, jlong native_matrix) {
50cb93a386Sopenharmony_ci    if (auto* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(native_instance)) {
51cb93a386Sopenharmony_ci        if (auto* matrix = reinterpret_cast<SkM44*>(native_matrix)) {
52cb93a386Sopenharmony_ci            builder->uniform(androidkit::utils::CString(env, jname)) = *matrix;
53cb93a386Sopenharmony_ci        }
54cb93a386Sopenharmony_ci    }
55cb93a386Sopenharmony_ci}
56cb93a386Sopenharmony_ci
57cb93a386Sopenharmony_cistatic jlong ShaderBuilder_MakeShader(JNIEnv* env, jobject, jlong native_instance) {
58cb93a386Sopenharmony_ci    if (auto* builder = reinterpret_cast<SkRuntimeShaderBuilder*>(native_instance)) {
59cb93a386Sopenharmony_ci        auto shader = builder->makeShader(nullptr, false);
60cb93a386Sopenharmony_ci        return reinterpret_cast<jlong>(shader.release());
61cb93a386Sopenharmony_ci    }
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci    return 0;
64cb93a386Sopenharmony_ci}
65cb93a386Sopenharmony_ci
66cb93a386Sopenharmony_ci}  // namespace
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ciint register_androidkit_RuntimeShaderBuilder(JNIEnv* env) {
69cb93a386Sopenharmony_ci    static const JNINativeMethod methods[] = {
70cb93a386Sopenharmony_ci        {"nCreate"          , "(Ljava/lang/String;)J"       , reinterpret_cast<void*>(ShaderBuilder_Create)},
71cb93a386Sopenharmony_ci        {"nRelease"         , "(J)V"                        , reinterpret_cast<void*>(ShaderBuilder_Release)},
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci        {"nSetUniformFloat" , "(JLjava/lang/String;F)V"     , reinterpret_cast<void*>(ShaderBuilder_SetUniformFloat)},
74cb93a386Sopenharmony_ci        {"nSetUniformFloat3", "(JLjava/lang/String;FFF)V"   , reinterpret_cast<void*>(ShaderBuilder_SetUniformFloat3)},
75cb93a386Sopenharmony_ci        {"nSetUniformMatrix", "(JLjava/lang/String;J)V"     , reinterpret_cast<void*>(ShaderBuilder_SetUniformMatrix)},
76cb93a386Sopenharmony_ci        {"nMakeShader"      , "(J)J"                        , reinterpret_cast<void*>(ShaderBuilder_MakeShader)},
77cb93a386Sopenharmony_ci    };
78cb93a386Sopenharmony_ci
79cb93a386Sopenharmony_ci    const auto clazz = env->FindClass("org/skia/androidkit/RuntimeShaderBuilder");
80cb93a386Sopenharmony_ci    return clazz
81cb93a386Sopenharmony_ci        ? env->RegisterNatives(clazz, methods, SK_ARRAY_COUNT(methods))
82cb93a386Sopenharmony_ci        : JNI_ERR;
83cb93a386Sopenharmony_ci}
84