1010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// found in the LICENSE file.
4010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
5010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "android_webview/browser/global_tile_manager.h"
6010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "android_webview/browser/global_tile_manager_client.h"
7010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/lazy_instance.h"
8010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
91320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciusing content::SynchronousCompositorMemoryPolicy;
101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
11010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace android_webview {
12010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
13010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace {
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
15010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)base::LazyInstance<GlobalTileManager>::Leaky g_tile_manager =
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    LAZY_INSTANCE_INITIALIZER;
175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
18010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// The soft limit of the number of file descriptors per process is 1024 on
19010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// Android and gralloc buffers may not be the only thing that uses file
20010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// descriptors. For each tile, there is a gralloc buffer backing it, which
21010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// uses 2 FDs.
22010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)const size_t kNumTilesLimit = 450;
23010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
24010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}  // namespace
25010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
26010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)// static
27010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)GlobalTileManager* GlobalTileManager::GetInstance() {
28010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return g_tile_manager.Pointer();
29010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
30010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
31010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void GlobalTileManager::Remove(Key key) {
32010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
33010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(mru_list_.end() != key);
34010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  total_allocated_tiles_ -= (*key)->GetMemoryPolicy().num_resources_limit;
36010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  mru_list_.erase(key);
37010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(IsConsistent());
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
39010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
40010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)size_t GlobalTileManager::Evict(size_t desired_num_tiles, Key key) {
41010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
42010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  size_t total_evicted_tiles = 0;
43010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
44010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Evicts from the least recent drawn view, until the disired number of tiles
45010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // can be reclaimed, or until we've evicted all inactive views.
46010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ListType::reverse_iterator it;
47010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (it = mru_list_.rbegin(); it != mru_list_.rend(); it++) {
48010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // key represents the view that requested the eviction, so we don't need to
49010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // evict the requester itself. And we only evict the inactive views,
50010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    // which are all the views after the requester.
51010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (*it == *key)
52010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      break;
53010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    size_t evicted_tiles = (*it)->GetMemoryPolicy().num_resources_limit;
551320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SynchronousCompositorMemoryPolicy zero_policy;
561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    (*it)->SetMemoryPolicy(zero_policy, true);
57010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
58010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    total_evicted_tiles += evicted_tiles;
59010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (total_evicted_tiles >= desired_num_tiles)
60010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      break;
61010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
62010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
63010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return total_evicted_tiles;
64010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
65010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void GlobalTileManager::SetTileLimit(size_t num_tiles_limit) {
675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  num_tiles_limit_ = num_tiles_limit;
685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid GlobalTileManager::RequestTiles(
711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    SynchronousCompositorMemoryPolicy new_policy,
721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    Key key) {
73010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(IsConsistent());
74010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  size_t new_num_of_tiles = new_policy.num_resources_limit;
761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  size_t old_num_of_tiles = (*key)->GetMemoryPolicy().num_resources_limit;
77010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  size_t num_of_active_views = std::distance(mru_list_.begin(), key) + 1;
78010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  size_t tiles_per_view_limit;
79010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (num_of_active_views == 0)
805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    tiles_per_view_limit = num_tiles_limit_;
81010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  else
825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    tiles_per_view_limit = num_tiles_limit_ / num_of_active_views;
83010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  new_num_of_tiles = std::min(new_num_of_tiles, tiles_per_view_limit);
84010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  size_t new_total_allocated_tiles =
85010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      total_allocated_tiles_ - old_num_of_tiles + new_num_of_tiles;
86010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Has enough tiles to satisfy the request.
875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (new_total_allocated_tiles <= num_tiles_limit_) {
88010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    total_allocated_tiles_ = new_total_allocated_tiles;
891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    new_policy.num_resources_limit = new_num_of_tiles;
901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    (*key)->SetMemoryPolicy(new_policy, false);
91010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
92010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
93010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  // Does not have enough tiles. Now evict other clients' tiles.
955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t tiles_left = num_tiles_limit_ - total_allocated_tiles_;
96010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  size_t evicted_tiles =
985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      Evict(new_total_allocated_tiles - num_tiles_limit_, key);
995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  if (evicted_tiles >= new_total_allocated_tiles - num_tiles_limit_) {
100010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    new_total_allocated_tiles -= evicted_tiles;
101010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    total_allocated_tiles_ = new_total_allocated_tiles;
1021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    new_policy.num_resources_limit = new_num_of_tiles;
1031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    (*key)->SetMemoryPolicy(new_policy, false);
104010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
105010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  } else {
1065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    total_allocated_tiles_ = num_tiles_limit_;
1071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    new_policy.num_resources_limit =
1081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        tiles_left + old_num_of_tiles + evicted_tiles;
1091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    (*key)->SetMemoryPolicy(new_policy, false);
110010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    return;
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
113010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
114010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)GlobalTileManager::Key GlobalTileManager::PushBack(
115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    GlobalTileManagerClient* client) {
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(mru_list_.end() ==
118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)         std::find(mru_list_.begin(), mru_list_.end(), client));
119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  mru_list_.push_back(client);
120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  Key back = mru_list_.end();
121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  back--;
122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return back;
123010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
124010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
125010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void GlobalTileManager::DidUse(Key key) {
126010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(sequence_checker_.CalledOnValidSequencedThread());
127010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(mru_list_.end() != key);
128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  mru_list_.splice(mru_list_.begin(), mru_list_, key);
130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)GlobalTileManager::GlobalTileManager()
1335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    : num_tiles_limit_(kNumTilesLimit), total_allocated_tiles_(0) {
134010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
135010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)GlobalTileManager::~GlobalTileManager() {
137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)bool GlobalTileManager::IsConsistent() const {
140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  size_t total_tiles = 0;
141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  ListType::const_iterator it;
142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  for (it = mru_list_.begin(); it != mru_list_.end(); it++) {
1431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    total_tiles += (*it)->GetMemoryPolicy().num_resources_limit;
144010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  }
145010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  bool is_consistent = (total_tiles <= num_tiles_limit_ &&
1475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                        total_tiles == total_allocated_tiles_);
148010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
149010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  return is_consistent;
150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
152010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}  // namespace webview
153