Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
recordopts.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2014 Google Inc.
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"
17#include "include/core/SkRect.h"
23
24constexpr int kTestRectSize = 50;
25constexpr int kDetectorGreenValue = 50;
26
27// Below are few functions to install "detector" color filters. The filter is there to assert that
28// the color value it sees is the expected. It will trigger only with kDetectorGreenValue, and
29// turn that value into full green. The idea is that if an optimization incorrectly changes
30// kDetectorGreenValue and then the incorrect value is observable by some part of the drawing
31// pipeline, that pixel will remain empty.
32
34 uint8_t tableA[256] = { 0, };
35 uint8_t tableR[256] = { 0, };
36 uint8_t tableG[256] = { 0, };
37 uint8_t tableB[256] = { 0, };
38 tableA[255] = 255;
39 tableG[kDetectorGreenValue] = 255;
40 return SkColorFilters::TableARGB(tableA, tableR, tableG, tableB);
41}
42
43// This detector detects that color filter phase of the pixel pipeline receives the correct value.
47
48// This detector detects that image filter phase of the pixel pipeline receives the correct value.
53
55}
56
58
59
60// Draws an pattern that can be optimized by alpha folding outer savelayer alpha value to
61// inner draw. Since we know that folding will happen to the inner draw, install a detector
62// to make sure that optimization does not change anything observable.
64 InstallDetectorFunc installDetector) {
66 SkPaint layerPaint;
67 layerPaint.setColor(SkColorSetARGB(128, 0, 0, 0));
68 canvas->saveLayer(&targetRect, &layerPaint);
69 SkPaint drawPaint;
70 drawPaint.setColor(shapeColor);
71 installDetector(&drawPaint);
72 canvas->drawRect(targetRect, drawPaint);
73 canvas->restore();
74}
75
76// Draws an pattern that can be optimized by alpha folding outer savelayer alpha value to
77// inner draw. A variant where the draw is not uniform color.
79 InstallDetectorFunc installDetector) {
81 bitmap.allocN32Pixels(kTestRectSize, kTestRectSize);
82 bitmap.eraseColor(shapeColor);
83 {
84 // Make the bitmap non-uniform color, so that it can not be optimized as uniform drawRect.
85 SkCanvas bitmapCanvas(bitmap);
86 SkPaint p;
87 p.setColor(SK_ColorWHITE);
88 SkASSERT(shapeColor != SK_ColorWHITE);
89 bitmapCanvas.drawRect(SkRect::MakeWH(SkIntToScalar(7), SkIntToScalar(7)), p);
90 }
91
93 SkPaint layerPaint;
94 layerPaint.setColor(SkColorSetARGB(129, 0, 0, 0));
95 canvas->saveLayer(&targetRect, &layerPaint);
96 SkPaint drawPaint;
97 installDetector(&drawPaint);
98 canvas->drawImage(bitmap.asImage(), 0, 0, SkSamplingOptions(), &drawPaint);
99 canvas->restore();
100}
101
102// Draws an pattern that can be optimized by alpha folding outer savelayer alpha value to
103// inner savelayer. We know that alpha folding happens to inner savelayer, so add detector there.
105 InstallDetectorFunc installDetector) {
106
108 sk_sp<SkPicture> shape;
109 {
110 SkPictureRecorder recorder;
111 SkCanvas* recordCanvas = recorder.beginRecording(SkIntToScalar(kTestRectSize + 2),
113 SkPaint shapePaint;
114 shapePaint.setColor(shapeColor);
115 recordCanvas->drawRect(targetRect, shapePaint);
116 shape = recorder.finishRecordingAsPicture();
117 }
118
119 SkPaint layerPaint;
120 layerPaint.setColor(SkColorSetARGB(130, 0, 0, 0));
121 canvas->saveLayer(&targetRect, &layerPaint);
122 canvas->save();
123 canvas->clipRect(targetRect);
124 SkPaint drawPaint;
125 drawPaint.setImageFilter(SkImageFilters::Picture(shape));
126 installDetector(&drawPaint);
127 canvas->saveLayer(&targetRect, &drawPaint);
128 canvas->restore();
129 canvas->restore();
130 canvas->restore();
131}
132
133// Draws two columns of rectangles. The test is correct when:
134// - Left and right columns always identical
135// - First 3 rows are green, with a white dent in the middle row
136// - Next 6 rows are green, with a grey dent in the middle row
137// (the grey dent is from the color filter removing everything but the "good" green, see below)
138// - Last 6 rows are grey
139DEF_SIMPLE_GM(recordopts, canvas, (kTestRectSize+1)*2, (kTestRectSize+1)*15) {
140 auto direct = GrAsDirectContext(canvas->recordingContext());
141 canvas->clear(SK_ColorTRANSPARENT);
142
143 typedef void (*TestVariantSequence)(SkCanvas*, SkColor, InstallDetectorFunc);
144 TestVariantSequence funcs[] = {
148 };
149
150 // Draw layer-related sequences that can be optimized by folding the opacity layer alpha to
151 // the inner draw operation. This tries to trigger the optimization, and relies on gm diffs
152 // to keep the color value correct over time.
153
154 // Draws two green rects side by side: one is without the optimization, the other is with
155 // the optimization applied.
156
157 SkColor shapeColor = SkColorSetARGB(255, 0, 255, 0);
158 for (size_t k = 0; k < std::size(funcs); ++k) {
159 canvas->save();
160
161 TestVariantSequence drawTestSequence = funcs[k];
162 drawTestSequence(canvas, shapeColor, no_detector_install);
163 if (direct) {
164 direct->flushAndSubmit();
165 }
166 canvas->translate(SkIntToScalar(kTestRectSize) + SkIntToScalar(1), SkIntToScalar(0));
167 {
168 SkPictureRecorder recorder;
169 drawTestSequence(recorder.beginRecording(SkIntToScalar(kTestRectSize),
171 shapeColor, no_detector_install);
172 recorder.finishRecordingAsPicture()->playback(canvas);
173 if (direct) {
174 direct->flushAndSubmit();
175 }
176 }
177 canvas->restore();
178 canvas->translate(SkIntToScalar(0), SkIntToScalar(kTestRectSize) + SkIntToScalar(1));
179 }
180
181 // Draw the same layer related sequences, but manipulate the sequences so that the result is
182 // incorrect if the alpha is folded or folded incorrectly. These test the observable state
183 // throughout the pixel pipeline, and thus may turn off the optimizations (this is why we
184 // trigger the optimizations above).
185
186 // Draws two green rects side by side: one is without the optimization, the other is with
187 // the possibility that optimization is applied.
188 // At the end, draws the same patterns in translucent black. This tests that the detectors
189 // work, eg. that if the value the detector sees is wrong, the resulting image shows this.
190 SkColor shapeColors[] = {
192 SkColorSetARGB(255, 0, (kDetectorGreenValue + 1), 0) // This tests that detectors work.
193 };
194
195 InstallDetectorFunc detectorInstallFuncs[] = {
198 };
199
200 for (size_t i = 0; i < std::size(shapeColors); ++i) {
201 shapeColor = shapeColors[i];
202 for (size_t j = 0; j < std::size(detectorInstallFuncs); ++j) {
203 InstallDetectorFunc detectorInstallFunc = detectorInstallFuncs[j];
204 for (size_t k = 0; k < std::size(funcs); ++k) {
205 TestVariantSequence drawTestSequence = funcs[k];
206 canvas->save();
207 drawTestSequence(canvas, shapeColor, detectorInstallFunc);
208 if (direct) {
209 direct->flushAndSubmit();
210 }
211 canvas->translate(SkIntToScalar(kTestRectSize + 1), SkIntToScalar(0));
212 {
213 SkPictureRecorder recorder;
214 drawTestSequence(recorder.beginRecording(SkIntToScalar(kTestRectSize),
216 shapeColor, detectorInstallFunc);
217 recorder.finishRecordingAsPicture()->playback(canvas);
218 if (direct) {
219 direct->flushAndSubmit();
220 }
221 }
222
223 canvas->restore();
224 canvas->translate(SkIntToScalar(0), SkIntToScalar(kTestRectSize + 1));
225 }
226
227 }
228 }
229}
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
#define SkASSERT(cond)
Definition SkAssert.h:116
uint32_t SkColor
Definition SkColor.h:37
constexpr SkColor SK_ColorTRANSPARENT
Definition SkColor.h:99
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition SkColor.h:49
constexpr SkColor SK_ColorWHITE
Definition SkColor.h:122
#define SkIntToScalar(x)
Definition SkScalar.h:57
int saveLayer(const SkRect *bounds, const SkPaint *paint)
Definition SkCanvas.cpp:500
void drawRect(const SkRect &rect, const SkPaint &paint)
void clipRect(const SkRect &rect, SkClipOp op, bool doAntiAlias)
void restore()
Definition SkCanvas.cpp:465
int save()
Definition SkCanvas.cpp:451
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition SkCanvas.h:1528
static sk_sp< SkColorFilter > TableARGB(const uint8_t tableA[256], const uint8_t tableR[256], const uint8_t tableG[256], const uint8_t tableB[256])
static sk_sp< SkImageFilter > ColorFilter(sk_sp< SkColorFilter > cf, sk_sp< SkImageFilter > input, const CropRect &cropRect={})
static sk_sp< SkImageFilter > Picture(sk_sp< SkPicture > pic, const SkRect &targetRect)
void setColor(SkColor color)
Definition SkPaint.cpp:119
sk_sp< SkImageFilter > refImageFilter() const
void setImageFilter(sk_sp< SkImageFilter > imageFilter)
void setColorFilter(sk_sp< SkColorFilter > colorFilter)
SkCanvas * beginRecording(const SkRect &bounds, sk_sp< SkBBoxHierarchy > bbh)
sk_sp< SkPicture > finishRecordingAsPicture()
virtual void playback(SkCanvas *canvas, AbortCallback *callback=nullptr) const =0
#define DEF_SIMPLE_GM(NAME, CANVAS, W, H)
Definition gm.h:50
static void install_detector_image_filter(SkPaint *drawPaint)
static sk_sp< SkColorFilter > make_detector_color_filter()
static void no_detector_install(SkPaint *)
constexpr int kDetectorGreenValue
constexpr int kTestRectSize
static void draw_save_layer_draw_rect_restore_sequence(SkCanvas *canvas, SkColor shapeColor, InstallDetectorFunc installDetector)
static void install_detector_color_filter(SkPaint *drawPaint)
void(* InstallDetectorFunc)(SkPaint *)
static void draw_svg_opacity_and_filter_layer_sequence(SkCanvas *canvas, SkColor shapeColor, InstallDetectorFunc installDetector)
static void draw_save_layer_draw_bitmap_restore_sequence(SkCanvas *canvas, SkColor shapeColor, InstallDetectorFunc installDetector)
static constexpr SkRect MakeWH(float w, float h)
Definition SkRect.h:609