OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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/display_item_list.h" | 5 #include "cc/paint/display_item_list.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <string> | 9 #include <string> |
10 | 10 |
(...skipping 82 matching lines...) Loading... | |
93 break; | 93 break; |
94 } | 94 } |
95 case DisplayItem::END_COMPOSITING: | 95 case DisplayItem::END_COMPOSITING: |
96 canvas->restore(); | 96 canvas->restore(); |
97 break; | 97 break; |
98 case DisplayItem::DRAWING: { | 98 case DisplayItem::DRAWING: { |
99 const auto& item = static_cast<const DrawingDisplayItem&>(base_item); | 99 const auto& item = static_cast<const DrawingDisplayItem&>(base_item); |
100 if (canvas->quickReject(item.picture->cullRect())) | 100 if (canvas->quickReject(item.picture->cullRect())) |
101 break; | 101 break; |
102 | 102 |
103 // SkPicture always does a wrapping save/restore on the canvas, so it is | 103 // TODO(enne): Maybe the PaintRecord itself could know whether this |
104 // not necessary here. | 104 // was needed? It's not clear whether these save/restore semantics |
105 // that SkPicture handles during playback are things that should be | |
106 // kept around. | |
107 canvas->save(); | |
105 item.picture->playback(canvas, callback); | 108 item.picture->playback(canvas, callback); |
109 canvas->restore(); | |
106 break; | 110 break; |
107 } | 111 } |
108 case DisplayItem::FLOAT_CLIP: { | 112 case DisplayItem::FLOAT_CLIP: { |
109 const auto& item = static_cast<const FloatClipDisplayItem&>(base_item); | 113 const auto& item = static_cast<const FloatClipDisplayItem&>(base_item); |
110 canvas->save(); | 114 canvas->save(); |
111 canvas->clipRect(gfx::RectFToSkRect(item.clip_rect)); | 115 canvas->clipRect(gfx::RectFToSkRect(item.clip_rect)); |
112 break; | 116 break; |
113 } | 117 } |
114 case DisplayItem::END_FLOAT_CLIP: | 118 case DisplayItem::END_FLOAT_CLIP: |
115 canvas->restore(); | 119 canvas->restore(); |
(...skipping 53 matching lines...) Loading... | |
169 // instead because it ignores canvas CTM. | 173 // instead because it ignores canvas CTM. |
170 SkRegion device_clip; | 174 SkRegion device_clip; |
171 device_clip.setRect(gfx::RectToSkIRect(canvas_target_playback_rect)); | 175 device_clip.setRect(gfx::RectToSkIRect(canvas_target_playback_rect)); |
172 canvas->clipRegion(device_clip); | 176 canvas->clipRegion(device_clip); |
173 } | 177 } |
174 canvas->scale(contents_scale, contents_scale); | 178 canvas->scale(contents_scale, contents_scale); |
175 Raster(canvas, callback); | 179 Raster(canvas, callback); |
176 canvas->restore(); | 180 canvas->restore(); |
177 } | 181 } |
178 | 182 |
183 // Atttempts to merge a CompositingDisplayItem and DrawingDisplayItem | |
184 // into a single "draw with alpha". This function returns true if | |
185 // it was successful. If false, then the caller is responsible for | |
186 // drawing these items. This is a DisplayItemList version of the | |
187 // SkRecord optimization SkRecordNoopSaveLayerDrawRestores. | |
188 static bool MergeAndDrawIfPossible(const CompositingDisplayItem& save_item, | |
189 const DrawingDisplayItem& draw_item, | |
190 SkCanvas* canvas) { | |
191 if (save_item.color_filter) | |
192 return false; | |
193 if (save_item.xfermode != SkBlendMode::kSrcOver) | |
194 return false; | |
195 // TODO(enne): I believe that lcd_text_requires_opaque_layer is not | |
vmpstr
2017/04/06 19:16:12
Is there a way to test this assumption via unittes
enne (OOO)
2017/04/06 23:17:05
I am punting!
| |
196 // relevant here and that lcd text is preserved post merge, but I haven't | |
197 // tested that. | |
198 const PaintRecord* record = draw_item.picture.get(); | |
199 if (record->approximateOpCount() != 1) | |
vmpstr
2017/04/06 19:16:12
Can you please leave a comment here that approxima
enne (OOO)
2017/04/06 23:17:05
Sorry about this. I was just trying to not change
| |
200 return false; | |
201 | |
202 const PaintOp* op = record->GetFirstOp(); | |
203 if (!op->IsDrawOp()) | |
204 return false; | |
205 | |
206 op->RasterWithAlpha(canvas, save_item.alpha); | |
207 return true; | |
208 } | |
209 | |
179 void DisplayItemList::Raster(SkCanvas* canvas, | 210 void DisplayItemList::Raster(SkCanvas* canvas, |
180 SkPicture::AbortCallback* callback) const { | 211 SkPicture::AbortCallback* callback) const { |
181 gfx::Rect canvas_playback_rect; | 212 gfx::Rect canvas_playback_rect; |
182 if (!GetCanvasClipBounds(canvas, &canvas_playback_rect)) | 213 if (!GetCanvasClipBounds(canvas, &canvas_playback_rect)) |
183 return; | 214 return; |
184 | 215 |
185 std::vector<size_t> indices; | 216 std::vector<size_t> indices; |
186 rtree_.Search(canvas_playback_rect, &indices); | 217 rtree_.Search(canvas_playback_rect, &indices); |
187 for (size_t index : indices) { | 218 for (size_t i = 0; i < indices.size(); ++i) { |
188 RasterItem(items_[index], canvas, callback); | 219 const DisplayItem& item = items_[indices[i]]; |
220 // Optimize empty begin/end compositing and merge begin/draw/end compositing | |
221 // where possible. | |
222 // TODO(enne): remove empty clips here too? | |
223 // TODO(enne): does this happen recursively? Or is this good enough? | |
224 if (i < indices.size() - 2 && item.type == DisplayItem::COMPOSITING) { | |
225 const DisplayItem& second = items_[indices[i + 1]]; | |
226 if (second.type == DisplayItem::END_COMPOSITING) { | |
227 i++; | |
228 // TODO(enne): does this ever happen? Is this worth catching? | |
229 continue; | |
230 } | |
231 const DisplayItem& third = items_[indices[i + 2]]; | |
232 if (second.type == DisplayItem::DRAWING && | |
233 third.type == DisplayItem::END_COMPOSITING) { | |
234 if (MergeAndDrawIfPossible( | |
235 static_cast<const CompositingDisplayItem&>(item), | |
236 static_cast<const DrawingDisplayItem&>(second), canvas)) { | |
237 i += 2; | |
238 continue; | |
239 } | |
240 } | |
241 } | |
242 | |
243 RasterItem(item, canvas, callback); | |
189 | 244 |
190 // We use a callback during solid color analysis on the compositor thread to | 245 // We use a callback during solid color analysis on the compositor thread to |
191 // break out early. Since we're handling a sequence of pictures via rtree | 246 // break out early. Since we're handling a sequence of pictures via rtree |
192 // query results ourselves, we have to respect the callback and early out. | 247 // query results ourselves, we have to respect the callback and early out. |
193 if (callback && callback->abort()) | 248 if (callback && callback->abort()) |
vmpstr
2017/04/06 19:16:12
nit: can you move this check to the top of the loo
| |
194 break; | 249 break; |
195 } | 250 } |
196 } | 251 } |
197 | 252 |
198 void DisplayItemList::GrowCurrentBeginItemVisualRect( | 253 void DisplayItemList::GrowCurrentBeginItemVisualRect( |
199 const gfx::Rect& visual_rect) { | 254 const gfx::Rect& visual_rect) { |
200 if (!begin_item_indices_.empty()) | 255 if (!begin_item_indices_.empty()) |
201 visual_rects_[begin_item_indices_.back()].Union(visual_rect); | 256 visual_rects_[begin_item_indices_.back()].Union(visual_rect); |
202 } | 257 } |
203 | 258 |
(...skipping 286 matching lines...) Loading... | |
490 float contents_scale, | 545 float contents_scale, |
491 std::vector<DrawImage>* images) { | 546 std::vector<DrawImage>* images) { |
492 image_map_.GetDiscardableImagesInRect(rect, contents_scale, images); | 547 image_map_.GetDiscardableImagesInRect(rect, contents_scale, images); |
493 } | 548 } |
494 | 549 |
495 gfx::Rect DisplayItemList::GetRectForImage(ImageId image_id) const { | 550 gfx::Rect DisplayItemList::GetRectForImage(ImageId image_id) const { |
496 return image_map_.GetRectForImage(image_id); | 551 return image_map_.GetRectForImage(image_id); |
497 } | 552 } |
498 | 553 |
499 } // namespace cc | 554 } // namespace cc |
OLD | NEW |