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

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

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

Powered by Google App Engine
This is Rietveld 408576698