diff options
author | 2022-10-27 00:17:00 +0000 | |
---|---|---|
committer | 2022-11-17 21:08:34 +0000 | |
commit | 79e5f58ff665fa8813bcfd92e6c2e61f081f5cd3 (patch) | |
tree | 7500602988318b24e2f1a12be7cb9cc9526213d8 | |
parent | fe5097cfbd4505bc4b1ea5194e5836456eaaca17 (diff) |
Exposed SkMeshSpecification
Exposed SkMeshSpecification through MeshSpecification, exposing Make
methods as well as constructing a Attribute and Varying data classes.
Bug: b/254354404
Test: build hwui
Change-Id: I1040bde091575ac4bb786f7600d016b7c9168831
-rw-r--r-- | graphics/java/android/graphics/MeshSpecification.java | 194 | ||||
-rw-r--r-- | libs/hwui/jni/MeshSpecification.cpp | 156 |
2 files changed, 350 insertions, 0 deletions
diff --git a/graphics/java/android/graphics/MeshSpecification.java b/graphics/java/android/graphics/MeshSpecification.java new file mode 100644 index 000000000000..b27c5e0ab728 --- /dev/null +++ b/graphics/java/android/graphics/MeshSpecification.java @@ -0,0 +1,194 @@ +/* + * 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. + */ + +package android.graphics; + +import android.annotation.IntDef; + +import libcore.util.NativeAllocationRegistry; + +/** + * Class responsible for holding specifications for {@link Mesh} creations. This class + * generates a {@link MeshSpecification} via the Make method, where multiple parameters to set up + * the mesh are supplied, including attributes, vertex stride, varyings, and + * vertex/fragment shaders. There are also additional methods to provide an optional + * {@link ColorSpace} as well as an alpha type. + * + * Note that there are several limitations on various mesh specifications: + * 1. The max amount of attributes allowed is 8. + * 2. The offset alignment length is 4 bytes. + * 2. The max stride length is 1024. + * 3. The max amount of varyings is 6. + * + * These should be kept in mind when generating a mesh specification, as exceeding them will + * lead to errors. + * + * @hide + */ +public class MeshSpecification { + private long mNativeMeshSpec; + + /** + * Constants for {@link #make(Attribute[], int, Varying[], String, String, ColorSpace, int)} + * to determine alpha type + */ + @IntDef({UNKNOWN, OPAQUE, PREMUL, UNPREMULT}) + public @interface AlphaType { + } + + public static final int UNKNOWN = 0; + public static final int OPAQUE = 1; + public static final int PREMUL = 2; + public static final int UNPREMULT = 3; + + /** + * Constants for {@link Attribute} and {@link Varying} for determining the data type. + */ + @IntDef({FLOAT, FLOAT2, FLOAT3, FLOAT4, UBYTE4}) + public @interface Type { + } + + public static final int FLOAT = 0; + public static final int FLOAT2 = 1; + public static final int FLOAT3 = 2; + public static final int FLOAT4 = 3; + public static final int UBYTE4 = 4; + + /** + * Data class to represent a single attribute in a shader. Note that type parameter must be + * one of {@link #FLOAT}, {@link #FLOAT2}, {@link #FLOAT3}, {@link #FLOAT4}, or {@link #UBYTE4}. + */ + public static class Attribute { + @Type + private int mType; + private int mOffset; + private String mName; + + public Attribute(@Type int type, int offset, String name) { + mType = type; + mOffset = offset; + mName = name; + } + } + + /** + * Data class to represent a single varying variable. Note that type parameter must be + * one of {@link #FLOAT}, {@link #FLOAT2}, {@link #FLOAT3}, {@link #FLOAT4}, or {@link #UBYTE4}. + */ + public static class Varying { + @Type + private int mType; + private String mName; + + public Varying(@Type int type, String name) { + mType = type; + mName = name; + } + } + + private static class MeshSpecificationHolder { + public static final NativeAllocationRegistry MESH_SPECIFICATION_REGISTRY = + NativeAllocationRegistry.createMalloced( + MeshSpecification.class.getClassLoader(), nativeGetFinalizer()); + } + + /** + * Creates a {@link MeshSpecification} object. + * + * @param attributes list of attributes represented by {@link Attribute}. Can hold a max of + * 8. + * @param vertexStride length of vertex stride. Max of 1024 is accepted. + * @param varyings List of varyings represented by {@link Varying}. Can hold a max of 6. + * @param vertexShader vertex shader to be supplied to the mesh. + * @param fragmentShader fragment shader to be suppied to the mesh. + * @return {@link MeshSpecification} object for use when creating {@link Mesh} + */ + public static MeshSpecification make(Attribute[] attributes, int vertexStride, + Varying[] varyings, String vertexShader, String fragmentShader) { + long nativeMeshSpec = + nativeMake(attributes, vertexStride, varyings, vertexShader, fragmentShader); + if (nativeMeshSpec == 0) { + throw new IllegalArgumentException("MeshSpecification construction failed"); + } + return new MeshSpecification(nativeMeshSpec); + } + + /** + * Creates a {@link MeshSpecification} object. + * + * @param attributes list of attributes represented by {@link Attribute}. Can hold a max of + * 8. + * @param vertexStride length of vertex stride. Max of 1024 is accepted. + * @param varyings List of varyings represented by {@link Varying}. Can hold a max of + * 6. + * @param vertexShader vertex shader to be supplied to the mesh. + * @param fragmentShader fragment shader to be supplied to the mesh. + * @param colorSpace {@link ColorSpace} to tell what color space to work in. + * @return {@link MeshSpecification} object for use when creating {@link Mesh} + */ + public static MeshSpecification make(Attribute[] attributes, int vertexStride, + Varying[] varyings, String vertexShader, String fragmentShader, ColorSpace colorSpace) { + long nativeMeshSpec = nativeMakeWithCS(attributes, vertexStride, varyings, vertexShader, + fragmentShader, colorSpace.getNativeInstance()); + if (nativeMeshSpec == 0) { + throw new IllegalArgumentException("MeshSpecification construction failed"); + } + return new MeshSpecification(nativeMeshSpec); + } + + /** + * Creates a {@link MeshSpecification} object. + * + * @param attributes list of attributes represented by {@link Attribute}. Can hold a max of + * 8. + * @param vertexStride length of vertex stride. Max of 1024 is accepted. + * @param varyings List of varyings represented by {@link Varying}. Can hold a max of 6. + * @param vertexShader vertex shader code to be supplied to the mesh. + * @param fragmentShader fragment shader code to be suppied to the mesh. + * @param colorSpace {@link ColorSpace} to tell what color space to work in. + * @param alphaType Describes how to interpret the alpha component for a pixel. Must be + * one of {@link AlphaType} values. + * @return {@link MeshSpecification} object for use when creating {@link Mesh} + */ + public static MeshSpecification make(Attribute[] attributes, int vertexStride, + Varying[] varyings, String vertexShader, String fragmentShader, ColorSpace colorSpace, + @AlphaType int alphaType) { + long nativeMeshSpec = nativeMakeWithAlpha(attributes, vertexStride, varyings, vertexShader, + fragmentShader, colorSpace.getNativeInstance(), alphaType); + if (nativeMeshSpec == 0) { + throw new IllegalArgumentException("MeshSpecification construction failed"); + } + return new MeshSpecification(nativeMeshSpec); + } + + private MeshSpecification(long meshSpec) { + mNativeMeshSpec = meshSpec; + MeshSpecificationHolder.MESH_SPECIFICATION_REGISTRY.registerNativeAllocation( + this, meshSpec); + } + + private static native long nativeGetFinalizer(); + + private static native long nativeMake(Attribute[] attributes, int vertexStride, + Varying[] varyings, String vertexShader, String fragmentShader); + + private static native long nativeMakeWithCS(Attribute[] attributes, int vertexStride, + Varying[] varyings, String vertexShader, String fragmentShader, long colorSpace); + + private static native long nativeMakeWithAlpha(Attribute[] attributes, int vertexStride, + Varying[] varyings, String vertexShader, String fragmentShader, long colorSpace, + int alphaType); +} diff --git a/libs/hwui/jni/MeshSpecification.cpp b/libs/hwui/jni/MeshSpecification.cpp new file mode 100644 index 000000000000..22fa4d39e2ed --- /dev/null +++ b/libs/hwui/jni/MeshSpecification.cpp @@ -0,0 +1,156 @@ +/* + * 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 meshSpec = SkMeshSpecification::Make(attributes, vertexStride, varyings, + SkString(skVertexShader.c_str()), + SkString(skFragmentShader.c_str())) + .specification; + return reinterpret_cast<jlong>(meshSpec.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 meshSpec = SkMeshSpecification::Make(attributes, vertexStride, varyings, + SkString(skVertexShader.c_str()), + SkString(skFragmentShader.c_str()), + GraphicsJNI::getNativeColorSpace(colorSpace)) + .specification; + + return reinterpret_cast<jlong>(meshSpec.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 meshSpec = SkMeshSpecification::Make( + attributes, vertexStride, varyings, SkString(skVertexShader.c_str()), + SkString(skFragmentShader.c_str()), + GraphicsJNI::getNativeColorSpace(colorSpace), SkAlphaType(alphaType)) + .specification; + return reinterpret_cast<jlong>(meshSpec.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
\ No newline at end of file |