Loading graphics/java/android/graphics/BaseCanvas.java +10 −1 Original line number Diff line number Diff line Loading @@ -668,12 +668,21 @@ public abstract class BaseCanvas { } /** * Draws a mesh object to the screen. * * @param mesh {@link Mesh} object that will be drawn to the screen * @param blendMode {@link BlendMode} used to blend mesh primitives with the Paint color/shader * @param paint {@link Paint} used to provide a color/shader/blend mode. * * @hide */ public void drawMesh(Mesh mesh, BlendMode blendMode, Paint paint) { public void drawMesh(@NonNull Mesh mesh, BlendMode blendMode, @NonNull Paint paint) { if (!isHardwareAccelerated() && onHwFeatureInSwMode()) { throw new RuntimeException("software rendering doesn't support meshes"); } if (blendMode == null) { blendMode = BlendMode.MODULATE; } nDrawMesh(this.mNativeCanvasWrapper, mesh.getNativeWrapperInstance(), blendMode.getXfermode().porterDuffMode, paint.getNativeInstance()); } Loading graphics/java/android/graphics/BaseRecordingCanvas.java +4 −1 Original line number Diff line number Diff line Loading @@ -607,7 +607,10 @@ public class BaseRecordingCanvas extends Canvas { } @Override public final void drawMesh(Mesh mesh, BlendMode blendMode, Paint paint) { public final void drawMesh(@NonNull Mesh mesh, BlendMode blendMode, @NonNull Paint paint) { if (blendMode == null) { blendMode = BlendMode.MODULATE; } nDrawMesh(mNativeCanvasWrapper, mesh.getNativeWrapperInstance(), blendMode.getXfermode().porterDuffMode, paint.getNativeInstance()); } Loading graphics/java/android/graphics/Mesh.java +52 −25 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.graphics; import android.annotation.IntDef; import android.annotation.NonNull; import libcore.util.NativeAllocationRegistry; import java.nio.Buffer; Loading @@ -25,8 +28,8 @@ import java.nio.ShortBuffer; * Class representing a mesh object. * * This class generates Mesh objects via the * {@link #make(MeshSpecification, Mode, Buffer, int, Rect)} and * {@link #makeIndexed(MeshSpecification, Mode, Buffer, int, ShortBuffer, Rect)} methods, * {@link #make(MeshSpecification, int, Buffer, int, Rect)} and * {@link #makeIndexed(MeshSpecification, int, Buffer, int, ShortBuffer, Rect)} methods, * where a {@link MeshSpecification} is required along with various attributes for * detailing the mesh object, including a mode, vertex buffer, optional index buffer, and bounds * for the mesh. Once generated, a mesh object can be drawn through Loading @@ -39,9 +42,20 @@ public class Mesh { private boolean mIsIndexed; /** * Enum to determine how the mesh is represented. * Determines how the mesh is represented and will be drawn. */ @IntDef({TRIANGLES, TRIANGLE_STRIP}) private @interface Mode {} /** * The mesh will be drawn with triangles without utilizing shared vertices. */ public static final int TRIANGLES = 0; /** * The mesh will be drawn with triangles utilizing shared vertices. */ public enum Mode {Triangles, TriangleStrip} public static final int TRIANGLE_STRIP = 1; private static class MeshHolder { public static final NativeAllocationRegistry MESH_SPECIFICATION_REGISTRY = Loading @@ -53,7 +67,8 @@ public class Mesh { * Generates a {@link Mesh} object. * * @param meshSpec {@link MeshSpecification} used when generating the mesh. * @param mode {@link Mode} enum * @param mode Determines what mode to draw the mesh in. Must be one of * {@link Mesh#TRIANGLES} or {@link Mesh#TRIANGLE_STRIP} * @param vertexBuffer vertex buffer representing through {@link Buffer}. This provides the data * for all attributes provided within the meshSpec for every vertex. That * is, a vertex buffer should be (attributes size * number of vertices) in Loading @@ -63,9 +78,13 @@ public class Mesh { * @param bounds bounds of the mesh object. * @return a new Mesh object. */ public static Mesh make(MeshSpecification meshSpec, Mode mode, Buffer vertexBuffer, int vertexCount, Rect bounds) { long nativeMesh = nativeMake(meshSpec.mNativeMeshSpec, mode.ordinal(), vertexBuffer, @NonNull public static Mesh make(@NonNull MeshSpecification meshSpec, @Mode int mode, @NonNull Buffer vertexBuffer, int vertexCount, @NonNull Rect bounds) { if (mode != TRIANGLES && mode != TRIANGLE_STRIP) { throw new IllegalArgumentException("Invalid value passed in for mode parameter"); } long nativeMesh = nativeMake(meshSpec.mNativeMeshSpec, mode, vertexBuffer, vertexBuffer.isDirect(), vertexCount, vertexBuffer.position(), bounds.left, bounds.top, bounds.right, bounds.bottom); if (nativeMesh == 0) { Loading @@ -78,7 +97,8 @@ public class Mesh { * Generates a {@link Mesh} object. * * @param meshSpec {@link MeshSpecification} used when generating the mesh. * @param mode {@link Mode} enum * @param mode Determines what mode to draw the mesh in. Must be one of * {@link Mesh#TRIANGLES} or {@link Mesh#TRIANGLE_STRIP} * @param vertexBuffer vertex buffer representing through {@link Buffer}. This provides the data * for all attributes provided within the meshSpec for every vertex. That * is, a vertex buffer should be (attributes size * number of vertices) in Loading @@ -92,9 +112,14 @@ public class Mesh { * @param bounds bounds of the mesh object. * @return a new Mesh object. */ public static Mesh makeIndexed(MeshSpecification meshSpec, Mode mode, Buffer vertexBuffer, int vertexCount, ShortBuffer indexBuffer, Rect bounds) { long nativeMesh = nativeMakeIndexed(meshSpec.mNativeMeshSpec, mode.ordinal(), vertexBuffer, @NonNull public static Mesh makeIndexed(@NonNull MeshSpecification meshSpec, @Mode int mode, @NonNull Buffer vertexBuffer, int vertexCount, @NonNull ShortBuffer indexBuffer, @NonNull Rect bounds) { if (mode != TRIANGLES && mode != TRIANGLE_STRIP) { throw new IllegalArgumentException("Invalid value passed in for mode parameter"); } long nativeMesh = nativeMakeIndexed(meshSpec.mNativeMeshSpec, mode, vertexBuffer, vertexBuffer.isDirect(), vertexCount, vertexBuffer.position(), indexBuffer, indexBuffer.isDirect(), indexBuffer.capacity(), indexBuffer.position(), bounds.left, bounds.top, bounds.right, bounds.bottom); Loading @@ -114,7 +139,7 @@ public class Mesh { * @param color the provided sRGB color will be converted into the shader program's output * colorspace and be available as a vec4 uniform in the program. */ public void setColorUniform(String uniformName, int color) { public void setColorUniform(@NonNull String uniformName, int color) { setUniform(uniformName, Color.valueOf(color).getComponents(), true); } Loading @@ -128,7 +153,7 @@ public class Mesh { * @param color the provided sRGB color will be converted into the shader program's output * colorspace and be available as a vec4 uniform in the program. */ public void setColorUniform(String uniformName, long color) { public void setColorUniform(@NonNull String uniformName, long color) { Color exSRGB = Color.valueOf(color).convert(ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB)); setUniform(uniformName, exSRGB.getComponents(), true); } Loading @@ -143,7 +168,7 @@ public class Mesh { * @param color the provided sRGB color will be converted into the shader program's output * colorspace and will be made available as a vec4 uniform in the program. */ public void setColorUniform(String uniformName, Color color) { public void setColorUniform(@NonNull String uniformName, @NonNull Color color) { if (color == null) { throw new NullPointerException("The color parameter must not be null"); } Loading @@ -160,7 +185,7 @@ public class Mesh { * @param uniformName name matching the float uniform declared in the shader program. * @param value float value corresponding to the float uniform with the given name. */ public void setFloatUniform(String uniformName, float value) { public void setFloatUniform(@NonNull String uniformName, float value) { setFloatUniform(uniformName, value, 0.0f, 0.0f, 0.0f, 1); } Loading @@ -173,7 +198,7 @@ public class Mesh { * @param value1 first float value corresponding to the float uniform with the given name. * @param value2 second float value corresponding to the float uniform with the given name. */ public void setFloatUniform(String uniformName, float value1, float value2) { public void setFloatUniform(@NonNull String uniformName, float value1, float value2) { setFloatUniform(uniformName, value1, value2, 0.0f, 0.0f, 2); } Loading @@ -188,7 +213,8 @@ public class Mesh { * @param value3 third float value corresponding to the float unifiform with the given * name. */ public void setFloatUniform(String uniformName, float value1, float value2, float value3) { public void setFloatUniform( @NonNull String uniformName, float value1, float value2, float value3) { setFloatUniform(uniformName, value1, value2, value3, 0.0f, 3); } Loading @@ -204,7 +230,7 @@ public class Mesh { * @param value4 fourth float value corresponding to the float uniform with the given name. */ public void setFloatUniform( String uniformName, float value1, float value2, float value3, float value4) { @NonNull String uniformName, float value1, float value2, float value3, float value4) { setFloatUniform(uniformName, value1, value2, value3, value4, 4); } Loading @@ -217,7 +243,7 @@ public class Mesh { * @param uniformName name matching the float uniform declared in the shader program. * @param values float value corresponding to the vec4 float uniform with the given name. */ public void setFloatUniform(String uniformName, float[] values) { public void setFloatUniform(@NonNull String uniformName, @NonNull float[] values) { setUniform(uniformName, values, false); } Loading Loading @@ -249,7 +275,7 @@ public class Mesh { * @param uniformName name matching the int uniform delcared in the shader program. * @param value value corresponding to the int uniform with the given name. */ public void setIntUniform(String uniformName, int value) { public void setIntUniform(@NonNull String uniformName, int value) { setIntUniform(uniformName, value, 0, 0, 0, 1); } Loading @@ -262,7 +288,7 @@ public class Mesh { * @param value1 first value corresponding to the int uniform with the given name. * @param value2 second value corresponding to the int uniform with the given name. */ public void setIntUniform(String uniformName, int value1, int value2) { public void setIntUniform(@NonNull String uniformName, int value1, int value2) { setIntUniform(uniformName, value1, value2, 0, 0, 2); } Loading @@ -276,7 +302,7 @@ public class Mesh { * @param value2 second value corresponding to the int uniform with the given name. * @param value3 third value corresponding to the int uniform with the given name. */ public void setIntUniform(String uniformName, int value1, int value2, int value3) { public void setIntUniform(@NonNull String uniformName, int value1, int value2, int value3) { setIntUniform(uniformName, value1, value2, value3, 0, 3); } Loading @@ -291,7 +317,8 @@ public class Mesh { * @param value3 third value corresponding to the int uniform with the given name. * @param value4 fourth value corresponding to the int uniform with the given name. */ public void setIntUniform(String uniformName, int value1, int value2, int value3, int value4) { public void setIntUniform( @NonNull String uniformName, int value1, int value2, int value3, int value4) { setIntUniform(uniformName, value1, value2, value3, value4, 4); } Loading @@ -304,7 +331,7 @@ public class Mesh { * @param uniformName name matching the int uniform delcared in the shader program. * @param values int values corresponding to the vec4 int uniform with the given name. */ public void setIntUniform(String uniformName, int[] values) { public void setIntUniform(@NonNull String uniformName, @NonNull int[] values) { if (uniformName == null) { throw new NullPointerException("The uniformName parameter must not be null"); } Loading graphics/java/android/graphics/MeshSpecification.java +35 −20 Original line number Diff line number Diff line Loading @@ -17,15 +17,18 @@ package android.graphics; import android.annotation.IntDef; import android.annotation.NonNull; import libcore.util.NativeAllocationRegistry; import java.util.List; /** * 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 {@link AlphaType}. * {@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. Loading @@ -42,12 +45,11 @@ public class MeshSpecification { long mNativeMeshSpec; /** * Constants for {@link #make(Attribute[], int, Varying[], String, String, ColorSpace, int)} * Constants for {@link #make(List, int, List, String, String)} * to determine alpha type. Describes how to interpret the alpha component of a pixel. */ @IntDef({UNKNOWN, OPAQUE, PREMUL, UNPREMULT}) public @interface AlphaType { } private @interface AlphaType {} /** * uninitialized. Loading @@ -73,8 +75,7 @@ public class MeshSpecification { * Constants for {@link Attribute} and {@link Varying} for determining the data type. */ @IntDef({FLOAT, FLOAT2, FLOAT3, FLOAT4, UBYTE4}) public @interface Type { } private @interface Type {} /** * Represents one float. Its equivalent shader type is float. Loading Loading @@ -118,7 +119,7 @@ public class MeshSpecification { private int mOffset; private String mName; public Attribute(@Type int type, int offset, String name) { public Attribute(@Type int type, int offset, @NonNull String name) { mType = type; mOffset = offset; mName = name; Loading @@ -134,7 +135,7 @@ public class MeshSpecification { private int mType; private String mName; public Varying(@Type int type, String name) { public Varying(@Type int type, @NonNull String name) { mType = type; mName = name; } Loading Loading @@ -162,10 +163,13 @@ public class MeshSpecification { * @param fragmentShader fragment shader to be supplied 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); @NonNull public static MeshSpecification make(@NonNull List<Attribute> attributes, int vertexStride, @NonNull List<Varying> varyings, @NonNull String vertexShader, @NonNull String fragmentShader) { long nativeMeshSpec = nativeMake(attributes.toArray(new Attribute[attributes.size()]), vertexStride, varyings.toArray(new Varying[varyings.size()]), vertexShader, fragmentShader); if (nativeMeshSpec == 0) { throw new IllegalArgumentException("MeshSpecification construction failed"); } Loading @@ -189,9 +193,12 @@ public class MeshSpecification { * @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, @NonNull public static MeshSpecification make(@NonNull List<Attribute> attributes, int vertexStride, @NonNull List<Varying> varyings, @NonNull String vertexShader, @NonNull String fragmentShader, @NonNull ColorSpace colorSpace) { long nativeMeshSpec = nativeMakeWithCS(attributes.toArray(new Attribute[attributes.size()]), vertexStride, varyings.toArray(new Varying[varyings.size()]), vertexShader, fragmentShader, colorSpace.getNativeInstance()); if (nativeMeshSpec == 0) { throw new IllegalArgumentException("MeshSpecification construction failed"); Loading @@ -215,13 +222,21 @@ public class MeshSpecification { * @param fragmentShader fragment shader to be supplied 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. * one of * {@link MeshSpecification#UNKNOWN}, * {@link MeshSpecification#OPAQUE}, * {@link MeshSpecification#PREMUL}, or * {@link MeshSpecification#UNPREMULT} * @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, @NonNull public static MeshSpecification make(@NonNull List<Attribute> attributes, int vertexStride, @NonNull List<Varying> varyings, @NonNull String vertexShader, @NonNull String fragmentShader, @NonNull ColorSpace colorSpace, @AlphaType int alphaType) { long nativeMeshSpec = nativeMakeWithAlpha(attributes, vertexStride, varyings, vertexShader, long nativeMeshSpec = nativeMakeWithAlpha(attributes.toArray(new Attribute[attributes.size()]), vertexStride, varyings.toArray(new Varying[varyings.size()]), vertexShader, fragmentShader, colorSpace.getNativeInstance(), alphaType); if (nativeMeshSpec == 0) { throw new IllegalArgumentException("MeshSpecification construction failed"); Loading libs/hwui/jni/Mesh.cpp +35 −22 Original line number Diff line number Diff line Loading @@ -44,10 +44,16 @@ static jlong make(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobject verte sk_sp<SkMesh::VertexBuffer> skVertexBuffer = genVertexBuffer(env, vertexBuffer, vertexCount * skMeshSpec->stride(), isDirect); auto skRect = SkRect::MakeLTRB(left, top, right, bottom); auto mesh = SkMesh::Make(skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset, nullptr, skRect) .mesh; auto meshPtr = std::make_unique<MeshWrapper>(MeshWrapper{mesh, MeshUniformBuilder(skMeshSpec)}); auto meshResult = SkMesh::Make( skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset, SkData::MakeWithCopy(skMeshSpec->uniforms().data(), skMeshSpec->uniformSize()), skRect); if (!meshResult.error.isEmpty()) { jniThrowException(env, "java/lang/IllegalArgumentException", meshResult.error.c_str()); } auto meshPtr = std::make_unique<MeshWrapper>( MeshWrapper{meshResult.mesh, MeshUniformBuilder(skMeshSpec)}); return reinterpret_cast<jlong>(meshPtr.release()); } Loading @@ -61,11 +67,17 @@ static jlong makeIndexed(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobjec sk_sp<SkMesh::IndexBuffer> skIndexBuffer = genIndexBuffer(env, indexBuffer, indexCount * gIndexByteSize, isIndexDirect); auto skRect = SkRect::MakeLTRB(left, top, right, bottom); auto mesh = SkMesh::MakeIndexed(skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset, skIndexBuffer, indexCount, indexOffset, nullptr, skRect) .mesh; auto meshPtr = std::make_unique<MeshWrapper>(MeshWrapper{mesh, MeshUniformBuilder(skMeshSpec)}); auto meshResult = SkMesh::MakeIndexed( skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset, skIndexBuffer, indexCount, indexOffset, SkData::MakeWithCopy(skMeshSpec->uniforms().data(), skMeshSpec->uniformSize()), skRect); if (!meshResult.error.isEmpty()) { jniThrowException(env, "java/lang/IllegalArgumentException", meshResult.error.c_str()); } auto meshPtr = std::make_unique<MeshWrapper>( MeshWrapper{meshResult.mesh, MeshUniformBuilder(skMeshSpec)}); return reinterpret_cast<jlong>(meshPtr.release()); } Loading Loading @@ -139,22 +151,22 @@ static void nativeUpdateFloatUniforms(JNIEnv* env, MeshUniformBuilder* builder, } } static void updateFloatUniforms(JNIEnv* env, jobject, jlong uniBuilder, jstring uniformName, static void updateFloatUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName, jfloat value1, jfloat value2, jfloat value3, jfloat value4, jint count) { auto* builder = reinterpret_cast<MeshUniformBuilder*>(uniBuilder); auto* wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper); ScopedUtfChars name(env, uniformName); const float values[4] = {value1, value2, value3, value4}; nativeUpdateFloatUniforms(env, builder, name.c_str(), values, count, false); nativeUpdateFloatUniforms(env, &wrapper->builder, name.c_str(), values, count, false); } static void updateFloatArrayUniforms(JNIEnv* env, jobject, jlong uniBuilder, jstring jUniformName, static void updateFloatArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring jUniformName, jfloatArray jvalues, jboolean isColor) { auto builder = reinterpret_cast<MeshUniformBuilder*>(uniBuilder); auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper); ScopedUtfChars name(env, jUniformName); AutoJavaFloatArray autoValues(env, jvalues, 0, kRO_JNIAccess); nativeUpdateFloatUniforms(env, builder, name.c_str(), autoValues.ptr(), autoValues.length(), isColor); nativeUpdateFloatUniforms(env, &wrapper->builder, name.c_str(), autoValues.ptr(), autoValues.length(), isColor); } static void nativeUpdateIntUniforms(JNIEnv* env, MeshUniformBuilder* builder, Loading @@ -171,20 +183,21 @@ static void nativeUpdateIntUniforms(JNIEnv* env, MeshUniformBuilder* builder, } } static void updateIntUniforms(JNIEnv* env, jobject, jlong uniBuilder, jstring uniformName, static void updateIntUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName, jint value1, jint value2, jint value3, jint value4, jint count) { auto builder = reinterpret_cast<MeshUniformBuilder*>(uniBuilder); auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper); ScopedUtfChars name(env, uniformName); const int values[4] = {value1, value2, value3, value4}; nativeUpdateIntUniforms(env, builder, name.c_str(), values, count); nativeUpdateIntUniforms(env, &wrapper->builder, name.c_str(), values, count); } static void updateIntArrayUniforms(JNIEnv* env, jobject, jlong uniBuilder, jstring uniformName, static void updateIntArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName, jintArray values) { auto builder = reinterpret_cast<MeshUniformBuilder*>(uniBuilder); auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper); ScopedUtfChars name(env, uniformName); AutoJavaIntArray autoValues(env, values, 0); nativeUpdateIntUniforms(env, builder, name.c_str(), autoValues.ptr(), autoValues.length()); nativeUpdateIntUniforms(env, &wrapper->builder, name.c_str(), autoValues.ptr(), autoValues.length()); } static void MeshWrapper_destroy(MeshWrapper* wrapper) { Loading Loading
graphics/java/android/graphics/BaseCanvas.java +10 −1 Original line number Diff line number Diff line Loading @@ -668,12 +668,21 @@ public abstract class BaseCanvas { } /** * Draws a mesh object to the screen. * * @param mesh {@link Mesh} object that will be drawn to the screen * @param blendMode {@link BlendMode} used to blend mesh primitives with the Paint color/shader * @param paint {@link Paint} used to provide a color/shader/blend mode. * * @hide */ public void drawMesh(Mesh mesh, BlendMode blendMode, Paint paint) { public void drawMesh(@NonNull Mesh mesh, BlendMode blendMode, @NonNull Paint paint) { if (!isHardwareAccelerated() && onHwFeatureInSwMode()) { throw new RuntimeException("software rendering doesn't support meshes"); } if (blendMode == null) { blendMode = BlendMode.MODULATE; } nDrawMesh(this.mNativeCanvasWrapper, mesh.getNativeWrapperInstance(), blendMode.getXfermode().porterDuffMode, paint.getNativeInstance()); } Loading
graphics/java/android/graphics/BaseRecordingCanvas.java +4 −1 Original line number Diff line number Diff line Loading @@ -607,7 +607,10 @@ public class BaseRecordingCanvas extends Canvas { } @Override public final void drawMesh(Mesh mesh, BlendMode blendMode, Paint paint) { public final void drawMesh(@NonNull Mesh mesh, BlendMode blendMode, @NonNull Paint paint) { if (blendMode == null) { blendMode = BlendMode.MODULATE; } nDrawMesh(mNativeCanvasWrapper, mesh.getNativeWrapperInstance(), blendMode.getXfermode().porterDuffMode, paint.getNativeInstance()); } Loading
graphics/java/android/graphics/Mesh.java +52 −25 Original line number Diff line number Diff line Loading @@ -16,6 +16,9 @@ package android.graphics; import android.annotation.IntDef; import android.annotation.NonNull; import libcore.util.NativeAllocationRegistry; import java.nio.Buffer; Loading @@ -25,8 +28,8 @@ import java.nio.ShortBuffer; * Class representing a mesh object. * * This class generates Mesh objects via the * {@link #make(MeshSpecification, Mode, Buffer, int, Rect)} and * {@link #makeIndexed(MeshSpecification, Mode, Buffer, int, ShortBuffer, Rect)} methods, * {@link #make(MeshSpecification, int, Buffer, int, Rect)} and * {@link #makeIndexed(MeshSpecification, int, Buffer, int, ShortBuffer, Rect)} methods, * where a {@link MeshSpecification} is required along with various attributes for * detailing the mesh object, including a mode, vertex buffer, optional index buffer, and bounds * for the mesh. Once generated, a mesh object can be drawn through Loading @@ -39,9 +42,20 @@ public class Mesh { private boolean mIsIndexed; /** * Enum to determine how the mesh is represented. * Determines how the mesh is represented and will be drawn. */ @IntDef({TRIANGLES, TRIANGLE_STRIP}) private @interface Mode {} /** * The mesh will be drawn with triangles without utilizing shared vertices. */ public static final int TRIANGLES = 0; /** * The mesh will be drawn with triangles utilizing shared vertices. */ public enum Mode {Triangles, TriangleStrip} public static final int TRIANGLE_STRIP = 1; private static class MeshHolder { public static final NativeAllocationRegistry MESH_SPECIFICATION_REGISTRY = Loading @@ -53,7 +67,8 @@ public class Mesh { * Generates a {@link Mesh} object. * * @param meshSpec {@link MeshSpecification} used when generating the mesh. * @param mode {@link Mode} enum * @param mode Determines what mode to draw the mesh in. Must be one of * {@link Mesh#TRIANGLES} or {@link Mesh#TRIANGLE_STRIP} * @param vertexBuffer vertex buffer representing through {@link Buffer}. This provides the data * for all attributes provided within the meshSpec for every vertex. That * is, a vertex buffer should be (attributes size * number of vertices) in Loading @@ -63,9 +78,13 @@ public class Mesh { * @param bounds bounds of the mesh object. * @return a new Mesh object. */ public static Mesh make(MeshSpecification meshSpec, Mode mode, Buffer vertexBuffer, int vertexCount, Rect bounds) { long nativeMesh = nativeMake(meshSpec.mNativeMeshSpec, mode.ordinal(), vertexBuffer, @NonNull public static Mesh make(@NonNull MeshSpecification meshSpec, @Mode int mode, @NonNull Buffer vertexBuffer, int vertexCount, @NonNull Rect bounds) { if (mode != TRIANGLES && mode != TRIANGLE_STRIP) { throw new IllegalArgumentException("Invalid value passed in for mode parameter"); } long nativeMesh = nativeMake(meshSpec.mNativeMeshSpec, mode, vertexBuffer, vertexBuffer.isDirect(), vertexCount, vertexBuffer.position(), bounds.left, bounds.top, bounds.right, bounds.bottom); if (nativeMesh == 0) { Loading @@ -78,7 +97,8 @@ public class Mesh { * Generates a {@link Mesh} object. * * @param meshSpec {@link MeshSpecification} used when generating the mesh. * @param mode {@link Mode} enum * @param mode Determines what mode to draw the mesh in. Must be one of * {@link Mesh#TRIANGLES} or {@link Mesh#TRIANGLE_STRIP} * @param vertexBuffer vertex buffer representing through {@link Buffer}. This provides the data * for all attributes provided within the meshSpec for every vertex. That * is, a vertex buffer should be (attributes size * number of vertices) in Loading @@ -92,9 +112,14 @@ public class Mesh { * @param bounds bounds of the mesh object. * @return a new Mesh object. */ public static Mesh makeIndexed(MeshSpecification meshSpec, Mode mode, Buffer vertexBuffer, int vertexCount, ShortBuffer indexBuffer, Rect bounds) { long nativeMesh = nativeMakeIndexed(meshSpec.mNativeMeshSpec, mode.ordinal(), vertexBuffer, @NonNull public static Mesh makeIndexed(@NonNull MeshSpecification meshSpec, @Mode int mode, @NonNull Buffer vertexBuffer, int vertexCount, @NonNull ShortBuffer indexBuffer, @NonNull Rect bounds) { if (mode != TRIANGLES && mode != TRIANGLE_STRIP) { throw new IllegalArgumentException("Invalid value passed in for mode parameter"); } long nativeMesh = nativeMakeIndexed(meshSpec.mNativeMeshSpec, mode, vertexBuffer, vertexBuffer.isDirect(), vertexCount, vertexBuffer.position(), indexBuffer, indexBuffer.isDirect(), indexBuffer.capacity(), indexBuffer.position(), bounds.left, bounds.top, bounds.right, bounds.bottom); Loading @@ -114,7 +139,7 @@ public class Mesh { * @param color the provided sRGB color will be converted into the shader program's output * colorspace and be available as a vec4 uniform in the program. */ public void setColorUniform(String uniformName, int color) { public void setColorUniform(@NonNull String uniformName, int color) { setUniform(uniformName, Color.valueOf(color).getComponents(), true); } Loading @@ -128,7 +153,7 @@ public class Mesh { * @param color the provided sRGB color will be converted into the shader program's output * colorspace and be available as a vec4 uniform in the program. */ public void setColorUniform(String uniformName, long color) { public void setColorUniform(@NonNull String uniformName, long color) { Color exSRGB = Color.valueOf(color).convert(ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB)); setUniform(uniformName, exSRGB.getComponents(), true); } Loading @@ -143,7 +168,7 @@ public class Mesh { * @param color the provided sRGB color will be converted into the shader program's output * colorspace and will be made available as a vec4 uniform in the program. */ public void setColorUniform(String uniformName, Color color) { public void setColorUniform(@NonNull String uniformName, @NonNull Color color) { if (color == null) { throw new NullPointerException("The color parameter must not be null"); } Loading @@ -160,7 +185,7 @@ public class Mesh { * @param uniformName name matching the float uniform declared in the shader program. * @param value float value corresponding to the float uniform with the given name. */ public void setFloatUniform(String uniformName, float value) { public void setFloatUniform(@NonNull String uniformName, float value) { setFloatUniform(uniformName, value, 0.0f, 0.0f, 0.0f, 1); } Loading @@ -173,7 +198,7 @@ public class Mesh { * @param value1 first float value corresponding to the float uniform with the given name. * @param value2 second float value corresponding to the float uniform with the given name. */ public void setFloatUniform(String uniformName, float value1, float value2) { public void setFloatUniform(@NonNull String uniformName, float value1, float value2) { setFloatUniform(uniformName, value1, value2, 0.0f, 0.0f, 2); } Loading @@ -188,7 +213,8 @@ public class Mesh { * @param value3 third float value corresponding to the float unifiform with the given * name. */ public void setFloatUniform(String uniformName, float value1, float value2, float value3) { public void setFloatUniform( @NonNull String uniformName, float value1, float value2, float value3) { setFloatUniform(uniformName, value1, value2, value3, 0.0f, 3); } Loading @@ -204,7 +230,7 @@ public class Mesh { * @param value4 fourth float value corresponding to the float uniform with the given name. */ public void setFloatUniform( String uniformName, float value1, float value2, float value3, float value4) { @NonNull String uniformName, float value1, float value2, float value3, float value4) { setFloatUniform(uniformName, value1, value2, value3, value4, 4); } Loading @@ -217,7 +243,7 @@ public class Mesh { * @param uniformName name matching the float uniform declared in the shader program. * @param values float value corresponding to the vec4 float uniform with the given name. */ public void setFloatUniform(String uniformName, float[] values) { public void setFloatUniform(@NonNull String uniformName, @NonNull float[] values) { setUniform(uniformName, values, false); } Loading Loading @@ -249,7 +275,7 @@ public class Mesh { * @param uniformName name matching the int uniform delcared in the shader program. * @param value value corresponding to the int uniform with the given name. */ public void setIntUniform(String uniformName, int value) { public void setIntUniform(@NonNull String uniformName, int value) { setIntUniform(uniformName, value, 0, 0, 0, 1); } Loading @@ -262,7 +288,7 @@ public class Mesh { * @param value1 first value corresponding to the int uniform with the given name. * @param value2 second value corresponding to the int uniform with the given name. */ public void setIntUniform(String uniformName, int value1, int value2) { public void setIntUniform(@NonNull String uniformName, int value1, int value2) { setIntUniform(uniformName, value1, value2, 0, 0, 2); } Loading @@ -276,7 +302,7 @@ public class Mesh { * @param value2 second value corresponding to the int uniform with the given name. * @param value3 third value corresponding to the int uniform with the given name. */ public void setIntUniform(String uniformName, int value1, int value2, int value3) { public void setIntUniform(@NonNull String uniformName, int value1, int value2, int value3) { setIntUniform(uniformName, value1, value2, value3, 0, 3); } Loading @@ -291,7 +317,8 @@ public class Mesh { * @param value3 third value corresponding to the int uniform with the given name. * @param value4 fourth value corresponding to the int uniform with the given name. */ public void setIntUniform(String uniformName, int value1, int value2, int value3, int value4) { public void setIntUniform( @NonNull String uniformName, int value1, int value2, int value3, int value4) { setIntUniform(uniformName, value1, value2, value3, value4, 4); } Loading @@ -304,7 +331,7 @@ public class Mesh { * @param uniformName name matching the int uniform delcared in the shader program. * @param values int values corresponding to the vec4 int uniform with the given name. */ public void setIntUniform(String uniformName, int[] values) { public void setIntUniform(@NonNull String uniformName, @NonNull int[] values) { if (uniformName == null) { throw new NullPointerException("The uniformName parameter must not be null"); } Loading
graphics/java/android/graphics/MeshSpecification.java +35 −20 Original line number Diff line number Diff line Loading @@ -17,15 +17,18 @@ package android.graphics; import android.annotation.IntDef; import android.annotation.NonNull; import libcore.util.NativeAllocationRegistry; import java.util.List; /** * 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 {@link AlphaType}. * {@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. Loading @@ -42,12 +45,11 @@ public class MeshSpecification { long mNativeMeshSpec; /** * Constants for {@link #make(Attribute[], int, Varying[], String, String, ColorSpace, int)} * Constants for {@link #make(List, int, List, String, String)} * to determine alpha type. Describes how to interpret the alpha component of a pixel. */ @IntDef({UNKNOWN, OPAQUE, PREMUL, UNPREMULT}) public @interface AlphaType { } private @interface AlphaType {} /** * uninitialized. Loading @@ -73,8 +75,7 @@ public class MeshSpecification { * Constants for {@link Attribute} and {@link Varying} for determining the data type. */ @IntDef({FLOAT, FLOAT2, FLOAT3, FLOAT4, UBYTE4}) public @interface Type { } private @interface Type {} /** * Represents one float. Its equivalent shader type is float. Loading Loading @@ -118,7 +119,7 @@ public class MeshSpecification { private int mOffset; private String mName; public Attribute(@Type int type, int offset, String name) { public Attribute(@Type int type, int offset, @NonNull String name) { mType = type; mOffset = offset; mName = name; Loading @@ -134,7 +135,7 @@ public class MeshSpecification { private int mType; private String mName; public Varying(@Type int type, String name) { public Varying(@Type int type, @NonNull String name) { mType = type; mName = name; } Loading Loading @@ -162,10 +163,13 @@ public class MeshSpecification { * @param fragmentShader fragment shader to be supplied 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); @NonNull public static MeshSpecification make(@NonNull List<Attribute> attributes, int vertexStride, @NonNull List<Varying> varyings, @NonNull String vertexShader, @NonNull String fragmentShader) { long nativeMeshSpec = nativeMake(attributes.toArray(new Attribute[attributes.size()]), vertexStride, varyings.toArray(new Varying[varyings.size()]), vertexShader, fragmentShader); if (nativeMeshSpec == 0) { throw new IllegalArgumentException("MeshSpecification construction failed"); } Loading @@ -189,9 +193,12 @@ public class MeshSpecification { * @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, @NonNull public static MeshSpecification make(@NonNull List<Attribute> attributes, int vertexStride, @NonNull List<Varying> varyings, @NonNull String vertexShader, @NonNull String fragmentShader, @NonNull ColorSpace colorSpace) { long nativeMeshSpec = nativeMakeWithCS(attributes.toArray(new Attribute[attributes.size()]), vertexStride, varyings.toArray(new Varying[varyings.size()]), vertexShader, fragmentShader, colorSpace.getNativeInstance()); if (nativeMeshSpec == 0) { throw new IllegalArgumentException("MeshSpecification construction failed"); Loading @@ -215,13 +222,21 @@ public class MeshSpecification { * @param fragmentShader fragment shader to be supplied 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. * one of * {@link MeshSpecification#UNKNOWN}, * {@link MeshSpecification#OPAQUE}, * {@link MeshSpecification#PREMUL}, or * {@link MeshSpecification#UNPREMULT} * @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, @NonNull public static MeshSpecification make(@NonNull List<Attribute> attributes, int vertexStride, @NonNull List<Varying> varyings, @NonNull String vertexShader, @NonNull String fragmentShader, @NonNull ColorSpace colorSpace, @AlphaType int alphaType) { long nativeMeshSpec = nativeMakeWithAlpha(attributes, vertexStride, varyings, vertexShader, long nativeMeshSpec = nativeMakeWithAlpha(attributes.toArray(new Attribute[attributes.size()]), vertexStride, varyings.toArray(new Varying[varyings.size()]), vertexShader, fragmentShader, colorSpace.getNativeInstance(), alphaType); if (nativeMeshSpec == 0) { throw new IllegalArgumentException("MeshSpecification construction failed"); Loading
libs/hwui/jni/Mesh.cpp +35 −22 Original line number Diff line number Diff line Loading @@ -44,10 +44,16 @@ static jlong make(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobject verte sk_sp<SkMesh::VertexBuffer> skVertexBuffer = genVertexBuffer(env, vertexBuffer, vertexCount * skMeshSpec->stride(), isDirect); auto skRect = SkRect::MakeLTRB(left, top, right, bottom); auto mesh = SkMesh::Make(skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset, nullptr, skRect) .mesh; auto meshPtr = std::make_unique<MeshWrapper>(MeshWrapper{mesh, MeshUniformBuilder(skMeshSpec)}); auto meshResult = SkMesh::Make( skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset, SkData::MakeWithCopy(skMeshSpec->uniforms().data(), skMeshSpec->uniformSize()), skRect); if (!meshResult.error.isEmpty()) { jniThrowException(env, "java/lang/IllegalArgumentException", meshResult.error.c_str()); } auto meshPtr = std::make_unique<MeshWrapper>( MeshWrapper{meshResult.mesh, MeshUniformBuilder(skMeshSpec)}); return reinterpret_cast<jlong>(meshPtr.release()); } Loading @@ -61,11 +67,17 @@ static jlong makeIndexed(JNIEnv* env, jobject, jlong meshSpec, jint mode, jobjec sk_sp<SkMesh::IndexBuffer> skIndexBuffer = genIndexBuffer(env, indexBuffer, indexCount * gIndexByteSize, isIndexDirect); auto skRect = SkRect::MakeLTRB(left, top, right, bottom); auto mesh = SkMesh::MakeIndexed(skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset, skIndexBuffer, indexCount, indexOffset, nullptr, skRect) .mesh; auto meshPtr = std::make_unique<MeshWrapper>(MeshWrapper{mesh, MeshUniformBuilder(skMeshSpec)}); auto meshResult = SkMesh::MakeIndexed( skMeshSpec, SkMesh::Mode(mode), skVertexBuffer, vertexCount, vertexOffset, skIndexBuffer, indexCount, indexOffset, SkData::MakeWithCopy(skMeshSpec->uniforms().data(), skMeshSpec->uniformSize()), skRect); if (!meshResult.error.isEmpty()) { jniThrowException(env, "java/lang/IllegalArgumentException", meshResult.error.c_str()); } auto meshPtr = std::make_unique<MeshWrapper>( MeshWrapper{meshResult.mesh, MeshUniformBuilder(skMeshSpec)}); return reinterpret_cast<jlong>(meshPtr.release()); } Loading Loading @@ -139,22 +151,22 @@ static void nativeUpdateFloatUniforms(JNIEnv* env, MeshUniformBuilder* builder, } } static void updateFloatUniforms(JNIEnv* env, jobject, jlong uniBuilder, jstring uniformName, static void updateFloatUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName, jfloat value1, jfloat value2, jfloat value3, jfloat value4, jint count) { auto* builder = reinterpret_cast<MeshUniformBuilder*>(uniBuilder); auto* wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper); ScopedUtfChars name(env, uniformName); const float values[4] = {value1, value2, value3, value4}; nativeUpdateFloatUniforms(env, builder, name.c_str(), values, count, false); nativeUpdateFloatUniforms(env, &wrapper->builder, name.c_str(), values, count, false); } static void updateFloatArrayUniforms(JNIEnv* env, jobject, jlong uniBuilder, jstring jUniformName, static void updateFloatArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring jUniformName, jfloatArray jvalues, jboolean isColor) { auto builder = reinterpret_cast<MeshUniformBuilder*>(uniBuilder); auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper); ScopedUtfChars name(env, jUniformName); AutoJavaFloatArray autoValues(env, jvalues, 0, kRO_JNIAccess); nativeUpdateFloatUniforms(env, builder, name.c_str(), autoValues.ptr(), autoValues.length(), isColor); nativeUpdateFloatUniforms(env, &wrapper->builder, name.c_str(), autoValues.ptr(), autoValues.length(), isColor); } static void nativeUpdateIntUniforms(JNIEnv* env, MeshUniformBuilder* builder, Loading @@ -171,20 +183,21 @@ static void nativeUpdateIntUniforms(JNIEnv* env, MeshUniformBuilder* builder, } } static void updateIntUniforms(JNIEnv* env, jobject, jlong uniBuilder, jstring uniformName, static void updateIntUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName, jint value1, jint value2, jint value3, jint value4, jint count) { auto builder = reinterpret_cast<MeshUniformBuilder*>(uniBuilder); auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper); ScopedUtfChars name(env, uniformName); const int values[4] = {value1, value2, value3, value4}; nativeUpdateIntUniforms(env, builder, name.c_str(), values, count); nativeUpdateIntUniforms(env, &wrapper->builder, name.c_str(), values, count); } static void updateIntArrayUniforms(JNIEnv* env, jobject, jlong uniBuilder, jstring uniformName, static void updateIntArrayUniforms(JNIEnv* env, jobject, jlong meshWrapper, jstring uniformName, jintArray values) { auto builder = reinterpret_cast<MeshUniformBuilder*>(uniBuilder); auto wrapper = reinterpret_cast<MeshWrapper*>(meshWrapper); ScopedUtfChars name(env, uniformName); AutoJavaIntArray autoValues(env, values, 0); nativeUpdateIntUniforms(env, builder, name.c_str(), autoValues.ptr(), autoValues.length()); nativeUpdateIntUniforms(env, &wrapper->builder, name.c_str(), autoValues.ptr(), autoValues.length()); } static void MeshWrapper_destroy(MeshWrapper* wrapper) { Loading