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

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

Issue 2748263002: Move cc::DisplayItemList and related classes into cc/paint/ (Closed)
Patch Set: none Created 3 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
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "cc/playback/discardable_image_map.h"
6
7 #include <stddef.h>
8
9 #include <algorithm>
10 #include <limits>
11
12 #include "base/containers/adapters.h"
13 #include "base/memory/ptr_util.h"
14 #include "cc/base/math_util.h"
15 #include "cc/playback/display_item_list.h"
16 #include "third_party/skia/include/core/SkPath.h"
17 #include "third_party/skia/include/utils/SkNWayCanvas.h"
18 #include "ui/gfx/geometry/rect_conversions.h"
19 #include "ui/gfx/skia_util.h"
20
21 namespace cc {
22
23 SkRect MapRect(const SkMatrix& matrix, const SkRect& src) {
24 SkRect dst;
25 matrix.mapRect(&dst, src);
26 return dst;
27 }
28
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
59 // non-overridden functions are no-ops.
60 class DiscardableImagesMetadataCanvas : public SkNWayCanvas {
61 public:
62 DiscardableImagesMetadataCanvas(
63 int width,
64 int height,
65 std::vector<std::pair<DrawImage, gfx::Rect>>* image_set,
66 std::unordered_map<ImageId, gfx::Rect>* image_id_to_rect)
67 : SkNWayCanvas(width, height),
68 image_set_(image_set),
69 image_id_to_rect_(image_id_to_rect),
70 canvas_bounds_(SkRect::MakeIWH(width, height)),
71 canvas_size_(width, height) {}
72
73 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 {
143 saved_paints_.push_back(rec.fPaint ? *rec.fPaint : SkPaint());
144 return SkNWayCanvas::getSaveLayerStrategy(rec);
145 }
146
147 void willSave() override {
148 saved_paints_.push_back(SkPaint());
149 return SkNWayCanvas::willSave();
150 }
151
152 void willRestore() override {
153 DCHECK_GT(saved_paints_.size(), 0u);
154 saved_paints_.pop_back();
155 SkNWayCanvas::willRestore();
156 }
157
158 private:
159 bool ComputePaintBounds(const SkRect& rect,
160 const SkPaint* current_paint,
161 SkRect* paint_bounds) {
162 *paint_bounds = rect;
163 if (current_paint) {
164 if (!current_paint->canComputeFastBounds())
165 return false;
166 *paint_bounds =
167 current_paint->computeFastBounds(*paint_bounds, paint_bounds);
168 }
169
170 for (const auto& paint : base::Reversed(saved_paints_)) {
171 if (!paint.canComputeFastBounds())
172 return false;
173 *paint_bounds = paint.computeFastBounds(*paint_bounds, paint_bounds);
174 }
175 return true;
176 }
177
178 void AddImage(sk_sp<const SkImage> image,
179 const SkRect& src_rect,
180 const SkRect& rect,
181 const SkMatrix& matrix,
182 const SkPaint* paint) {
183 if (!image->isLazyGenerated())
184 return;
185
186 SkRect paint_rect;
187 bool computed_paint_bounds = ComputePaintBounds(rect, paint, &paint_rect);
188 if (!computed_paint_bounds) {
189 // TODO(vmpstr): UMA this case.
190 paint_rect = canvas_bounds_;
191 }
192
193 if (!paint_rect.intersects(canvas_bounds_))
194 return;
195
196 SkFilterQuality filter_quality = kNone_SkFilterQuality;
197 if (paint) {
198 filter_quality = paint->getFilterQuality();
199 }
200
201 SkIRect src_irect;
202 src_rect.roundOut(&src_irect);
203 gfx::Rect image_rect = SafeClampPaintRectToSize(paint_rect, canvas_size_);
204
205 (*image_id_to_rect_)[image->uniqueID()].Union(image_rect);
206 image_set_->push_back(std::make_pair(
207 DrawImage(std::move(image), src_irect, filter_quality, matrix),
208 image_rect));
209 }
210
211 // Currently this function only handles extracting images from SkImageShaders
212 // embedded in SkPaints. Other embedded image cases, such as SkPictures,
213 // are not yet handled.
214 void AddPaintImage(const SkRect& rect, const SkPaint& paint) {
215 SkShader* shader = paint.getShader();
216 if (shader) {
217 SkMatrix matrix;
218 SkShader::TileMode xy[2];
219 SkImage* image = shader->isAImage(&matrix, xy);
220 if (image) {
221 const SkMatrix& ctm = getTotalMatrix();
222 matrix.postConcat(ctm);
223 // TODO(ericrk): Handle cases where we only need a sub-rect from the
224 // image. crbug.com/671821
225 AddImage(sk_ref_sp(image), SkRect::MakeFromIRect(image->bounds()),
226 MapRect(ctm, rect), matrix, &paint);
227 }
228 }
229 }
230
231 std::vector<std::pair<DrawImage, gfx::Rect>>* image_set_;
232 std::unordered_map<ImageId, gfx::Rect>* image_id_to_rect_;
233 const SkRect canvas_bounds_;
234 const gfx::Size canvas_size_;
235 std::vector<SkPaint> saved_paints_;
236 };
237
238 } // namespace
239
240 DiscardableImageMap::DiscardableImageMap() {}
241
242 DiscardableImageMap::~DiscardableImageMap() {}
243
244 std::unique_ptr<SkCanvas> DiscardableImageMap::BeginGeneratingMetadata(
245 const gfx::Size& bounds) {
246 DCHECK(all_images_.empty());
247 return base::MakeUnique<DiscardableImagesMetadataCanvas>(
248 bounds.width(), bounds.height(), &all_images_, &image_id_to_rect_);
249 }
250
251 void DiscardableImageMap::EndGeneratingMetadata() {
252 images_rtree_.Build(all_images_,
253 [](const std::pair<DrawImage, gfx::Rect>& image) {
254 return image.second;
255 });
256 }
257
258 void DiscardableImageMap::GetDiscardableImagesInRect(
259 const gfx::Rect& rect,
260 float contents_scale,
261 std::vector<DrawImage>* images) const {
262 std::vector<size_t> indices;
263 images_rtree_.Search(rect, &indices);
264 for (size_t index : indices)
265 images->push_back(all_images_[index].first.ApplyScale(contents_scale));
266 }
267
268 gfx::Rect DiscardableImageMap::GetRectForImage(ImageId image_id) const {
269 const auto& it = image_id_to_rect_.find(image_id);
270 return it == image_id_to_rect_.end() ? gfx::Rect() : it->second;
271 }
272
273 DiscardableImageMap::ScopedMetadataGenerator::ScopedMetadataGenerator(
274 DiscardableImageMap* image_map,
275 const gfx::Size& bounds)
276 : image_map_(image_map),
277 metadata_canvas_(image_map->BeginGeneratingMetadata(bounds)) {}
278
279 DiscardableImageMap::ScopedMetadataGenerator::~ScopedMetadataGenerator() {
280 image_map_->EndGeneratingMetadata();
281 }
282
283 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698