Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3998)

Unified Diff: chrome/browser/renderer_host/backing_store_manager.cc

Issue 6532073: Move core pieces of browser\renderer_host to src\content. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/renderer_host/backing_store_manager.cc
===================================================================
--- chrome/browser/renderer_host/backing_store_manager.cc (revision 75488)
+++ chrome/browser/renderer_host/backing_store_manager.cc (working copy)
@@ -1,287 +0,0 @@
-// Copyright (c) 2010 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 "chrome/browser/renderer_host/backing_store_manager.h"
-
-#include "base/sys_info.h"
-#include "base/command_line.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/browser/renderer_host/backing_store.h"
-#include "chrome/browser/renderer_host/render_widget_host.h"
-#include "chrome/common/chrome_constants.h"
-#include "chrome/common/mru_cache.h"
-#include "chrome/common/notification_service.h"
-
-namespace {
-
-// There are two separate caches, |large_cache| and |small_cache|. large_cache
-// is meant for large items (tabs, popup windows), while small_cache is meant
-// for small items (extension toolstrips and buttons, etc.). The idea is that
-// we'll almost always try to evict from large_cache first since small_cache
-// items will tend to be visible more of the time.
-typedef OwningMRUCache<RenderWidgetHost*, BackingStore*> BackingStoreCache;
-static BackingStoreCache* large_cache = NULL;
-static BackingStoreCache* small_cache = NULL;
-
-// Threshold is based on a single large-monitor-width toolstrip.
-// (32bpp, 32 pixels high, 1920 pixels wide)
-// TODO(erikkay) 32bpp assumption isn't great.
-const size_t kSmallThreshold = 4 * 32 * 1920;
-
-// Pick a large monitor size to use as a multiplier. This is multiplied by the
-// max number of large backing stores (usually tabs) to pick a ceiling on the
-// max memory to use.
-// TODO(erikkay) Perhaps we should actually use monitor size? That way we
-// could make an assertion like "worse case, there are two tabs in the cache".
-// However, the small_cache might mess up these calculations a bit.
-// TODO(erikkay) 32bpp assumption isn't great.
-const size_t kMemoryMultiplier = 4 * 1920 * 1200; // ~9MB
-
-// The maximum number of large BackingStoreCache objects (tabs) to use.
-// Use a minimum of 2, and add one for each 256MB of physical memory you have.
-// Cap at 5, the thinking being that even if you have a gigantic amount of
-// RAM, there's a limit to how much caching helps beyond a certain number
-// of tabs. If users *really* want unlimited stores, allow it via the
-// --disable-backing-store-limit flag.
-static size_t MaxNumberOfBackingStores() {
- static bool unlimited = false;
- const CommandLine& command = *CommandLine::ForCurrentProcess();
- unlimited = command.HasSwitch(switches::kDisableBackingStoreLimit);
-
-
- if (unlimited) {
- // 100 isn't truly unlimited, but given that backing stores count against
- // GDI memory, it's well past any reasonable number. Many systems will
- // begin to fail in strange ways well before they hit 100 stores.
- return 100;
- } else {
- return std::min(5, 2 + (base::SysInfo::AmountOfPhysicalMemoryMB() / 256));
- }
-}
-
-// The maximum about of memory to use for all BackingStoreCache object combined.
-static size_t MaxBackingStoreMemory() {
- // Compute in terms of the number of large monitor's worth of backing-store.
- return MaxNumberOfBackingStores() * kMemoryMultiplier;
-}
-
-// Expires the given |backing_store| from |cache|.
-void ExpireBackingStoreAt(BackingStoreCache* cache,
- BackingStoreCache::iterator backing_store) {
- NotificationService::current()->Notify(
- NotificationType::RENDER_WIDGET_HOST_WILL_DESTROY_BACKING_STORE,
- Source<RenderWidgetHost>(backing_store->first),
- Details<BackingStore>(backing_store->second));
- cache->Erase(backing_store);
-}
-
-size_t ExpireLastBackingStore(BackingStoreCache* cache) {
- if (cache->size() < 1)
- return 0;
-
- // Crazy C++ alert: rbegin.base() is a forward iterator pointing to end(),
- // so we need to do -- to move one back to the actual last item.
- BackingStoreCache::iterator entry = --cache->rbegin().base();
- size_t entry_size = entry->second->MemorySize();
- ExpireBackingStoreAt(cache, entry);
- return entry_size;
-}
-
-void CreateCacheSpace(size_t size) {
- // Given a request for |size|, first free from the large cache (until there's
- // only one item left) and then do the same from the small cache if we still
- // don't have enough.
- while (size > 0 && (large_cache->size() > 1 || small_cache->size() > 1)) {
- BackingStoreCache* cache =
- (large_cache->size() > 1) ? large_cache : small_cache;
- while (size > 0 && cache->size() > 1) {
- size_t entry_size = ExpireLastBackingStore(cache);
- if (size > entry_size)
- size -= entry_size;
- else
- size = 0;
- }
- }
- DCHECK(size == 0);
-}
-
-// Creates the backing store for the host based on the dimensions passed in.
-// Removes the existing backing store if there is one.
-BackingStore* CreateBackingStore(RenderWidgetHost* host,
- const gfx::Size& backing_store_size) {
- // Remove any existing backing store in case we're replacing it.
- BackingStoreManager::RemoveBackingStore(host);
-
- if (!large_cache) {
- large_cache = new BackingStoreCache(BackingStoreCache::NO_AUTO_EVICT);
- small_cache = new BackingStoreCache(BackingStoreCache::NO_AUTO_EVICT);
- }
-
- // TODO(erikkay) 32bpp is not always accurate
- size_t new_mem = backing_store_size.GetArea() * 4;
- size_t current_mem = BackingStoreManager::MemorySize();
- size_t max_mem = MaxBackingStoreMemory();
- DCHECK(new_mem < max_mem);
- if (current_mem + new_mem > max_mem) {
- // Need to remove old backing stores to make room for the new one. We
- // don't want to do this when the backing store is being replace by a new
- // one for the same tab, but this case won't get called then: we'll have
- // removed the old one in the RemoveBackingStore above, and the cache
- // won't be over-sized.
- CreateCacheSpace((current_mem + new_mem) - max_mem);
- }
- DCHECK((BackingStoreManager::MemorySize() + new_mem) <= max_mem);
-
- BackingStoreCache* cache;
- if (new_mem > kSmallThreshold) {
- // Limit the number of large backing stores (tabs) to the memory tier number
- // (between 2-5). While we allow a larger amount of memory for people who
- // have large windows, this means that those who use small browser windows
- // won't ever cache more than 5 tabs, so they pay a smaller memory cost.
- if (large_cache->size() >= MaxNumberOfBackingStores())
- ExpireLastBackingStore(large_cache);
- cache = large_cache;
- } else {
- cache = small_cache;
- }
- BackingStore* backing_store = host->AllocBackingStore(backing_store_size);
- if (backing_store)
- cache->Put(host, backing_store);
- return backing_store;
-}
-
-int ComputeTotalArea(const std::vector<gfx::Rect>& rects) {
- // We assume that the given rects are non-overlapping, which is a property of
- // the paint rects generated by the PaintAggregator.
-#ifndef NDEBUG
- for (size_t i = 0; i < rects.size(); ++i) {
- for (size_t j = 0; j < rects.size(); ++j) {
- if (i != j)
- DCHECK(!rects[i].Intersects(rects[j]));
- }
- }
-#endif
- int area = 0;
- for (size_t i = 0; i < rects.size(); ++i)
- area += rects[i].size().GetArea();
- return area;
-}
-
-} // namespace
-
-// BackingStoreManager ---------------------------------------------------------
-
-// static
-BackingStore* BackingStoreManager::GetBackingStore(
- RenderWidgetHost* host,
- const gfx::Size& desired_size) {
- BackingStore* backing_store = Lookup(host);
- if (backing_store) {
- // If we already have a backing store, then make sure it is the correct
- // size.
- if (backing_store->size() == desired_size)
- return backing_store;
- backing_store = NULL;
- }
-
- return backing_store;
-}
-
-// static
-void BackingStoreManager::PrepareBackingStore(
- RenderWidgetHost* host,
- const gfx::Size& backing_store_size,
- TransportDIB::Id bitmap,
- const gfx::Rect& bitmap_rect,
- const std::vector<gfx::Rect>& copy_rects,
- bool* needs_full_paint) {
- BackingStore* backing_store = GetBackingStore(host, backing_store_size);
- if (!backing_store) {
- // We need to get Webkit to generate a new paint here, as we
- // don't have a previous snapshot.
- if (bitmap_rect.size() != backing_store_size ||
- bitmap_rect.x() != 0 || bitmap_rect.y() != 0 ||
- ComputeTotalArea(copy_rects) != backing_store_size.GetArea() ||
- !(backing_store = CreateBackingStore(host, backing_store_size))) {
- DCHECK(needs_full_paint != NULL);
- *needs_full_paint = true;
- // Makes no sense to paint the transport dib if we are going
- // to request a full paint.
- return;
- }
- }
-
- backing_store->PaintToBackingStore(host->process(), bitmap,
- bitmap_rect, copy_rects);
-}
-
-// static
-BackingStore* BackingStoreManager::Lookup(RenderWidgetHost* host) {
- if (large_cache) {
- BackingStoreCache::iterator it = large_cache->Get(host);
- if (it != large_cache->end())
- return it->second;
-
- // This moves host to the front of the MRU.
- it = small_cache->Get(host);
- if (it != small_cache->end())
- return it->second;
- }
- return NULL;
-}
-
-// static
-void BackingStoreManager::RemoveBackingStore(RenderWidgetHost* host) {
- if (!large_cache)
- return;
-
- BackingStoreCache* cache = large_cache;
- BackingStoreCache::iterator it = cache->Peek(host);
- if (it == cache->end()) {
- cache = small_cache;
- it = cache->Peek(host);
- if (it == cache->end())
- return;
- }
- cache->Erase(it);
-}
-
-// static
-void BackingStoreManager::RemoveAllBackingStores() {
- if (large_cache) {
- large_cache->Clear();
- small_cache->Clear();
- }
-}
-
-// static
-bool BackingStoreManager::ExpireBackingStoreForTest(RenderWidgetHost* host) {
- BackingStoreCache* cache = large_cache;
-
- BackingStoreCache::iterator it = cache->Peek(host);
- if (it == cache->end()) {
- cache = small_cache;
- it = cache->Peek(host);
- if (it == cache->end())
- return false;
- }
- ExpireBackingStoreAt(cache, it);
- return true;
-}
-
-// static
-size_t BackingStoreManager::MemorySize() {
- if (!large_cache)
- return 0;
-
- size_t mem = 0;
- BackingStoreCache::iterator it;
- for (it = large_cache->begin(); it != large_cache->end(); ++it)
- mem += it->second->MemorySize();
-
- for (it = small_cache->begin(); it != small_cache->end(); ++it)
- mem += it->second->MemorySize();
-
- return mem;
-}

Powered by Google App Engine
This is Rietveld 408576698