xref: /aosp_15_r20/frameworks/base/libs/hwui/jni/MeshSpecification.cpp (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1*d57664e9SAndroid Build Coastguard Worker /*
2*d57664e9SAndroid Build Coastguard Worker  * Copyright (C) 2022 The Android Open Source Project
3*d57664e9SAndroid Build Coastguard Worker  *
4*d57664e9SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*d57664e9SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*d57664e9SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*d57664e9SAndroid Build Coastguard Worker  *
8*d57664e9SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*d57664e9SAndroid Build Coastguard Worker  *
10*d57664e9SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*d57664e9SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*d57664e9SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*d57664e9SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*d57664e9SAndroid Build Coastguard Worker  * limitations under the License.
15*d57664e9SAndroid Build Coastguard Worker  */
16*d57664e9SAndroid Build Coastguard Worker 
17*d57664e9SAndroid Build Coastguard Worker #include <SkMesh.h>
18*d57664e9SAndroid Build Coastguard Worker 
19*d57664e9SAndroid Build Coastguard Worker #include "GraphicsJNI.h"
20*d57664e9SAndroid Build Coastguard Worker #include "graphics_jni_helpers.h"
21*d57664e9SAndroid Build Coastguard Worker 
22*d57664e9SAndroid Build Coastguard Worker namespace android {
23*d57664e9SAndroid Build Coastguard Worker 
24*d57664e9SAndroid Build Coastguard Worker using Attribute = SkMeshSpecification::Attribute;
25*d57664e9SAndroid Build Coastguard Worker using Varying = SkMeshSpecification::Varying;
26*d57664e9SAndroid Build Coastguard Worker 
27*d57664e9SAndroid Build Coastguard Worker static struct {
28*d57664e9SAndroid Build Coastguard Worker     jclass clazz{};
29*d57664e9SAndroid Build Coastguard Worker     jfieldID type{};
30*d57664e9SAndroid Build Coastguard Worker     jfieldID offset{};
31*d57664e9SAndroid Build Coastguard Worker     jfieldID name{};
32*d57664e9SAndroid Build Coastguard Worker } gAttributeInfo;
33*d57664e9SAndroid Build Coastguard Worker 
34*d57664e9SAndroid Build Coastguard Worker static struct {
35*d57664e9SAndroid Build Coastguard Worker     jclass clazz{};
36*d57664e9SAndroid Build Coastguard Worker     jfieldID type{};
37*d57664e9SAndroid Build Coastguard Worker     jfieldID name{};
38*d57664e9SAndroid Build Coastguard Worker } gVaryingInfo;
39*d57664e9SAndroid Build Coastguard Worker 
extractAttributes(JNIEnv * env,jobjectArray attributes)40*d57664e9SAndroid Build Coastguard Worker std::vector<Attribute> extractAttributes(JNIEnv* env, jobjectArray attributes) {
41*d57664e9SAndroid Build Coastguard Worker     int size = env->GetArrayLength(attributes);
42*d57664e9SAndroid Build Coastguard Worker     std::vector<Attribute> attVector;
43*d57664e9SAndroid Build Coastguard Worker     attVector.reserve(size);
44*d57664e9SAndroid Build Coastguard Worker     for (int i = 0; i < size; i++) {
45*d57664e9SAndroid Build Coastguard Worker         jobject attribute = env->GetObjectArrayElement(attributes, i);
46*d57664e9SAndroid Build Coastguard Worker         auto name = (jstring)env->GetObjectField(attribute, gAttributeInfo.name);
47*d57664e9SAndroid Build Coastguard Worker         auto attName = ScopedUtfChars(env, name);
48*d57664e9SAndroid Build Coastguard Worker         Attribute temp{Attribute::Type(env->GetIntField(attribute, gAttributeInfo.type)),
49*d57664e9SAndroid Build Coastguard Worker                        static_cast<size_t>(env->GetIntField(attribute, gAttributeInfo.offset)),
50*d57664e9SAndroid Build Coastguard Worker                        SkString(attName.c_str())};
51*d57664e9SAndroid Build Coastguard Worker         attVector.push_back(std::move(temp));
52*d57664e9SAndroid Build Coastguard Worker     }
53*d57664e9SAndroid Build Coastguard Worker     return attVector;
54*d57664e9SAndroid Build Coastguard Worker }
55*d57664e9SAndroid Build Coastguard Worker 
extractVaryings(JNIEnv * env,jobjectArray varyings)56*d57664e9SAndroid Build Coastguard Worker std::vector<Varying> extractVaryings(JNIEnv* env, jobjectArray varyings) {
57*d57664e9SAndroid Build Coastguard Worker     int size = env->GetArrayLength(varyings);
58*d57664e9SAndroid Build Coastguard Worker     std::vector<Varying> varyVector;
59*d57664e9SAndroid Build Coastguard Worker     varyVector.reserve(size);
60*d57664e9SAndroid Build Coastguard Worker     for (int i = 0; i < size; i++) {
61*d57664e9SAndroid Build Coastguard Worker         jobject varying = env->GetObjectArrayElement(varyings, i);
62*d57664e9SAndroid Build Coastguard Worker         auto name = (jstring)env->GetObjectField(varying, gVaryingInfo.name);
63*d57664e9SAndroid Build Coastguard Worker         auto varyName = ScopedUtfChars(env, name);
64*d57664e9SAndroid Build Coastguard Worker         Varying temp{Varying::Type(env->GetIntField(varying, gVaryingInfo.type)),
65*d57664e9SAndroid Build Coastguard Worker                      SkString(varyName.c_str())};
66*d57664e9SAndroid Build Coastguard Worker         varyVector.push_back(std::move(temp));
67*d57664e9SAndroid Build Coastguard Worker     }
68*d57664e9SAndroid Build Coastguard Worker 
69*d57664e9SAndroid Build Coastguard Worker     return varyVector;
70*d57664e9SAndroid Build Coastguard Worker }
71*d57664e9SAndroid Build Coastguard Worker 
Make(JNIEnv * env,jobject thiz,jobjectArray attributeArray,jint vertexStride,jobjectArray varyingArray,jstring vertexShader,jstring fragmentShader)72*d57664e9SAndroid Build Coastguard Worker static jlong Make(JNIEnv* env, jobject thiz, jobjectArray attributeArray, jint vertexStride,
73*d57664e9SAndroid Build Coastguard Worker                   jobjectArray varyingArray, jstring vertexShader, jstring fragmentShader) {
74*d57664e9SAndroid Build Coastguard Worker     auto attributes = extractAttributes(env, attributeArray);
75*d57664e9SAndroid Build Coastguard Worker     auto varyings = extractVaryings(env, varyingArray);
76*d57664e9SAndroid Build Coastguard Worker     auto skVertexShader = ScopedUtfChars(env, vertexShader);
77*d57664e9SAndroid Build Coastguard Worker     auto skFragmentShader = ScopedUtfChars(env, fragmentShader);
78*d57664e9SAndroid Build Coastguard Worker     auto meshSpecResult = SkMeshSpecification::Make(attributes, vertexStride, varyings,
79*d57664e9SAndroid Build Coastguard Worker                                                     SkString(skVertexShader.c_str()),
80*d57664e9SAndroid Build Coastguard Worker                                                     SkString(skFragmentShader.c_str()));
81*d57664e9SAndroid Build Coastguard Worker     if (meshSpecResult.specification.get() == nullptr) {
82*d57664e9SAndroid Build Coastguard Worker         jniThrowException(env, "java/lang/IllegalArgumentException", meshSpecResult.error.c_str());
83*d57664e9SAndroid Build Coastguard Worker     }
84*d57664e9SAndroid Build Coastguard Worker 
85*d57664e9SAndroid Build Coastguard Worker     return reinterpret_cast<jlong>(meshSpecResult.specification.release());
86*d57664e9SAndroid Build Coastguard Worker }
87*d57664e9SAndroid Build Coastguard Worker 
MakeWithCS(JNIEnv * env,jobject thiz,jobjectArray attributeArray,jint vertexStride,jobjectArray varyingArray,jstring vertexShader,jstring fragmentShader,jlong colorSpace)88*d57664e9SAndroid Build Coastguard Worker static jlong MakeWithCS(JNIEnv* env, jobject thiz, jobjectArray attributeArray, jint vertexStride,
89*d57664e9SAndroid Build Coastguard Worker                         jobjectArray varyingArray, jstring vertexShader, jstring fragmentShader,
90*d57664e9SAndroid Build Coastguard Worker                         jlong colorSpace) {
91*d57664e9SAndroid Build Coastguard Worker     auto attributes = extractAttributes(env, attributeArray);
92*d57664e9SAndroid Build Coastguard Worker     auto varyings = extractVaryings(env, varyingArray);
93*d57664e9SAndroid Build Coastguard Worker     auto skVertexShader = ScopedUtfChars(env, vertexShader);
94*d57664e9SAndroid Build Coastguard Worker     auto skFragmentShader = ScopedUtfChars(env, fragmentShader);
95*d57664e9SAndroid Build Coastguard Worker     auto meshSpecResult = SkMeshSpecification::Make(
96*d57664e9SAndroid Build Coastguard Worker             attributes, vertexStride, varyings, SkString(skVertexShader.c_str()),
97*d57664e9SAndroid Build Coastguard Worker             SkString(skFragmentShader.c_str()), GraphicsJNI::getNativeColorSpace(colorSpace));
98*d57664e9SAndroid Build Coastguard Worker 
99*d57664e9SAndroid Build Coastguard Worker     if (meshSpecResult.specification.get() == nullptr) {
100*d57664e9SAndroid Build Coastguard Worker         jniThrowException(env, "java/lang/IllegalArgumentException", meshSpecResult.error.c_str());
101*d57664e9SAndroid Build Coastguard Worker     }
102*d57664e9SAndroid Build Coastguard Worker 
103*d57664e9SAndroid Build Coastguard Worker     return reinterpret_cast<jlong>(meshSpecResult.specification.release());
104*d57664e9SAndroid Build Coastguard Worker }
105*d57664e9SAndroid Build Coastguard Worker 
MakeWithAlpha(JNIEnv * env,jobject thiz,jobjectArray attributeArray,jint vertexStride,jobjectArray varyingArray,jstring vertexShader,jstring fragmentShader,jlong colorSpace,jint alphaType)106*d57664e9SAndroid Build Coastguard Worker static jlong MakeWithAlpha(JNIEnv* env, jobject thiz, jobjectArray attributeArray,
107*d57664e9SAndroid Build Coastguard Worker                            jint vertexStride, jobjectArray varyingArray, jstring vertexShader,
108*d57664e9SAndroid Build Coastguard Worker                            jstring fragmentShader, jlong colorSpace, jint alphaType) {
109*d57664e9SAndroid Build Coastguard Worker     auto attributes = extractAttributes(env, attributeArray);
110*d57664e9SAndroid Build Coastguard Worker     auto varyings = extractVaryings(env, varyingArray);
111*d57664e9SAndroid Build Coastguard Worker     auto skVertexShader = ScopedUtfChars(env, vertexShader);
112*d57664e9SAndroid Build Coastguard Worker     auto skFragmentShader = ScopedUtfChars(env, fragmentShader);
113*d57664e9SAndroid Build Coastguard Worker     auto meshSpecResult = SkMeshSpecification::Make(
114*d57664e9SAndroid Build Coastguard Worker             attributes, vertexStride, varyings, SkString(skVertexShader.c_str()),
115*d57664e9SAndroid Build Coastguard Worker             SkString(skFragmentShader.c_str()), GraphicsJNI::getNativeColorSpace(colorSpace),
116*d57664e9SAndroid Build Coastguard Worker             SkAlphaType(alphaType));
117*d57664e9SAndroid Build Coastguard Worker 
118*d57664e9SAndroid Build Coastguard Worker     if (meshSpecResult.specification.get() == nullptr) {
119*d57664e9SAndroid Build Coastguard Worker         jniThrowException(env, "java/lang/IllegalArgumentException", meshSpecResult.error.c_str());
120*d57664e9SAndroid Build Coastguard Worker     }
121*d57664e9SAndroid Build Coastguard Worker 
122*d57664e9SAndroid Build Coastguard Worker     return reinterpret_cast<jlong>(meshSpecResult.specification.release());
123*d57664e9SAndroid Build Coastguard Worker }
124*d57664e9SAndroid Build Coastguard Worker 
MeshSpecification_safeUnref(SkMeshSpecification * meshSpec)125*d57664e9SAndroid Build Coastguard Worker static void MeshSpecification_safeUnref(SkMeshSpecification* meshSpec) {
126*d57664e9SAndroid Build Coastguard Worker     SkSafeUnref(meshSpec);
127*d57664e9SAndroid Build Coastguard Worker }
128*d57664e9SAndroid Build Coastguard Worker 
getMeshSpecificationFinalizer(CRITICAL_JNI_PARAMS)129*d57664e9SAndroid Build Coastguard Worker static jlong getMeshSpecificationFinalizer(CRITICAL_JNI_PARAMS) {
130*d57664e9SAndroid Build Coastguard Worker     return static_cast<jlong>(reinterpret_cast<uintptr_t>(&MeshSpecification_safeUnref));
131*d57664e9SAndroid Build Coastguard Worker }
132*d57664e9SAndroid Build Coastguard Worker 
133*d57664e9SAndroid Build Coastguard Worker static const JNINativeMethod gMeshSpecificationMethods[] = {
134*d57664e9SAndroid Build Coastguard Worker         {"nativeGetFinalizer", "()J", (void*)getMeshSpecificationFinalizer},
135*d57664e9SAndroid Build Coastguard Worker         {"nativeMake",
136*d57664e9SAndroid Build Coastguard Worker          "([Landroid/graphics/MeshSpecification$Attribute;I[Landroid/graphics/"
137*d57664e9SAndroid Build Coastguard Worker          "MeshSpecification$Varying;"
138*d57664e9SAndroid Build Coastguard Worker          "Ljava/lang/String;Ljava/lang/String;)J",
139*d57664e9SAndroid Build Coastguard Worker          (void*)Make},
140*d57664e9SAndroid Build Coastguard Worker         {"nativeMakeWithCS",
141*d57664e9SAndroid Build Coastguard Worker          "([Landroid/graphics/MeshSpecification$Attribute;I"
142*d57664e9SAndroid Build Coastguard Worker          "[Landroid/graphics/MeshSpecification$Varying;Ljava/lang/String;Ljava/lang/String;J)J",
143*d57664e9SAndroid Build Coastguard Worker          (void*)MakeWithCS},
144*d57664e9SAndroid Build Coastguard Worker         {"nativeMakeWithAlpha",
145*d57664e9SAndroid Build Coastguard Worker          "([Landroid/graphics/MeshSpecification$Attribute;I"
146*d57664e9SAndroid Build Coastguard Worker          "[Landroid/graphics/MeshSpecification$Varying;Ljava/lang/String;Ljava/lang/String;JI)J",
147*d57664e9SAndroid Build Coastguard Worker          (void*)MakeWithAlpha}};
148*d57664e9SAndroid Build Coastguard Worker 
register_android_graphics_MeshSpecification(JNIEnv * env)149*d57664e9SAndroid Build Coastguard Worker int register_android_graphics_MeshSpecification(JNIEnv* env) {
150*d57664e9SAndroid Build Coastguard Worker     android::RegisterMethodsOrDie(env, "android/graphics/MeshSpecification",
151*d57664e9SAndroid Build Coastguard Worker                                   gMeshSpecificationMethods, NELEM(gMeshSpecificationMethods));
152*d57664e9SAndroid Build Coastguard Worker 
153*d57664e9SAndroid Build Coastguard Worker     gAttributeInfo.clazz = env->FindClass("android/graphics/MeshSpecification$Attribute");
154*d57664e9SAndroid Build Coastguard Worker     gAttributeInfo.type = env->GetFieldID(gAttributeInfo.clazz, "mType", "I");
155*d57664e9SAndroid Build Coastguard Worker     gAttributeInfo.offset = env->GetFieldID(gAttributeInfo.clazz, "mOffset", "I");
156*d57664e9SAndroid Build Coastguard Worker     gAttributeInfo.name = env->GetFieldID(gAttributeInfo.clazz, "mName", "Ljava/lang/String;");
157*d57664e9SAndroid Build Coastguard Worker 
158*d57664e9SAndroid Build Coastguard Worker     gVaryingInfo.clazz = env->FindClass("android/graphics/MeshSpecification$Varying");
159*d57664e9SAndroid Build Coastguard Worker     gVaryingInfo.type = env->GetFieldID(gVaryingInfo.clazz, "mType", "I");
160*d57664e9SAndroid Build Coastguard Worker     gVaryingInfo.name = env->GetFieldID(gVaryingInfo.clazz, "mName", "Ljava/lang/String;");
161*d57664e9SAndroid Build Coastguard Worker     return 0;
162*d57664e9SAndroid Build Coastguard Worker }
163*d57664e9SAndroid Build Coastguard Worker 
164*d57664e9SAndroid Build Coastguard Worker }  // namespace android
165