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(const gfx::PointF
& p1
, const 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(const gfx::PointF (&points
)[8],
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
);
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
,
55 &num_vertices_in_clipped_quad
);
56 return PolygonArea(clipped_quad
, num_vertices_in_clipped_quad
);
59 void OverdrawMetrics::DidPaint(const gfx::Rect
& painted_rect
) {
60 if (!record_metrics_for_frame_
)
64 static_cast<float>(painted_rect
.width()) * painted_rect
.height();
67 void OverdrawMetrics::DidCullTilesForUpload(int count
) {
68 if (record_metrics_for_frame_
)
69 tiles_culled_for_upload_
+= count
;
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_
)
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
,
85 pixels_uploaded_opaque_
+= upload_opaque_area
;
86 pixels_uploaded_translucent_
+= upload_area
- upload_opaque_area
;
89 void OverdrawMetrics::DidUseContentsTextureMemoryBytes(
90 size_t contents_texture_use_bytes
) {
91 if (!record_metrics_for_frame_
)
94 contents_texture_use_bytes_
+= contents_texture_use_bytes
;
97 void OverdrawMetrics::DidUseRenderSurfaceTextureMemoryBytes(
98 size_t render_surface_use_bytes
) {
99 if (!record_metrics_for_frame_
)
102 render_surface_texture_use_bytes_
+= render_surface_use_bytes
;
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_
)
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
));
117 pixels_culled_for_drawing_
+= before_cull_area
- after_cull_area
;
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_
)
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
,
133 pixels_drawn_opaque_
+= after_cull_opaque_area
;
134 pixels_drawn_translucent_
+= after_cull_area
- after_cull_opaque_area
;
137 void OverdrawMetrics::RecordMetrics(
138 const LayerTreeHost
* layer_tree_host
) const {
139 if (record_metrics_for_frame_
)
140 RecordMetricsInternal
<LayerTreeHost
>(UpdateAndCommit
, layer_tree_host
);
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
);
151 static gfx::Size
DrawViewportSize(const LayerTreeHost
* host
) {
152 return host
->device_viewport_size();
154 static gfx::Size
DrawViewportSize(const LayerTreeHostImpl
* host_impl
) {
155 return host_impl
->DrawViewportSize();
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
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;
175 switch (metrics_type
) {
176 case DrawingToScreen
: {
177 UMA_HISTOGRAM_CUSTOM_COUNTS(
178 "Renderer4.pixelCountOpaque_Draw",
179 static_cast<int>(normalization
* pixels_drawn_opaque_
),
181 UMA_HISTOGRAM_CUSTOM_COUNTS(
182 "Renderer4.pixelCountTranslucent_Draw",
183 static_cast<int>(normalization
* pixels_drawn_translucent_
),
185 UMA_HISTOGRAM_CUSTOM_COUNTS(
186 "Renderer4.pixelCountCulled_Draw",
187 static_cast<int>(normalization
* pixels_culled_for_drawing_
),
190 TRACE_COUNTER_ID1("cc",
193 pixels_culled_for_drawing_
);
197 pixels_drawn_opaque_
,
198 "PixelsDrawnTranslucent",
199 pixels_drawn_translucent_
);
202 case UpdateAndCommit
: {
203 UMA_HISTOGRAM_CUSTOM_COUNTS(
204 "Renderer4.pixelCountPainted",
205 static_cast<int>(normalization
* pixels_painted_
),
207 UMA_HISTOGRAM_CUSTOM_COUNTS(
208 "Renderer4.pixelCountOpaque_Upload",
209 static_cast<int>(normalization
* pixels_uploaded_opaque_
),
211 UMA_HISTOGRAM_CUSTOM_COUNTS(
212 "Renderer4.pixelCountTranslucent_Upload",
213 static_cast<int>(normalization
* pixels_uploaded_translucent_
),
215 UMA_HISTOGRAM_CUSTOM_COUNTS(
216 "Renderer4.tileCountCulled_Upload",
217 static_cast<int>(tile_normalization
* tiles_culled_for_upload_
),
219 UMA_HISTOGRAM_CUSTOM_COUNTS(
220 "Renderer4.renderSurfaceTextureBytes_ViewportScaled",
222 byte_normalization
* render_surface_texture_use_bytes_
),
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_
),
232 UMA_HISTOGRAM_CUSTOM_COUNTS(
233 "Renderer4.contentsTextureBytes_Unscaled",
234 static_cast<int>(contents_texture_use_bytes_
/ 1000),
235 1000, 100000000, 50);
237 TRACE_COUNTER_ID1("cc",
240 tiles_culled_for_upload_
);
243 "PixelsUploadedOpaque",
244 pixels_uploaded_opaque_
,
245 "PixelsUploadedTranslucent",
246 pixels_uploaded_translucent_
);
249 // This must be in a different scope than the TRACE_EVENT2 above.
251 "OverdrawPaintMetrics",
256 // This must be in a different scope than the TRACE_EVENTs above.
258 "OverdrawPaintMetrics",
259 "ContentsTextureBytes",
260 contents_texture_use_bytes_
,
261 "RenderSurfaceTextureBytes",
262 render_surface_texture_use_bytes_
);