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.
5 #include "cc/debug/overdraw_metrics.h"
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"
18 OverdrawMetrics::OverdrawMetrics(bool record_metrics_for_frame
)
19 : record_metrics_for_frame_(record_metrics_for_frame
),
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) {}
30 static inline float WedgeProduct(gfx::PointF p1
, gfx::PointF p2
) {
31 return p1
.x() * p2
.y() - p1
.y() * p2
.x();
34 // Calculates area of an arbitrary convex polygon with up to 8 points.
35 static inline float PolygonArea(gfx::PointF points
[8], int num_points
) {
40 for (int i
= 0; i
< num_points
; ++i
)
41 area
+= WedgeProduct(points
[i
], points
[(i
+1)%num_points
]);
42 return std::abs(0.5f
* area
);
45 // Takes a given quad, maps it by the given transformation, and gives the area
46 // of the resulting polygon.
47 static inline float AreaOfMappedQuad(const gfx::Transform
& transform
,
48 const gfx::QuadF
& quad
) {
49 gfx::PointF clipped_quad
[8];
50 int num_vertices_in_clipped_quad
= 0;
51 MathUtil::MapClippedQuad(transform
,
54 &num_vertices_in_clipped_quad
);
55 return PolygonArea(clipped_quad
, num_vertices_in_clipped_quad
);
58 void OverdrawMetrics::DidPaint(gfx::Rect painted_rect
) {
59 if (!record_metrics_for_frame_
)
63 static_cast<float>(painted_rect
.width()) * painted_rect
.height();
66 void OverdrawMetrics::DidCullTilesForUpload(int count
) {
67 if (record_metrics_for_frame_
)
68 tiles_culled_for_upload_
+= count
;
71 void OverdrawMetrics::DidUpload(const gfx::Transform
& transform_to_target
,
72 gfx::Rect upload_rect
,
73 gfx::Rect opaque_rect
) {
74 if (!record_metrics_for_frame_
)
78 AreaOfMappedQuad(transform_to_target
, gfx::QuadF(upload_rect
));
79 float upload_opaque_area
=
80 AreaOfMappedQuad(transform_to_target
,
81 gfx::QuadF(gfx::IntersectRects(opaque_rect
,
84 pixels_uploaded_opaque_
+= upload_opaque_area
;
85 pixels_uploaded_translucent_
+= upload_area
- upload_opaque_area
;
88 void OverdrawMetrics::DidUseContentsTextureMemoryBytes(
89 size_t contents_texture_use_bytes
) {
90 if (!record_metrics_for_frame_
)
93 contents_texture_use_bytes_
+= contents_texture_use_bytes
;
96 void OverdrawMetrics::DidUseRenderSurfaceTextureMemoryBytes(
97 size_t render_surface_use_bytes
) {
98 if (!record_metrics_for_frame_
)
101 render_surface_texture_use_bytes_
+= render_surface_use_bytes
;
104 void OverdrawMetrics::DidCullForDrawing(
105 const gfx::Transform
& transform_to_target
,
106 gfx::Rect before_cull_rect
,
107 gfx::Rect after_cull_rect
) {
108 if (!record_metrics_for_frame_
)
111 float before_cull_area
=
112 AreaOfMappedQuad(transform_to_target
, gfx::QuadF(before_cull_rect
));
113 float after_cull_area
=
114 AreaOfMappedQuad(transform_to_target
, gfx::QuadF(after_cull_rect
));
116 pixels_culled_for_drawing_
+= before_cull_area
- after_cull_area
;
119 void OverdrawMetrics::DidDraw(const gfx::Transform
& transform_to_target
,
120 gfx::Rect after_cull_rect
,
121 gfx::Rect opaque_rect
) {
122 if (!record_metrics_for_frame_
)
125 float after_cull_area
=
126 AreaOfMappedQuad(transform_to_target
, gfx::QuadF(after_cull_rect
));
127 float after_cull_opaque_area
=
128 AreaOfMappedQuad(transform_to_target
,
129 gfx::QuadF(gfx::IntersectRects(opaque_rect
,
132 pixels_drawn_opaque_
+= after_cull_opaque_area
;
133 pixels_drawn_translucent_
+= after_cull_area
- after_cull_opaque_area
;
136 void OverdrawMetrics::RecordMetrics(
137 const LayerTreeHost
* layer_tree_host
) const {
138 if (record_metrics_for_frame_
)
139 RecordMetricsInternal
<LayerTreeHost
>(UpdateAndCommit
, layer_tree_host
);
142 void OverdrawMetrics::RecordMetrics(
143 const LayerTreeHostImpl
* layer_tree_host_impl
) const {
144 if (record_metrics_for_frame_
) {
145 RecordMetricsInternal
<LayerTreeHostImpl
>(DrawingToScreen
,
146 layer_tree_host_impl
);
150 static gfx::Size
DrawViewportSize(const LayerTreeHost
* host
) {
151 return host
->device_viewport_size();
153 static gfx::Size
DrawViewportSize(const LayerTreeHostImpl
* host_impl
) {
154 return host_impl
->DrawViewportSize();
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
163 float normalization
= 1000.f
/ (DrawViewportSize(layer_tree_host
).width() *
164 DrawViewportSize(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
/ (DrawViewportSize(layer_tree_host
).width() / 256.f
*
169 DrawViewportSize(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;
174 switch (metrics_type
) {
175 case DrawingToScreen
: {
176 UMA_HISTOGRAM_CUSTOM_COUNTS(
177 "Renderer4.pixelCountOpaque_Draw",
178 static_cast<int>(normalization
* pixels_drawn_opaque_
),
180 UMA_HISTOGRAM_CUSTOM_COUNTS(
181 "Renderer4.pixelCountTranslucent_Draw",
182 static_cast<int>(normalization
* pixels_drawn_translucent_
),
184 UMA_HISTOGRAM_CUSTOM_COUNTS(
185 "Renderer4.pixelCountCulled_Draw",
186 static_cast<int>(normalization
* pixels_culled_for_drawing_
),
189 TRACE_COUNTER_ID1("cc",
192 pixels_culled_for_drawing_
);
196 pixels_drawn_opaque_
,
197 "PixelsDrawnTranslucent",
198 pixels_drawn_translucent_
);
201 case UpdateAndCommit
: {
202 UMA_HISTOGRAM_CUSTOM_COUNTS(
203 "Renderer4.pixelCountPainted",
204 static_cast<int>(normalization
* pixels_painted_
),
206 UMA_HISTOGRAM_CUSTOM_COUNTS(
207 "Renderer4.pixelCountOpaque_Upload",
208 static_cast<int>(normalization
* pixels_uploaded_opaque_
),
210 UMA_HISTOGRAM_CUSTOM_COUNTS(
211 "Renderer4.pixelCountTranslucent_Upload",
212 static_cast<int>(normalization
* pixels_uploaded_translucent_
),
214 UMA_HISTOGRAM_CUSTOM_COUNTS(
215 "Renderer4.tileCountCulled_Upload",
216 static_cast<int>(tile_normalization
* tiles_culled_for_upload_
),
218 UMA_HISTOGRAM_CUSTOM_COUNTS(
219 "Renderer4.renderSurfaceTextureBytes_ViewportScaled",
221 byte_normalization
* render_surface_texture_use_bytes_
),
223 UMA_HISTOGRAM_CUSTOM_COUNTS(
224 "Renderer4.renderSurfaceTextureBytes_Unscaled",
225 static_cast<int>(render_surface_texture_use_bytes_
/ 1000),
226 1000, 100000000, 50);
227 UMA_HISTOGRAM_CUSTOM_COUNTS(
228 "Renderer4.contentsTextureBytes_ViewportScaled",
229 static_cast<int>(byte_normalization
* contents_texture_use_bytes_
),
231 UMA_HISTOGRAM_CUSTOM_COUNTS(
232 "Renderer4.contentsTextureBytes_Unscaled",
233 static_cast<int>(contents_texture_use_bytes_
/ 1000),
234 1000, 100000000, 50);
236 TRACE_COUNTER_ID1("cc",
239 tiles_culled_for_upload_
);
242 "PixelsUploadedOpaque",
243 pixels_uploaded_opaque_
,
244 "PixelsUploadedTranslucent",
245 pixels_uploaded_translucent_
);
248 // This must be in a different scope than the TRACE_EVENT2 above.
250 "OverdrawPaintMetrics",
255 // This must be in a different scope than the TRACE_EVENTs above.
257 "OverdrawPaintMetrics",
258 "ContentsTextureBytes",
259 contents_texture_use_bytes_
,
260 "RenderSurfaceTextureBytes",
261 render_surface_texture_use_bytes_
);