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

Side by Side Diff: skia/ext/analysis_canvas.cc

Issue 12316084: cc: Consolidate the analysis_canvas operations (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixed unittest Created 7 years, 9 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 | Annotate | Revision Log
« cc/tile_manager.cc ('K') | « skia/ext/analysis_canvas.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/debug/trace_event.h" 5 #include "base/debug/trace_event.h"
6 #include "skia/ext/analysis_canvas.h" 6 #include "skia/ext/analysis_canvas.h"
7 #include "third_party/skia/include/core/SkDevice.h" 7 #include "third_party/skia/include/core/SkDevice.h"
8 #include "third_party/skia/include/core/SkDraw.h" 8 #include "third_party/skia/include/core/SkDraw.h"
9 #include "third_party/skia/include/core/SkRRect.h" 9 #include "third_party/skia/include/core/SkRRect.h"
10 #include "third_party/skia/src/core/SkRasterClip.h"
10 #include "ui/gfx/rect_conversions.h" 11 #include "ui/gfx/rect_conversions.h"
11 12
12 namespace { 13 namespace {
13 14
14 // FIXME: Arbitrary number. Requires tuning & experimentation. 15 // FIXME: Arbitrary number. Requires tuning & experimentation.
15 // Probably requires per-platform tuning; N10 average draw call takes 16 // Probably requires per-platform tuning; N10 average draw call takes
16 // 25x as long as Z620. 17 // 25x as long as Z620.
17 const int gPictureCostThreshold = 1000; 18 const int gPictureCostThreshold = 1000;
18 19
20 static bool isSolidColorPaint(const SkPaint& paint) {
21 SkXfermode::Mode xferMode;
22
23 // getXfermode can return a NULL, but that is handled
24 // gracefully by AsMode (NULL turns into kSrcOver mode).
25 SkXfermode::AsMode(paint.getXfermode(), &xferMode);
26
27 // Paint is solid color if the following holds:
28 // - Alpha is 1.0, style is fill, and there are no special effects
29 // - Xfer mode is either kSrc or kSrcOver (kSrcOver is equivalent
30 // to kSrc if source alpha is 1.0, which is already checked).
31 return (paint.getAlpha() == 255 &&
32 !paint.getShader() &&
33 !paint.getLooper() &&
34 !paint.getMaskFilter() &&
35 !paint.getColorFilter() &&
36 paint.getStyle() == SkPaint::kFill_Style &&
37 (xferMode == SkXfermode::kSrc_Mode ||
38 xferMode == SkXfermode::kSrcOver_Mode));
19 } 39 }
20 40
41 } // namespace
42
21 namespace skia { 43 namespace skia {
22 44
23 AnalysisDevice::AnalysisDevice(const SkBitmap& bm) 45 AnalysisDevice::AnalysisDevice(const SkBitmap& bm)
24 : INHERITED(bm) 46 : INHERITED(bm)
25 , estimatedCost_(0) { 47 , estimatedCost_(0)
48 , isForcedNotSolid_(false)
49 , isForcedNotTransparent_(false)
50 , isSolidColor_(false)
51 , isTransparent_(false) {
26 52
27 } 53 }
28 54
29 AnalysisDevice::~AnalysisDevice() { 55 AnalysisDevice::~AnalysisDevice() {
30
Tom Hudson 2013/02/27 14:49:36 Nit: Is this whitespace change dictated by the Chr
31 } 56 }
32 57
33 int AnalysisDevice::getEstimatedCost() const { 58 int AnalysisDevice::getEstimatedCost() const {
34 return estimatedCost_; 59 return estimatedCost_;
35 } 60 }
36 61
62 bool AnalysisDevice::getColorIfSolid(SkColor* color) const {
63 if (isSolidColor_)
64 *color = color_;
65 return isSolidColor_;
66 }
67
68 bool AnalysisDevice::isTransparent() const {
69 return isTransparent_;
70 }
71
72 void AnalysisDevice::setForceNotSolid(bool flag) {
73 isForcedNotSolid_ = flag;
74 if (isForcedNotSolid_)
75 isSolidColor_ = false;
76 }
77
78 void AnalysisDevice::setForceNotTransparent(bool flag) {
79 isForcedNotTransparent_ = flag;
80 if (isForcedNotTransparent_)
81 isTransparent_ = false;
82 }
83
37 void AnalysisDevice::clear(SkColor color) { 84 void AnalysisDevice::clear(SkColor color) {
38 ++estimatedCost_; 85 ++estimatedCost_;
86
87 isTransparent_ = (!isForcedNotTransparent_ && SkColorGetA(color) == 0);
88
89 if (!isForcedNotSolid_ && SkColorGetA(color) == 255) {
90 isSolidColor_ = true;
91 color_ = color;
92 }
93 else {
94 isSolidColor_ = false;
95 }
39 } 96 }
40 97
41 void AnalysisDevice::drawPaint(const SkDraw&, const SkPaint& paint) { 98 void AnalysisDevice::drawPaint(const SkDraw&, const SkPaint& paint) {
42 ++estimatedCost_; 99 ++estimatedCost_;
100 isSolidColor_ = false;
101 isTransparent_ = false;
43 } 102 }
44 103
45 void AnalysisDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode, 104 void AnalysisDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode,
46 size_t count, const SkPoint[], 105 size_t count, const SkPoint[],
47 const SkPaint& paint) { 106 const SkPaint& paint) {
48 ++estimatedCost_; 107 ++estimatedCost_;
108 isSolidColor_ = false;
109 isTransparent_ = false;
49 } 110 }
50 111
51 void AnalysisDevice::drawRect(const SkDraw&, const SkRect& r, 112 void AnalysisDevice::drawRect(const SkDraw& draw, const SkRect& rect,
52 const SkPaint& paint) { 113 const SkPaint& paint) {
114
53 // FIXME: if there's a pending image decode & resize, more expensive 115 // FIXME: if there's a pending image decode & resize, more expensive
54 if (paint.getMaskFilter()) { 116 if (paint.getMaskFilter()) {
55 estimatedCost_ += 300; 117 estimatedCost_ += 300;
56 } 118 }
57 ++estimatedCost_; 119 ++estimatedCost_;
120
121 SkRect drawBitmapRect;
122 draw.fBitmap->getBounds(&drawBitmapRect);
123 SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
124 SkRect canvasRect = SkRect::MakeWH(width(), height());
125 SkRect deviceRect;
126 draw.fMatrix->mapRect(&deviceRect, rect);
127
128
129 // This draw is equivalent to clear(), if the following conditions hold:
130 // - Clip rect is an actual rectangle.
131 // - The rect we're drawing (post-transform) contains the clip rect.
132 // That is, all of clip rect will be colored by the rect.
133 // - Clip rect contains the canvas rect.
134 // That is, we're not clipping to a portion of this canvas.
135 bool isFullQuad = (draw.fRC->isRect() &&
136 deviceRect.contains(clipRect) &&
137 clipRect.contains(canvasRect) &&
138 drawBitmapRect.contains(canvasRect));
139
140 SkXfermode::Mode xferMode;
141 SkXfermode::AsMode(paint.getXfermode(), &xferMode);
142
143 // This canvas will become transparent if the following holds:
144 // - The quad is a full tile quad
145 // - We're not in "forced not transparent" mode
146 // - Transfer mode is clear (0 color, 0 alpha)
147 //
148 // If the paint alpha is not 0, or if the transfrer mode is
149 // not src, then this canvas will not be transparent.
150 //
151 // In all other cases, we keep the current transparent value
152 if (isFullQuad &&
153 !isForcedNotTransparent_ &&
154 xferMode == SkXfermode::kClear_Mode) {
155 isTransparent_ = true;
156 }
157 else if (paint.getAlpha() != 0 ||
158 xferMode != SkXfermode::kSrc_Mode) {
159 isTransparent_ = false;
160 }
161
162 // This bitmap is solid if and only if the following holds.
163 // Note that this might be overly conservative:
164 // - We're not in "forced not solid" mode
165 // - Paint is solid color
166 // - The quad is a full tile quad
167 if (!isForcedNotSolid_ &&
168 isSolidColorPaint(paint) &&
169 isFullQuad) {
170 isSolidColor_ = true;
171 color_ = paint.getColor();
172 }
173 else {
174 isSolidColor_ = false;
175 }
58 } 176 }
59 177
60 void AnalysisDevice::drawOval(const SkDraw&, const SkRect& oval, 178 void AnalysisDevice::drawOval(const SkDraw&, const SkRect& oval,
61 const SkPaint& paint) { 179 const SkPaint& paint) {
62 ++estimatedCost_; 180 ++estimatedCost_;
181 isSolidColor_ = false;
182 isTransparent_ = false;
63 } 183 }
64 184
65 void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path, 185 void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path,
66 const SkPaint& paint, 186 const SkPaint& paint,
67 const SkMatrix* prePathMatrix , 187 const SkMatrix* prePathMatrix ,
68 bool pathIsMutable ) { 188 bool pathIsMutable ) {
69 // On Z620, every antialiased path costs us about 300us. 189 // On Z620, every antialiased path costs us about 300us.
70 // We've only seen this in practice on filled paths, but 190 // We've only seen this in practice on filled paths, but
71 // we expect it to apply to all path stroking modes. 191 // we expect it to apply to all path stroking modes.
72 if (paint.getMaskFilter()) { 192 if (paint.getMaskFilter()) {
73 estimatedCost_ += 300; 193 estimatedCost_ += 300;
74 } 194 }
75 ++estimatedCost_; 195 ++estimatedCost_;
196 isSolidColor_ = false;
197 isTransparent_ = false;
76 } 198 }
77 199
78 void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, 200 void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap,
79 const SkIRect* srcRectOrNull, 201 const SkIRect* srcRectOrNull,
80 const SkMatrix& matrix, const SkPaint& paint) 202 const SkMatrix& matrix, const SkPaint& paint) {
81 {
82 ++estimatedCost_; 203 ++estimatedCost_;
204 isSolidColor_ = false;
205 isTransparent_ = false;
83 } 206 }
84 207
85 void AnalysisDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap, 208 void AnalysisDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap,
86 int x, int y, const SkPaint& paint) { 209 int x, int y, const SkPaint& paint) {
87 ++estimatedCost_; 210 ++estimatedCost_;
211 isSolidColor_ = false;
212 isTransparent_ = false;
88 } 213 }
89 214
90 void AnalysisDevice::drawBitmapRect(const SkDraw&, const SkBitmap&, 215 void AnalysisDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap&,
91 const SkRect* srcOrNull, const SkRect& dst, 216 const SkRect* srcOrNull, const SkRect& rect,
Tom Hudson 2013/02/27 14:49:36 Nit: I think you've changed this parameter name fr
92 const SkPaint& paint) { 217 const SkPaint& paint) {
93 ++estimatedCost_; 218 ++estimatedCost_;
219 isSolidColor_ = false;
220
221 SkRect drawBitmapRect;
222 draw.fBitmap->getBounds(&drawBitmapRect);
223 SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
224 SkRect bitmapRect = SkRect::MakeWH(width(), height());
225 SkRect deviceRect;
226 draw.fMatrix->mapRect(&deviceRect, rect);
227
228 // This draw is equivalent to clear(), if the following conditions hold:
Tom Hudson 2013/02/27 14:49:36 Both of these clauses are duplicated from drawRect
229 // - Clip rect is an actual rectangle.
230 // - The rect we're drawing (post-transform) contains the clip rect.
231 // That is, all of clip rect will be colored by the rect.
232 // - Clip rect contains the canvas rect.
233 // That is, we're not clipping to a portion of this canvas.
234 bool isFullQuad = (draw.fRC->isRect() &&
235 deviceRect.contains(clipRect) &&
236 clipRect.contains(bitmapRect) &&
237 drawBitmapRect.contains(bitmapRect));
238
239 SkXfermode::Mode xferMode;
240 SkXfermode::AsMode(paint.getXfermode(), &xferMode);
241
242 // This canvas will become transparent if the following holds:
243 // - The quad is a full tile quad
244 // - We're not in "forced not transparent" mode
245 // - Transfer mode is clear (0 color, 0 alpha)
246 //
247 // If the paint alpha is not 0, or if the transfrer mode is
248 // not src, then this canvas will not be transparent.
249 //
250 // In all other cases, we keep the current transparent value
251 if (isFullQuad &&
252 !isForcedNotTransparent_ &&
253 xferMode == SkXfermode::kClear_Mode) {
254 isTransparent_ = true;
255 }
256 else if (paint.getAlpha() != 0 ||
257 xferMode != SkXfermode::kSrc_Mode) {
258 isTransparent_ = false;
259 }
94 } 260 }
95 261
96 262
97 void AnalysisDevice::drawText(const SkDraw&, const void* text, size_t len, 263 void AnalysisDevice::drawText(const SkDraw&, const void* text, size_t len,
98 SkScalar x, SkScalar y, const SkPaint& paint) 264 SkScalar x, SkScalar y, const SkPaint& paint) {
99 {
100 ++estimatedCost_; 265 ++estimatedCost_;
266 isSolidColor_ = false;
267 isTransparent_ = false;
101 } 268 }
102 269
103 void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t le n, 270 void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t le n,
104 const SkScalar pos[], SkScalar constY, 271 const SkScalar pos[], SkScalar constY,
105 int scalarsPerPos, const SkPaint& paint) { 272 int scalarsPerPos, const SkPaint& paint) {
106 // FIXME: On Z620, every glyph cache miss costs us about 10us. 273 // FIXME: On Z620, every glyph cache miss costs us about 10us.
107 // We don't have a good mechanism for predicting glyph cache misses. 274 // We don't have a good mechanism for predicting glyph cache misses.
108 ++estimatedCost_; 275 ++estimatedCost_;
276 isSolidColor_ = false;
277 isTransparent_ = false;
109 } 278 }
110 279
111 void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, 280 void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len,
112 const SkPath& path, const SkMatrix* matrix, 281 const SkPath& path, const SkMatrix* matrix,
113 const SkPaint& paint) { 282 const SkPaint& paint) {
114 ++estimatedCost_; 283 ++estimatedCost_;
284 isSolidColor_ = false;
285 isTransparent_ = false;
115 } 286 }
116 287
117 #ifdef SK_BUILD_FOR_ANDROID 288 #ifdef SK_BUILD_FOR_ANDROID
118 void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, 289 void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, const void* text,
119 size_t len, 290 size_t len,
120 const SkPoint pos[], const SkPaint& paint, 291 const SkPoint pos[], const SkPaint& paint,
121 const SkPath& path, const SkMatrix* matrix) 292 const SkPath& path, const SkMatrix* matrix) {
122 {
123 ++estimatedCost_; 293 ++estimatedCost_;
294 isSolidColor_ = false;
295 isTransparent_ = false;
124 } 296 }
125 #endif 297 #endif
126 298
127 void AnalysisDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, 299 void AnalysisDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode,
128 int vertexCount, 300 int vertexCount,
129 const SkPoint verts[], const SkPoint texs[], 301 const SkPoint verts[], const SkPoint texs[],
130 const SkColor colors[], SkXfermode* xmode, 302 const SkColor colors[], SkXfermode* xmode,
131 const uint16_t indices[], int indexCount, 303 const uint16_t indices[], int indexCount,
132 const SkPaint& paint) { 304 const SkPaint& paint) {
133 ++estimatedCost_; 305 ++estimatedCost_;
306 isSolidColor_ = false;
307 isTransparent_ = false;
134 } 308 }
135 309
136 void AnalysisDevice::drawDevice(const SkDraw&, SkDevice*, int x, int y, 310 void AnalysisDevice::drawDevice(const SkDraw&, SkDevice*, int x, int y,
137 const SkPaint&) { 311 const SkPaint&) {
138 ++estimatedCost_; 312 ++estimatedCost_;
313 isSolidColor_ = false;
314 isTransparent_ = false;
139 } 315 }
140 316
141 317
142 318
143
144 AnalysisCanvas::AnalysisCanvas(AnalysisDevice* device) 319 AnalysisCanvas::AnalysisCanvas(AnalysisDevice* device)
145 : INHERITED(device) { 320 : INHERITED(device)
146 321 , savedLayerStackSize_(0) {
147 } 322 }
148 323
149 AnalysisCanvas::~AnalysisCanvas() { 324 AnalysisCanvas::~AnalysisCanvas() {
150 } 325 }
151 326
152 327
153 bool AnalysisCanvas::isCheap() const { 328 bool AnalysisCanvas::isCheap() const {
154 return getEstimatedCost() < gPictureCostThreshold; 329 return getEstimatedCost() < gPictureCostThreshold;
155 } 330 }
156 331
332 bool AnalysisCanvas::getColorIfSolid(SkColor* color) const {
333 return (static_cast<AnalysisDevice*>(getDevice()))->getColorIfSolid(color);
334 }
335
336 bool AnalysisCanvas::isTransparent() const {
337 return (static_cast<AnalysisDevice*>(getDevice()))->isTransparent();
338 }
339
157 int AnalysisCanvas::getEstimatedCost() const { 340 int AnalysisCanvas::getEstimatedCost() const {
158 return (static_cast<AnalysisDevice*>(getDevice()))->getEstimatedCost(); 341 return (static_cast<AnalysisDevice*>(getDevice()))->getEstimatedCost();
159 } 342 }
160 343
161
162 bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op, 344 bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op,
163 bool doAA) { 345 bool doAA) {
164 return INHERITED::clipRect(rect, op, doAA); 346 return INHERITED::clipRect(rect, op, doAA);
165 } 347 }
166 348
167 bool AnalysisCanvas::clipPath(const SkPath& path, SkRegion::Op op, 349 bool AnalysisCanvas::clipPath(const SkPath& path, SkRegion::Op op,
168 bool doAA) { 350 bool doAA) {
169 return INHERITED::clipRect(path.getBounds(), op, doAA); 351 return INHERITED::clipRect(path.getBounds(), op, doAA);
170 } 352 }
171 353
172 bool AnalysisCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, 354 bool AnalysisCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op,
173 bool doAA) { 355 bool doAA) {
174 return INHERITED::clipRect(rrect.getBounds(), op, doAA); 356 return INHERITED::clipRect(rrect.getBounds(), op, doAA);
175 } 357 }
176 358
177 int AnalysisCanvas::saveLayer(const SkRect* bounds, const SkPaint*, 359 int AnalysisCanvas::save(SkCanvas::SaveFlags flags) {
360 INHERITED::save(flags);
361 }
362
363 int AnalysisCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
178 SkCanvas::SaveFlags flags) { 364 SkCanvas::SaveFlags flags) {
365 // If after we draw to the saved layer, we have to blend with the current
366 // layer, then we can conservatively say that the canvas will not be of
367 // solid color.
Tom Hudson 2013/02/27 14:49:36 Thanks for adding these explanations.
368 if ((paint && !isSolidColorPaint(*paint)) ||
369 (bounds && !bounds->contains(
370 SkRect::MakeWH(getDevice()->width(), getDevice()->height()))))
371 (static_cast<AnalysisDevice*>(getDevice()))->setForceNotSolid(true);
372
373 // If after we draw to the save layer, we have to blend with the current
374 // layer using any part of the current layer's alpha, then we can
375 // conservatively say that the canvas will not be transparent.
376 SkXfermode::Mode xferMode = SkXfermode::kSrc_Mode;
377 if (paint)
378 SkXfermode::AsMode(paint->getXfermode(), &xferMode);
379 if (xferMode != SkXfermode::kSrc_Mode)
380 (static_cast<AnalysisDevice*>(getDevice()))->setForceNotTransparent(true);
381
382 ++savedLayerStackSize_;
383
179 // Actually saving a layer here could cause a new bitmap to be created 384 // Actually saving a layer here could cause a new bitmap to be created
180 // and real rendering to occur. 385 // and real rendering to occur.
181 int count = SkCanvas::save(flags); 386 int count = INHERITED::save(flags);
182 if (bounds) { 387 if (bounds) {
183 INHERITED::clipRectBounds(bounds, flags, NULL); 388 INHERITED::clipRectBounds(bounds, flags, NULL);
184 } 389 }
185 return count; 390 return count;
186 } 391 }
187 392
393 void AnalysisCanvas::restore() {
394 INHERITED::restore();
395
396 if (--savedLayerStackSize_ == 0) {
397 (static_cast<AnalysisDevice*>(getDevice()))->setForceNotSolid(false);
398 (static_cast<AnalysisDevice*>(getDevice()))->setForceNotTransparent(false);
399 }
400 }
401
188 } // namespace skia 402 } // namespace skia
189 403
190 404
OLDNEW
« cc/tile_manager.cc ('K') | « skia/ext/analysis_canvas.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698