165 lines
7.1 KiB
C++
Executable File
165 lines
7.1 KiB
C++
Executable File
/*
|
|
* Copyright (C) 2022 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include <SkMesh.h>
|
|
|
|
#include "GraphicsJNI.h"
|
|
#include "graphics_jni_helpers.h"
|
|
|
|
namespace android {
|
|
|
|
using Attribute = SkMeshSpecification::Attribute;
|
|
using Varying = SkMeshSpecification::Varying;
|
|
|
|
static struct {
|
|
jclass clazz{};
|
|
jfieldID type{};
|
|
jfieldID offset{};
|
|
jfieldID name{};
|
|
} gAttributeInfo;
|
|
|
|
static struct {
|
|
jclass clazz{};
|
|
jfieldID type{};
|
|
jfieldID name{};
|
|
} gVaryingInfo;
|
|
|
|
std::vector<Attribute> extractAttributes(JNIEnv* env, jobjectArray attributes) {
|
|
int size = env->GetArrayLength(attributes);
|
|
std::vector<Attribute> attVector;
|
|
attVector.reserve(size);
|
|
for (int i = 0; i < size; i++) {
|
|
jobject attribute = env->GetObjectArrayElement(attributes, i);
|
|
auto name = (jstring)env->GetObjectField(attribute, gAttributeInfo.name);
|
|
auto attName = ScopedUtfChars(env, name);
|
|
Attribute temp{Attribute::Type(env->GetIntField(attribute, gAttributeInfo.type)),
|
|
static_cast<size_t>(env->GetIntField(attribute, gAttributeInfo.offset)),
|
|
SkString(attName.c_str())};
|
|
attVector.push_back(std::move(temp));
|
|
}
|
|
return attVector;
|
|
}
|
|
|
|
std::vector<Varying> extractVaryings(JNIEnv* env, jobjectArray varyings) {
|
|
int size = env->GetArrayLength(varyings);
|
|
std::vector<Varying> varyVector;
|
|
varyVector.reserve(size);
|
|
for (int i = 0; i < size; i++) {
|
|
jobject varying = env->GetObjectArrayElement(varyings, i);
|
|
auto name = (jstring)env->GetObjectField(varying, gVaryingInfo.name);
|
|
auto varyName = ScopedUtfChars(env, name);
|
|
Varying temp{Varying::Type(env->GetIntField(varying, gVaryingInfo.type)),
|
|
SkString(varyName.c_str())};
|
|
varyVector.push_back(std::move(temp));
|
|
}
|
|
|
|
return varyVector;
|
|
}
|
|
|
|
static jlong Make(JNIEnv* env, jobject thiz, jobjectArray attributeArray, jint vertexStride,
|
|
jobjectArray varyingArray, jstring vertexShader, jstring fragmentShader) {
|
|
auto attributes = extractAttributes(env, attributeArray);
|
|
auto varyings = extractVaryings(env, varyingArray);
|
|
auto skVertexShader = ScopedUtfChars(env, vertexShader);
|
|
auto skFragmentShader = ScopedUtfChars(env, fragmentShader);
|
|
auto meshSpecResult = SkMeshSpecification::Make(attributes, vertexStride, varyings,
|
|
SkString(skVertexShader.c_str()),
|
|
SkString(skFragmentShader.c_str()));
|
|
if (meshSpecResult.specification.get() == nullptr) {
|
|
jniThrowException(env, "java/lang/IllegalArgumentException", meshSpecResult.error.c_str());
|
|
}
|
|
|
|
return reinterpret_cast<jlong>(meshSpecResult.specification.release());
|
|
}
|
|
|
|
static jlong MakeWithCS(JNIEnv* env, jobject thiz, jobjectArray attributeArray, jint vertexStride,
|
|
jobjectArray varyingArray, jstring vertexShader, jstring fragmentShader,
|
|
jlong colorSpace) {
|
|
auto attributes = extractAttributes(env, attributeArray);
|
|
auto varyings = extractVaryings(env, varyingArray);
|
|
auto skVertexShader = ScopedUtfChars(env, vertexShader);
|
|
auto skFragmentShader = ScopedUtfChars(env, fragmentShader);
|
|
auto meshSpecResult = SkMeshSpecification::Make(
|
|
attributes, vertexStride, varyings, SkString(skVertexShader.c_str()),
|
|
SkString(skFragmentShader.c_str()), GraphicsJNI::getNativeColorSpace(colorSpace));
|
|
|
|
if (meshSpecResult.specification.get() == nullptr) {
|
|
jniThrowException(env, "java/lang/IllegalArgumentException", meshSpecResult.error.c_str());
|
|
}
|
|
|
|
return reinterpret_cast<jlong>(meshSpecResult.specification.release());
|
|
}
|
|
|
|
static jlong MakeWithAlpha(JNIEnv* env, jobject thiz, jobjectArray attributeArray,
|
|
jint vertexStride, jobjectArray varyingArray, jstring vertexShader,
|
|
jstring fragmentShader, jlong colorSpace, jint alphaType) {
|
|
auto attributes = extractAttributes(env, attributeArray);
|
|
auto varyings = extractVaryings(env, varyingArray);
|
|
auto skVertexShader = ScopedUtfChars(env, vertexShader);
|
|
auto skFragmentShader = ScopedUtfChars(env, fragmentShader);
|
|
auto meshSpecResult = SkMeshSpecification::Make(
|
|
attributes, vertexStride, varyings, SkString(skVertexShader.c_str()),
|
|
SkString(skFragmentShader.c_str()), GraphicsJNI::getNativeColorSpace(colorSpace),
|
|
SkAlphaType(alphaType));
|
|
|
|
if (meshSpecResult.specification.get() == nullptr) {
|
|
jniThrowException(env, "java/lang/IllegalArgumentException", meshSpecResult.error.c_str());
|
|
}
|
|
|
|
return reinterpret_cast<jlong>(meshSpecResult.specification.release());
|
|
}
|
|
|
|
static void MeshSpecification_safeUnref(SkMeshSpecification* meshSpec) {
|
|
SkSafeUnref(meshSpec);
|
|
}
|
|
|
|
static jlong getMeshSpecificationFinalizer() {
|
|
return static_cast<jlong>(reinterpret_cast<uintptr_t>(&MeshSpecification_safeUnref));
|
|
}
|
|
|
|
static const JNINativeMethod gMeshSpecificationMethods[] = {
|
|
{"nativeGetFinalizer", "()J", (void*)getMeshSpecificationFinalizer},
|
|
{"nativeMake",
|
|
"([Landroid/graphics/MeshSpecification$Attribute;I[Landroid/graphics/"
|
|
"MeshSpecification$Varying;"
|
|
"Ljava/lang/String;Ljava/lang/String;)J",
|
|
(void*)Make},
|
|
{"nativeMakeWithCS",
|
|
"([Landroid/graphics/MeshSpecification$Attribute;I"
|
|
"[Landroid/graphics/MeshSpecification$Varying;Ljava/lang/String;Ljava/lang/String;J)J",
|
|
(void*)MakeWithCS},
|
|
{"nativeMakeWithAlpha",
|
|
"([Landroid/graphics/MeshSpecification$Attribute;I"
|
|
"[Landroid/graphics/MeshSpecification$Varying;Ljava/lang/String;Ljava/lang/String;JI)J",
|
|
(void*)MakeWithAlpha}};
|
|
|
|
int register_android_graphics_MeshSpecification(JNIEnv* env) {
|
|
android::RegisterMethodsOrDie(env, "android/graphics/MeshSpecification",
|
|
gMeshSpecificationMethods, NELEM(gMeshSpecificationMethods));
|
|
|
|
gAttributeInfo.clazz = env->FindClass("android/graphics/MeshSpecification$Attribute");
|
|
gAttributeInfo.type = env->GetFieldID(gAttributeInfo.clazz, "mType", "I");
|
|
gAttributeInfo.offset = env->GetFieldID(gAttributeInfo.clazz, "mOffset", "I");
|
|
gAttributeInfo.name = env->GetFieldID(gAttributeInfo.clazz, "mName", "Ljava/lang/String;");
|
|
|
|
gVaryingInfo.clazz = env->FindClass("android/graphics/MeshSpecification$Varying");
|
|
gVaryingInfo.type = env->GetFieldID(gVaryingInfo.clazz, "mType", "I");
|
|
gVaryingInfo.name = env->GetFieldID(gVaryingInfo.clazz, "mName", "Ljava/lang/String;");
|
|
return 0;
|
|
}
|
|
|
|
} // namespace android
|