xref: /aosp_15_r20/external/skia/src/gpu/ganesh/gradients/README.md (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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