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

Side by Side Diff: cc/paint/discardable_image_map.cc

Issue 2842333003: cc: Update discardable image metadata generation to get PaintImages. (Closed)
Patch Set: win Created 3 years, 7 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 | « cc/paint/discardable_image_map.h ('k') | cc/paint/discardable_image_map_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 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 "cc/paint/discardable_image_map.h" 5 #include "cc/paint/discardable_image_map.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <limits> 10 #include <limits>
11 11
12 #include "base/containers/adapters.h"
13 #include "base/containers/flat_map.h"
14 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
15 #include "cc/base/math_util.h" 13 #include "cc/paint/discardable_image_store.h"
16 #include "cc/paint/display_item_list.h"
17 #include "third_party/skia/include/core/SkPath.h"
18 #include "third_party/skia/include/utils/SkNWayCanvas.h"
19 #include "ui/gfx/geometry/rect_conversions.h"
20 #include "ui/gfx/skia_util.h"
21 14
22 namespace cc { 15 namespace cc {
23 16
24 SkRect MapRect(const SkMatrix& matrix, const SkRect& src) {
25 SkRect dst;
26 matrix.mapRect(&dst, src);
27 return dst;
28 }
29
30 // Returns a rect clamped to |max_size|. Note that |paint_rect| should intersect
31 // or be contained by a rect defined by (0, 0) and |max_size|.
32 gfx::Rect SafeClampPaintRectToSize(const SkRect& paint_rect,
33 const gfx::Size& max_size) {
34 // bounds_rect.x() + bounds_rect.width() (aka bounds_rect.right()) might
35 // overflow integer bounds, so do custom intersect, since gfx::Rect::Intersect
36 // uses bounds_rect.right().
37 gfx::RectF bounds_rect = gfx::SkRectToRectF(paint_rect);
38 float x_offset_if_negative = bounds_rect.x() < 0.f ? bounds_rect.x() : 0.f;
39 float y_offset_if_negative = bounds_rect.y() < 0.f ? bounds_rect.y() : 0.f;
40 bounds_rect.set_x(std::max(0.f, bounds_rect.x()));
41 bounds_rect.set_y(std::max(0.f, bounds_rect.y()));
42
43 // Verify that the rects intersect or that bound_rect is contained by
44 // max_size.
45 DCHECK_GE(bounds_rect.width(), -x_offset_if_negative);
46 DCHECK_GE(bounds_rect.height(), -y_offset_if_negative);
47 DCHECK_GE(max_size.width(), bounds_rect.x());
48 DCHECK_GE(max_size.height(), bounds_rect.y());
49
50 bounds_rect.set_width(std::min(bounds_rect.width() + x_offset_if_negative,
51 max_size.width() - bounds_rect.x()));
52 bounds_rect.set_height(std::min(bounds_rect.height() + y_offset_if_negative,
53 max_size.height() - bounds_rect.y()));
54 return gfx::ToEnclosingRect(bounds_rect);
55 }
56
57 namespace {
58
59 // We're using an NWay canvas with no added canvases, so in effect
60 // non-overridden functions are no-ops.
61 class DiscardableImagesMetadataCanvas : public SkNWayCanvas {
62 public:
63 DiscardableImagesMetadataCanvas(
64 int width,
65 int height,
66 std::vector<std::pair<DrawImage, gfx::Rect>>* image_set,
67 base::flat_map<ImageId, gfx::Rect>* image_id_to_rect)
68 : SkNWayCanvas(width, height),
69 image_set_(image_set),
70 image_id_to_rect_(image_id_to_rect),
71 canvas_bounds_(SkRect::MakeIWH(width, height)),
72 canvas_size_(width, height) {}
73
74 protected:
75 // we need to "undo" the behavior of SkNWayCanvas, which will try to forward
76 // it.
77 void onDrawPicture(const SkPicture* picture,
78 const SkMatrix* matrix,
79 const SkPaint* paint) override {
80 SkCanvas::onDrawPicture(picture, matrix, paint);
81 }
82
83 void onDrawImage(const SkImage* image,
84 SkScalar x,
85 SkScalar y,
86 const SkPaint* paint) override {
87 const SkMatrix& ctm = getTotalMatrix();
88 AddImage(
89 sk_ref_sp(image), SkRect::MakeIWH(image->width(), image->height()),
90 MapRect(ctm, SkRect::MakeXYWH(x, y, image->width(), image->height())),
91 ctm, paint);
92 }
93
94 void onDrawImageRect(const SkImage* image,
95 const SkRect* src,
96 const SkRect& dst,
97 const SkPaint* paint,
98 SrcRectConstraint) override {
99 const SkMatrix& ctm = getTotalMatrix();
100 SkRect src_storage;
101 if (!src) {
102 src_storage = SkRect::MakeIWH(image->width(), image->height());
103 src = &src_storage;
104 }
105 SkMatrix matrix;
106 matrix.setRectToRect(*src, dst, SkMatrix::kFill_ScaleToFit);
107 matrix.preConcat(ctm);
108 AddImage(sk_ref_sp(image), *src, MapRect(ctm, dst), matrix, paint);
109 }
110
111 void onDrawImageNine(const SkImage* image,
112 const SkIRect& center,
113 const SkRect& dst,
114 const SkPaint* paint) override {
115 // No cc embedder issues image nine calls.
116 NOTREACHED();
117 }
118
119 void onDrawRect(const SkRect& r, const SkPaint& paint) override {
120 AddPaintImage(r, paint);
121 }
122
123 void onDrawPath(const SkPath& path, const SkPaint& paint) override {
124 AddPaintImage(path.getBounds(), paint);
125 }
126
127 void onDrawOval(const SkRect& r, const SkPaint& paint) override {
128 AddPaintImage(r, paint);
129 }
130
131 void onDrawArc(const SkRect& r,
132 SkScalar start_angle,
133 SkScalar sweep_angle,
134 bool use_center,
135 const SkPaint& paint) override {
136 AddPaintImage(r, paint);
137 }
138
139 void onDrawRRect(const SkRRect& rr, const SkPaint& paint) override {
140 AddPaintImage(rr.rect(), paint);
141 }
142
143 SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec& rec) override {
144 saved_paints_.push_back(rec.fPaint ? *rec.fPaint : SkPaint());
145 return SkNWayCanvas::getSaveLayerStrategy(rec);
146 }
147
148 void willSave() override {
149 saved_paints_.push_back(SkPaint());
150 return SkNWayCanvas::willSave();
151 }
152
153 void willRestore() override {
154 DCHECK_GT(saved_paints_.size(), 0u);
155 saved_paints_.pop_back();
156 SkNWayCanvas::willRestore();
157 }
158
159 private:
160 bool ComputePaintBounds(const SkRect& rect,
161 const SkPaint* current_paint,
162 SkRect* paint_bounds) {
163 *paint_bounds = rect;
164 if (current_paint) {
165 if (!current_paint->canComputeFastBounds())
166 return false;
167 *paint_bounds =
168 current_paint->computeFastBounds(*paint_bounds, paint_bounds);
169 }
170
171 for (const auto& paint : base::Reversed(saved_paints_)) {
172 if (!paint.canComputeFastBounds())
173 return false;
174 *paint_bounds = paint.computeFastBounds(*paint_bounds, paint_bounds);
175 }
176
177 return true;
178 }
179
180 void AddImage(sk_sp<const SkImage> image,
181 const SkRect& src_rect,
182 const SkRect& rect,
183 const SkMatrix& matrix,
184 const SkPaint* paint) {
185 if (!image->isLazyGenerated())
186 return;
187
188 SkRect paint_rect;
189 bool computed_paint_bounds = ComputePaintBounds(rect, paint, &paint_rect);
190 if (!computed_paint_bounds) {
191 // TODO(vmpstr): UMA this case.
192 paint_rect = canvas_bounds_;
193 }
194
195 if (!paint_rect.intersects(canvas_bounds_))
196 return;
197
198 SkFilterQuality filter_quality = kNone_SkFilterQuality;
199 if (paint) {
200 filter_quality = paint->getFilterQuality();
201 }
202
203 SkIRect src_irect;
204 src_rect.roundOut(&src_irect);
205 gfx::Rect image_rect = SafeClampPaintRectToSize(paint_rect, canvas_size_);
206
207 // During raster, we use the device clip bounds on the canvas, which outsets
208 // the actual clip by 1 due to the possibility of antialiasing. Account for
209 // this here by outsetting the image rect by 1. Note that this only affects
210 // queries into the rtree, which will now return images that only touch the
211 // bounds of the query rect.
212 //
213 // Note that it's not sufficient for us to inset the device clip bounds at
214 // raster time, since we might be sending a larger-than-one-item display
215 // item to skia, which means that skia will internally determine whether to
216 // raster the picture (using device clip bounds that are outset).
217 image_rect.Inset(-1, -1);
218
219 // The true target color space will be assigned when it is known, in
220 // GetDiscardableImagesInRect.
221 gfx::ColorSpace target_color_space;
222
223 (*image_id_to_rect_)[image->uniqueID()].Union(image_rect);
224 image_set_->push_back(
225 std::make_pair(DrawImage(std::move(image), src_irect, filter_quality,
226 matrix, target_color_space),
227 image_rect));
228 }
229
230 // Currently this function only handles extracting images from SkImageShaders
231 // embedded in SkPaints. Other embedded image cases, such as SkPictures,
232 // are not yet handled.
233 void AddPaintImage(const SkRect& rect, const SkPaint& paint) {
234 SkShader* shader = paint.getShader();
235 if (shader) {
236 SkMatrix matrix;
237 SkShader::TileMode xy[2];
238 SkImage* image = shader->isAImage(&matrix, xy);
239 if (image) {
240 const SkMatrix& ctm = getTotalMatrix();
241 matrix.postConcat(ctm);
242 // TODO(ericrk): Handle cases where we only need a sub-rect from the
243 // image. crbug.com/671821
244 AddImage(sk_ref_sp(image), SkRect::MakeFromIRect(image->bounds()),
245 MapRect(ctm, rect), matrix, &paint);
246 }
247 }
248 }
249
250 std::vector<std::pair<DrawImage, gfx::Rect>>* image_set_;
251 base::flat_map<ImageId, gfx::Rect>* image_id_to_rect_;
252 const SkRect canvas_bounds_;
253 const gfx::Size canvas_size_;
254 std::vector<SkPaint> saved_paints_;
255 };
256
257 } // namespace
258
259 DiscardableImageMap::DiscardableImageMap() {} 17 DiscardableImageMap::DiscardableImageMap() {}
260 18
261 DiscardableImageMap::~DiscardableImageMap() {} 19 DiscardableImageMap::~DiscardableImageMap() {}
262 20
263 std::unique_ptr<SkCanvas> DiscardableImageMap::BeginGeneratingMetadata( 21 std::unique_ptr<DiscardableImageStore>
264 const gfx::Size& bounds) { 22 DiscardableImageMap::BeginGeneratingMetadata(const gfx::Size& bounds) {
265 DCHECK(all_images_.empty()); 23 DCHECK(all_images_.empty());
266 return base::MakeUnique<DiscardableImagesMetadataCanvas>( 24 return base::MakeUnique<DiscardableImageStore>(
267 bounds.width(), bounds.height(), &all_images_, &image_id_to_rect_); 25 bounds.width(), bounds.height(), &all_images_, &image_id_to_rect_);
268 } 26 }
269 27
270 void DiscardableImageMap::EndGeneratingMetadata() { 28 void DiscardableImageMap::EndGeneratingMetadata() {
271 images_rtree_.Build(all_images_, 29 images_rtree_.Build(all_images_,
272 [](const std::pair<DrawImage, gfx::Rect>& image) { 30 [](const std::pair<DrawImage, gfx::Rect>& image) {
273 return image.second; 31 return image.second;
274 }); 32 });
275 } 33 }
276 34
(...skipping 13 matching lines...) Expand all
290 48
291 gfx::Rect DiscardableImageMap::GetRectForImage(ImageId image_id) const { 49 gfx::Rect DiscardableImageMap::GetRectForImage(ImageId image_id) const {
292 const auto& it = image_id_to_rect_.find(image_id); 50 const auto& it = image_id_to_rect_.find(image_id);
293 return it == image_id_to_rect_.end() ? gfx::Rect() : it->second; 51 return it == image_id_to_rect_.end() ? gfx::Rect() : it->second;
294 } 52 }
295 53
296 DiscardableImageMap::ScopedMetadataGenerator::ScopedMetadataGenerator( 54 DiscardableImageMap::ScopedMetadataGenerator::ScopedMetadataGenerator(
297 DiscardableImageMap* image_map, 55 DiscardableImageMap* image_map,
298 const gfx::Size& bounds) 56 const gfx::Size& bounds)
299 : image_map_(image_map), 57 : image_map_(image_map),
300 metadata_canvas_(image_map->BeginGeneratingMetadata(bounds)) {} 58 image_store_(image_map->BeginGeneratingMetadata(bounds)) {}
301 59
302 DiscardableImageMap::ScopedMetadataGenerator::~ScopedMetadataGenerator() { 60 DiscardableImageMap::ScopedMetadataGenerator::~ScopedMetadataGenerator() {
303 image_map_->EndGeneratingMetadata(); 61 image_map_->EndGeneratingMetadata();
304 } 62 }
305 63
306 } // namespace cc 64 } // namespace cc
OLDNEW
« no previous file with comments | « cc/paint/discardable_image_map.h ('k') | cc/paint/discardable_image_map_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698