// Copyright 2012 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "cc/overdraw_metrics.h" #include "base/debug/trace_event.h" #include "base/metrics/histogram.h" #include "cc/layer_tree_host.h" #include "cc/layer_tree_host_impl.h" #include "cc/math_util.h" #include "ui/gfx/quad_f.h" #include "ui/gfx/rect.h" #include <public/WebTransformationMatrix.h> using WebKit::WebTransformationMatrix; namespace cc { OverdrawMetrics::OverdrawMetrics(bool recordMetricsForFrame) : m_recordMetricsForFrame(recordMetricsForFrame) , m_pixelsPainted(0) , m_pixelsUploadedOpaque(0) , m_pixelsUploadedTranslucent(0) , m_tilesCulledForUpload(0) , m_contentsTextureUseBytes(0) , m_renderSurfaceTextureUseBytes(0) , m_pixelsDrawnOpaque(0) , m_pixelsDrawnTranslucent(0) , m_pixelsCulledForDrawing(0) { } void OverdrawMetrics::didPaint(const gfx::Rect& paintedRect) { if (!m_recordMetricsForFrame) return; m_pixelsPainted += static_cast<float>(paintedRect.width()) * paintedRect.height(); } void OverdrawMetrics::didCullTilesForUpload(int count) { if (m_recordMetricsForFrame) m_tilesCulledForUpload += count; } void OverdrawMetrics::didUpload(const WebTransformationMatrix& transformToTarget, const gfx::Rect& uploadRect, const gfx::Rect& opaqueRect) { if (!m_recordMetricsForFrame) return; gfx::Rect uploadOpaqueRect = gfx::IntersectRects(opaqueRect, uploadRect); float uploadArea = static_cast<float>(uploadRect.width()) * uploadRect.height(); float uploadOpaqueArea = static_cast<float>(uploadOpaqueRect.width()) * uploadOpaqueRect.height(); m_pixelsUploadedOpaque += uploadOpaqueArea; m_pixelsUploadedTranslucent += uploadArea - uploadOpaqueArea; } void OverdrawMetrics::didUseContentsTextureMemoryBytes(size_t contentsTextureUseBytes) { if (!m_recordMetricsForFrame) return; m_contentsTextureUseBytes += contentsTextureUseBytes; } void OverdrawMetrics::didUseRenderSurfaceTextureMemoryBytes(size_t renderSurfaceUseBytes) { if (!m_recordMetricsForFrame) return; m_renderSurfaceTextureUseBytes += renderSurfaceUseBytes; } void OverdrawMetrics::didCullForDrawing(const WebTransformationMatrix& transformToTarget, const gfx::Rect& beforeCullRect, const gfx::Rect& afterCullRect) { if (!m_recordMetricsForFrame) return; float beforeCullArea = static_cast<float>(beforeCullRect.width()) * beforeCullRect.height(); float afterCullArea = static_cast<float>(afterCullRect.width()) * afterCullRect.height(); m_pixelsCulledForDrawing += beforeCullArea - afterCullArea; } void OverdrawMetrics::didDraw(const WebTransformationMatrix& transformToTarget, const gfx::Rect& afterCullRect, const gfx::Rect& opaqueRect) { if (!m_recordMetricsForFrame) return; gfx::Rect afterCullOpaqueRect = gfx::IntersectRects(opaqueRect, afterCullRect); float afterCullArea = static_cast<float>(afterCullRect.width()) * afterCullRect.height(); float afterCullOpaqueArea = static_cast<float>(afterCullOpaqueRect.width()) * afterCullOpaqueRect.height(); m_pixelsDrawnOpaque += afterCullOpaqueArea; m_pixelsDrawnTranslucent += afterCullArea - afterCullOpaqueArea; } void OverdrawMetrics::recordMetrics(const LayerTreeHost* layerTreeHost) const { if (m_recordMetricsForFrame) recordMetricsInternal<LayerTreeHost>(UpdateAndCommit, layerTreeHost); } void OverdrawMetrics::recordMetrics(const LayerTreeHostImpl* layerTreeHost) const { if (m_recordMetricsForFrame) recordMetricsInternal<LayerTreeHostImpl>(DrawingToScreen, layerTreeHost); } template<typename LayerTreeHostType> void OverdrawMetrics::recordMetricsInternal(MetricsType metricsType, const LayerTreeHostType* layerTreeHost) const { // This gives approximately 10x the percentage of pixels to fill the viewport once. float normalization = 1000.f / (layerTreeHost->deviceViewportSize().width() * layerTreeHost->deviceViewportSize().height()); // This gives approximately 100x the percentage of tiles to fill the viewport once, if all tiles were 256x256. float tileNormalization = 10000.f / (layerTreeHost->deviceViewportSize().width() / 256.f * layerTreeHost->deviceViewportSize().height() / 256.f); // This gives approximately 10x the percentage of bytes to fill the viewport once, assuming 4 bytes per pixel. float byteNormalization = normalization / 4; switch (metricsType) { case DrawingToScreen: { HISTOGRAM_CUSTOM_COUNTS("Renderer4.pixelCountOpaque_Draw", static_cast<int>(normalization * m_pixelsDrawnOpaque), 100, 1000000, 50); HISTOGRAM_CUSTOM_COUNTS("Renderer4.pixelCountTranslucent_Draw", static_cast<int>(normalization * m_pixelsDrawnTranslucent), 100, 1000000, 50); HISTOGRAM_CUSTOM_COUNTS("Renderer4.pixelCountCulled_Draw", static_cast<int>(normalization * m_pixelsCulledForDrawing), 100, 1000000, 50); TRACE_COUNTER_ID1("cc", "DrawPixelsCulled", layerTreeHost, m_pixelsCulledForDrawing); TRACE_EVENT2("cc", "OverdrawMetrics", "PixelsDrawnOpaque", m_pixelsDrawnOpaque, "PixelsDrawnTranslucent", m_pixelsDrawnTranslucent); break; } case UpdateAndCommit: { HISTOGRAM_CUSTOM_COUNTS("Renderer4.pixelCountPainted", static_cast<int>(normalization * m_pixelsPainted), 100, 1000000, 50); HISTOGRAM_CUSTOM_COUNTS("Renderer4.pixelCountOpaque_Upload", static_cast<int>(normalization * m_pixelsUploadedOpaque), 100, 1000000, 50); HISTOGRAM_CUSTOM_COUNTS("Renderer4.pixelCountTranslucent_Upload", static_cast<int>(normalization * m_pixelsUploadedTranslucent), 100, 1000000, 50); HISTOGRAM_CUSTOM_COUNTS("Renderer4.tileCountCulled_Upload", static_cast<int>(tileNormalization * m_tilesCulledForUpload), 100, 10000000, 50); HISTOGRAM_CUSTOM_COUNTS("Renderer4.renderSurfaceTextureBytes_ViewportScaled", static_cast<int>(byteNormalization * m_renderSurfaceTextureUseBytes), 10, 1000000, 50); HISTOGRAM_CUSTOM_COUNTS("Renderer4.renderSurfaceTextureBytes_Unscaled", static_cast<int>(m_renderSurfaceTextureUseBytes / 1000), 1000, 100000000, 50); HISTOGRAM_CUSTOM_COUNTS("Renderer4.contentsTextureBytes_ViewportScaled", static_cast<int>(byteNormalization * m_contentsTextureUseBytes), 10, 1000000, 50); HISTOGRAM_CUSTOM_COUNTS("Renderer4.contentsTextureBytes_Unscaled", static_cast<int>(m_contentsTextureUseBytes / 1000), 1000, 100000000, 50); { TRACE_COUNTER_ID1("cc", "UploadTilesCulled", layerTreeHost, m_tilesCulledForUpload); TRACE_EVENT2("cc", "OverdrawMetrics", "PixelsUploadedOpaque", m_pixelsUploadedOpaque, "PixelsUploadedTranslucent", m_pixelsUploadedTranslucent); } { // This must be in a different scope than the TRACE_EVENT2 above. TRACE_EVENT1("cc", "OverdrawPaintMetrics", "PixelsPainted", m_pixelsPainted); } { // This must be in a different scope than the TRACE_EVENTs above. TRACE_EVENT2("cc", "OverdrawPaintMetrics", "ContentsTextureBytes", m_contentsTextureUseBytes, "RenderSurfaceTextureBytes", m_renderSurfaceTextureUseBytes); } break; } } } } // namespace cc