/* * 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 #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 extractAttributes(JNIEnv* env, jobjectArray attributes) { int size = env->GetArrayLength(attributes); std::vector 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(env->GetIntField(attribute, gAttributeInfo.offset)), SkString(attName.c_str())}; attVector.push_back(std::move(temp)); } return attVector; } std::vector extractVaryings(JNIEnv* env, jobjectArray varyings) { int size = env->GetArrayLength(varyings); std::vector 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(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(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(meshSpecResult.specification.release()); } static void MeshSpecification_safeUnref(SkMeshSpecification* meshSpec) { SkSafeUnref(meshSpec); } static jlong getMeshSpecificationFinalizer() { return static_cast(reinterpret_cast(&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