| /* |
| * 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 |