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