OLD | NEW |
| (Empty) |
1 // Copyright 2012 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/debug/overdraw_metrics.h" | |
6 | |
7 #include "base/debug/trace_event.h" | |
8 #include "base/metrics/histogram.h" | |
9 #include "cc/base/math_util.h" | |
10 #include "cc/trees/layer_tree_host.h" | |
11 #include "cc/trees/layer_tree_host_impl.h" | |
12 #include "ui/gfx/quad_f.h" | |
13 #include "ui/gfx/rect.h" | |
14 #include "ui/gfx/transform.h" | |
15 | |
16 namespace cc { | |
17 | |
18 OverdrawMetrics::OverdrawMetrics(bool record_metrics_for_frame) | |
19 : record_metrics_for_frame_(record_metrics_for_frame), | |
20 pixels_painted_(0), | |
21 pixels_uploaded_opaque_(0), | |
22 pixels_uploaded_translucent_(0), | |
23 tiles_culled_for_upload_(0), | |
24 contents_texture_use_bytes_(0), | |
25 render_surface_texture_use_bytes_(0), | |
26 pixels_drawn_opaque_(0), | |
27 pixels_drawn_translucent_(0), | |
28 pixels_culled_for_drawing_(0) {} | |
29 | |
30 static inline float WedgeProduct(const gfx::PointF& p1, const gfx::PointF& p2) { | |
31 return p1.x() * p2.y() - p1.y() * p2.x(); | |
32 } | |
33 | |
34 // Calculates area of an arbitrary convex polygon with up to 8 points. | |
35 static inline float PolygonArea(const gfx::PointF (&points)[8], | |
36 int num_points) { | |
37 if (num_points < 3) | |
38 return 0; | |
39 | |
40 float area = 0; | |
41 for (int i = 0; i < num_points; ++i) | |
42 area += WedgeProduct(points[i], points[(i+1)%num_points]); | |
43 return std::abs(0.5f * area); | |
44 } | |
45 | |
46 // Takes a given quad, maps it by the given transformation, and gives the area | |
47 // of the resulting polygon. | |
48 static inline float AreaOfMappedQuad(const gfx::Transform& transform, | |
49 const gfx::QuadF& quad) { | |
50 gfx::PointF clipped_quad[8]; | |
51 int num_vertices_in_clipped_quad = 0; | |
52 MathUtil::MapClippedQuad(transform, | |
53 quad, | |
54 clipped_quad, | |
55 &num_vertices_in_clipped_quad); | |
56 return PolygonArea(clipped_quad, num_vertices_in_clipped_quad); | |
57 } | |
58 | |
59 void OverdrawMetrics::DidPaint(const gfx::Rect& painted_rect) { | |
60 if (!record_metrics_for_frame_) | |
61 return; | |
62 | |
63 pixels_painted_ += | |
64 static_cast<float>(painted_rect.width()) * painted_rect.height(); | |
65 } | |
66 | |
67 void OverdrawMetrics::DidCullTilesForUpload(int count) { | |
68 if (record_metrics_for_frame_) | |
69 tiles_culled_for_upload_ += count; | |
70 } | |
71 | |
72 void OverdrawMetrics::DidUpload(const gfx::Transform& transform_to_target, | |
73 const gfx::Rect& upload_rect, | |
74 const gfx::Rect& opaque_rect) { | |
75 if (!record_metrics_for_frame_) | |
76 return; | |
77 | |
78 float upload_area = | |
79 AreaOfMappedQuad(transform_to_target, gfx::QuadF(upload_rect)); | |
80 float upload_opaque_area = | |
81 AreaOfMappedQuad(transform_to_target, | |
82 gfx::QuadF(gfx::IntersectRects(opaque_rect, | |
83 upload_rect))); | |
84 | |
85 pixels_uploaded_opaque_ += upload_opaque_area; | |
86 pixels_uploaded_translucent_ += upload_area - upload_opaque_area; | |
87 } | |
88 | |
89 void OverdrawMetrics::DidUseContentsTextureMemoryBytes( | |
90 size_t contents_texture_use_bytes) { | |
91 if (!record_metrics_for_frame_) | |
92 return; | |
93 | |
94 contents_texture_use_bytes_ += contents_texture_use_bytes; | |
95 } | |
96 | |
97 void OverdrawMetrics::DidUseRenderSurfaceTextureMemoryBytes( | |
98 size_t render_surface_use_bytes) { | |
99 if (!record_metrics_for_frame_) | |
100 return; | |
101 | |
102 render_surface_texture_use_bytes_ += render_surface_use_bytes; | |
103 } | |
104 | |
105 void OverdrawMetrics::DidCullForDrawing( | |
106 const gfx::Transform& transform_to_target, | |
107 const gfx::Rect& before_cull_rect, | |
108 const gfx::Rect& after_cull_rect) { | |
109 if (!record_metrics_for_frame_) | |
110 return; | |
111 | |
112 float before_cull_area = | |
113 AreaOfMappedQuad(transform_to_target, gfx::QuadF(before_cull_rect)); | |
114 float after_cull_area = | |
115 AreaOfMappedQuad(transform_to_target, gfx::QuadF(after_cull_rect)); | |
116 | |
117 pixels_culled_for_drawing_ += before_cull_area - after_cull_area; | |
118 } | |
119 | |
120 void OverdrawMetrics::DidDraw(const gfx::Transform& transform_to_target, | |
121 const gfx::Rect& after_cull_rect, | |
122 const gfx::Rect& opaque_rect) { | |
123 if (!record_metrics_for_frame_) | |
124 return; | |
125 | |
126 float after_cull_area = | |
127 AreaOfMappedQuad(transform_to_target, gfx::QuadF(after_cull_rect)); | |
128 float after_cull_opaque_area = | |
129 AreaOfMappedQuad(transform_to_target, | |
130 gfx::QuadF(gfx::IntersectRects(opaque_rect, | |
131 after_cull_rect))); | |
132 | |
133 pixels_drawn_opaque_ += after_cull_opaque_area; | |
134 pixels_drawn_translucent_ += after_cull_area - after_cull_opaque_area; | |
135 } | |
136 | |
137 void OverdrawMetrics::RecordMetrics( | |
138 const LayerTreeHost* layer_tree_host) const { | |
139 if (record_metrics_for_frame_) | |
140 RecordMetricsInternal<LayerTreeHost>(UpdateAndCommit, layer_tree_host); | |
141 } | |
142 | |
143 void OverdrawMetrics::RecordMetrics( | |
144 const LayerTreeHostImpl* layer_tree_host_impl) const { | |
145 if (record_metrics_for_frame_) { | |
146 RecordMetricsInternal<LayerTreeHostImpl>(DrawingToScreen, | |
147 layer_tree_host_impl); | |
148 } | |
149 } | |
150 | |
151 static gfx::Size DrawViewportSize(const LayerTreeHost* host) { | |
152 return host->device_viewport_size(); | |
153 } | |
154 static gfx::Size DrawViewportSize(const LayerTreeHostImpl* host_impl) { | |
155 return host_impl->DrawViewportSize(); | |
156 } | |
157 | |
158 template <typename LayerTreeHostType> | |
159 void OverdrawMetrics::RecordMetricsInternal( | |
160 MetricsType metrics_type, | |
161 const LayerTreeHostType* layer_tree_host) const { | |
162 // This gives approximately 10x the percentage of pixels to fill the viewport | |
163 // once. | |
164 float normalization = 1000.f / (DrawViewportSize(layer_tree_host).width() * | |
165 DrawViewportSize(layer_tree_host).height()); | |
166 // This gives approximately 100x the percentage of tiles to fill the viewport | |
167 // once, if all tiles were 256x256. | |
168 float tile_normalization = | |
169 10000.f / (DrawViewportSize(layer_tree_host).width() / 256.f * | |
170 DrawViewportSize(layer_tree_host).height() / 256.f); | |
171 // This gives approximately 10x the percentage of bytes to fill the viewport | |
172 // once, assuming 4 bytes per pixel. | |
173 float byte_normalization = normalization / 4; | |
174 | |
175 switch (metrics_type) { | |
176 case DrawingToScreen: { | |
177 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
178 "Renderer4.pixelCountOpaque_Draw", | |
179 static_cast<int>(normalization * pixels_drawn_opaque_), | |
180 100, 1000000, 50); | |
181 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
182 "Renderer4.pixelCountTranslucent_Draw", | |
183 static_cast<int>(normalization * pixels_drawn_translucent_), | |
184 100, 1000000, 50); | |
185 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
186 "Renderer4.pixelCountCulled_Draw", | |
187 static_cast<int>(normalization * pixels_culled_for_drawing_), | |
188 100, 1000000, 50); | |
189 | |
190 TRACE_COUNTER_ID1("cc", | |
191 "DrawPixelsCulled", | |
192 layer_tree_host, | |
193 pixels_culled_for_drawing_); | |
194 TRACE_EVENT2("cc", | |
195 "OverdrawMetrics", | |
196 "PixelsDrawnOpaque", | |
197 pixels_drawn_opaque_, | |
198 "PixelsDrawnTranslucent", | |
199 pixels_drawn_translucent_); | |
200 break; | |
201 } | |
202 case UpdateAndCommit: { | |
203 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
204 "Renderer4.pixelCountPainted", | |
205 static_cast<int>(normalization * pixels_painted_), | |
206 100, 1000000, 50); | |
207 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
208 "Renderer4.pixelCountOpaque_Upload", | |
209 static_cast<int>(normalization * pixels_uploaded_opaque_), | |
210 100, 1000000, 50); | |
211 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
212 "Renderer4.pixelCountTranslucent_Upload", | |
213 static_cast<int>(normalization * pixels_uploaded_translucent_), | |
214 100, 1000000, 50); | |
215 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
216 "Renderer4.tileCountCulled_Upload", | |
217 static_cast<int>(tile_normalization * tiles_culled_for_upload_), | |
218 100, 10000000, 50); | |
219 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
220 "Renderer4.renderSurfaceTextureBytes_ViewportScaled", | |
221 static_cast<int>( | |
222 byte_normalization * render_surface_texture_use_bytes_), | |
223 10, 1000000, 50); | |
224 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
225 "Renderer4.renderSurfaceTextureBytes_Unscaled", | |
226 static_cast<int>(render_surface_texture_use_bytes_ / 1000), | |
227 1000, 100000000, 50); | |
228 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
229 "Renderer4.contentsTextureBytes_ViewportScaled", | |
230 static_cast<int>(byte_normalization * contents_texture_use_bytes_), | |
231 10, 1000000, 50); | |
232 UMA_HISTOGRAM_CUSTOM_COUNTS( | |
233 "Renderer4.contentsTextureBytes_Unscaled", | |
234 static_cast<int>(contents_texture_use_bytes_ / 1000), | |
235 1000, 100000000, 50); | |
236 { | |
237 TRACE_COUNTER_ID1("cc", | |
238 "UploadTilesCulled", | |
239 layer_tree_host, | |
240 tiles_culled_for_upload_); | |
241 TRACE_EVENT2("cc", | |
242 "OverdrawMetrics", | |
243 "PixelsUploadedOpaque", | |
244 pixels_uploaded_opaque_, | |
245 "PixelsUploadedTranslucent", | |
246 pixels_uploaded_translucent_); | |
247 } | |
248 { | |
249 // This must be in a different scope than the TRACE_EVENT2 above. | |
250 TRACE_EVENT1("cc", | |
251 "OverdrawPaintMetrics", | |
252 "PixelsPainted", | |
253 pixels_painted_); | |
254 } | |
255 { | |
256 // This must be in a different scope than the TRACE_EVENTs above. | |
257 TRACE_EVENT2("cc", | |
258 "OverdrawPaintMetrics", | |
259 "ContentsTextureBytes", | |
260 contents_texture_use_bytes_, | |
261 "RenderSurfaceTextureBytes", | |
262 render_surface_texture_use_bytes_); | |
263 } | |
264 break; | |
265 } | |
266 } | |
267 } | |
268 | |
269 } // namespace cc | |
OLD | NEW |