xref: /third_party/skia/src/gpu/gradients/README.md (revision cb93a386)
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