Home | History | Annotate | Download | only in debug
      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(gfx::PointF p1, 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(gfx::PointF points[8], int num_points) {
     36   if (num_points < 3)
     37     return 0;
     38 
     39   float area = 0;
     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);
     43 }
     44 
     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,
     52                            quad,
     53                            clipped_quad,
     54                            &num_vertices_in_clipped_quad);
     55   return PolygonArea(clipped_quad, num_vertices_in_clipped_quad);
     56 }
     57 
     58 void OverdrawMetrics::DidPaint(gfx::Rect painted_rect) {
     59   if (!record_metrics_for_frame_)
     60     return;
     61 
     62   pixels_painted_ +=
     63       static_cast<float>(painted_rect.width()) * painted_rect.height();
     64 }
     65 
     66 void OverdrawMetrics::DidCullTilesForUpload(int count) {
     67   if (record_metrics_for_frame_)
     68     tiles_culled_for_upload_ += count;
     69 }
     70 
     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_)
     75     return;
     76 
     77   float upload_area =
     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,
     82                                                       upload_rect)));
     83 
     84   pixels_uploaded_opaque_ += upload_opaque_area;
     85   pixels_uploaded_translucent_ += upload_area - upload_opaque_area;
     86 }
     87 
     88 void OverdrawMetrics::DidUseContentsTextureMemoryBytes(
     89     size_t contents_texture_use_bytes) {
     90   if (!record_metrics_for_frame_)
     91     return;
     92 
     93   contents_texture_use_bytes_ += contents_texture_use_bytes;
     94 }
     95 
     96 void OverdrawMetrics::DidUseRenderSurfaceTextureMemoryBytes(
     97     size_t render_surface_use_bytes) {
     98   if (!record_metrics_for_frame_)
     99     return;
    100 
    101   render_surface_texture_use_bytes_ += render_surface_use_bytes;
    102 }
    103 
    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_)
    109     return;
    110 
    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));
    115 
    116   pixels_culled_for_drawing_ += before_cull_area - after_cull_area;
    117 }
    118 
    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_)
    123     return;
    124 
    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,
    130                                                       after_cull_rect)));
    131 
    132   pixels_drawn_opaque_ += after_cull_opaque_area;
    133   pixels_drawn_translucent_ += after_cull_area - after_cull_opaque_area;
    134 }
    135 
    136 void OverdrawMetrics::RecordMetrics(
    137     const LayerTreeHost* layer_tree_host) const {
    138   if (record_metrics_for_frame_)
    139     RecordMetricsInternal<LayerTreeHost>(UpdateAndCommit, layer_tree_host);
    140 }
    141 
    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);
    147   }
    148 }
    149 
    150 static gfx::Size DrawViewportSize(const LayerTreeHost* host) {
    151   return host->device_viewport_size();
    152 }
    153 static gfx::Size DrawViewportSize(const LayerTreeHostImpl* host_impl) {
    154   return host_impl->DrawViewportSize();
    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 / (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;
    173 
    174   switch (metrics_type) {
    175     case DrawingToScreen: {
    176       UMA_HISTOGRAM_CUSTOM_COUNTS(
    177           "Renderer4.pixelCountOpaque_Draw",
    178           static_cast<int>(normalization * pixels_drawn_opaque_),
    179           100, 1000000, 50);
    180       UMA_HISTOGRAM_CUSTOM_COUNTS(
    181           "Renderer4.pixelCountTranslucent_Draw",
    182           static_cast<int>(normalization * pixels_drawn_translucent_),
    183           100, 1000000, 50);
    184       UMA_HISTOGRAM_CUSTOM_COUNTS(
    185           "Renderer4.pixelCountCulled_Draw",
    186           static_cast<int>(normalization * pixels_culled_for_drawing_),
    187           100, 1000000, 50);
    188 
    189       TRACE_COUNTER_ID1("cc",
    190                         "DrawPixelsCulled",
    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;
    200     }
    201     case UpdateAndCommit: {
    202       UMA_HISTOGRAM_CUSTOM_COUNTS(
    203           "Renderer4.pixelCountPainted",
    204           static_cast<int>(normalization * pixels_painted_),
    205           100, 1000000, 50);
    206       UMA_HISTOGRAM_CUSTOM_COUNTS(
    207           "Renderer4.pixelCountOpaque_Upload",
    208           static_cast<int>(normalization * pixels_uploaded_opaque_),
    209           100, 1000000, 50);
    210       UMA_HISTOGRAM_CUSTOM_COUNTS(
    211           "Renderer4.pixelCountTranslucent_Upload",
    212           static_cast<int>(normalization * pixels_uploaded_translucent_),
    213           100, 1000000, 50);
    214       UMA_HISTOGRAM_CUSTOM_COUNTS(
    215           "Renderer4.tileCountCulled_Upload",
    216           static_cast<int>(tile_normalization * tiles_culled_for_upload_),
    217           100, 10000000, 50);
    218       UMA_HISTOGRAM_CUSTOM_COUNTS(
    219           "Renderer4.renderSurfaceTextureBytes_ViewportScaled",
    220           static_cast<int>(
    221               byte_normalization * render_surface_texture_use_bytes_),
    222           10, 1000000, 50);
    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_),
    230           10, 1000000, 50);
    231       UMA_HISTOGRAM_CUSTOM_COUNTS(
    232           "Renderer4.contentsTextureBytes_Unscaled",
    233           static_cast<int>(contents_texture_use_bytes_ / 1000),
    234           1000, 100000000, 50);
    235       {
    236         TRACE_COUNTER_ID1("cc",
    237                           "UploadTilesCulled",
    238                           layer_tree_host,
    239                           tiles_culled_for_upload_);
    240         TRACE_EVENT2("cc",
    241                      "OverdrawMetrics",
    242                      "PixelsUploadedOpaque",
    243                      pixels_uploaded_opaque_,
    244                      "PixelsUploadedTranslucent",
    245                      pixels_uploaded_translucent_);
    246       }
    247       {
    248         // This must be in a different scope than the TRACE_EVENT2 above.
    249         TRACE_EVENT1("cc",
    250                      "OverdrawPaintMetrics",
    251                      "PixelsPainted",
    252                      pixels_painted_);
    253       }
    254       {
    255         // This must be in a different scope than the TRACE_EVENTs above.
    256         TRACE_EVENT2("cc",
    257                      "OverdrawPaintMetrics",
    258                      "ContentsTextureBytes",
    259                      contents_texture_use_bytes_,
    260                      "RenderSurfaceTextureBytes",
    261                      render_surface_texture_use_bytes_);
    262       }
    263       break;
    264     }
    265   }
    266 }
    267 
    268 }  // namespace cc
    269