Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(58)

Side by Side Diff: gm/recordopts.cpp

Issue 835973005: Fold alpha to the inner savelayer in savelayer-savelayer-restore patterns (Closed) Base URL: https://skia.googlesource.com/skia.git@record-opt-savelayer-draw-non-opaque
Patch Set: remove one too many inttoscalar Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | gyp/gmslides.gypi » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.h"
9 #include "SkCanvas.h"
10 #include "SkPath.h"
11 #include "SkPictureRecorder.h"
12 #include "SkTableColorFilter.h"
13 #include "SkColorFilterImageFilter.h"
14 #include "SkPictureImageFilter.h"
15
16 static const int kTestRectSize = 50;
17 static const int kDetectorGreenValue = 50;
18
19 // Below are few functions to install "detector" color filters. The filter is th ere to assert that
20 // the color value it sees is the expected. It will trigger only with kDetectorG reenValue, and
21 // turn that value into full green. The idea is that if an optimization incorrec tly changes
22 // kDetectorGreenValue and then the incorrect value is observable by some part o f the drawing
23 // pipeline, that pixel will remain empty.
24
25 static SkColorFilter* make_detector_color_filter() {
26 uint8_t tableA[256] = { 0, };
27 uint8_t tableR[256] = { 0, };
28 uint8_t tableG[256] = { 0, };
29 uint8_t tableB[256] = { 0, };
30 tableA[255] = 255;
31 tableG[kDetectorGreenValue] = 255;
32 return SkTableColorFilter::CreateARGB(tableA, tableR, tableG, tableB);
33 }
34
35 // This detector detects that color filter phase of the pixel pipeline receives the correct value.
36 static void install_detector_color_filter(SkPaint* drawPaint) {
37 drawPaint->setColorFilter(make_detector_color_filter())->unref();
38 }
39
40 // This detector detects that image filter phase of the pixel pipeline receives the correct value.
41 static void install_detector_image_filter(SkPaint* drawPaint) {
42 SkAutoTUnref<SkColorFilter> colorFilter(make_detector_color_filter());
43 SkImageFilter* imageFilter =
44 SkColorFilterImageFilter::Create(colorFilter, drawPaint->getImageFil ter());
45 drawPaint->setImageFilter(imageFilter)->unref();
46 }
47
48 static void no_detector_install(SkPaint*) {
49 }
50
51 typedef void(*InstallDetectorFunc)(SkPaint*);
52
53
54 // Draws an pattern that can be optimized by alpha folding outer savelayer alpha value to
55 // inner draw. Since we know that folding will happen to the inner draw, install a detector
56 // to make sure that optimization does not change anything observable.
57 static void draw_save_layer_draw_rect_restore_sequence(SkCanvas* canvas, SkColor shapeColor,
58 InstallDetectorFunc insta llDetector) {
59 SkRect targetRect(SkRect::MakeWH(SkIntToScalar(kTestRectSize), SkIntToScalar (kTestRectSize)));
60 SkPaint layerPaint;
61 layerPaint.setColor(SkColorSetARGB(128, 0, 0, 0));
62 canvas->saveLayer(&targetRect, &layerPaint);
63 SkPaint drawPaint;
64 drawPaint.setColor(shapeColor);
65 installDetector(&drawPaint);
66 canvas->drawRect(targetRect, drawPaint);
67 canvas->restore();
68 }
69
70 // Draws an pattern that can be optimized by alpha folding outer savelayer alpha value to
71 // inner draw. A variant where the draw is not uniform color.
72 static void draw_save_layer_draw_bitmap_restore_sequence(SkCanvas* canvas, SkCol or shapeColor,
73 InstallDetectorFunc ins tallDetector) {
74 SkBitmap bitmap;
75 bitmap.allocN32Pixels(kTestRectSize, kTestRectSize);
76 bitmap.eraseColor(shapeColor);
77 {
78 // Make the bitmap non-uniform color, so that it can not be optimized as uniform drawRect.
79 SkCanvas canvas(bitmap);
80 SkPaint p;
81 p.setColor(SK_ColorWHITE);
82 SkASSERT(shapeColor != SK_ColorWHITE);
83 canvas.drawRect(SkRect::MakeWH(SkIntToScalar(7), SkIntToScalar(7)), p);
84 canvas.flush();
85 }
86
87 SkRect targetRect(SkRect::MakeWH(SkIntToScalar(kTestRectSize), SkIntToScalar (kTestRectSize)));
88 SkPaint layerPaint;
89 layerPaint.setColor(SkColorSetARGB(129, 0, 0, 0));
90 canvas->saveLayer(&targetRect, &layerPaint);
91 SkPaint drawPaint;
92 installDetector(&drawPaint);
93 canvas->drawBitmap(bitmap, SkIntToScalar(0), SkIntToScalar(0), &drawPain t);
94 canvas->restore();
95 }
96
97 // Draws an pattern that can be optimized by alpha folding outer savelayer alpha value to
98 // inner savelayer. We know that alpha folding happens to inner savelayer, so ad d detector there.
99 static void draw_svg_opacity_and_filter_layer_sequence(SkCanvas* canvas, SkColor shapeColor,
100 InstallDetectorFunc insta llDetector) {
101
102 SkRect targetRect(SkRect::MakeWH(SkIntToScalar(kTestRectSize), SkIntToScalar (kTestRectSize)));
103 SkAutoTUnref<SkPicture> shape;
104 {
105 SkPictureRecorder recorder;
106 SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(kTestRectSize + 2),
107 SkIntToScalar(kTestRectSize + 2));
108 SkPaint shapePaint;
109 shapePaint.setColor(shapeColor);
110 canvas->drawRect(targetRect, shapePaint);
111 shape.reset(recorder.endRecordingAsPicture());
112 }
113
114 SkPaint layerPaint;
115 layerPaint.setColor(SkColorSetARGB(130, 0, 0, 0));
116 canvas->saveLayer(&targetRect, &layerPaint);
117 canvas->save();
118 canvas->clipRect(targetRect);
119 SkPaint drawPaint;
120 drawPaint.setImageFilter(SkPictureImageFilter::Create(shape))->unref ();
121 installDetector(&drawPaint);
122 canvas->saveLayer(&targetRect, &drawPaint);
123 canvas->restore();
124 canvas->restore();
125 canvas->restore();
126 }
127
128 // Draws two columns of rectangles. The test is correct when:
129 // - Left and right columns always identical
130 // - First 3 rows are green, with a white dent in the middle row
131 // - Next 6 rows are green, with a grey dent in the middle row
132 // (the grey dent is from the color filter removing everything but the "good" green, see below)
133 // - Last 6 rows are grey
134 DEF_SIMPLE_GM(recordopts, canvas, (kTestRectSize+1)*2, (kTestRectSize+1)*15) {
135 canvas->clear(SK_ColorTRANSPARENT);
136
137 typedef void (*TestVariantSequence)(SkCanvas*, SkColor, InstallDetectorFunc) ;
138 TestVariantSequence funcs[] = {
139 draw_save_layer_draw_rect_restore_sequence,
140 draw_save_layer_draw_bitmap_restore_sequence,
141 draw_svg_opacity_and_filter_layer_sequence,
142 };
143
144 // Draw layer-related sequences that can be optimized by folding the opacity layer alpha to
145 // the inner draw operation. This tries to trigger the optimization, and rel ies on gm diffs
146 // to keep the color value correct over time.
147
148 // Draws two green rects side by side: one is without the optimization, the other is with
149 // the optimization applied.
150
151 SkColor shapeColor = SkColorSetARGB(255, 0, 255, 0);
152 for (size_t k = 0; k < SK_ARRAY_COUNT(funcs); ++k) {
153 canvas->save();
154
155 TestVariantSequence drawTestSequence = funcs[k];
156 drawTestSequence(canvas, shapeColor, no_detector_install);
157 canvas->flush();
158 canvas->translate(SkIntToScalar(kTestRectSize) + SkIntToScalar(1), SkInt ToScalar(0));
159 {
160 SkPictureRecorder recorder;
161 drawTestSequence(recorder.beginRecording(SkIntToScalar(kTestRectSize ),
162 SkIntToScalar(kTestRectSize )),
163 shapeColor, no_detector_install);
164 SkAutoTUnref<SkPicture> optimizedPicture(recorder.endRecordingAsPict ure());
165 optimizedPicture->playback(canvas);
166 canvas->flush();
167 }
168 canvas->restore();
169 canvas->translate(SkIntToScalar(0), SkIntToScalar(kTestRectSize) + SkInt ToScalar(1));
170 }
171
172 // Draw the same layer related sequences, but manipulate the sequences so th at the result is
173 // incorrect if the alpha is folded or folded incorrectly. These test the ob servable state
174 // throughout the pixel pipeline, and thus may turn off the optimizations (t his is why we
175 // trigger the optimizations above).
176
177 // Draws two green rects side by side: one is without the optimization, the other is with
178 // the possibility that optimization is applied.
179 // At the end, draws the same patterns in translucent black. This tests that the detectors
180 // work, eg. that if the value the detector sees is wrong, the resulting ima ge shows this.
181 SkColor shapeColors[] = {
182 SkColorSetARGB(255, 0, kDetectorGreenValue, 0),
183 SkColorSetARGB(255, 0, kDetectorGreenValue + 1, 0) // This tests that de tectors work.
184 };
185
186 InstallDetectorFunc detectorInstallFuncs[] = {
187 install_detector_image_filter,
188 install_detector_color_filter
189 };
190
191 for (size_t i = 0; i < SK_ARRAY_COUNT(shapeColors); ++i) {
192 shapeColor = shapeColors[i];
193 for (size_t j = 0; j < SK_ARRAY_COUNT(shapeColors); ++j) {
194 InstallDetectorFunc detectorInstallFunc = detectorInstallFuncs[j];
195 for (size_t k = 0; k < SK_ARRAY_COUNT(funcs); ++k) {
196 TestVariantSequence drawTestSequence = funcs[k];
197 canvas->save();
198 drawTestSequence(canvas, shapeColor, detectorInstallFunc);
199 canvas->flush();
200 canvas->translate(SkIntToScalar(kTestRectSize) + SkIntToScalar(1 ), SkIntToScalar(0));
201 {
202 SkPictureRecorder recorder;
203 drawTestSequence(recorder.beginRecording(SkIntToScalar(kTest RectSize),
204 SkIntToScalar(kTest RectSize)),
205 shapeColor, detectorInstallFunc);
206 SkAutoTUnref<SkPicture> optimizedPicture(recorder.endRecordi ngAsPicture());
207 optimizedPicture->playback(canvas);
208 canvas->flush();
209 }
210
211 canvas->restore();
212 canvas->translate(SkIntToScalar(0), SkIntToScalar(kTestRectSize) + SkIntToScalar(1));
213 }
214
215 }
216 }
217 }
218
OLDNEW
« no previous file with comments | « no previous file | gyp/gmslides.gypi » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698