// 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/resources/picture_pile.h" #include <algorithm> #include <limits> #include <vector> #include "cc/base/region.h" #include "cc/debug/rendering_stats_instrumentation.h" #include "cc/resources/picture_pile_impl.h" namespace { // Layout pixel buffer around the visible layer rect to record. Any base // picture that intersects the visible layer rect expanded by this distance // will be recorded. const int kPixelDistanceToRecord = 8000; } // namespace namespace cc { PicturePile::PicturePile() { } PicturePile::~PicturePile() { } bool PicturePile::Update( ContentLayerClient* painter, SkColor background_color, bool contents_opaque, const Region& invalidation, gfx::Rect visible_layer_rect, RenderingStatsInstrumentation* stats_instrumentation) { background_color_ = background_color; contents_opaque_ = contents_opaque; gfx::Rect interest_rect = visible_layer_rect; interest_rect.Inset( -kPixelDistanceToRecord, -kPixelDistanceToRecord, -kPixelDistanceToRecord, -kPixelDistanceToRecord); bool invalidated = false; for (Region::Iterator i(invalidation); i.has_rect(); i.next()) { gfx::Rect invalidation = i.rect(); // Split this inflated invalidation across tile boundaries and apply it // to all tiles that it touches. for (TilingData::Iterator iter(&tiling_, invalidation); iter; ++iter) { const PictureMapKey& key = iter.index(); PictureMap::iterator picture_it = picture_map_.find(key); if (picture_it == picture_map_.end()) continue; invalidated = picture_it->second.Invalidate() || invalidated; } } gfx::Rect record_rect; for (TilingData::Iterator it(&tiling_, interest_rect); it; ++it) { const PictureMapKey& key = it.index(); const PictureInfo& info = picture_map_[key]; if (!info.picture.get()) { gfx::Rect tile = PaddedRect(key); record_rect.Union(tile); } } if (record_rect.IsEmpty()) { if (invalidated) UpdateRecordedRegion(); return invalidated; } int repeat_count = std::max(1, slow_down_raster_scale_factor_for_debug_); scoped_refptr<Picture> picture = Picture::Create(record_rect); { base::TimeDelta best_duration = base::TimeDelta::FromInternalValue( std::numeric_limits<int64>::max()); for (int i = 0; i < repeat_count; i++) { base::TimeTicks start_time = stats_instrumentation->StartRecording(); picture->Record(painter, tile_grid_info_); base::TimeDelta duration = stats_instrumentation->EndRecording(start_time); best_duration = std::min(duration, best_duration); } int recorded_pixel_count = picture->LayerRect().width() * picture->LayerRect().height(); stats_instrumentation->AddRecord(best_duration, recorded_pixel_count); if (num_raster_threads_ > 1) picture->GatherPixelRefs(tile_grid_info_); picture->CloneForDrawing(num_raster_threads_); } for (TilingData::Iterator it(&tiling_, record_rect); it; ++it) { const PictureMapKey& key = it.index(); gfx::Rect tile = PaddedRect(key); if (record_rect.Contains(tile)) { PictureInfo& info = picture_map_[key]; info.picture = picture; } } UpdateRecordedRegion(); return true; } } // namespace cc