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