1ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang// Copyright 2011 The Chromium Authors. All rights reserved. 2ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang// Use of this source code is governed by a BSD-style license that can be 31b362b15af34006e6a11974088a46d42b903418eJohann// found in the LICENSE file. 41b362b15af34006e6a11974088a46d42b903418eJohann 51b362b15af34006e6a11974088a46d42b903418eJohann#include "cc/layers/tiled_layer.h" 61b362b15af34006e6a11974088a46d42b903418eJohann 71b362b15af34006e6a11974088a46d42b903418eJohann#include <algorithm> 81b362b15af34006e6a11974088a46d42b903418eJohann#include <vector> 91b362b15af34006e6a11974088a46d42b903418eJohann 10ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "base/auto_reset.h" 11ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "base/basictypes.h" 12ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#include "build/build_config.h" 131b362b15af34006e6a11974088a46d42b903418eJohann#include "cc/base/simple_enclosed_region.h" 141b362b15af34006e6a11974088a46d42b903418eJohann#include "cc/layers/layer_impl.h" 151b362b15af34006e6a11974088a46d42b903418eJohann#include "cc/layers/tiled_layer_impl.h" 161b362b15af34006e6a11974088a46d42b903418eJohann#include "cc/resources/layer_updater.h" 171b362b15af34006e6a11974088a46d42b903418eJohann#include "cc/resources/prioritized_resource.h" 181b362b15af34006e6a11974088a46d42b903418eJohann#include "cc/resources/priority_calculator.h" 191b362b15af34006e6a11974088a46d42b903418eJohann#include "cc/trees/layer_tree_host.h" 201b362b15af34006e6a11974088a46d42b903418eJohann#include "cc/trees/occlusion_tracker.h" 211b362b15af34006e6a11974088a46d42b903418eJohann#include "third_party/khronos/GLES2/gl2.h" 221b362b15af34006e6a11974088a46d42b903418eJohann#include "ui/gfx/rect_conversions.h" 231b362b15af34006e6a11974088a46d42b903418eJohann 241b362b15af34006e6a11974088a46d42b903418eJohannnamespace cc { 25ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang 26ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang// Maximum predictive expansion of the visible area. 27ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuangstatic const int kMaxPredictiveTilesCount = 2; 281b362b15af34006e6a11974088a46d42b903418eJohann 291b362b15af34006e6a11974088a46d42b903418eJohann// Number of rows/columns of tiles to pre-paint. 301b362b15af34006e6a11974088a46d42b903418eJohann// We should increase these further as all textures are 311b362b15af34006e6a11974088a46d42b903418eJohann// prioritized and we insure performance doesn't suffer. 321b362b15af34006e6a11974088a46d42b903418eJohannstatic const int kPrepaintRows = 4; 331b362b15af34006e6a11974088a46d42b903418eJohannstatic const int kPrepaintColumns = 2; 341b362b15af34006e6a11974088a46d42b903418eJohann 351b362b15af34006e6a11974088a46d42b903418eJohannclass UpdatableTile : public LayerTilingData::Tile { 361b362b15af34006e6a11974088a46d42b903418eJohann public: 371b362b15af34006e6a11974088a46d42b903418eJohann static scoped_ptr<UpdatableTile> Create( 381b362b15af34006e6a11974088a46d42b903418eJohann scoped_ptr<LayerUpdater::Resource> updater_resource) { 391b362b15af34006e6a11974088a46d42b903418eJohann return make_scoped_ptr(new UpdatableTile(updater_resource.Pass())); 401b362b15af34006e6a11974088a46d42b903418eJohann } 411b362b15af34006e6a11974088a46d42b903418eJohann 421b362b15af34006e6a11974088a46d42b903418eJohann LayerUpdater::Resource* updater_resource() { return updater_resource_.get(); } 431b362b15af34006e6a11974088a46d42b903418eJohann PrioritizedResource* managed_resource() { 441b362b15af34006e6a11974088a46d42b903418eJohann return updater_resource_->texture(); 451b362b15af34006e6a11974088a46d42b903418eJohann } 461b362b15af34006e6a11974088a46d42b903418eJohann 471b362b15af34006e6a11974088a46d42b903418eJohann bool is_dirty() const { return !dirty_rect.IsEmpty(); } 481b362b15af34006e6a11974088a46d42b903418eJohann 491b362b15af34006e6a11974088a46d42b903418eJohann // Reset update state for the current frame. This should occur before painting 501b362b15af34006e6a11974088a46d42b903418eJohann // for all layers. Since painting one layer can invalidate another layer after 511b362b15af34006e6a11974088a46d42b903418eJohann // it has already painted, mark all non-dirty tiles as valid before painting 521b362b15af34006e6a11974088a46d42b903418eJohann // such that invalidations during painting won't prevent them from being 531b362b15af34006e6a11974088a46d42b903418eJohann // pushed. 541b362b15af34006e6a11974088a46d42b903418eJohann void ResetUpdateState() { 551b362b15af34006e6a11974088a46d42b903418eJohann update_rect = gfx::Rect(); 561b362b15af34006e6a11974088a46d42b903418eJohann occluded = false; 571b362b15af34006e6a11974088a46d42b903418eJohann partial_update = false; 581b362b15af34006e6a11974088a46d42b903418eJohann valid_for_frame = !is_dirty(); 591b362b15af34006e6a11974088a46d42b903418eJohann } 601b362b15af34006e6a11974088a46d42b903418eJohann 611b362b15af34006e6a11974088a46d42b903418eJohann // This promises to update the tile and therefore also guarantees the tile 621b362b15af34006e6a11974088a46d42b903418eJohann // will be valid for this frame. dirty_rect is copied into update_rect so we 631b362b15af34006e6a11974088a46d42b903418eJohann // can continue to track re-entrant invalidations that occur during painting. 641b362b15af34006e6a11974088a46d42b903418eJohann void MarkForUpdate() { 651b362b15af34006e6a11974088a46d42b903418eJohann valid_for_frame = true; 661b362b15af34006e6a11974088a46d42b903418eJohann update_rect = dirty_rect; 671b362b15af34006e6a11974088a46d42b903418eJohann dirty_rect = gfx::Rect(); 681b362b15af34006e6a11974088a46d42b903418eJohann } 691b362b15af34006e6a11974088a46d42b903418eJohann 701b362b15af34006e6a11974088a46d42b903418eJohann gfx::Rect dirty_rect; 711b362b15af34006e6a11974088a46d42b903418eJohann gfx::Rect update_rect; 721b362b15af34006e6a11974088a46d42b903418eJohann bool partial_update; 731b362b15af34006e6a11974088a46d42b903418eJohann bool valid_for_frame; 741b362b15af34006e6a11974088a46d42b903418eJohann bool occluded; 751b362b15af34006e6a11974088a46d42b903418eJohann 761b362b15af34006e6a11974088a46d42b903418eJohann private: 771b362b15af34006e6a11974088a46d42b903418eJohann explicit UpdatableTile(scoped_ptr<LayerUpdater::Resource> updater_resource) 781b362b15af34006e6a11974088a46d42b903418eJohann : partial_update(false), 791b362b15af34006e6a11974088a46d42b903418eJohann valid_for_frame(false), 801b362b15af34006e6a11974088a46d42b903418eJohann occluded(false), 811b362b15af34006e6a11974088a46d42b903418eJohann updater_resource_(updater_resource.Pass()) {} 821b362b15af34006e6a11974088a46d42b903418eJohann 831b362b15af34006e6a11974088a46d42b903418eJohann scoped_ptr<LayerUpdater::Resource> updater_resource_; 841b362b15af34006e6a11974088a46d42b903418eJohann 851b362b15af34006e6a11974088a46d42b903418eJohann DISALLOW_COPY_AND_ASSIGN(UpdatableTile); 861b362b15af34006e6a11974088a46d42b903418eJohann}; 871b362b15af34006e6a11974088a46d42b903418eJohann 881b362b15af34006e6a11974088a46d42b903418eJohannTiledLayer::TiledLayer() 891b362b15af34006e6a11974088a46d42b903418eJohann : ContentsScalingLayer(), 901b362b15af34006e6a11974088a46d42b903418eJohann texture_format_(RGBA_8888), 91ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang skips_draw_(false), 921b362b15af34006e6a11974088a46d42b903418eJohann failed_update_(false), 931b362b15af34006e6a11974088a46d42b903418eJohann tiling_option_(AUTO_TILE) { 941b362b15af34006e6a11974088a46d42b903418eJohann tiler_ = 951b362b15af34006e6a11974088a46d42b903418eJohann LayerTilingData::Create(gfx::Size(), LayerTilingData::HAS_BORDER_TEXELS); 961b362b15af34006e6a11974088a46d42b903418eJohann} 971b362b15af34006e6a11974088a46d42b903418eJohann 981b362b15af34006e6a11974088a46d42b903418eJohannTiledLayer::~TiledLayer() {} 991b362b15af34006e6a11974088a46d42b903418eJohann 1001b362b15af34006e6a11974088a46d42b903418eJohannscoped_ptr<LayerImpl> TiledLayer::CreateLayerImpl(LayerTreeImpl* tree_impl) { 1011b362b15af34006e6a11974088a46d42b903418eJohann return TiledLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>(); 1021b362b15af34006e6a11974088a46d42b903418eJohann} 1031b362b15af34006e6a11974088a46d42b903418eJohann 1041b362b15af34006e6a11974088a46d42b903418eJohannvoid TiledLayer::UpdateTileSizeAndTilingOption() { 1051b362b15af34006e6a11974088a46d42b903418eJohann DCHECK(layer_tree_host()); 1061b362b15af34006e6a11974088a46d42b903418eJohann 1071b362b15af34006e6a11974088a46d42b903418eJohann gfx::Size default_tile_size = layer_tree_host()->settings().default_tile_size; 1081b362b15af34006e6a11974088a46d42b903418eJohann gfx::Size max_untiled_layer_size = 1091b362b15af34006e6a11974088a46d42b903418eJohann layer_tree_host()->settings().max_untiled_layer_size; 1101b362b15af34006e6a11974088a46d42b903418eJohann int layer_width = content_bounds().width(); 1111b362b15af34006e6a11974088a46d42b903418eJohann int layer_height = content_bounds().height(); 1121b362b15af34006e6a11974088a46d42b903418eJohann 1131b362b15af34006e6a11974088a46d42b903418eJohann gfx::Size tile_size(std::min(default_tile_size.width(), layer_width), 1141b362b15af34006e6a11974088a46d42b903418eJohann std::min(default_tile_size.height(), layer_height)); 1151b362b15af34006e6a11974088a46d42b903418eJohann 1161b362b15af34006e6a11974088a46d42b903418eJohann // Tile if both dimensions large, or any one dimension large and the other 1171b362b15af34006e6a11974088a46d42b903418eJohann // extends into a second tile but the total layer area isn't larger than that 1181b362b15af34006e6a11974088a46d42b903418eJohann // of the largest possible untiled layer. This heuristic allows for long 1191b362b15af34006e6a11974088a46d42b903418eJohann // skinny layers (e.g. scrollbars) that are Nx1 tiles to minimize wasted 1201b362b15af34006e6a11974088a46d42b903418eJohann // texture space but still avoids creating very large tiles. 1211b362b15af34006e6a11974088a46d42b903418eJohann bool any_dimension_large = layer_width > max_untiled_layer_size.width() || 1221b362b15af34006e6a11974088a46d42b903418eJohann layer_height > max_untiled_layer_size.height(); 1231b362b15af34006e6a11974088a46d42b903418eJohann bool any_dimension_one_tile = 1241b362b15af34006e6a11974088a46d42b903418eJohann (layer_width <= default_tile_size.width() || 1251b362b15af34006e6a11974088a46d42b903418eJohann layer_height <= default_tile_size.height()) && 1261b362b15af34006e6a11974088a46d42b903418eJohann (layer_width * layer_height) <= (max_untiled_layer_size.width() * 1271b362b15af34006e6a11974088a46d42b903418eJohann max_untiled_layer_size.height()); 1281b362b15af34006e6a11974088a46d42b903418eJohann bool auto_tiled = any_dimension_large && !any_dimension_one_tile; 1291b362b15af34006e6a11974088a46d42b903418eJohann 1301b362b15af34006e6a11974088a46d42b903418eJohann bool is_tiled; 1311b362b15af34006e6a11974088a46d42b903418eJohann if (tiling_option_ == ALWAYS_TILE) 1321b362b15af34006e6a11974088a46d42b903418eJohann is_tiled = true; 1331b362b15af34006e6a11974088a46d42b903418eJohann else if (tiling_option_ == NEVER_TILE) 1341b362b15af34006e6a11974088a46d42b903418eJohann is_tiled = false; 1351b362b15af34006e6a11974088a46d42b903418eJohann else 1361b362b15af34006e6a11974088a46d42b903418eJohann is_tiled = auto_tiled; 1371b362b15af34006e6a11974088a46d42b903418eJohann 1381b362b15af34006e6a11974088a46d42b903418eJohann gfx::Size requested_size = is_tiled ? tile_size : content_bounds(); 1391b362b15af34006e6a11974088a46d42b903418eJohann const int max_size = 1401b362b15af34006e6a11974088a46d42b903418eJohann layer_tree_host()->GetRendererCapabilities().max_texture_size; 1411b362b15af34006e6a11974088a46d42b903418eJohann requested_size.SetToMin(gfx::Size(max_size, max_size)); 1421b362b15af34006e6a11974088a46d42b903418eJohann SetTileSize(requested_size); 1431b362b15af34006e6a11974088a46d42b903418eJohann} 1441b362b15af34006e6a11974088a46d42b903418eJohann 1451b362b15af34006e6a11974088a46d42b903418eJohannvoid TiledLayer::UpdateBounds() { 1461b362b15af34006e6a11974088a46d42b903418eJohann gfx::Size old_tiling_size = tiler_->tiling_size(); 1471b362b15af34006e6a11974088a46d42b903418eJohann gfx::Size new_tiling_size = content_bounds(); 1481b362b15af34006e6a11974088a46d42b903418eJohann if (old_tiling_size == new_tiling_size) 1491b362b15af34006e6a11974088a46d42b903418eJohann return; 1501b362b15af34006e6a11974088a46d42b903418eJohann tiler_->SetTilingSize(new_tiling_size); 1511b362b15af34006e6a11974088a46d42b903418eJohann 1521b362b15af34006e6a11974088a46d42b903418eJohann // Invalidate any areas that the new bounds exposes. 1531b362b15af34006e6a11974088a46d42b903418eJohann Region new_region = 1541b362b15af34006e6a11974088a46d42b903418eJohann SubtractRegions(gfx::Rect(new_tiling_size), gfx::Rect(old_tiling_size)); 1551b362b15af34006e6a11974088a46d42b903418eJohann for (Region::Iterator new_rects(new_region); new_rects.has_rect(); 1561b362b15af34006e6a11974088a46d42b903418eJohann new_rects.next()) 1571b362b15af34006e6a11974088a46d42b903418eJohann InvalidateContentRect(new_rects.rect()); 1581b362b15af34006e6a11974088a46d42b903418eJohann UpdateDrawsContent(HasDrawableContent()); 1591b362b15af34006e6a11974088a46d42b903418eJohann} 1601b362b15af34006e6a11974088a46d42b903418eJohann 1611b362b15af34006e6a11974088a46d42b903418eJohannvoid TiledLayer::SetTileSize(const gfx::Size& size) { 1621b362b15af34006e6a11974088a46d42b903418eJohann tiler_->SetTileSize(size); 1631b362b15af34006e6a11974088a46d42b903418eJohann UpdateDrawsContent(HasDrawableContent()); 1641b362b15af34006e6a11974088a46d42b903418eJohann} 1651b362b15af34006e6a11974088a46d42b903418eJohann 1661b362b15af34006e6a11974088a46d42b903418eJohannvoid TiledLayer::SetBorderTexelOption( 1671b362b15af34006e6a11974088a46d42b903418eJohann LayerTilingData::BorderTexelOption border_texel_option) { 1681b362b15af34006e6a11974088a46d42b903418eJohann tiler_->SetBorderTexelOption(border_texel_option); 1691b362b15af34006e6a11974088a46d42b903418eJohann UpdateDrawsContent(HasDrawableContent()); 1701b362b15af34006e6a11974088a46d42b903418eJohann} 1711b362b15af34006e6a11974088a46d42b903418eJohann 1721b362b15af34006e6a11974088a46d42b903418eJohannbool TiledLayer::HasDrawableContent() const { 1731b362b15af34006e6a11974088a46d42b903418eJohann bool has_more_than_one_tile = 1741b362b15af34006e6a11974088a46d42b903418eJohann (tiler_->num_tiles_x() > 1) || (tiler_->num_tiles_y() > 1); 1751b362b15af34006e6a11974088a46d42b903418eJohann 1761b362b15af34006e6a11974088a46d42b903418eJohann return !(tiling_option_ == NEVER_TILE && has_more_than_one_tile) && 1771b362b15af34006e6a11974088a46d42b903418eJohann ContentsScalingLayer::HasDrawableContent(); 1781b362b15af34006e6a11974088a46d42b903418eJohann} 1791b362b15af34006e6a11974088a46d42b903418eJohann 1801b362b15af34006e6a11974088a46d42b903418eJohannvoid TiledLayer::ReduceMemoryUsage() { 1811b362b15af34006e6a11974088a46d42b903418eJohann if (Updater()) 1821b362b15af34006e6a11974088a46d42b903418eJohann Updater()->ReduceMemoryUsage(); 1831b362b15af34006e6a11974088a46d42b903418eJohann} 1841b362b15af34006e6a11974088a46d42b903418eJohann 1851b362b15af34006e6a11974088a46d42b903418eJohannvoid TiledLayer::SetIsMask(bool is_mask) { 1861b362b15af34006e6a11974088a46d42b903418eJohann set_tiling_option(is_mask ? NEVER_TILE : AUTO_TILE); 1871b362b15af34006e6a11974088a46d42b903418eJohann} 1881b362b15af34006e6a11974088a46d42b903418eJohann 1891b362b15af34006e6a11974088a46d42b903418eJohannvoid TiledLayer::PushPropertiesTo(LayerImpl* layer) { 1901b362b15af34006e6a11974088a46d42b903418eJohann ContentsScalingLayer::PushPropertiesTo(layer); 1911b362b15af34006e6a11974088a46d42b903418eJohann 1921b362b15af34006e6a11974088a46d42b903418eJohann TiledLayerImpl* tiled_layer = static_cast<TiledLayerImpl*>(layer); 1931b362b15af34006e6a11974088a46d42b903418eJohann 1941b362b15af34006e6a11974088a46d42b903418eJohann tiled_layer->set_skips_draw(skips_draw_); 1951b362b15af34006e6a11974088a46d42b903418eJohann tiled_layer->SetTilingData(*tiler_); 1961b362b15af34006e6a11974088a46d42b903418eJohann std::vector<UpdatableTile*> invalid_tiles; 1971b362b15af34006e6a11974088a46d42b903418eJohann 1981b362b15af34006e6a11974088a46d42b903418eJohann for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); 1991b362b15af34006e6a11974088a46d42b903418eJohann iter != tiler_->tiles().end(); 2001b362b15af34006e6a11974088a46d42b903418eJohann ++iter) { 2011b362b15af34006e6a11974088a46d42b903418eJohann int i = iter->first.first; 2021b362b15af34006e6a11974088a46d42b903418eJohann int j = iter->first.second; 2031b362b15af34006e6a11974088a46d42b903418eJohann UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); 2041b362b15af34006e6a11974088a46d42b903418eJohann // TODO(enne): This should not ever be null. 2051b362b15af34006e6a11974088a46d42b903418eJohann if (!tile) 2061b362b15af34006e6a11974088a46d42b903418eJohann continue; 2071b362b15af34006e6a11974088a46d42b903418eJohann 2081b362b15af34006e6a11974088a46d42b903418eJohann if (!tile->managed_resource()->have_backing_texture()) { 2091b362b15af34006e6a11974088a46d42b903418eJohann // Evicted tiles get deleted from both layers 2101b362b15af34006e6a11974088a46d42b903418eJohann invalid_tiles.push_back(tile); 2111b362b15af34006e6a11974088a46d42b903418eJohann continue; 2121b362b15af34006e6a11974088a46d42b903418eJohann } 2131b362b15af34006e6a11974088a46d42b903418eJohann 2141b362b15af34006e6a11974088a46d42b903418eJohann if (!tile->valid_for_frame) { 2151b362b15af34006e6a11974088a46d42b903418eJohann // Invalidated tiles are set so they can get different debug colors. 2161b362b15af34006e6a11974088a46d42b903418eJohann tiled_layer->PushInvalidTile(i, j); 217ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin continue; 218ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin } 219ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 220ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin tiled_layer->PushTileProperties( 221ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin i, 222ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin j, 223ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin tile->managed_resource()->resource_id(), 224ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin tile->managed_resource()->contents_swizzled()); 225ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin } 226ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin for (std::vector<UpdatableTile*>::const_iterator iter = invalid_tiles.begin(); 227ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin iter != invalid_tiles.end(); 228ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin ++iter) 229ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin tiler_->TakeTile((*iter)->i(), (*iter)->j()); 230ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 231ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin // TiledLayer must push properties every frame, since viewport state and 232ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin // occlusion from anywhere in the tree can change what the layer decides to 233ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin // push to the impl tree. 234ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin needs_push_properties_ = true; 235ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin} 236ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 237ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter GultekinPrioritizedResourceManager* TiledLayer::ResourceManager() { 238ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin if (!layer_tree_host()) 239ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin return NULL; 240ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin return layer_tree_host()->contents_texture_manager(); 241ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin} 242ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 243ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekinconst PrioritizedResource* TiledLayer::ResourceAtForTesting(int i, 244ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin int j) const { 245ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin UpdatableTile* tile = TileAt(i, j); 246ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin if (!tile) 247ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin return NULL; 248ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin return tile->managed_resource(); 249ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin} 250ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 251ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekinvoid TiledLayer::SetLayerTreeHost(LayerTreeHost* host) { 252ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin if (host && host != layer_tree_host()) { 253ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin for (LayerTilingData::TileMap::const_iterator 254ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin iter = tiler_->tiles().begin(); 255ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin iter != tiler_->tiles().end(); 256ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin ++iter) { 257ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); 258ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin // TODO(enne): This should not ever be null. 259ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin if (!tile) 260ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin continue; 261ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin tile->managed_resource()->SetTextureManager( 262ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin host->contents_texture_manager()); 263ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin } 264ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin } 265ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin ContentsScalingLayer::SetLayerTreeHost(host); 266ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin} 267ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 268ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter GultekinUpdatableTile* TiledLayer::TileAt(int i, int j) const { 269ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin return static_cast<UpdatableTile*>(tiler_->TileAt(i, j)); 270ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin} 271ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 272ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter GultekinUpdatableTile* TiledLayer::CreateTile(int i, int j) { 273ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin CreateUpdaterIfNeeded(); 274ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 275ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin scoped_ptr<UpdatableTile> tile( 276ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin UpdatableTile::Create(Updater()->CreateResource(ResourceManager()))); 277ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin tile->managed_resource()->SetDimensions(tiler_->tile_size(), texture_format_); 278ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 279ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin UpdatableTile* added_tile = tile.get(); 280ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin tiler_->AddTile(tile.PassAs<LayerTilingData::Tile>(), i, j); 281ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 282ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin added_tile->dirty_rect = tiler_->TileRect(added_tile); 283ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 284ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin // Temporary diagnostic crash. 285ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin CHECK(added_tile); 286ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin CHECK(TileAt(i, j)); 287ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 288ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin return added_tile; 289ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin} 290ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekin 291ca15b5fc158a9df465aaf1acfe38d8cb5042c81bKunter Gultekinvoid TiledLayer::SetNeedsDisplayRect(const gfx::RectF& dirty_rect) { 292ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang InvalidateContentRect(LayerRectToContentRect(dirty_rect)); 2931b362b15af34006e6a11974088a46d42b903418eJohann ContentsScalingLayer::SetNeedsDisplayRect(dirty_rect); 2941b362b15af34006e6a11974088a46d42b903418eJohann} 2951b362b15af34006e6a11974088a46d42b903418eJohann 2961b362b15af34006e6a11974088a46d42b903418eJohannvoid TiledLayer::InvalidateContentRect(const gfx::Rect& content_rect) { 2971b362b15af34006e6a11974088a46d42b903418eJohann UpdateBounds(); 2981b362b15af34006e6a11974088a46d42b903418eJohann if (tiler_->is_empty() || content_rect.IsEmpty() || skips_draw_) 2991b362b15af34006e6a11974088a46d42b903418eJohann return; 3001b362b15af34006e6a11974088a46d42b903418eJohann 3011b362b15af34006e6a11974088a46d42b903418eJohann for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); 302 iter != tiler_->tiles().end(); 303 ++iter) { 304 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); 305 DCHECK(tile); 306 // TODO(enne): This should not ever be null. 307 if (!tile) 308 continue; 309 gfx::Rect bound = tiler_->TileRect(tile); 310 bound.Intersect(content_rect); 311 tile->dirty_rect.Union(bound); 312 } 313} 314 315// Returns true if tile is dirty and only part of it needs to be updated. 316bool TiledLayer::TileOnlyNeedsPartialUpdate(UpdatableTile* tile) { 317 return !tile->dirty_rect.Contains(tiler_->TileRect(tile)) && 318 tile->managed_resource()->have_backing_texture(); 319} 320 321bool TiledLayer::UpdateTiles(int left, 322 int top, 323 int right, 324 int bottom, 325 ResourceUpdateQueue* queue, 326 const OcclusionTracker<Layer>* occlusion, 327 bool* updated) { 328 CreateUpdaterIfNeeded(); 329 330 bool ignore_occlusions = !occlusion; 331 if (!HaveTexturesForTiles(left, top, right, bottom, ignore_occlusions)) { 332 failed_update_ = true; 333 return false; 334 } 335 336 gfx::Rect update_rect; 337 gfx::Rect paint_rect; 338 MarkTilesForUpdate( 339 &update_rect, &paint_rect, left, top, right, bottom, ignore_occlusions); 340 341 if (paint_rect.IsEmpty()) 342 return true; 343 344 *updated = true; 345 UpdateTileTextures( 346 update_rect, paint_rect, left, top, right, bottom, queue, occlusion); 347 return true; 348} 349 350void TiledLayer::MarkOcclusionsAndRequestTextures( 351 int left, 352 int top, 353 int right, 354 int bottom, 355 const OcclusionTracker<Layer>* occlusion) { 356 int occluded_tile_count = 0; 357 bool succeeded = true; 358 for (int j = top; j <= bottom; ++j) { 359 for (int i = left; i <= right; ++i) { 360 UpdatableTile* tile = TileAt(i, j); 361 DCHECK(tile); // Did SetTexturePriorities get skipped? 362 // TODO(enne): This should not ever be null. 363 if (!tile) 364 continue; 365 // Did ResetUpdateState get skipped? Are we doing more than one occlusion 366 // pass? 367 DCHECK(!tile->occluded); 368 gfx::Rect visible_tile_rect = gfx::IntersectRects( 369 tiler_->tile_bounds(i, j), visible_content_rect()); 370 if (!draw_transform_is_animating() && occlusion && 371 occlusion->GetCurrentOcclusionForLayer(draw_transform()) 372 .IsOccluded(visible_tile_rect)) { 373 tile->occluded = true; 374 occluded_tile_count++; 375 } else { 376 succeeded &= tile->managed_resource()->RequestLate(); 377 } 378 } 379 } 380} 381 382bool TiledLayer::HaveTexturesForTiles(int left, 383 int top, 384 int right, 385 int bottom, 386 bool ignore_occlusions) { 387 for (int j = top; j <= bottom; ++j) { 388 for (int i = left; i <= right; ++i) { 389 UpdatableTile* tile = TileAt(i, j); 390 DCHECK(tile); // Did SetTexturePriorites get skipped? 391 // TODO(enne): This should not ever be null. 392 if (!tile) 393 continue; 394 395 // Ensure the entire tile is dirty if we don't have the texture. 396 if (!tile->managed_resource()->have_backing_texture()) 397 tile->dirty_rect = tiler_->TileRect(tile); 398 399 // If using occlusion and the visible region of the tile is occluded, 400 // don't reserve a texture or update the tile. 401 if (tile->occluded && !ignore_occlusions) 402 continue; 403 404 if (!tile->managed_resource()->can_acquire_backing_texture()) 405 return false; 406 } 407 } 408 return true; 409} 410 411void TiledLayer::MarkTilesForUpdate(gfx::Rect* update_rect, 412 gfx::Rect* paint_rect, 413 int left, 414 int top, 415 int right, 416 int bottom, 417 bool ignore_occlusions) { 418 for (int j = top; j <= bottom; ++j) { 419 for (int i = left; i <= right; ++i) { 420 UpdatableTile* tile = TileAt(i, j); 421 DCHECK(tile); // Did SetTexturePriorites get skipped? 422 // TODO(enne): This should not ever be null. 423 if (!tile) 424 continue; 425 if (tile->occluded && !ignore_occlusions) 426 continue; 427 428 // Prepare update rect from original dirty rects. 429 update_rect->Union(tile->dirty_rect); 430 431 // TODO(reveman): Decide if partial update should be allowed based on cost 432 // of update. https://bugs.webkit.org/show_bug.cgi?id=77376 433 if (tile->is_dirty() && 434 !layer_tree_host()->AlwaysUsePartialTextureUpdates()) { 435 // If we get a partial update, we use the same texture, otherwise return 436 // the current texture backing, so we don't update visible textures 437 // non-atomically. If the current backing is in-use, it won't be 438 // deleted until after the commit as the texture manager will not allow 439 // deletion or recycling of in-use textures. 440 if (TileOnlyNeedsPartialUpdate(tile) && 441 layer_tree_host()->RequestPartialTextureUpdate()) { 442 tile->partial_update = true; 443 } else { 444 tile->dirty_rect = tiler_->TileRect(tile); 445 tile->managed_resource()->ReturnBackingTexture(); 446 } 447 } 448 449 paint_rect->Union(tile->dirty_rect); 450 tile->MarkForUpdate(); 451 } 452 } 453} 454 455void TiledLayer::UpdateTileTextures(const gfx::Rect& update_rect, 456 const gfx::Rect& paint_rect, 457 int left, 458 int top, 459 int right, 460 int bottom, 461 ResourceUpdateQueue* queue, 462 const OcclusionTracker<Layer>* occlusion) { 463 // The update_rect should be in layer space. So we have to convert the 464 // paint_rect from content space to layer space. 465 float width_scale = 1 / draw_properties().contents_scale_x; 466 float height_scale = 1 / draw_properties().contents_scale_y; 467 update_rect_ = gfx::ScaleRect(update_rect, width_scale, height_scale); 468 469 // Calling PrepareToUpdate() calls into WebKit to paint, which may have the 470 // side effect of disabling compositing, which causes our reference to the 471 // texture updater to be deleted. However, we can't free the memory backing 472 // the SkCanvas until the paint finishes, so we grab a local reference here to 473 // hold the updater alive until the paint completes. 474 scoped_refptr<LayerUpdater> protector(Updater()); 475 Updater()->PrepareToUpdate(content_bounds(), 476 paint_rect, 477 tiler_->tile_size(), 478 1.f / width_scale, 479 1.f / height_scale); 480 481 for (int j = top; j <= bottom; ++j) { 482 for (int i = left; i <= right; ++i) { 483 UpdatableTile* tile = TileAt(i, j); 484 DCHECK(tile); // Did SetTexturePriorites get skipped? 485 // TODO(enne): This should not ever be null. 486 if (!tile) 487 continue; 488 489 gfx::Rect tile_rect = tiler_->tile_bounds(i, j); 490 491 // Use update_rect as the above loop copied the dirty rect for this frame 492 // to update_rect. 493 gfx::Rect dirty_rect = tile->update_rect; 494 if (dirty_rect.IsEmpty()) 495 continue; 496 497 // source_rect starts as a full-sized tile with border texels included. 498 gfx::Rect source_rect = tiler_->TileRect(tile); 499 source_rect.Intersect(dirty_rect); 500 // Paint rect not guaranteed to line up on tile boundaries, so 501 // make sure that source_rect doesn't extend outside of it. 502 source_rect.Intersect(paint_rect); 503 504 tile->update_rect = source_rect; 505 506 if (source_rect.IsEmpty()) 507 continue; 508 509 const gfx::Point anchor = tiler_->TileRect(tile).origin(); 510 511 // Calculate tile-space rectangle to upload into. 512 gfx::Vector2d dest_offset = source_rect.origin() - anchor; 513 CHECK_GE(dest_offset.x(), 0); 514 CHECK_GE(dest_offset.y(), 0); 515 516 // Offset from paint rectangle to this tile's dirty rectangle. 517 gfx::Vector2d paint_offset = source_rect.origin() - paint_rect.origin(); 518 CHECK_GE(paint_offset.x(), 0); 519 CHECK_GE(paint_offset.y(), 0); 520 CHECK_LE(paint_offset.x() + source_rect.width(), paint_rect.width()); 521 CHECK_LE(paint_offset.y() + source_rect.height(), paint_rect.height()); 522 523 tile->updater_resource()->Update( 524 queue, source_rect, dest_offset, tile->partial_update); 525 } 526 } 527} 528 529// This picks a small animated layer to be anything less than one viewport. This 530// is specifically for page transitions which are viewport-sized layers. The 531// extra tile of padding is due to these layers being slightly larger than the 532// viewport in some cases. 533bool TiledLayer::IsSmallAnimatedLayer() const { 534 if (!draw_transform_is_animating() && !screen_space_transform_is_animating()) 535 return false; 536 gfx::Size viewport_size = 537 layer_tree_host() ? layer_tree_host()->device_viewport_size() 538 : gfx::Size(); 539 gfx::Rect content_rect(content_bounds()); 540 return content_rect.width() <= 541 viewport_size.width() + tiler_->tile_size().width() && 542 content_rect.height() <= 543 viewport_size.height() + tiler_->tile_size().height(); 544} 545 546namespace { 547// TODO(epenner): Remove this and make this based on distance once distance can 548// be calculated for offscreen layers. For now, prioritize all small animated 549// layers after 512 pixels of pre-painting. 550void SetPriorityForTexture(const gfx::Rect& visible_rect, 551 const gfx::Rect& tile_rect, 552 bool draws_to_root, 553 bool is_small_animated_layer, 554 PrioritizedResource* texture) { 555 int priority = PriorityCalculator::LowestPriority(); 556 if (!visible_rect.IsEmpty()) { 557 priority = PriorityCalculator::PriorityFromDistance( 558 visible_rect, tile_rect, draws_to_root); 559 } 560 561 if (is_small_animated_layer) { 562 priority = PriorityCalculator::max_priority( 563 priority, PriorityCalculator::SmallAnimatedLayerMinPriority()); 564 } 565 566 if (priority != PriorityCalculator::LowestPriority()) 567 texture->set_request_priority(priority); 568} 569} // namespace 570 571void TiledLayer::SetTexturePriorities(const PriorityCalculator& priority_calc) { 572 UpdateBounds(); 573 ResetUpdateState(); 574 UpdateScrollPrediction(); 575 576 if (tiler_->has_empty_bounds()) 577 return; 578 579 bool draws_to_root = !render_target()->parent(); 580 bool small_animated_layer = IsSmallAnimatedLayer(); 581 582 // Minimally create the tiles in the desired pre-paint rect. 583 gfx::Rect create_tiles_rect = IdlePaintRect(); 584 if (small_animated_layer) 585 create_tiles_rect = gfx::Rect(content_bounds()); 586 if (!create_tiles_rect.IsEmpty()) { 587 int left, top, right, bottom; 588 tiler_->ContentRectToTileIndices( 589 create_tiles_rect, &left, &top, &right, &bottom); 590 for (int j = top; j <= bottom; ++j) { 591 for (int i = left; i <= right; ++i) { 592 if (!TileAt(i, j)) 593 CreateTile(i, j); 594 } 595 } 596 } 597 598 // Now update priorities on all tiles we have in the layer, no matter where 599 // they are. 600 for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); 601 iter != tiler_->tiles().end(); 602 ++iter) { 603 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); 604 // TODO(enne): This should not ever be null. 605 if (!tile) 606 continue; 607 gfx::Rect tile_rect = tiler_->TileRect(tile); 608 SetPriorityForTexture(predicted_visible_rect_, 609 tile_rect, 610 draws_to_root, 611 small_animated_layer, 612 tile->managed_resource()); 613 } 614} 615 616SimpleEnclosedRegion TiledLayer::VisibleContentOpaqueRegion() const { 617 if (skips_draw_) 618 return SimpleEnclosedRegion(); 619 return Layer::VisibleContentOpaqueRegion(); 620} 621 622void TiledLayer::ResetUpdateState() { 623 skips_draw_ = false; 624 failed_update_ = false; 625 626 LayerTilingData::TileMap::const_iterator end = tiler_->tiles().end(); 627 for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); 628 iter != end; 629 ++iter) { 630 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); 631 // TODO(enne): This should not ever be null. 632 if (!tile) 633 continue; 634 tile->ResetUpdateState(); 635 } 636} 637 638namespace { 639gfx::Rect ExpandRectByDelta(const gfx::Rect& rect, const gfx::Vector2d& delta) { 640 int width = rect.width() + std::abs(delta.x()); 641 int height = rect.height() + std::abs(delta.y()); 642 int x = rect.x() + ((delta.x() < 0) ? delta.x() : 0); 643 int y = rect.y() + ((delta.y() < 0) ? delta.y() : 0); 644 return gfx::Rect(x, y, width, height); 645} 646} 647 648void TiledLayer::UpdateScrollPrediction() { 649 // This scroll prediction is very primitive and should be replaced by a 650 // a recursive calculation on all layers which uses actual scroll/animation 651 // velocities. To insure this doesn't miss-predict, we only use it to predict 652 // the visible_rect if: 653 // - content_bounds() hasn't changed. 654 // - visible_rect.size() hasn't changed. 655 // These two conditions prevent rotations, scales, pinch-zooms etc. where 656 // the prediction would be incorrect. 657 gfx::Vector2d delta = visible_content_rect().CenterPoint() - 658 previous_visible_rect_.CenterPoint(); 659 predicted_scroll_ = -delta; 660 predicted_visible_rect_ = visible_content_rect(); 661 if (previous_content_bounds_ == content_bounds() && 662 previous_visible_rect_.size() == visible_content_rect().size()) { 663 // Only expand the visible rect in the major scroll direction, to prevent 664 // massive paints due to diagonal scrolls. 665 gfx::Vector2d major_scroll_delta = 666 (std::abs(delta.x()) > std::abs(delta.y())) ? 667 gfx::Vector2d(delta.x(), 0) : 668 gfx::Vector2d(0, delta.y()); 669 predicted_visible_rect_ = 670 ExpandRectByDelta(visible_content_rect(), major_scroll_delta); 671 672 // Bound the prediction to prevent unbounded paints, and clamp to content 673 // bounds. 674 gfx::Rect bound = visible_content_rect(); 675 bound.Inset(-tiler_->tile_size().width() * kMaxPredictiveTilesCount, 676 -tiler_->tile_size().height() * kMaxPredictiveTilesCount); 677 bound.Intersect(gfx::Rect(content_bounds())); 678 predicted_visible_rect_.Intersect(bound); 679 } 680 previous_content_bounds_ = content_bounds(); 681 previous_visible_rect_ = visible_content_rect(); 682} 683 684bool TiledLayer::Update(ResourceUpdateQueue* queue, 685 const OcclusionTracker<Layer>* occlusion) { 686 DCHECK(!skips_draw_ && !failed_update_); // Did ResetUpdateState get skipped? 687 688 // Tiled layer always causes commits to wait for activation, as it does 689 // not support pending trees. 690 SetNextCommitWaitsForActivation(); 691 692 bool updated = false; 693 694 { 695 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, 696 true); 697 698 updated |= ContentsScalingLayer::Update(queue, occlusion); 699 UpdateBounds(); 700 } 701 702 if (tiler_->has_empty_bounds() || !DrawsContent()) 703 return false; 704 705 // Animation pre-paint. If the layer is small, try to paint it all 706 // immediately whether or not it is occluded, to avoid paint/upload 707 // hiccups while it is animating. 708 if (IsSmallAnimatedLayer()) { 709 int left, top, right, bottom; 710 tiler_->ContentRectToTileIndices(gfx::Rect(content_bounds()), 711 &left, 712 &top, 713 &right, 714 &bottom); 715 UpdateTiles(left, top, right, bottom, queue, NULL, &updated); 716 if (updated) 717 return updated; 718 // This was an attempt to paint the entire layer so if we fail it's okay, 719 // just fallback on painting visible etc. below. 720 failed_update_ = false; 721 } 722 723 if (predicted_visible_rect_.IsEmpty()) 724 return updated; 725 726 // Visible painting. First occlude visible tiles and paint the non-occluded 727 // tiles. 728 int left, top, right, bottom; 729 tiler_->ContentRectToTileIndices( 730 predicted_visible_rect_, &left, &top, &right, &bottom); 731 MarkOcclusionsAndRequestTextures(left, top, right, bottom, occlusion); 732 skips_draw_ = !UpdateTiles( 733 left, top, right, bottom, queue, occlusion, &updated); 734 if (skips_draw_) 735 tiler_->reset(); 736 if (skips_draw_ || updated) 737 return true; 738 739 // If we have already painting everything visible. Do some pre-painting while 740 // idle. 741 gfx::Rect idle_paint_content_rect = IdlePaintRect(); 742 if (idle_paint_content_rect.IsEmpty()) 743 return updated; 744 745 // Prepaint anything that was occluded but inside the layer's visible region. 746 if (!UpdateTiles(left, top, right, bottom, queue, NULL, &updated) || 747 updated) 748 return updated; 749 750 int prepaint_left, prepaint_top, prepaint_right, prepaint_bottom; 751 tiler_->ContentRectToTileIndices(idle_paint_content_rect, 752 &prepaint_left, 753 &prepaint_top, 754 &prepaint_right, 755 &prepaint_bottom); 756 757 // Then expand outwards one row/column at a time until we find a dirty 758 // row/column to update. Increment along the major and minor scroll directions 759 // first. 760 gfx::Vector2d delta = -predicted_scroll_; 761 delta = gfx::Vector2d(delta.x() == 0 ? 1 : delta.x(), 762 delta.y() == 0 ? 1 : delta.y()); 763 gfx::Vector2d major_delta = 764 (std::abs(delta.x()) > std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0) 765 : gfx::Vector2d(0, delta.y()); 766 gfx::Vector2d minor_delta = 767 (std::abs(delta.x()) <= std::abs(delta.y())) ? gfx::Vector2d(delta.x(), 0) 768 : gfx::Vector2d(0, delta.y()); 769 gfx::Vector2d deltas[4] = { major_delta, minor_delta, -major_delta, 770 -minor_delta }; 771 for (int i = 0; i < 4; i++) { 772 if (deltas[i].y() > 0) { 773 while (bottom < prepaint_bottom) { 774 ++bottom; 775 if (!UpdateTiles( 776 left, bottom, right, bottom, queue, NULL, &updated) || 777 updated) 778 return updated; 779 } 780 } 781 if (deltas[i].y() < 0) { 782 while (top > prepaint_top) { 783 --top; 784 if (!UpdateTiles( 785 left, top, right, top, queue, NULL, &updated) || 786 updated) 787 return updated; 788 } 789 } 790 if (deltas[i].x() < 0) { 791 while (left > prepaint_left) { 792 --left; 793 if (!UpdateTiles( 794 left, top, left, bottom, queue, NULL, &updated) || 795 updated) 796 return updated; 797 } 798 } 799 if (deltas[i].x() > 0) { 800 while (right < prepaint_right) { 801 ++right; 802 if (!UpdateTiles( 803 right, top, right, bottom, queue, NULL, &updated) || 804 updated) 805 return updated; 806 } 807 } 808 } 809 return updated; 810} 811 812void TiledLayer::OnOutputSurfaceCreated() { 813 // Ensure that all textures are of the right format. 814 for (LayerTilingData::TileMap::const_iterator iter = tiler_->tiles().begin(); 815 iter != tiler_->tiles().end(); 816 ++iter) { 817 UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second); 818 if (!tile) 819 continue; 820 PrioritizedResource* resource = tile->managed_resource(); 821 resource->SetDimensions(resource->size(), texture_format_); 822 } 823} 824 825bool TiledLayer::NeedsIdlePaint() { 826 // Don't trigger more paints if we failed (as we'll just fail again). 827 if (failed_update_ || visible_content_rect().IsEmpty() || 828 tiler_->has_empty_bounds() || !DrawsContent()) 829 return false; 830 831 gfx::Rect idle_paint_content_rect = IdlePaintRect(); 832 if (idle_paint_content_rect.IsEmpty()) 833 return false; 834 835 int left, top, right, bottom; 836 tiler_->ContentRectToTileIndices( 837 idle_paint_content_rect, &left, &top, &right, &bottom); 838 839 for (int j = top; j <= bottom; ++j) { 840 for (int i = left; i <= right; ++i) { 841 UpdatableTile* tile = TileAt(i, j); 842 DCHECK(tile); // Did SetTexturePriorities get skipped? 843 if (!tile) 844 continue; 845 846 bool updated = !tile->update_rect.IsEmpty(); 847 bool can_acquire = 848 tile->managed_resource()->can_acquire_backing_texture(); 849 bool dirty = 850 tile->is_dirty() || !tile->managed_resource()->have_backing_texture(); 851 if (!updated && can_acquire && dirty) 852 return true; 853 } 854 } 855 return false; 856} 857 858gfx::Rect TiledLayer::IdlePaintRect() { 859 // Don't inflate an empty rect. 860 if (visible_content_rect().IsEmpty()) 861 return gfx::Rect(); 862 863 gfx::Rect prepaint_rect = visible_content_rect(); 864 prepaint_rect.Inset(-tiler_->tile_size().width() * kPrepaintColumns, 865 -tiler_->tile_size().height() * kPrepaintRows); 866 gfx::Rect content_rect(content_bounds()); 867 prepaint_rect.Intersect(content_rect); 868 869 return prepaint_rect; 870} 871 872} // namespace cc 873