script-astra/Android/Sdk/sources/android-35/android/graphics/MeshSpecification.java

407 lines
16 KiB
Java
Raw Normal View History

2025-01-20 15:15:20 +00:00
/*
* 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 android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Size;
import android.annotation.SuppressLint;
import libcore.util.NativeAllocationRegistry;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Class responsible for holding specifications for {@link Mesh} creations. This class generates a
* {@link MeshSpecification} via the
* {@link MeshSpecification#make(Attribute[], int, Varying[], String, String)} method,
* where multiple parameters to set up the mesh are supplied, including attributes, vertex stride,
* {@link Varying}, and vertex/fragment shaders. There are also additional methods to provide an
* optional {@link ColorSpace} as well as an alpha type.
*
* For example a vertex shader that leverages a {@link Varying} may look like the following:
*
* <pre>
* Varyings main(const Attributes attributes) {
* Varyings varyings;
* varyings.position = attributes.position;
* return varyings;
* }
* </pre>
*
* The corresponding fragment shader that may consume the varying look like the following:
*
* <pre>
* float2 main(const Varyings varyings, out float4 color) {
* color = vec4(1.0, 0.0, 0.0, 1.0);
* return varyings.position;
* }
* </pre>
*
* The color returned from this fragment shader is blended with the other parameters that are
* configured on the Paint object (ex. {@link Paint#setBlendMode(BlendMode)} used to draw the mesh.
*
* The position returned in the fragment shader can be consumed by any following fragment shaders in
* the shader chain.
*
* See https://developer.android.com/develop/ui/views/graphics/agsl for more information
* regarding Android Graphics Shader Language.
*
* 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.
*/
public class MeshSpecification {
long mNativeMeshSpec;
/**
* Constants for {@link #make(Attribute[], int, Varying[], String, String)}
* to determine alpha type. Describes how to interpret the alpha component of a pixel.
*
* @hide
*/
@IntDef(
prefix = {"ALPHA_TYPE_"},
value = {ALPHA_TYPE_UNKNOWN, ALPHA_TYPE_OPAQUE, ALPHA_TYPE_PREMULTIPLIED,
ALPHA_TYPE_UNPREMULTIPLIED}
)
@Retention(RetentionPolicy.SOURCE)
private @interface AlphaType {}
/**
* uninitialized.
*/
public static final int ALPHA_TYPE_UNKNOWN = 0;
/**
* Pixel is opaque.
*/
public static final int ALPHA_TYPE_OPAQUE = 1;
/**
* Pixel components are premultiplied by alpha.
*/
public static final int ALPHA_TYPE_PREMULTIPLIED = 2;
/**
* Pixel components are independent of alpha.
*/
public static final int ALPHA_TYPE_UNPREMULTIPLIED = 3;
/**
* Constants for {@link Attribute} and {@link Varying} for determining the data type.
*
* @hide
*/
@IntDef(
prefix = {"TYPE_"},
value = {TYPE_FLOAT, TYPE_FLOAT2, TYPE_FLOAT3, TYPE_FLOAT4, TYPE_UBYTE4}
)
@Retention(RetentionPolicy.SOURCE)
private @interface Type {}
/**
* Represents one float. Its equivalent shader type is float.
*/
public static final int TYPE_FLOAT = 0;
/**
* Represents two floats. Its equivalent shader type is float2.
*/
public static final int TYPE_FLOAT2 = 1;
/**
* Represents three floats. Its equivalent shader type is float3.
*/
public static final int TYPE_FLOAT3 = 2;
/**
* Represents four floats. Its equivalent shader type is float4.
*/
public static final int TYPE_FLOAT4 = 3;
/**
* Represents four bytes. Its equivalent shader type is half4.
*/
public static final int TYPE_UBYTE4 = 4;
/**
* Data class to represent a single attribute in a shader. An attribute is a variable that
* accompanies a vertex, this can be a color or texture coordinates.
*
* See https://developer.android.com/develop/ui/views/graphics/agsl for more information
* regarding Android Graphics Shader Language.
*
* Note that offset is the offset in number of bytes. For example, if we had two attributes
*
* <pre>
* Float3 att1
* Float att2
* </pre>
*
* att1 would have an offset of 0, while att2 would have an offset of 12 bytes.
*
* This is consumed as part of
* {@link MeshSpecification#make(Attribute[], int, Varying[], String, String, ColorSpace, int)}
* to create a {@link MeshSpecification} instance.
*/
public static class Attribute {
@Type
private final int mType;
private final int mOffset;
private final String mName;
public Attribute(@Type int type, int offset, @NonNull String name) {
mType = type;
mOffset = offset;
mName = name;
}
/**
* Return the corresponding data type for this {@link Attribute}.
*/
@Type
public int getType() {
return mType;
}
/**
* Return the offset of the attribute in bytes
*/
public int getOffset() {
return mOffset;
}
/**
* Return the name of this {@link Attribute}
*/
@NonNull
public String getName() {
return mName;
}
@Override
public String toString() {
return "Attribute{"
+ "mType=" + mType
+ ", mOffset=" + mOffset
+ ", mName='" + mName + '\''
+ '}';
}
}
/**
* Data class to represent a single varying variable. A Varying variable can be altered by the
* vertex shader defined on the mesh but not by the fragment shader defined by AGSL.
*
* See https://developer.android.com/develop/ui/views/graphics/agsl for more information
* regarding Android Graphics Shader Language.
*
* This is consumed as part of
* {@link MeshSpecification#make(Attribute[], int, Varying[], String, String, ColorSpace, int)}
* to create a {@link MeshSpecification} instance.
*/
public static class Varying {
@Type
private final int mType;
private final String mName;
public Varying(@Type int type, @NonNull String name) {
mType = type;
mName = name;
}
/**
* Return the corresponding data type for this {@link Varying}.
*/
@Type
public int getType() {
return mType;
}
/**
* Return the name of this {@link Varying}
*/
@NonNull
public String getName() {
return mName;
}
@Override
public String toString() {
return "Varying{"
+ "mType=" + mType
+ ", mName='" + mName + '\''
+ '}';
}
}
private static class MeshSpecificationHolder {
public static final NativeAllocationRegistry MESH_SPECIFICATION_REGISTRY =
NativeAllocationRegistry.createMalloced(
MeshSpecification.class.getClassLoader(), nativeGetFinalizer());
}
/**
* Creates a {@link MeshSpecification} object for use within {@link Mesh}. This uses a default
* color space of {@link ColorSpace.Named#SRGB} and alphaType of
* {@link #ALPHA_TYPE_PREMULTIPLIED}.
*
* @param attributes list of attributes represented by {@link Attribute}. Can hold a max of
* 8.
* @param vertexStride length of vertex stride in bytes. This should be the size of a single
* vertex' attributes. Max of 1024 is accepted.
* @param varyings List of varyings represented by {@link Varying}. Can hold a max of 6.
* Note that `position` is provided by default, does not need to be
* provided in the list, and does not count towards
* the 6 varyings allowed.
* @param vertexShader vertex shader to be supplied to the mesh. Ensure that the position
* varying is set within the shader to get proper results.
* See {@link MeshSpecification} for an example vertex shader
* implementation
* @param fragmentShader fragment shader to be supplied to the mesh.
* See {@link MeshSpecification} for an example fragment shader
* implementation
* @return {@link MeshSpecification} object for use when creating {@link Mesh}
*/
@NonNull
public static MeshSpecification make(
@SuppressLint("ArrayReturn") @NonNull @Size(max = 8) Attribute[] attributes,
@IntRange(from = 1, to = 1024) int vertexStride,
@SuppressLint("ArrayReturn") @NonNull @Size(max = 6) Varying[] varyings,
@NonNull String vertexShader,
@NonNull 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. This uses a default alphaType of
* {@link #ALPHA_TYPE_PREMULTIPLIED}.
*
* @param attributes list of attributes represented by {@link Attribute}. Can hold a max of
* 8.
* @param vertexStride length of vertex stride in bytes. This should be the size of a single
* vertex' attributes. Max of 1024 is accepted.
* @param varyings List of varyings represented by {@link Varying}. Can hold a max of 6.
* Note that `position` is provided by default, does not need to be
* provided in the list, and does not count towards
* the 6 varyings allowed.
* @param vertexShader vertex shader to be supplied to the mesh. Ensure that the position
* varying is set within the shader to get proper results.
* See {@link MeshSpecification} for an example vertex shader
* implementation
* @param fragmentShader fragment shader to be supplied to the mesh.
* See {@link MeshSpecification} for an example fragment shader
* implementation
* @param colorSpace {@link ColorSpace} to tell what color space to work in.
* @return {@link MeshSpecification} object for use when creating {@link Mesh}
*/
@NonNull
public static MeshSpecification make(
@SuppressLint("ArrayReturn") @NonNull @Size(max = 8) Attribute[] attributes,
@IntRange(from = 1, to = 1024) int vertexStride,
@SuppressLint("ArrayReturn") @NonNull @Size(max = 6) Varying[] varyings,
@NonNull String vertexShader,
@NonNull String fragmentShader,
@NonNull 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 in bytes. This should be the size of a single
* vertex' attributes. Max of 1024 is accepted.
* @param varyings List of varyings represented by {@link Varying}. Can hold a max of 6.
* Note that `position` is provided by default, does not need to be
* provided in the list, and does not count towards
* the 6 varyings allowed.
* @param vertexShader vertex shader to be supplied to the mesh. Ensure that the position
* varying is set within the shader to get proper results.
* See {@link MeshSpecification} for an example vertex shader
* implementation
* @param fragmentShader fragment shader to be supplied to the mesh.
* See {@link MeshSpecification} for an example fragment shader
* implementation
* @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 MeshSpecification#ALPHA_TYPE_UNKNOWN},
* {@link MeshSpecification#ALPHA_TYPE_OPAQUE},
* {@link MeshSpecification#ALPHA_TYPE_PREMULTIPLIED}, or
* {@link MeshSpecification#ALPHA_TYPE_UNPREMULTIPLIED}
* @return {@link MeshSpecification} object for use when creating {@link Mesh}
*/
@NonNull
public static MeshSpecification make(
@SuppressLint("ArrayReturn") @NonNull @Size(max = 8) Attribute[] attributes,
@IntRange(from = 1, to = 1024) int vertexStride,
@SuppressLint("ArrayReturn") @NonNull @Size(max = 6) Varying[] varyings,
@NonNull String vertexShader,
@NonNull String fragmentShader,
@NonNull 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);
}