1cb93a386Sopenharmony_ciGradients on the GPU 2cb93a386Sopenharmony_ci==================== 3cb93a386Sopenharmony_ci 4cb93a386Sopenharmony_ciGradients can be thought of, at a very high level, as three pieces: 5cb93a386Sopenharmony_ci 6cb93a386Sopenharmony_ci1. A color interpolator ("colorizer") that is one dimensional, returning a color 7cb93a386Sopenharmony_ci for an interpolant value "t" within the range [0.0, 1.0]. This encapsulates 8cb93a386Sopenharmony_ci the definition of specific color stops and how to wrap, tile, or clamp out 9cb93a386Sopenharmony_ci of bound inputs. A color interpolator will be named `GrXxxxxGradientColorizer`. 10cb93a386Sopenharmony_ci2. A layout that converts from 2D geometry/position to the one dimensional 11cb93a386Sopenharmony_ci domain of the color interpolator. This is how a linear or radial gradient 12cb93a386Sopenharmony_ci distinguishes itself. When designing a new gradient shape, this is the 13cb93a386Sopenharmony_ci component that will need to be implemented. A layout will generally be 14cb93a386Sopenharmony_ci named `GrYyyyyGradientLayout`. 15cb93a386Sopenharmony_ci3. A top-level effect that composes the layout and color interpolator together. 16cb93a386Sopenharmony_ci This processor is also responsible for implementing the clamping behavior, 17cb93a386Sopenharmony_ci which is abstracted away from both the layout and colorization. 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci`GrClampedGradientEffect` handles clamped and decal tile modes, while 20cb93a386Sopenharmony_ci`GrTiledGradientEffect` implements repeat and mirror tile modes. The 21cb93a386Sopenharmony_ci`GrClampedGradientEffect` requires border colors to be specified outside of its 22cb93a386Sopenharmony_cicolorizer child, but these border colors may be defined by the gradient color 23cb93a386Sopenharmony_cistops. Both of these top-level effects delegate calculating the t interpolant to 24cb93a386Sopenharmony_cithe layout child processor, then perform their respective tile mode operations, 25cb93a386Sopenharmony_ciand finally convert the tiled t value (guaranteed to be within 0 and 1) into an 26cb93a386Sopenharmony_cioutput color using the colorizer child processor. 27cb93a386Sopenharmony_ci 28cb93a386Sopenharmony_ciFragment processors only support returning colors; conceptually, however, 29cb93a386Sopenharmony_cilayout processors need to generate an interpolant, not a color. So the 30cb93a386Sopenharmony_cilayout processor encodes its result into a color as follows: 31cb93a386Sopenharmony_ci 32cb93a386Sopenharmony_ci- `sk_OutColor.r`: computed t interpolant [0.0, 1.0], untiled 33cb93a386Sopenharmony_ci- `sk_OutColor.g`: Positive value = render, negative value = discard pixel. 34cb93a386Sopenharmony_ci- `sk_OutColor.b`: unused 35cb93a386Sopenharmony_ci- `sk_OutColor.a`: unused 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ciLayouts can report "invalid gradient location" by outputting a negative value 38cb93a386Sopenharmony_ciinto the `sk_OutColor.g` component. (Currently, the two-point conical gradient 39cb93a386Sopenharmony_cidoes this.) When this happens, the top-level effect immediately returns transparent 40cb93a386Sopenharmony_ciblack and does not invoke the colorizer at all. When the gradient location is valid, 41cb93a386Sopenharmony_cithe top-level effect samples from the colorizer at the explicit coordinate (t, 0). The 42cb93a386Sopenharmony_ciy coordinate will always be zero and can be ignored by the colorizer. 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ciThere are several hand-written colorizers for analytic color cases; these are 45cb93a386Sopenharmony_cievaluated directly in the shader. Generated texture maps can also be used to 46cb93a386Sopenharmony_cicolorize a gradient; in this case, a `GrTextureEffect` will be used as the colorizer. 47cb93a386Sopenharmony_ci 48cb93a386Sopenharmony_ci`GrGradientShader` provides static factory functions to create 49cb93a386Sopenharmony_ci`GrFragmentProcessor` graphs that reproduce a particular `SkGradientShader`. 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ciOptimization Flags 52cb93a386Sopenharmony_ci================== 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ciAt an abstract level, gradient shaders are compatible with coverage as alpha 55cb93a386Sopenharmony_ciand, under certain conditions, preserve opacity when the inputs are opaque. To 56cb93a386Sopenharmony_cireduce the amount of duplicate code and boilerplate, these optimization 57cb93a386Sopenharmony_cidecisions are implemented in the top-level effects and not in the colorizers. It 58cb93a386Sopenharmony_ciis assumed that all colorizer FPs will be compatible with coverage as alpha and 59cb93a386Sopenharmony_ciwill preserve opacity if input colors are opaque. Since this is assumed by the 60cb93a386Sopenharmony_citop-level effects, they do not need to report these optimizations or check input 61cb93a386Sopenharmony_ciopacity (this does mean if the colorizers are used independently from the 62cb93a386Sopenharmony_citop-level effect shader that the reported flags might not be optimal, but since 63cb93a386Sopenharmony_cithat is unlikely, this convention really simplifies the colorizer 64cb93a386Sopenharmony_ciimplementations). 65cb93a386Sopenharmony_ci 66cb93a386Sopenharmony_ciUnlike colorizers, which do not need to report any optimization flags, layout 67cb93a386Sopenharmony_ciFPs should report opacity preserving optimizations because they can impact the 68cb93a386Sopenharmony_ciopacity of a pixel outside of how the gradient would otherwise color it. 69cb93a386Sopenharmony_ciLayouts that potentially reject pixels (i.e. could output a negative y value) 70cb93a386Sopenharmony_cimust not report kPreservesOpaqueInput_OptimizationFlag. Layouts that never 71cb93a386Sopenharmony_cireject a pixel should report kPreservesOpaqueInput_OptimizationFlag since the 72cb93a386Sopenharmony_citop-level effects can optimize away checking if the layout rejects a pixel. 73