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.ColorInt;
20 import android.annotation.ColorLong;
21 import android.annotation.NonNull;
22 import android.util.ArrayMap;
23 import android.view.Window;
24 
25 import libcore.util.NativeAllocationRegistry;
26 
27 /**
28  * <p>A {@link RuntimeShader} calculates a per-pixel color based on the output of a user defined
29  * Android Graphics Shading Language (AGSL) function.</p>
30  *
31  * <h3>Android Graphics Shading Language</h3>
32  * <p>The AGSL syntax is very similar to OpenGL ES Shading Language, but there are some important
33  * differences that are highlighted here. Most of these differences are summed up in one basic fact:
34  * <b>With GPU shading languages, you are programming a stage of the GPU pipeline. With AGSL, you
35  * are programming a stage of the {@link Canvas} or {@link RenderNode} drawing pipeline.</b></p>
36  *
37  * <p>In particular, a GLSL fragment shader controls the entire behavior of the GPU between the
38  * rasterizer and the blending hardware. That shader does all of the work to compute a color, and
39  * the color it generates is exactly what is fed to the blending stage of the pipeline.</p>
40  *
41  * <p>In contrast, AGSL functions exist as part of a larger pipeline. When you issue a
42  * {@link Canvas} drawing operation, Android (generally) assembles a single GPU fragment shader to
43  * do all of the required work. This shader typically includes several pieces. For example, it might
44  * include:</p>
45  * <ul>
46  *  <li>Evaluating whether a pixel falls inside or outside of the shape being drawn (or on the
47  *  border, where it might apply antialiasing).</li>
48  *  <li>Evaluating whether a pixel falls inside or outside of the clipping region (again, with
49  *  possible antialiasing logic for border pixels).</li>
50  *  <li>Logic for the {@link Shader}, {@link ColorFilter}, and {@link BlendMode} on the
51  *  {@link Paint}.</li>
52  *  <li>Color space conversion code, as part of Android's color management.</li>
53  * </ul>
54  *
55  * <p>A {@link RuntimeShader}, like other {@link Shader} types, effectively contributes a function
56  * to the GPU's fragment shader.</p>
57  *
58  * <h3>AGSL Shader Execution</h3>
59  * <p>Just like a GLSL shader, an AGSL shader begins execution in a main function. Unlike GLSL, the
60  * function receives as an input parameter the position of the pixel within the {@link Canvas} or
61  * {@link RenderNode} coordinate space (similar to gl_fragCoord) and returns the color to be shaded
62  * as a vec4 (similar to out vec4 color or gl_FragColor in GLSL).</p>
63  *
64  * <pre class="prettyprint">
65  * vec4 main(vec2 canvas_coordinates);
66  * </pre>
67  *
68  * <p>AGSL and GLSL use different coordinate spaces by default. In GLSL, the fragment coordinate
69  * (fragCoord) is relative to the lower left. AGSL matches the screen coordinate system of the
70  * Android {@link Canvas} which has its origin as the upper left corner. This means that the
71  * coordinates provided as a parameter in the main function are local to the canvas with the
72  * exception of any {@link Shader#getLocalMatrix(Matrix)} transformations applied to this shader.
73  * Additionally, if the shader is invoked by another using {@link #setInputShader(String, Shader)},
74  * then that parent shader may modify the input coordinates arbitrarily.</p>
75  *
76  * <h3>AGSL and Color Spaces</h3>
77  * <p>Android Graphics and by extension {@link RuntimeShader} are color managed.  The working
78  * {@link ColorSpace} for an AGSL shader is defined to be the color space of the destination, which
79  * in most cases is determined by {@link Window#setColorMode(int)}.</p>
80  *
81  * <p>When authoring an AGSL shader, you won't know what the working color space is. For many
82  * effects, this is fine because by default color inputs are automatically converted into the
83  * working color space. For certain effects, it may be important to do some math in a fixed, known
84  * color space. A common example is lighting - to get physically accurate lighting, math should be
85  * done in a linear color space. To help with this, AGSL provides two intrinsic functions that
86  * convert colors between the working color space and the
87  * {@link ColorSpace.Named#LINEAR_EXTENDED_SRGB} color space:
88  *
89  * <pre class="prettyprint">
90  * vec3 toLinearSrgb(vec3 color);
91  * vec3 fromLinearSrgb(vec3 color);</pre>
92  *
93  * <h3>AGSL and Premultiplied Alpha</h3>
94  * <p>When dealing with transparent colors, there are two (common) possible representations:
95  * straight (unassociated) alpha and premultiplied (associated) alpha. In ASGL the color returned
96  * by the main function is expected to be premultiplied.  AGSL's use of premultiplied alpha
97  * implies:
98  * </p>
99  *
100  * <ul>
101  *  <li>If your AGSL shader will return transparent colors, be sure to multiply the RGB by A.  The
102  *  resulting color should be [R*A, G*A, B*A, A], not [R, G, B, A].</li>
103  *  <li>For more complex shaders, you must understand which of your colors are premultiplied vs.
104  *  straight. Many operations don't make sense if you mix both kinds of color together.</li>
105  * </ul>
106  *
107  * <h3>Uniforms</h3>
108  * <p>AGSL, like GLSL, exposes the concept of uniforms. An AGSL uniform is defined as a read-only,
109  * global variable that is accessible by the AGSL code and is initialized by a number of setter
110  * methods on {@link RuntimeShader}. AGSL exposes two primitive uniform data types (float, int) and
111  * two specialized types (colors, shaders) that are outlined below.</p>
112  *
113  * <h4>Primitive Uniforms</h4>
114  * <p>There are two primitive uniform types supported by AGSL, float and int. For these types and
115  * uniforms representing a grouping of these types, like arrays and matrices, there are
116  * corresponding {@link RuntimeShader} methods to initialize them.
117  * <table border="2" width="85%" align="center" cellpadding="5">
118  *     <thead>
119  *         <tr><th>Java Type</th> <th>AGSL Type</th> <th>Method</th> </tr>
120  *     </thead>
121  *
122  *     <tbody>
123  *     <tr>
124  *         <td rowspan="4">Floats</td>
125  *         <td>float</td>
126  *         <td>{@link RuntimeShader#setFloatUniform(String, float)}</td>
127  *     </tr>
128  *     <tr>
129  *         <td>vec2</td>
130  *         <td>{@link RuntimeShader#setFloatUniform(String, float, float)}</td>
131  *     </tr>
132  *     <tr>
133  *         <td>vec3</td>
134  *         <td>{@link RuntimeShader#setFloatUniform(String, float, float, float)}</td>
135  *     </tr>
136  *     <tr>
137  *         <td>vec4</td>
138  *         <td>{@link RuntimeShader#setFloatUniform(String, float, float, float, float)}</td>
139  *     </tr>
140  *     <tr>
141  *         <td rowspan="4">Integers</td>
142  *         <td>int</td>
143  *         <td>{@link RuntimeShader#setIntUniform(String, int)}</td>
144  *     </tr>
145  *     <tr>
146  *         <td>ivec2</td>
147  *         <td>{@link RuntimeShader#setIntUniform(String, int, int)}</td>
148  *     </tr>
149  *     <tr>
150  *         <td>ivec3</td>
151  *         <td>{@link RuntimeShader#setIntUniform(String, int, int, int)}</td>
152  *     </tr>
153  *     <tr>
154  *         <td>ivec4</td>
155  *         <td>{@link RuntimeShader#setIntUniform(String, int, int, int, int)}</td>
156  *     </tr>
157  *     <tr>
158  *         <td rowspan="2">Matrices and Arrays</td>
159  *         <td>mat2, mat3, and mat4, and float[]</td>
160  *         <td>{@link RuntimeShader#setFloatUniform(String, float[])}</td>
161  *     </tr>
162  *     <tr>
163  *         <td>int[]</td>
164  *         <td>{@link RuntimeShader#setIntUniform(String, int[])}</td>
165  *     </tr>
166  *     </tbody>
167  * </table>
168  *
169  * For example, a simple AGSL shader making use of a float uniform to modulate the transparency
170  * of the output color would look like:</p>
171  *
172  * <pre class="prettyprint">
173  * uniform float alpha;
174  * vec4 main(vec2 canvas_coordinates) {
175  *     vec3 red = vec3(1.0, 0.0, 0.0);
176  *     return vec4(red * alpha, alpha);
177  * }</pre>
178  *
179  * <p>After creating a {@link RuntimeShader} with that program the uniform can then be initialized
180  * and updated per frame by calling {@link RuntimeShader#setFloatUniform(String, float)} with the
181  * value of alpha.  The value of a primitive uniform defaults to 0 if it is declared in the AGSL
182  * shader but not initialized.</p>
183  *
184  * <h4>Color Uniforms</h4>
185  * <p>AGSL doesn't know if uniform variables contain colors, it won't automatically convert them to
186  * the working colorspace of the shader at runtime.  However, you can label your vec4 uniform with
187  * the "layout(color)" qualifier which lets Android know that the uniform will be used as a color.
188  * Doing so allows AGSL to transform the uniform value to the working color space. In AGSL, declare
189  * the uniform like this:
190  *
191  * <pre class="prettyprint">
192  * layout(color) uniform vec4 inputColorA;
193  * layout(color) uniform vec4 inputColorB;
194  * vec4 main(vec2 canvas_coordinates) {
195  *     // blend the two colors together and return the resulting color
196  *     return mix(inputColorA, inputColorB, 0.5);
197  * }</pre>
198  *
199  * <p>After creating a {@link RuntimeShader} with that program the uniforms can
200  * then be initialized and updated per frame by calling
201  * {@link RuntimeShader#setColorUniform(String, int)},
202  * {@link RuntimeShader#setColorUniform(String, long)}, or
203  * {@link RuntimeShader#setColorUniform(String, Color)} with the desired colors.  The value of a
204  * color uniform is undefined if it is declared in the AGSL shader but not initialized.</p>
205  *
206  * <h4>Shader Uniforms</h4>
207  * In GLSL, a fragment shader can sample a texture. For AGSL instead of sampling textures you can
208  * sample from any {@link Shader}, which includes but is not limited to {@link BitmapShader}. To
209  * make it clear that you are operating on an {@link Shader} object there is no "sample"
210  * method. Instead, the shader uniform has an "eval()" method. This distinction enables AGSL shaders
211  * to sample from existing bitmap and gradient shaders as well as other {@link RuntimeShader}
212  * objects.  In AGSL, declare the uniform like this:
213  *
214  * <pre class="prettyprint">
215  * uniform shader myShader;
216  * vec4 main(vec2 canvas_coordinates) {
217  *     // swap the red and blue color channels when sampling from myShader
218  *     return myShader.eval(canvas_coordinates).bgra;
219  * }</pre>
220  *
221  * <p>After creating a {@link RuntimeShader} with that program the shader uniform can
222  * then be initialized and updated per frame by calling
223  * {@link RuntimeShader#setInputShader(String, Shader)} with the desired shader. The value of a
224  * shader uniform is undefined if it is declared in the AGSL shader but not initialized.</p>
225  *
226  * <p>Although most {@link BitmapShader}s contain colors that should be color managed, some contain
227  * data that isn't actually colors. This includes bitmaps storing normals, material properties
228  * (e.g. roughness), heightmaps, or any other purely mathematical data that happens to be stored in
229  * a bitmap. When using these kinds of shaders in AGSL, you probably want to initialize them with
230  * {@link #setInputBuffer(String, BitmapShader)}. Shaders initialized this way work much like
231  * a regular {@link BitmapShader} (including filtering and tiling), with a few major differences:
232  * <ul>
233  *  <li>No color space transformation is applied (the color space of the bitmap is ignored).</li>
234  *  <li>Bitmaps that return false for {@link Bitmap#isPremultiplied()} are not automatically
235  *  premultiplied.</li>
236  * </ul>
237  *
238  * <p>In addition, when sampling from a {@link BitmapShader} be aware that the shader does not use
239  * normalized coordinates (like a texture in GLSL). It uses (0, 0) in the upper-left corner, and
240  * (width, height) in the bottom-right corner. Normally, this is exactly what you want. If you're
241  * evaluating the shader with coordinates based on the ones passed to your AGSL program, the scale
242  * is correct. However, if you want to adjust those coordinates (to do some kind of re-mapping of
243  * the bitmap), remember that the coordinates are local to the canvas.</p>
244  *
245  */
246 public class RuntimeShader extends Shader {
247 
248     private static class NoImagePreloadHolder {
249         public static final NativeAllocationRegistry sRegistry =
250                 NativeAllocationRegistry.createMalloced(
251                 RuntimeShader.class.getClassLoader(), nativeGetFinalizer());
252     }
253 
254     /**
255      * Current native shader builder instance.
256      */
257     private long mNativeInstanceRuntimeShaderBuilder;
258 
259     /**
260      * For tracking GC usage. Keep a java-side reference for reachable objects to
261      * enable better heap tracking & tooling support
262      */
263     private ArrayMap<String, Shader> mShaderUniforms = new ArrayMap<>();
264 
265     /**
266      * Creates a new RuntimeShader.
267      *
268      * @param shader The text of AGSL shader program to run.
269      */
RuntimeShader(@onNull String shader)270     public RuntimeShader(@NonNull String shader) {
271         // colorspace is required, but the RuntimeShader always produces colors in the destination
272         // buffer's colorspace regardless of the value specified here.
273         super(ColorSpace.get(ColorSpace.Named.SRGB));
274         if (shader == null) {
275             throw new NullPointerException("RuntimeShader requires a non-null AGSL string");
276         }
277         mNativeInstanceRuntimeShaderBuilder = nativeCreateBuilder(shader);
278         NoImagePreloadHolder.sRegistry.registerNativeAllocation(
279                 this, mNativeInstanceRuntimeShaderBuilder);
280     }
281 
282     /**
283      * Sets the uniform color value corresponding to this shader.  If the shader does not have a
284      * uniform with that name or if the uniform is declared with a type other than vec3 or vec4 and
285      * corresponding layout(color) annotation then an IllegalArgumentException is thrown.
286      *
287      * @param uniformName name matching the color uniform declared in the AGSL shader program
288      * @param color the provided sRGB color will be transformed into the shader program's output
289      *              colorspace and will be available as a vec4 uniform in the program.
290      */
setColorUniform(@onNull String uniformName, @ColorInt int color)291     public void setColorUniform(@NonNull String uniformName, @ColorInt int color) {
292         setUniform(uniformName, Color.valueOf(color).getComponents(), true);
293     }
294 
295     /**
296      * Sets the uniform color value corresponding to this shader.  If the shader does not have a
297      * uniform with that name or if the uniform is declared with a type other than vec3 or vec4 and
298      * corresponding layout(color) annotation then an IllegalArgumentException is thrown.
299      *
300      * @param uniformName name matching the color uniform declared in the AGSL shader program
301      * @param color the provided sRGB color will be transformed into the shader program's output
302      *              colorspace and will be available as a vec4 uniform in the program.
303      */
setColorUniform(@onNull String uniformName, @ColorLong long color)304     public void setColorUniform(@NonNull String uniformName, @ColorLong long color) {
305         Color exSRGB = Color.valueOf(color).convert(ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB));
306         setUniform(uniformName, exSRGB.getComponents(), true);
307     }
308 
309     /**
310      * Sets the uniform color value corresponding to this shader.  If the shader does not have a
311      * uniform with that name or if the uniform is declared with a type other than vec3 or vec4 and
312      * corresponding layout(color) annotation then an IllegalArgumentException is thrown.
313      *
314      * @param uniformName name matching the color uniform declared in the AGSL shader program
315      * @param color the provided sRGB color will be transformed into the shader program's output
316      *              colorspace and will be available as a vec4 uniform in the program.
317      */
setColorUniform(@onNull String uniformName, @NonNull Color color)318     public void setColorUniform(@NonNull String uniformName, @NonNull Color color) {
319         if (color == null) {
320             throw new NullPointerException("The color parameter must not be null");
321         }
322         Color exSRGB = color.convert(ColorSpace.get(ColorSpace.Named.EXTENDED_SRGB));
323         setUniform(uniformName, exSRGB.getComponents(), true);
324     }
325 
326     /**
327      * Sets the uniform value corresponding to this shader.  If the shader does not have a uniform
328      * with that name or if the uniform is declared with a type other than a float or float[1]
329      * then an IllegalArgumentException is thrown.
330      *
331      * @param uniformName name matching the uniform declared in the AGSL shader program
332      */
setFloatUniform(@onNull String uniformName, float value)333     public void setFloatUniform(@NonNull String uniformName, float value) {
334         setFloatUniform(uniformName, value, 0.0f, 0.0f, 0.0f, 1);
335     }
336 
337     /**
338      * Sets the uniform value corresponding to this shader.  If the shader does not have a uniform
339      * with that name or if the uniform is declared with a type other than vec2 or float[2] then an
340      * IllegalArgumentException is thrown.
341      *
342      * @param uniformName name matching the uniform declared in the AGSL shader program
343      */
setFloatUniform(@onNull String uniformName, float value1, float value2)344     public void setFloatUniform(@NonNull String uniformName, float value1, float value2) {
345         setFloatUniform(uniformName, value1, value2, 0.0f, 0.0f, 2);
346 
347     }
348 
349     /**
350      * Sets the uniform value corresponding to this shader.  If the shader does not have a uniform
351      * with that name or if the uniform is declared with a type other than vec3 or float[3] then an
352      * IllegalArgumentException is thrown.
353      *
354      * @param uniformName name matching the uniform declared in the AGSL shader program
355      */
setFloatUniform(@onNull String uniformName, float value1, float value2, float value3)356     public void setFloatUniform(@NonNull String uniformName, float value1, float value2,
357             float value3) {
358         setFloatUniform(uniformName, value1, value2, value3, 0.0f, 3);
359 
360     }
361 
362     /**
363      * Sets the uniform value corresponding to this shader.  If the shader does not have a uniform
364      * with that name or if the uniform is declared with a type other than vec4 or float[4] then an
365      * IllegalArgumentException is thrown.
366      *
367      * @param uniformName name matching the uniform declared in the AGSL shader program
368      */
setFloatUniform(@onNull String uniformName, float value1, float value2, float value3, float value4)369     public void setFloatUniform(@NonNull String uniformName, float value1, float value2,
370             float value3, float value4) {
371         setFloatUniform(uniformName, value1, value2, value3, value4, 4);
372     }
373 
374     /**
375      * Sets the uniform value corresponding to this shader.  If the shader does not have a uniform
376      * with that name or if the uniform is declared with a type other than a float (for N=1), vecN,
377      * or float[N] where N is the length of the values param then an IllegalArgumentException is
378      * thrown.
379      *
380      * @param uniformName name matching the uniform declared in the AGSL shader program
381      */
setFloatUniform(@onNull String uniformName, @NonNull float[] values)382     public void setFloatUniform(@NonNull String uniformName, @NonNull float[] values) {
383         setUniform(uniformName, values, false);
384     }
385 
setFloatUniform(@onNull String uniformName, float value1, float value2, float value3, float value4, int count)386     private void setFloatUniform(@NonNull String uniformName, float value1, float value2,
387             float value3, float value4, int count) {
388         if (uniformName == null) {
389             throw new NullPointerException("The uniformName parameter must not be null");
390         }
391 
392         nativeUpdateUniforms(mNativeInstanceRuntimeShaderBuilder, uniformName, value1, value2,
393                 value3, value4, count);
394         discardNativeInstance();
395     }
396 
setUniform(@onNull String uniformName, @NonNull float[] values, boolean isColor)397     private void setUniform(@NonNull String uniformName, @NonNull float[] values, boolean isColor) {
398         if (uniformName == null) {
399             throw new NullPointerException("The uniformName parameter must not be null");
400         }
401         if (values == null) {
402             throw new NullPointerException("The uniform values parameter must not be null");
403         }
404 
405         nativeUpdateUniforms(mNativeInstanceRuntimeShaderBuilder, uniformName, values, isColor);
406         discardNativeInstance();
407     }
408 
409     /**
410      * Sets the uniform value corresponding to this shader.  If the shader does not have a uniform
411      * with that name or if the uniform is declared with a type other than an int or int[1]
412      * then an IllegalArgumentException is thrown.
413      *
414      * @param uniformName name matching the uniform declared in the AGSL shader program
415      */
setIntUniform(@onNull String uniformName, int value)416     public void setIntUniform(@NonNull String uniformName, int value) {
417         setIntUniform(uniformName, value, 0, 0, 0, 1);
418     }
419 
420     /**
421      * Sets the uniform value corresponding to this shader.  If the shader does not have a uniform
422      * with that name or if the uniform is declared with a type other than ivec2 or int[2] then an
423      * IllegalArgumentException is thrown.
424      *
425      * @param uniformName name matching the uniform declared in the AGSL shader program
426      */
setIntUniform(@onNull String uniformName, int value1, int value2)427     public void setIntUniform(@NonNull String uniformName, int value1, int value2) {
428         setIntUniform(uniformName, value1, value2, 0, 0, 2);
429 
430     }
431 
432     /**
433      * Sets the uniform value corresponding to this shader.  If the shader does not have a uniform
434      * with that name or if the uniform is declared with a type other than ivec3 or int[3] then an
435      * IllegalArgumentException is thrown.
436      *
437      * @param uniformName name matching the uniform declared in the AGSL shader program
438      */
setIntUniform(@onNull String uniformName, int value1, int value2, int value3)439     public void setIntUniform(@NonNull String uniformName, int value1, int value2, int value3) {
440         setIntUniform(uniformName, value1, value2, value3, 0, 3);
441 
442     }
443 
444     /**
445      * Sets the uniform value corresponding to this shader.  If the shader does not have a uniform
446      * with that name or if the uniform is declared with a type other than ivec4 or int[4] then an
447      * IllegalArgumentException is thrown.
448      *
449      * @param uniformName name matching the uniform declared in the AGSL shader program
450      */
setIntUniform(@onNull String uniformName, int value1, int value2, int value3, int value4)451     public void setIntUniform(@NonNull String uniformName, int value1, int value2,
452             int value3, int value4) {
453         setIntUniform(uniformName, value1, value2, value3, value4, 4);
454     }
455 
456     /**
457      * Sets the uniform value corresponding to this shader.  If the shader does not have a uniform
458      * with that name or if the uniform is declared with a type other than an int (for N=1), ivecN,
459      * or int[N] where N is the length of the values param then an IllegalArgumentException is
460      * thrown.
461      *
462      * @param uniformName name matching the uniform declared in the AGSL shader program
463      */
setIntUniform(@onNull String uniformName, @NonNull int[] values)464     public void setIntUniform(@NonNull String uniformName, @NonNull int[] values) {
465         if (uniformName == null) {
466             throw new NullPointerException("The uniformName parameter must not be null");
467         }
468         if (values == null) {
469             throw new NullPointerException("The uniform values parameter must not be null");
470         }
471         nativeUpdateUniforms(mNativeInstanceRuntimeShaderBuilder, uniformName, values);
472         discardNativeInstance();
473     }
474 
setIntUniform(@onNull String uniformName, int value1, int value2, int value3, int value4, int count)475     private void setIntUniform(@NonNull String uniformName, int value1, int value2, int value3,
476             int value4, int count) {
477         if (uniformName == null) {
478             throw new NullPointerException("The uniformName parameter must not be null");
479         }
480 
481         nativeUpdateUniforms(mNativeInstanceRuntimeShaderBuilder, uniformName, value1, value2,
482                 value3, value4, count);
483         discardNativeInstance();
484     }
485 
486     /**
487      * Assigns the uniform shader to the provided shader parameter.  If the shader program does not
488      * have a uniform shader with that name then an IllegalArgumentException is thrown.
489      *
490      * @param shaderName name matching the uniform declared in the AGSL shader program
491      * @param shader shader passed into the AGSL shader program for sampling
492      */
setInputShader(@onNull String shaderName, @NonNull Shader shader)493     public void setInputShader(@NonNull String shaderName, @NonNull Shader shader) {
494         if (shaderName == null) {
495             throw new NullPointerException("The shaderName parameter must not be null");
496         }
497         if (shader == null) {
498             throw new NullPointerException("The shader parameter must not be null");
499         }
500         mShaderUniforms.put(shaderName, shader);
501         nativeUpdateShader(
502                     mNativeInstanceRuntimeShaderBuilder, shaderName, shader.getNativeInstance());
503         discardNativeInstance();
504     }
505 
506     /**
507      * Assigns the uniform shader to the provided shader parameter.  If the shader program does not
508      * have a uniform shader with that name then an IllegalArgumentException is thrown.
509      *
510      * Unlike setInputShader this method returns samples directly from the bitmap's buffer. This
511      * means that there will be no transformation of the sampled pixels, such as colorspace
512      * conversion or alpha premultiplication.
513      */
setInputBuffer(@onNull String shaderName, @NonNull BitmapShader shader)514     public void setInputBuffer(@NonNull String shaderName, @NonNull BitmapShader shader) {
515         if (shaderName == null) {
516             throw new NullPointerException("The shaderName parameter must not be null");
517         }
518         if (shader == null) {
519             throw new NullPointerException("The shader parameter must not be null");
520         }
521 
522         mShaderUniforms.put(shaderName, shader);
523         nativeUpdateShader(mNativeInstanceRuntimeShaderBuilder, shaderName,
524                 shader.getNativeInstanceWithDirectSampling());
525         discardNativeInstance();
526     }
527 
528 
529     /** @hide */
530     @Override
createNativeInstance(long nativeMatrix, boolean filterFromPaint)531     protected long createNativeInstance(long nativeMatrix, boolean filterFromPaint) {
532         return nativeCreateShader(mNativeInstanceRuntimeShaderBuilder, nativeMatrix);
533     }
534 
535     /** @hide */
getNativeShaderBuilder()536     protected long getNativeShaderBuilder() {
537         return mNativeInstanceRuntimeShaderBuilder;
538     }
539 
nativeGetFinalizer()540     private static native long nativeGetFinalizer();
nativeCreateBuilder(String agsl)541     private static native long nativeCreateBuilder(String agsl);
nativeCreateShader(long shaderBuilder, long matrix)542     private static native long nativeCreateShader(long shaderBuilder, long matrix);
nativeUpdateUniforms( long shaderBuilder, String uniformName, float[] uniforms, boolean isColor)543     private static native void nativeUpdateUniforms(
544             long shaderBuilder, String uniformName, float[] uniforms, boolean isColor);
nativeUpdateUniforms( long shaderBuilder, String uniformName, float value1, float value2, float value3, float value4, int count)545     private static native void nativeUpdateUniforms(
546             long shaderBuilder, String uniformName, float value1, float value2, float value3,
547             float value4, int count);
nativeUpdateUniforms( long shaderBuilder, String uniformName, int[] uniforms)548     private static native void nativeUpdateUniforms(
549             long shaderBuilder, String uniformName, int[] uniforms);
nativeUpdateUniforms( long shaderBuilder, String uniformName, int value1, int value2, int value3, int value4, int count)550     private static native void nativeUpdateUniforms(
551             long shaderBuilder, String uniformName, int value1, int value2, int value3,
552             int value4, int count);
nativeUpdateShader( long shaderBuilder, String shaderName, long shader)553     private static native void nativeUpdateShader(
554             long shaderBuilder, String shaderName, long shader);
555 }
556 
557