OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "chrome/renderer/paint_aggregator.h" | 5 #include "chrome/renderer/paint_aggregator.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 | 9 |
10 // ---------------------------------------------------------------------------- | 10 // ---------------------------------------------------------------------------- |
(...skipping 16 matching lines...) Expand all Loading... |
27 // This constant sets the max ratio of paint rect area to scroll rect area that | 27 // This constant sets the max ratio of paint rect area to scroll rect area that |
28 // we will tolerate before dograding the scroll into a repaint. | 28 // we will tolerate before dograding the scroll into a repaint. |
29 static const float kMaxRedundantPaintToScrollArea = 0.8f; | 29 static const float kMaxRedundantPaintToScrollArea = 0.8f; |
30 | 30 |
31 // The maximum number of paint rects. If we exceed this limit, then we'll | 31 // The maximum number of paint rects. If we exceed this limit, then we'll |
32 // start combining paint rects (see CombinePaintRects). This limiting is | 32 // start combining paint rects (see CombinePaintRects). This limiting is |
33 // important since the WebKit code associated with deciding what to paint given | 33 // important since the WebKit code associated with deciding what to paint given |
34 // a paint rect can be significant. | 34 // a paint rect can be significant. |
35 static const size_t kMaxPaintRects = 5; | 35 static const size_t kMaxPaintRects = 5; |
36 | 36 |
| 37 // If the combined area of paint rects divided by the area of the union of all |
| 38 // paint rects exceeds this threshold, then we will combine the paint rects. |
| 39 static const float kMaxPaintRectsAreaRatio = 0.3f; |
| 40 |
37 PaintAggregator::PendingUpdate::PendingUpdate() {} | 41 PaintAggregator::PendingUpdate::PendingUpdate() {} |
38 | 42 |
39 PaintAggregator::PendingUpdate::~PendingUpdate() {} | 43 PaintAggregator::PendingUpdate::~PendingUpdate() {} |
40 | 44 |
41 gfx::Rect PaintAggregator::PendingUpdate::GetScrollDamage() const { | 45 gfx::Rect PaintAggregator::PendingUpdate::GetScrollDamage() const { |
42 // Should only be scrolling in one direction at a time. | 46 // Should only be scrolling in one direction at a time. |
43 DCHECK(!(scroll_delta.x() && scroll_delta.y())); | 47 DCHECK(!(scroll_delta.x() && scroll_delta.y())); |
44 | 48 |
45 gfx::Rect damaged_rect; | 49 gfx::Rect damaged_rect; |
46 | 50 |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
82 } | 86 } |
83 | 87 |
84 bool PaintAggregator::HasPendingUpdate() const { | 88 bool PaintAggregator::HasPendingUpdate() const { |
85 return !update_.scroll_rect.IsEmpty() || !update_.paint_rects.empty(); | 89 return !update_.scroll_rect.IsEmpty() || !update_.paint_rects.empty(); |
86 } | 90 } |
87 | 91 |
88 void PaintAggregator::ClearPendingUpdate() { | 92 void PaintAggregator::ClearPendingUpdate() { |
89 update_ = PendingUpdate(); | 93 update_ = PendingUpdate(); |
90 } | 94 } |
91 | 95 |
| 96 void PaintAggregator::PopPendingUpdate(PendingUpdate* update) { |
| 97 // Combine paint rects if their combined area is not sufficiently less than |
| 98 // the area of the union of all paint rects. We skip this if there is a |
| 99 // scroll rect since scrolling benefits from smaller paint rects. |
| 100 if (update_.scroll_rect.IsEmpty() && update_.paint_rects.size() > 1) { |
| 101 int paint_area = 0; |
| 102 gfx::Rect union_rect; |
| 103 for (size_t i = 0; i < update_.paint_rects.size(); ++i) { |
| 104 paint_area += update_.paint_rects[i].size().GetArea(); |
| 105 union_rect = union_rect.Union(update_.paint_rects[i]); |
| 106 } |
| 107 int union_area = union_rect.size().GetArea(); |
| 108 if (float(paint_area) / float(union_area) > kMaxPaintRectsAreaRatio) |
| 109 CombinePaintRects(); |
| 110 } |
| 111 *update = update_; |
| 112 ClearPendingUpdate(); |
| 113 } |
| 114 |
92 void PaintAggregator::InvalidateRect(const gfx::Rect& rect) { | 115 void PaintAggregator::InvalidateRect(const gfx::Rect& rect) { |
93 // Combine overlapping paints using smallest bounding box. | 116 // Combine overlapping paints using smallest bounding box. |
94 for (size_t i = 0; i < update_.paint_rects.size(); ++i) { | 117 for (size_t i = 0; i < update_.paint_rects.size(); ++i) { |
95 const gfx::Rect& existing_rect = update_.paint_rects[i]; | 118 const gfx::Rect& existing_rect = update_.paint_rects[i]; |
96 if (existing_rect.Contains(rect)) // Optimize out redundancy. | 119 if (existing_rect.Contains(rect)) // Optimize out redundancy. |
97 return; | 120 return; |
98 if (rect.Intersects(existing_rect) || rect.SharesEdgeWith(existing_rect)) { | 121 if (rect.Intersects(existing_rect) || rect.SharesEdgeWith(existing_rect)) { |
99 // Re-invalidate in case the union intersects other paint rects. | 122 // Re-invalidate in case the union intersects other paint rects. |
100 gfx::Rect combined_rect = existing_rect.Union(rect); | 123 gfx::Rect combined_rect = existing_rect.Union(rect); |
101 update_.paint_rects.erase(update_.paint_rects.begin() + i); | 124 update_.paint_rects.erase(update_.paint_rects.begin() + i); |
(...skipping 18 matching lines...) Expand all Loading... |
120 update_.paint_rects.erase(update_.paint_rects.end() - 1); | 143 update_.paint_rects.erase(update_.paint_rects.end() - 1); |
121 } | 144 } |
122 } | 145 } |
123 | 146 |
124 if (update_.paint_rects.size() > kMaxPaintRects) | 147 if (update_.paint_rects.size() > kMaxPaintRects) |
125 CombinePaintRects(); | 148 CombinePaintRects(); |
126 | 149 |
127 // Track how large the paint_rects vector grows during an invalidation | 150 // Track how large the paint_rects vector grows during an invalidation |
128 // sequence. Note: A subsequent invalidation may end up being combined | 151 // sequence. Note: A subsequent invalidation may end up being combined |
129 // with all existing paints, which means that tracking the size of | 152 // with all existing paints, which means that tracking the size of |
130 // paint_rects at the time when GetPendingUpdate() is called may mask | 153 // paint_rects at the time when PopPendingUpdate() is called may mask |
131 // certain performance problems. | 154 // certain performance problems. |
132 HISTOGRAM_COUNTS_100("MPArch.RW_IntermediatePaintRectCount", | 155 HISTOGRAM_COUNTS_100("MPArch.RW_IntermediatePaintRectCount", |
133 update_.paint_rects.size()); | 156 update_.paint_rects.size()); |
134 } | 157 } |
135 | 158 |
136 void PaintAggregator::ScrollRect(int dx, int dy, const gfx::Rect& clip_rect) { | 159 void PaintAggregator::ScrollRect(int dx, int dy, const gfx::Rect& clip_rect) { |
137 // We only support scrolling along one axis at a time. | 160 // We only support scrolling along one axis at a time. |
138 if (dx != 0 && dy != 0) { | 161 if (dx != 0 && dy != 0) { |
139 InvalidateRect(clip_rect); | 162 InvalidateRect(clip_rect); |
140 return; | 163 return; |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 inner = inner.Union(existing_rect); | 275 inner = inner.Union(existing_rect); |
253 } else { | 276 } else { |
254 outer = outer.Union(existing_rect); | 277 outer = outer.Union(existing_rect); |
255 } | 278 } |
256 } | 279 } |
257 update_.paint_rects.clear(); | 280 update_.paint_rects.clear(); |
258 update_.paint_rects.push_back(inner); | 281 update_.paint_rects.push_back(inner); |
259 update_.paint_rects.push_back(outer); | 282 update_.paint_rects.push_back(outer); |
260 } | 283 } |
261 } | 284 } |
OLD | NEW |