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

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: changed analysis location 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) {
Justin Novosad 2013/03/05 22:14:02 I think isPaintOpaque (SkPaintPriv.cpp in skia) co
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 static bool isFullQuad(const SkDraw& draw,
42 const SkRect& canvasRect,
43 const SkRect& drawnRect) {
44 SkRect drawBitmapRect;
45 draw.fBitmap->getBounds(&drawBitmapRect);
46 SkRect clipRect = SkRect::Make(draw.fRC->getBounds());
47 SkRect deviceRect;
48 draw.fMatrix->mapRect(&deviceRect, drawnRect);
Justin Novosad 2013/03/05 22:14:02 The way this is implemented, you will sometimes ge
49
50 // The drawn rect covers the full canvas, if the following conditions hold:
51 // - Clip rect is an actual rectangle.
52 // - The rect we're drawing (post-transform) contains the clip rect.
53 // That is, all of clip rect will be colored by the rect.
54 // - Clip rect contains the canvas rect.
55 // That is, we're not clipping to a portion of this canvas.
56 // - The bitmap into which the draw call happens is at least as
57 // big as the canvas rect
58 return draw.fRC->isRect() &&
Justin Novosad 2013/03/05 22:14:02 This is not safe. AnalysisCanvas converts clipPat
59 deviceRect.contains(clipRect) &&
60 clipRect.contains(canvasRect) &&
61 drawBitmapRect.contains(canvasRect);
62 }
63
64 } // namespace
65
21 namespace skia { 66 namespace skia {
22 67
23 AnalysisDevice::AnalysisDevice(const SkBitmap& bm) 68 AnalysisDevice::AnalysisDevice(const SkBitmap& bm)
24 : INHERITED(bm) 69 : INHERITED(bm)
25 , estimatedCost_(0) { 70 , estimatedCost_(0)
71 , isForcedNotSolid_(false)
72 , isForcedNotTransparent_(false)
73 , isSolidColor_(false)
74 , isTransparent_(false) {
26 75
27 } 76 }
28 77
29 AnalysisDevice::~AnalysisDevice() { 78 AnalysisDevice::~AnalysisDevice() {
30 79
31 } 80 }
32 81
33 int AnalysisDevice::getEstimatedCost() const { 82 int AnalysisDevice::getEstimatedCost() const {
34 return estimatedCost_; 83 return estimatedCost_;
35 } 84 }
36 85
86 bool AnalysisDevice::getColorIfSolid(SkColor* color) const {
87 if (isSolidColor_)
88 *color = color_;
89 return isSolidColor_;
90 }
91
92 bool AnalysisDevice::isTransparent() const {
93 return isTransparent_;
94 }
95
96 void AnalysisDevice::setForceNotSolid(bool flag) {
97 isForcedNotSolid_ = flag;
98 if (isForcedNotSolid_)
99 isSolidColor_ = false;
100 }
101
102 void AnalysisDevice::setForceNotTransparent(bool flag) {
103 isForcedNotTransparent_ = flag;
104 if (isForcedNotTransparent_)
105 isTransparent_ = false;
106 }
107
37 void AnalysisDevice::clear(SkColor color) { 108 void AnalysisDevice::clear(SkColor color) {
38 ++estimatedCost_; 109 ++estimatedCost_;
110
111 isTransparent_ = (!isForcedNotTransparent_ && SkColorGetA(color) == 0);
112
113 if (!isForcedNotSolid_ && SkColorGetA(color) == 255) {
114 isSolidColor_ = true;
115 color_ = color;
116 }
117 else {
118 isSolidColor_ = false;
119 }
39 } 120 }
40 121
41 void AnalysisDevice::drawPaint(const SkDraw&, const SkPaint& paint) { 122 void AnalysisDevice::drawPaint(const SkDraw&, const SkPaint& paint) {
Justin Novosad 2013/03/05 22:14:02 This method could do more. it fills the entire cli
42 ++estimatedCost_; 123 ++estimatedCost_;
124 isSolidColor_ = false;
125 isTransparent_ = false;
43 } 126 }
44 127
45 void AnalysisDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode, 128 void AnalysisDevice::drawPoints(const SkDraw&, SkCanvas::PointMode mode,
46 size_t count, const SkPoint[], 129 size_t count, const SkPoint[],
47 const SkPaint& paint) { 130 const SkPaint& paint) {
48 ++estimatedCost_; 131 ++estimatedCost_;
132 isSolidColor_ = false;
133 isTransparent_ = false;
49 } 134 }
50 135
51 void AnalysisDevice::drawRect(const SkDraw&, const SkRect& r, 136 void AnalysisDevice::drawRect(const SkDraw& draw, const SkRect& rect,
52 const SkPaint& paint) { 137 const SkPaint& paint) {
138
53 // FIXME: if there's a pending image decode & resize, more expensive 139 // FIXME: if there's a pending image decode & resize, more expensive
54 if (paint.getMaskFilter()) { 140 if (paint.getMaskFilter()) {
55 estimatedCost_ += 300; 141 estimatedCost_ += 300;
56 } 142 }
57 ++estimatedCost_; 143 ++estimatedCost_;
144
145 bool doesCoverCanvas = isFullQuad(draw,
146 SkRect::MakeWH(width(), height()),
147 rect);
148
149 SkXfermode::Mode xferMode;
150 SkXfermode::AsMode(paint.getXfermode(), &xferMode);
151
152 // This canvas will become transparent if the following holds:
153 // - The quad is a full tile quad
154 // - We're not in "forced not transparent" mode
155 // - Transfer mode is clear (0 color, 0 alpha)
156 //
157 // If the paint alpha is not 0, or if the transfrer mode is
158 // not src, then this canvas will not be transparent.
159 //
160 // In all other cases, we keep the current transparent value
161 if (doesCoverCanvas &&
162 !isForcedNotTransparent_ &&
163 xferMode == SkXfermode::kClear_Mode) {
164 isTransparent_ = true;
165 }
166 else if (paint.getAlpha() != 0 ||
167 xferMode != SkXfermode::kSrc_Mode) {
168 isTransparent_ = false;
169 }
170
171 // This bitmap is solid if and only if the following holds.
172 // Note that this might be overly conservative:
173 // - We're not in "forced not solid" mode
174 // - Paint is solid color
175 // - The quad is a full tile quad
176 if (!isForcedNotSolid_ &&
177 isSolidColorPaint(paint) &&
178 doesCoverCanvas) {
179 isSolidColor_ = true;
180 color_ = paint.getColor();
181 }
182 else {
183 isSolidColor_ = false;
184 }
58 } 185 }
59 186
60 void AnalysisDevice::drawOval(const SkDraw&, const SkRect& oval, 187 void AnalysisDevice::drawOval(const SkDraw&, const SkRect& oval,
Justin Novosad 2013/03/05 22:14:02 FWIW: It is trivial to compute whether an oval con
61 const SkPaint& paint) { 188 const SkPaint& paint) {
62 ++estimatedCost_; 189 ++estimatedCost_;
190 isSolidColor_ = false;
191 isTransparent_ = false;
63 } 192 }
64 193
65 void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path, 194 void AnalysisDevice::drawPath(const SkDraw&, const SkPath& path,
66 const SkPaint& paint, 195 const SkPaint& paint,
67 const SkMatrix* prePathMatrix , 196 const SkMatrix* prePathMatrix ,
68 bool pathIsMutable ) { 197 bool pathIsMutable ) {
69 // On Z620, every antialiased path costs us about 300us. 198 // On Z620, every antialiased path costs us about 300us.
70 // We've only seen this in practice on filled paths, but 199 // We've only seen this in practice on filled paths, but
71 // we expect it to apply to all path stroking modes. 200 // we expect it to apply to all path stroking modes.
72 if (paint.getMaskFilter()) { 201 if (paint.getMaskFilter()) {
73 estimatedCost_ += 300; 202 estimatedCost_ += 300;
74 } 203 }
75 ++estimatedCost_; 204 ++estimatedCost_;
205 isSolidColor_ = false;
206 isTransparent_ = false;
76 } 207 }
77 208
78 void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap, 209 void AnalysisDevice::drawBitmap(const SkDraw&, const SkBitmap& bitmap,
79 const SkIRect* srcRectOrNull, 210 const SkIRect* srcRectOrNull,
80 const SkMatrix& matrix, const SkPaint& paint) 211 const SkMatrix& matrix, const SkPaint& paint) {
81 {
82 ++estimatedCost_; 212 ++estimatedCost_;
213 isSolidColor_ = false;
214 isTransparent_ = false;
83 } 215 }
84 216
85 void AnalysisDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap, 217 void AnalysisDevice::drawSprite(const SkDraw&, const SkBitmap& bitmap,
86 int x, int y, const SkPaint& paint) { 218 int x, int y, const SkPaint& paint) {
87 ++estimatedCost_; 219 ++estimatedCost_;
220 isSolidColor_ = false;
221 isTransparent_ = false;
88 } 222 }
89 223
90 void AnalysisDevice::drawBitmapRect(const SkDraw&, const SkBitmap&, 224 void AnalysisDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap&,
91 const SkRect* srcOrNull, const SkRect& dst, 225 const SkRect* srcOrNull, const SkRect& dst,
92 const SkPaint& paint) { 226 const SkPaint& paint) {
93 ++estimatedCost_; 227 ++estimatedCost_;
228
229 // Call drawRect to determine transparency,
230 // but reset solid color to false.
231 drawRect(draw, dst, paint);
232 isSolidColor_ = false;
94 } 233 }
95 234
96 235
97 void AnalysisDevice::drawText(const SkDraw&, const void* text, size_t len, 236 void AnalysisDevice::drawText(const SkDraw&, const void* text, size_t len,
98 SkScalar x, SkScalar y, const SkPaint& paint) 237 SkScalar x, SkScalar y, const SkPaint& paint) {
99 {
100 ++estimatedCost_; 238 ++estimatedCost_;
239 isSolidColor_ = false;
240 isTransparent_ = false;
101 } 241 }
102 242
103 void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t le n, 243 void AnalysisDevice::drawPosText(const SkDraw& draw, const void* text, size_t le n,
104 const SkScalar pos[], SkScalar constY, 244 const SkScalar pos[], SkScalar constY,
105 int scalarsPerPos, const SkPaint& paint) { 245 int scalarsPerPos, const SkPaint& paint) {
106 // FIXME: On Z620, every glyph cache miss costs us about 10us. 246 // FIXME: On Z620, every glyph cache miss costs us about 10us.
107 // We don't have a good mechanism for predicting glyph cache misses. 247 // We don't have a good mechanism for predicting glyph cache misses.
108 ++estimatedCost_; 248 ++estimatedCost_;
249 isSolidColor_ = false;
250 isTransparent_ = false;
109 } 251 }
110 252
111 void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len, 253 void AnalysisDevice::drawTextOnPath(const SkDraw&, const void* text, size_t len,
112 const SkPath& path, const SkMatrix* matrix, 254 const SkPath& path, const SkMatrix* matrix,
113 const SkPaint& paint) { 255 const SkPaint& paint) {
114 ++estimatedCost_; 256 ++estimatedCost_;
257 isSolidColor_ = false;
258 isTransparent_ = false;
115 } 259 }
116 260
117 #ifdef SK_BUILD_FOR_ANDROID 261 #ifdef SK_BUILD_FOR_ANDROID
118 void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, const void* text, 262 void AnalysisDevice::drawPosTextOnPath(const SkDraw& draw, const void* text,
119 size_t len, 263 size_t len,
120 const SkPoint pos[], const SkPaint& paint, 264 const SkPoint pos[], const SkPaint& paint,
121 const SkPath& path, const SkMatrix* matrix) 265 const SkPath& path, const SkMatrix* matrix) {
122 {
123 ++estimatedCost_; 266 ++estimatedCost_;
267 isSolidColor_ = false;
268 isTransparent_ = false;
124 } 269 }
125 #endif 270 #endif
126 271
127 void AnalysisDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode, 272 void AnalysisDevice::drawVertices(const SkDraw&, SkCanvas::VertexMode,
128 int vertexCount, 273 int vertexCount,
129 const SkPoint verts[], const SkPoint texs[], 274 const SkPoint verts[], const SkPoint texs[],
130 const SkColor colors[], SkXfermode* xmode, 275 const SkColor colors[], SkXfermode* xmode,
131 const uint16_t indices[], int indexCount, 276 const uint16_t indices[], int indexCount,
132 const SkPaint& paint) { 277 const SkPaint& paint) {
133 ++estimatedCost_; 278 ++estimatedCost_;
279 isSolidColor_ = false;
280 isTransparent_ = false;
134 } 281 }
135 282
136 void AnalysisDevice::drawDevice(const SkDraw&, SkDevice*, int x, int y, 283 void AnalysisDevice::drawDevice(const SkDraw&, SkDevice*, int x, int y,
137 const SkPaint&) { 284 const SkPaint&) {
138 ++estimatedCost_; 285 ++estimatedCost_;
286 isSolidColor_ = false;
287 isTransparent_ = false;
139 } 288 }
140 289
141 290
142 291
143
144 AnalysisCanvas::AnalysisCanvas(AnalysisDevice* device) 292 AnalysisCanvas::AnalysisCanvas(AnalysisDevice* device)
145 : INHERITED(device) { 293 : INHERITED(device)
146 294 , savedLayerStackSize_(0) {
147 } 295 }
148 296
149 AnalysisCanvas::~AnalysisCanvas() { 297 AnalysisCanvas::~AnalysisCanvas() {
150 } 298 }
151 299
152 300
153 bool AnalysisCanvas::isCheap() const { 301 bool AnalysisCanvas::isCheap() const {
154 return getEstimatedCost() < gPictureCostThreshold; 302 return getEstimatedCost() < gPictureCostThreshold;
155 } 303 }
156 304
305 bool AnalysisCanvas::getColorIfSolid(SkColor* color) const {
306 return (static_cast<AnalysisDevice*>(getDevice()))->getColorIfSolid(color);
307 }
308
309 bool AnalysisCanvas::isTransparent() const {
310 return (static_cast<AnalysisDevice*>(getDevice()))->isTransparent();
311 }
312
157 int AnalysisCanvas::getEstimatedCost() const { 313 int AnalysisCanvas::getEstimatedCost() const {
158 return (static_cast<AnalysisDevice*>(getDevice()))->getEstimatedCost(); 314 return (static_cast<AnalysisDevice*>(getDevice()))->getEstimatedCost();
159 } 315 }
160 316
161
162 bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op, 317 bool AnalysisCanvas::clipRect(const SkRect& rect, SkRegion::Op op,
163 bool doAA) { 318 bool doAA) {
164 return INHERITED::clipRect(rect, op, doAA); 319 return INHERITED::clipRect(rect, op, doAA);
165 } 320 }
166 321
167 bool AnalysisCanvas::clipPath(const SkPath& path, SkRegion::Op op, 322 bool AnalysisCanvas::clipPath(const SkPath& path, SkRegion::Op op,
168 bool doAA) { 323 bool doAA) {
169 return INHERITED::clipRect(path.getBounds(), op, doAA); 324 return INHERITED::clipRect(path.getBounds(), op, doAA);
170 } 325 }
171 326
172 bool AnalysisCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, 327 bool AnalysisCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op,
173 bool doAA) { 328 bool doAA) {
174 return INHERITED::clipRect(rrect.getBounds(), op, doAA); 329 return INHERITED::clipRect(rrect.getBounds(), op, doAA);
175 } 330 }
176 331
177 int AnalysisCanvas::saveLayer(const SkRect* bounds, const SkPaint*, 332 int AnalysisCanvas::save(SkCanvas::SaveFlags flags) {
333 INHERITED::save(flags);
334 }
335
336 int AnalysisCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
178 SkCanvas::SaveFlags flags) { 337 SkCanvas::SaveFlags flags) {
338 // If after we draw to the saved layer, we have to blend with the current
339 // layer, then we can conservatively say that the canvas will not be of
340 // solid color.
341 if ((paint && !isSolidColorPaint(*paint)) ||
342 (bounds && !bounds->contains(
343 SkRect::MakeWH(getDevice()->width(), getDevice()->height()))))
344 (static_cast<AnalysisDevice*>(getDevice()))->setForceNotSolid(true);
345
346 // If after we draw to the save layer, we have to blend with the current
347 // layer using any part of the current layer's alpha, then we can
348 // conservatively say that the canvas will not be transparent.
349 SkXfermode::Mode xferMode = SkXfermode::kSrc_Mode;
350 if (paint)
351 SkXfermode::AsMode(paint->getXfermode(), &xferMode);
352 if (xferMode != SkXfermode::kSrc_Mode)
353 (static_cast<AnalysisDevice*>(getDevice()))->setForceNotTransparent(true);
354
355 ++savedLayerStackSize_;
356
179 // Actually saving a layer here could cause a new bitmap to be created 357 // Actually saving a layer here could cause a new bitmap to be created
180 // and real rendering to occur. 358 // and real rendering to occur.
181 int count = SkCanvas::save(flags); 359 int count = INHERITED::save(flags);
182 if (bounds) { 360 if (bounds) {
183 INHERITED::clipRectBounds(bounds, flags, NULL); 361 INHERITED::clipRectBounds(bounds, flags, NULL);
184 } 362 }
185 return count; 363 return count;
186 } 364 }
187 365
366 void AnalysisCanvas::restore() {
367 INHERITED::restore();
368
369 if (--savedLayerStackSize_ == 0) {
Justin Novosad 2013/03/05 22:14:02 This is overly conservative. You could store the
370 (static_cast<AnalysisDevice*>(getDevice()))->setForceNotSolid(false);
371 (static_cast<AnalysisDevice*>(getDevice()))->setForceNotTransparent(false);
372 }
373 }
374
188 } // namespace skia 375 } // namespace skia
189 376
190 377
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