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