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