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