1 /* 2 * Copyright 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.graphics; 18 19 import android.annotation.NonNull; 20 21 import libcore.util.NativeAllocationRegistry; 22 23 /** 24 * Shader that calculates pixel output with a program (fragment shader) running on a GPU. 25 * @hide 26 */ 27 public class RuntimeShader extends Shader { 28 29 private static class NoImagePreloadHolder { 30 public static final NativeAllocationRegistry sRegistry = 31 NativeAllocationRegistry.createMalloced( 32 RuntimeShader.class.getClassLoader(), nativeGetFinalizer()); 33 } 34 35 private boolean mIsOpaque; 36 37 /** 38 * Current native shader builder instance. 39 */ 40 private long mNativeInstanceRuntimeShaderBuilder; 41 42 /** 43 * Creates a new RuntimeShader. 44 * 45 * @param sksl The text of SKSL program to run on the GPU. 46 * @param uniforms Array of parameters passed by the SKSL shader. Array size depends 47 * on number of uniforms declared by sksl. 48 * @param isOpaque True if all pixels have alpha 1.0f. 49 */ RuntimeShader(@onNull String sksl, boolean isOpaque)50 public RuntimeShader(@NonNull String sksl, boolean isOpaque) { 51 super(ColorSpace.get(ColorSpace.Named.SRGB)); 52 mIsOpaque = isOpaque; 53 mNativeInstanceRuntimeShaderBuilder = nativeCreateBuilder(sksl); 54 NoImagePreloadHolder.sRegistry.registerNativeAllocation( 55 this, mNativeInstanceRuntimeShaderBuilder); 56 } 57 58 /** 59 * Sets the uniform value corresponding to this shader. If the shader does not have a uniform 60 * with that name or if the uniform is declared with a type other than float then an 61 * IllegalArgumentException is thrown. 62 * 63 * @param uniformName name matching the uniform declared in the SKSL shader 64 * @param value 65 */ setUniform(@onNull String uniformName, float value)66 public void setUniform(@NonNull String uniformName, float value) { 67 setUniform(uniformName, new float[] {value}); 68 } 69 70 /** 71 * Sets the uniform value corresponding to this shader. If the shader does not have a uniform 72 * with that name or if the uniform is declared with a type other than float2/vec2 then an 73 * IllegalArgumentException is thrown. 74 * 75 * @param uniformName name matching the uniform declared in the SKSL shader 76 * @param value1 77 * @param value2 78 */ setUniform(@onNull String uniformName, float value1, float value2)79 public void setUniform(@NonNull String uniformName, float value1, float value2) { 80 setUniform(uniformName, new float[] {value1, value2}); 81 } 82 83 /** 84 * Sets the uniform value corresponding to this shader. If the shader does not have a uniform 85 * with that name or if the uniform is declared with a type other than a vecN/floatN where N is 86 * the size of the values array then an IllegalArgumentException is thrown. 87 * 88 * @param uniformName name matching the uniform declared in the SKSL shader 89 * @param values 90 */ setUniform(@onNull String uniformName, float[] values)91 public void setUniform(@NonNull String uniformName, float[] values) { 92 nativeUpdateUniforms(mNativeInstanceRuntimeShaderBuilder, uniformName, values); 93 discardNativeInstance(); 94 } 95 96 /** 97 * Sets the uniform shader that is declares as input to this shader. If the shader does not 98 * have a uniform shader with that name then an IllegalArgumentException is thrown. 99 * 100 * @param shaderName name matching the uniform declared in the SKSL shader 101 * @param shader shader passed into the SKSL shader for sampling 102 */ setInputShader(@onNull String shaderName, @NonNull Shader shader)103 public void setInputShader(@NonNull String shaderName, @NonNull Shader shader) { 104 nativeUpdateShader( 105 mNativeInstanceRuntimeShaderBuilder, shaderName, shader.getNativeInstance()); 106 discardNativeInstance(); 107 } 108 109 /** @hide */ 110 @Override createNativeInstance(long nativeMatrix, boolean filterFromPaint)111 protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) { 112 return nativeCreateShader(mNativeInstanceRuntimeShaderBuilder, nativeMatrix, mIsOpaque); 113 } 114 getNativeShaderBuilder()115 public long getNativeShaderBuilder() { 116 return mNativeInstanceRuntimeShaderBuilder; 117 } 118 isOpaque()119 public boolean isOpaque() { 120 return mIsOpaque; 121 } 122 nativeGetFinalizer()123 private static native long nativeGetFinalizer(); nativeCreateBuilder(String sksl)124 private static native long nativeCreateBuilder(String sksl); nativeCreateShader( long shaderBuilder, long matrix, boolean isOpaque)125 private static native long nativeCreateShader( 126 long shaderBuilder, long matrix, boolean isOpaque); nativeUpdateUniforms( long shaderBuilder, String uniformName, float[] uniforms)127 private static native void nativeUpdateUniforms( 128 long shaderBuilder, String uniformName, float[] uniforms); nativeUpdateShader( long shaderBuilder, String shaderName, long shader)129 private static native void nativeUpdateShader( 130 long shaderBuilder, String shaderName, long shader); 131 } 132 133