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