Flutter Engine
The Flutter Engine
workingspace.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2023 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "gm/gm.h"
13#include "include/core/SkData.h"
19
21 // Why not use SkShaders::Color? We want a shader that inhibits any paint optimization by any
22 // backend. The CPU backend will ask the shader portion of the pipeline if it's constant.
23 // If so, that portion of the pipeline is executed to get the color, and the color filter is
24 // directly applied to the result. The only way to have the color filter run as part of the
25 // full CPU pipeline is to have a shader that returns false for isConstant:
26 SkBitmap bmp;
28 bmp.eraseColor(color);
30}
31
33 // This will return the paint color (unless it's a child of a runtime effect)
34 SkBitmap bmp;
38}
39
41 return SkRuntimeEffect::MakeForShader(SkString("uniform half4 c;"
42 "half4 main(float2 xy) { return c; }"))
44}
45
47 return SkRuntimeEffect::MakeForShader(SkString("layout(color) uniform half4 c;"
48 "half4 main(float2 xy) { return c; }"))
50}
51
53 const SkPoint pts[] = {{0, 0}, {40, 40}};
55 return SkGradientShader::MakeLinear(pts, colors, nullptr, nullptr, 2, SkTileMode::kClamp);
56}
57
59 return SkRuntimeEffect::MakeForColorFilter(SkString("uniform half4 c;"
60 "half4 main(half4 color) { return c; }"))
62}
63
65 return SkRuntimeEffect::MakeForColorFilter(SkString("layout(color) uniform half4 c;"
66 "half4 main(half4 color) { return c; }"))
68}
69
73 SkString("uniform shader s;"
74 "half4 main(half4 color) { return s.eval(float2(0)); }"))
75 .effect->makeColorFilter(nullptr, children);
76}
77
80}
81
83 return cf->makeWithWorkingColorSpace(SkColorSpace::MakeSRGB()->makeColorSpin());
84}
85
87 return shader->makeWithWorkingColorSpace(SkColorSpace::MakeSRGB()->makeColorSpin());
88}
89
92}
93
94DEF_SIMPLE_GM_CAN_FAIL(workingspace, canvas, errorMsg, 200, 350) {
95 if (!canvas->getSurface()) {
96 // The only backend that really fails is DDL (because the color filter fails to evaluate on
97 // the CPU when we do paint optimization). We can't identify DDL separate from other
98 // recording backends, so skip this GM for all of them:
99 *errorMsg = "Not supported in recording/DDL mode";
101 }
102
103 // This GM checks that changing the working color space of a color filter does the right thing.
104 // We create a variety of color filters that are sensitive to the working space, and test them
105 // with both fixed-input color (so that paint optimization can apply the filter on the CPU),
106 // and with a shader input (so they're forced to evaluate in the drawing pipeline).
107 //
108 // In all cases, the tests are designed to draw green if implemented correctly. Any other color
109 // (red or blue, most likely) is an error.
110 //
111 // The bottom row is the exception - it draws red-to-green gradients. The first two should be
112 // "ugly" (via brown). The last one should be "nice" (via yellow).
113
114 canvas->translate(5, 5);
115 canvas->save();
116
117 auto cell = [&](sk_sp<SkShader> shader,
118 sk_sp<SkColorFilter> colorFilter,
119 SkColor4f paintColor = SkColors::kBlack) {
121 paint.setColor(paintColor);
122 paint.setShader(shader);
123 paint.setColorFilter(colorFilter);
124 canvas->drawRect({0, 0, 40, 40}, paint);
125 canvas->translate(50, 0);
126 };
127
128 auto nextRow = [&]() {
129 canvas->restore();
130 canvas->translate(0, 50);
131 canvas->save();
132 };
133
134 auto blackShader = color_shader(SkColors::kBlack);
135
136 cell(nullptr, raw_cf(SkColors::kGreen));
137 cell(nullptr, managed_cf(SkColors::kGreen));
138 cell(nullptr, indirect_cf(SkColors::kGreen));
139 cell(nullptr, mode_cf(SkColors::kGreen));
140
141 nextRow();
142
143 cell(blackShader, raw_cf(SkColors::kGreen));
144 cell(blackShader, managed_cf(SkColors::kGreen));
145 cell(blackShader, indirect_cf(SkColors::kGreen));
146 cell(blackShader, mode_cf(SkColors::kGreen));
147
148 nextRow();
149
150 cell(nullptr, spin(raw_cf(SkColors::kRed))); // Un-managed red turns into green
151 cell(nullptr, spin(managed_cf(SkColors::kGreen)));
152 cell(nullptr, spin(indirect_cf(SkColors::kGreen)));
153 cell(nullptr, spin(mode_cf(SkColors::kGreen)));
154
155 nextRow();
156
157 cell(blackShader, spin(raw_cf(SkColors::kRed))); // Un-managed red turns into green
158 cell(blackShader, spin(managed_cf(SkColors::kGreen)));
159 cell(blackShader, spin(indirect_cf(SkColors::kGreen)));
160 cell(blackShader, spin(mode_cf(SkColors::kGreen)));
161
162 nextRow();
163
164 cell(raw_shader(SkColors::kGreen), nullptr);
165 cell(managed_shader(SkColors::kGreen), nullptr);
166 cell(color_shader(SkColors::kGreen), nullptr);
167 cell(paint_color_shader(), nullptr, SkColors::kGreen);
168
169 nextRow();
170
171 cell(spin(raw_shader(SkColors::kRed)), nullptr); // Un-managed red turns into green
172 cell(spin(managed_shader(SkColors::kGreen)), nullptr);
173 cell(spin(color_shader(SkColors::kGreen)), nullptr);
174 cell(spin(paint_color_shader()), nullptr, SkColors::kGreen);
175
176 nextRow();
177
178 cell(gradient_shader(), nullptr); // Red to green, via ugly brown
179 cell(spin(gradient_shader()), nullptr); // Same (spin doesn't change anything)
180 cell(linear(gradient_shader()), nullptr); // Red to green, via bright yellow
181
183}
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
void allocPixels(const SkImageInfo &info, size_t rowBytes)
Definition: SkBitmap.cpp:258
sk_sp< SkShader > makeShader(SkTileMode tmx, SkTileMode tmy, const SkSamplingOptions &, const SkMatrix *localMatrix=nullptr) const
Definition: SkBitmap.cpp:669
void eraseColor(SkColor4f) const
Definition: SkBitmap.cpp:442
sk_sp< SkColorFilter > makeWithWorkingColorSpace(sk_sp< SkColorSpace >) const
static sk_sp< SkColorFilter > Blend(const SkColor4f &c, sk_sp< SkColorSpace >, SkBlendMode mode)
static sk_sp< SkColorSpace > MakeSRGB()
static sk_sp< SkColorSpace > MakeSRGBLinear()
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
Definition: SkData.cpp:111
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
sk_sp< SkShader > makeShader(sk_sp< const SkData > uniforms, sk_sp< SkShader > children[], size_t childCount, const SkMatrix *localMatrix=nullptr) const
static Result MakeForColorFilter(SkString sksl, const Options &)
static Result MakeForShader(SkString sksl, const Options &)
sk_sp< SkColorFilter > makeColorFilter(sk_sp< const SkData > uniforms) const
sk_sp< SkShader > makeWithWorkingColorSpace(sk_sp< SkColorSpace >) const
Definition: SkShader.cpp:51
const Paint & paint
Definition: color_source.cc:38
DlColor color
constexpr SkColor4f kGreen
Definition: SkColor.h:441
constexpr SkColor4f kRed
Definition: SkColor.h:440
constexpr SkColor4f kWhite
Definition: SkColor.h:439
constexpr SkColor4f kBlack
Definition: SkColor.h:435
PODArray< SkColor > colors
Definition: SkRecords.h:276
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static SkImageInfo MakeA8(int width, int height)
sk_sp< SkRuntimeEffect > effect
static sk_sp< SkColorFilter > mode_cf(SkColor4f color)
static sk_sp< SkColorFilter > raw_cf(SkColor4f color)
static sk_sp< SkColorFilter > spin(sk_sp< SkColorFilter > cf)
static sk_sp< SkShader > linear(sk_sp< SkShader > shader)
static sk_sp< SkShader > paint_color_shader()
static sk_sp< SkColorFilter > indirect_cf(SkColor4f color)
static sk_sp< SkShader > managed_shader(SkColor4f color)
static sk_sp< SkColorFilter > managed_cf(SkColor4f color)
static sk_sp< SkShader > gradient_shader()
DEF_SIMPLE_GM_CAN_FAIL(workingspace, canvas, errorMsg, 200, 350)
static sk_sp< SkShader > color_shader(SkColor4f color)
static sk_sp< SkShader > raw_shader(SkColor4f color)