Index: cc/paint/display_item_list.cc |
diff --git a/cc/paint/display_item_list.cc b/cc/paint/display_item_list.cc |
index 830b3fbb15ffed9066378c28404c6e5b35aaf8d4..3ea0148ef122ddfb444d9df3afca56a70ac736f9 100644 |
--- a/cc/paint/display_item_list.cc |
+++ b/cc/paint/display_item_list.cc |
@@ -100,9 +100,13 @@ NOINLINE DISABLE_CFI_PERF void RasterItem(const DisplayItem& base_item, |
if (canvas->quickReject(item.picture->cullRect())) |
break; |
- // SkPicture always does a wrapping save/restore on the canvas, so it is |
- // not necessary here. |
+ // TODO(enne): Maybe the PaintRecord itself could know whether this |
vmpstr
2017/03/28 18:27:14
I think it makes sense for the paint record to fig
enne (OOO)
2017/03/28 19:28:05
I think this just needs some investigation. I thi
|
+ // was needed? It's not clear whether these save/restore semantics |
+ // that SkPicture handles during playback are things that should be |
+ // kept around. |
+ canvas->save(); |
item.picture->playback(canvas, callback); |
+ canvas->restore(); |
break; |
} |
case DisplayItem::FLOAT_CLIP: { |
@@ -176,6 +180,28 @@ void DisplayItemList::Raster(SkCanvas* canvas, |
canvas->restore(); |
} |
+static bool MergeAndDrawIfPossible(const CompositingDisplayItem& save_item, |
vmpstr
2017/03/28 18:27:14
nit: Can you add a comment mentioning what this do
enne (OOO)
2017/03/28 19:28:05
Done.
|
+ const DrawingDisplayItem& draw_item, |
+ SkCanvas* canvas) { |
+ if (save_item.color_filter) |
+ return false; |
+ if (save_item.xfermode != SkBlendMode::kSrcOver) |
+ return false; |
+ // TODO(enne): I believe that lcd_text_requires_opaque_layer is not |
+ // relevant here and that lcd text is preserved post merge, but I haven't |
+ // tested that. |
+ const PaintRecord* record = draw_item.picture.get(); |
+ if (record->approximateOpCount() != 1) |
vmpstr
2017/03/28 18:27:14
I'm a bit <_< at "approximate" here... Is this gua
enne (OOO)
2017/03/28 19:28:05
This is the SkPicture API. This patch changes Pai
|
+ return false; |
+ |
+ const PaintOp* op = record->GetFirstOp(); |
+ if (!op->IsDrawOp()) |
+ return false; |
+ |
+ op->RasterWithAlpha(canvas, save_item.alpha); |
vmpstr
2017/03/28 18:27:14
Hmm is there a way to guard/dcheck against future
enne (OOO)
2017/03/28 19:28:05
I think there's really no way to guard. There's n
|
+ return true; |
+} |
+ |
void DisplayItemList::Raster(SkCanvas* canvas, |
SkPicture::AbortCallback* callback) const { |
gfx::Rect canvas_playback_rect; |
@@ -184,8 +210,32 @@ void DisplayItemList::Raster(SkCanvas* canvas, |
std::vector<size_t> indices; |
rtree_.Search(canvas_playback_rect, &indices); |
- for (size_t index : indices) { |
- RasterItem(items_[index], canvas, callback); |
+ for (size_t i = 0; i < indices.size(); ++i) { |
+ const DisplayItem& item = items_[indices[i]]; |
+ // Optimize empty begin/end compositing and merge begin/draw/end compositing |
+ // where possible. |
+ // TODO(enne): remove empty clips here too? |
+ // TODO(enne): does this happen recursively? Or is this good enough? |
+ if (i < indices.size() - 2 && item.type == DisplayItem::COMPOSITING) { |
+ const DisplayItem& second = items_[indices[i + 1]]; |
+ if (second.type == DisplayItem::END_COMPOSITING) { |
+ i += 2; |
vmpstr
2017/03/28 18:27:14
I think this has to be ++i because of the ++i in t
enne (OOO)
2017/03/28 19:28:05
OOPS
|
+ // TODO(enne): does this ever happen? Is this worth catching? |
vmpstr
2017/03/28 18:27:14
I think this is possible in this situation:
- Com
enne (OOO)
2017/03/28 19:28:05
Yeah, I'm not saying it's not impossible. It just
|
+ continue; |
+ } |
+ const DisplayItem& third = items_[indices[i + 2]]; |
+ if (second.type == DisplayItem::DRAWING && |
+ third.type == DisplayItem::END_COMPOSITING) { |
+ if (MergeAndDrawIfPossible( |
+ static_cast<const CompositingDisplayItem&>(item), |
+ static_cast<const DrawingDisplayItem&>(second), canvas)) { |
+ i += 3; |
vmpstr
2017/03/28 18:27:14
+= 2?
enne (OOO)
2017/03/28 19:28:05
***<_<***
|
+ continue; |
+ } |
+ } |
+ } |
+ |
+ RasterItem(item, canvas, callback); |
// We use a callback during solid color analysis on the compositor thread to |
// break out early. Since we're handling a sequence of pictures via rtree |