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 "content/renderer/paint_aggregator.h" | 5 #include "content/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 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
68 if (dy > 0) { | 68 if (dy > 0) { |
69 damaged_rect.set_y(scroll_rect.y()); | 69 damaged_rect.set_y(scroll_rect.y()); |
70 damaged_rect.set_height(dy); | 70 damaged_rect.set_height(dy); |
71 } else { | 71 } else { |
72 damaged_rect.set_y(scroll_rect.bottom() + dy); | 72 damaged_rect.set_y(scroll_rect.bottom() + dy); |
73 damaged_rect.set_height(-dy); | 73 damaged_rect.set_height(-dy); |
74 } | 74 } |
75 } | 75 } |
76 | 76 |
77 // In case the scroll offset exceeds the width/height of the scroll rect | 77 // In case the scroll offset exceeds the width/height of the scroll rect |
78 return scroll_rect.Intersect(damaged_rect); | 78 damaged_rect.Intersect(scroll_rect); |
| 79 return damaged_rect; |
79 } | 80 } |
80 | 81 |
81 gfx::Rect PaintAggregator::PendingUpdate::GetPaintBounds() const { | 82 gfx::Rect PaintAggregator::PendingUpdate::GetPaintBounds() const { |
82 gfx::Rect bounds; | 83 gfx::Rect bounds; |
83 for (size_t i = 0; i < paint_rects.size(); ++i) | 84 for (size_t i = 0; i < paint_rects.size(); ++i) |
84 bounds = bounds.Union(paint_rects[i]); | 85 bounds.Union(paint_rects[i]); |
85 return bounds; | 86 return bounds; |
86 } | 87 } |
87 | 88 |
88 bool PaintAggregator::HasPendingUpdate() const { | 89 bool PaintAggregator::HasPendingUpdate() const { |
89 return !update_.scroll_rect.IsEmpty() || !update_.paint_rects.empty(); | 90 return !update_.scroll_rect.IsEmpty() || !update_.paint_rects.empty(); |
90 } | 91 } |
91 | 92 |
92 void PaintAggregator::ClearPendingUpdate() { | 93 void PaintAggregator::ClearPendingUpdate() { |
93 update_ = PendingUpdate(); | 94 update_ = PendingUpdate(); |
94 } | 95 } |
95 | 96 |
96 void PaintAggregator::PopPendingUpdate(PendingUpdate* update) { | 97 void PaintAggregator::PopPendingUpdate(PendingUpdate* update) { |
97 // Combine paint rects if their combined area is not sufficiently less than | 98 // 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 // 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 // scroll rect since scrolling benefits from smaller paint rects. |
100 if (update_.scroll_rect.IsEmpty() && update_.paint_rects.size() > 1) { | 101 if (update_.scroll_rect.IsEmpty() && update_.paint_rects.size() > 1) { |
101 int paint_area = 0; | 102 int paint_area = 0; |
102 gfx::Rect union_rect; | 103 gfx::Rect union_rect; |
103 for (size_t i = 0; i < update_.paint_rects.size(); ++i) { | 104 for (size_t i = 0; i < update_.paint_rects.size(); ++i) { |
104 paint_area += update_.paint_rects[i].size().GetArea(); | 105 paint_area += update_.paint_rects[i].size().GetArea(); |
105 union_rect = union_rect.Union(update_.paint_rects[i]); | 106 union_rect.Union(update_.paint_rects[i]); |
106 } | 107 } |
107 int union_area = union_rect.size().GetArea(); | 108 int union_area = union_rect.size().GetArea(); |
108 if (float(paint_area) / float(union_area) > kMaxPaintRectsAreaRatio) | 109 if (float(paint_area) / float(union_area) > kMaxPaintRectsAreaRatio) |
109 CombinePaintRects(); | 110 CombinePaintRects(); |
110 } | 111 } |
111 *update = update_; | 112 *update = update_; |
112 ClearPendingUpdate(); | 113 ClearPendingUpdate(); |
113 } | 114 } |
114 | 115 |
115 void PaintAggregator::InvalidateRect(const gfx::Rect& rect) { | 116 void PaintAggregator::InvalidateRect(const gfx::Rect& rect) { |
116 // Combine overlapping paints using smallest bounding box. | 117 // Combine overlapping paints using smallest bounding box. |
117 for (size_t i = 0; i < update_.paint_rects.size(); ++i) { | 118 for (size_t i = 0; i < update_.paint_rects.size(); ++i) { |
118 const gfx::Rect& existing_rect = update_.paint_rects[i]; | 119 const gfx::Rect& existing_rect = update_.paint_rects[i]; |
119 if (existing_rect.Contains(rect)) // Optimize out redundancy. | 120 if (existing_rect.Contains(rect)) // Optimize out redundancy. |
120 return; | 121 return; |
121 if (rect.Intersects(existing_rect) || rect.SharesEdgeWith(existing_rect)) { | 122 if (rect.Intersects(existing_rect) || rect.SharesEdgeWith(existing_rect)) { |
122 // Re-invalidate in case the union intersects other paint rects. | 123 // Re-invalidate in case the union intersects other paint rects. |
123 gfx::Rect combined_rect = existing_rect.Union(rect); | 124 gfx::Rect combined_rect = existing_rect; |
| 125 combined_rect.Union(rect); |
124 update_.paint_rects.erase(update_.paint_rects.begin() + i); | 126 update_.paint_rects.erase(update_.paint_rects.begin() + i); |
125 InvalidateRect(combined_rect); | 127 InvalidateRect(combined_rect); |
126 return; | 128 return; |
127 } | 129 } |
128 } | 130 } |
129 | 131 |
130 // Add a non-overlapping paint. | 132 // Add a non-overlapping paint. |
131 update_.paint_rects.push_back(rect); | 133 update_.paint_rects.push_back(rect); |
132 | 134 |
133 // If the new paint overlaps with a scroll, then it forces an invalidation of | 135 // If the new paint overlaps with a scroll, then it forces an invalidation of |
134 // the scroll. If the new paint is contained by a scroll, then trim off the | 136 // the scroll. If the new paint is contained by a scroll, then trim off the |
135 // scroll damage to avoid redundant painting. | 137 // scroll damage to avoid redundant painting. |
136 if (!update_.scroll_rect.IsEmpty()) { | 138 if (!update_.scroll_rect.IsEmpty()) { |
137 if (ShouldInvalidateScrollRect(rect)) { | 139 if (ShouldInvalidateScrollRect(rect)) { |
138 InvalidateScrollRect(); | 140 InvalidateScrollRect(); |
139 } else if (update_.scroll_rect.Contains(rect)) { | 141 } else if (update_.scroll_rect.Contains(rect)) { |
140 update_.paint_rects[update_.paint_rects.size() - 1] = | 142 gfx::Rect paint_rect = rect; |
141 rect.Subtract(update_.GetScrollDamage()); | 143 paint_rect.Subtract(update_.GetScrollDamage()); |
| 144 update_.paint_rects[update_.paint_rects.size() - 1] = paint_rect; |
142 if (update_.paint_rects[update_.paint_rects.size() - 1].IsEmpty()) | 145 if (update_.paint_rects[update_.paint_rects.size() - 1].IsEmpty()) |
143 update_.paint_rects.erase(update_.paint_rects.end() - 1); | 146 update_.paint_rects.erase(update_.paint_rects.end() - 1); |
144 } | 147 } |
145 } | 148 } |
146 | 149 |
147 if (update_.paint_rects.size() > kMaxPaintRects) | 150 if (update_.paint_rects.size() > kMaxPaintRects) |
148 CombinePaintRects(); | 151 CombinePaintRects(); |
149 | 152 |
150 // Track how large the paint_rects vector grows during an invalidation | 153 // Track how large the paint_rects vector grows during an invalidation |
151 // sequence. Note: A subsequent invalidation may end up being combined | 154 // sequence. Note: A subsequent invalidation may end up being combined |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 // an invalidation of the scroll. | 209 // an invalidation of the scroll. |
207 if (ShouldInvalidateScrollRect(gfx::Rect())) | 210 if (ShouldInvalidateScrollRect(gfx::Rect())) |
208 InvalidateScrollRect(); | 211 InvalidateScrollRect(); |
209 } | 212 } |
210 | 213 |
211 gfx::Rect PaintAggregator::ScrollPaintRect(const gfx::Rect& paint_rect, | 214 gfx::Rect PaintAggregator::ScrollPaintRect(const gfx::Rect& paint_rect, |
212 int dx, int dy) const { | 215 int dx, int dy) const { |
213 gfx::Rect result = paint_rect; | 216 gfx::Rect result = paint_rect; |
214 | 217 |
215 result.Offset(dx, dy); | 218 result.Offset(dx, dy); |
216 result = update_.scroll_rect.Intersect(result); | 219 result.Intersect(update_.scroll_rect); |
217 | 220 |
218 // Subtract out the scroll damage rect to avoid redundant painting. | 221 // Subtract out the scroll damage rect to avoid redundant painting. |
219 return result.Subtract(update_.GetScrollDamage()); | 222 result.Subtract(update_.GetScrollDamage()); |
| 223 return result; |
220 } | 224 } |
221 | 225 |
222 bool PaintAggregator::ShouldInvalidateScrollRect(const gfx::Rect& rect) const { | 226 bool PaintAggregator::ShouldInvalidateScrollRect(const gfx::Rect& rect) const { |
223 if (!rect.IsEmpty()) { | 227 if (!rect.IsEmpty()) { |
224 if (!update_.scroll_rect.Intersects(rect)) | 228 if (!update_.scroll_rect.Intersects(rect)) |
225 return false; | 229 return false; |
226 | 230 |
227 if (!update_.scroll_rect.Contains(rect)) | 231 if (!update_.scroll_rect.Contains(rect)) |
228 return true; | 232 return true; |
229 } | 233 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 // | 268 // |
265 if (update_.scroll_rect.IsEmpty()) { | 269 if (update_.scroll_rect.IsEmpty()) { |
266 gfx::Rect bounds = update_.GetPaintBounds(); | 270 gfx::Rect bounds = update_.GetPaintBounds(); |
267 update_.paint_rects.clear(); | 271 update_.paint_rects.clear(); |
268 update_.paint_rects.push_back(bounds); | 272 update_.paint_rects.push_back(bounds); |
269 } else { | 273 } else { |
270 gfx::Rect inner, outer; | 274 gfx::Rect inner, outer; |
271 for (size_t i = 0; i < update_.paint_rects.size(); ++i) { | 275 for (size_t i = 0; i < update_.paint_rects.size(); ++i) { |
272 const gfx::Rect& existing_rect = update_.paint_rects[i]; | 276 const gfx::Rect& existing_rect = update_.paint_rects[i]; |
273 if (update_.scroll_rect.Contains(existing_rect)) { | 277 if (update_.scroll_rect.Contains(existing_rect)) { |
274 inner = inner.Union(existing_rect); | 278 inner.Union(existing_rect); |
275 } else { | 279 } else { |
276 outer = outer.Union(existing_rect); | 280 outer.Union(existing_rect); |
277 } | 281 } |
278 } | 282 } |
279 update_.paint_rects.clear(); | 283 update_.paint_rects.clear(); |
280 update_.paint_rects.push_back(inner); | 284 update_.paint_rects.push_back(inner); |
281 update_.paint_rects.push_back(outer); | 285 update_.paint_rects.push_back(outer); |
282 } | 286 } |
283 } | 287 } |
OLD | NEW |