summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-22 22:50:28 +0000
committerccameron@chromium.org <ccameron@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-10-22 22:50:28 +0000
commita0a008420151bf3f117f294250e35641af25f213 (patch)
tree7cd0378a4d4b0570d1654a695b97c0957568aff6 /cc
parent6c12c50736a7f2cce5d8776c9d64b85e3435aec6 (diff)
downloadchromium_src-a0a008420151bf3f117f294250e35641af25f213.zip
chromium_src-a0a008420151bf3f117f294250e35641af25f213.tar.gz
chromium_src-a0a008420151bf3f117f294250e35641af25f213.tar.bz2
Conditionalize memory allocation limit based on visibility
Replace the single value with a ManagedMemoryPolicy structure which has the limit in bytes when visible and when not visible, and also has a priority cutoff when visible and when not visible. In CCRendererClient, separate the methods for specifying and enforcing a memory policy. This is so that one may decrease the consumption of a renderer that has grown over time, without disallowing growth in the future. BUG=134750 Review URL: https://chromiumcodereview.appspot.com/11196038 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@163420 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/cc.gyp2
-rw-r--r--cc/delegated_renderer_layer_impl_unittest.cc2
-rw-r--r--cc/gl_renderer.cc2
-rw-r--r--cc/gl_renderer_unittest.cc3
-rw-r--r--cc/layer_tree_host_impl.cc24
-rw-r--r--cc/layer_tree_host_impl.h10
-rw-r--r--cc/layer_tree_host_impl_unittest.cc25
-rw-r--r--cc/layer_tree_host_unittest.cc6
-rw-r--r--cc/managed_memory_policy.cc45
-rw-r--r--cc/managed_memory_policy.h29
-rw-r--r--cc/prioritized_texture_manager.cc48
-rw-r--r--cc/prioritized_texture_manager.h22
-rw-r--r--cc/prioritized_texture_unittest.cc69
-rw-r--r--cc/priority_calculator.cc40
-rw-r--r--cc/priority_calculator.h10
-rw-r--r--cc/renderer.h4
-rw-r--r--cc/single_thread_proxy.cc4
-rw-r--r--cc/single_thread_proxy.h2
-rw-r--r--cc/software_renderer_unittest.cc3
-rw-r--r--cc/thread_proxy.cc4
-rw-r--r--cc/thread_proxy.h2
21 files changed, 289 insertions, 67 deletions
diff --git a/cc/cc.gyp b/cc/cc.gyp
index 2397cd2..9bd6bcb 100644
--- a/cc/cc.gyp
+++ b/cc/cc.gyp
@@ -73,6 +73,8 @@
'CCLayerTreeHostCommon.h',
'layer_tree_host_impl.cc',
'layer_tree_host_impl.h',
+ 'managed_memory_policy.cc',
+ 'managed_memory_policy.h',
'math_util.cc',
'math_util.h',
'occlusion_tracker.cc',
diff --git a/cc/delegated_renderer_layer_impl_unittest.cc b/cc/delegated_renderer_layer_impl_unittest.cc
index 2ebc763..7e37259 100644
--- a/cc/delegated_renderer_layer_impl_unittest.cc
+++ b/cc/delegated_renderer_layer_impl_unittest.cc
@@ -51,7 +51,7 @@ public:
virtual void setNeedsRedrawOnImplThread() OVERRIDE { }
virtual void setNeedsCommitOnImplThread() OVERRIDE { }
virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE { }
- virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes) OVERRIDE { return true; }
+ virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE { return true; }
protected:
scoped_ptr<CCGraphicsContext> createContext()
diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc
index 51d46f5..908aedf 100644
--- a/cc/gl_renderer.cc
+++ b/cc/gl_renderer.cc
@@ -1075,7 +1075,7 @@ void CCRendererGL::onMemoryAllocationChangedOnImplThread(WebKit::WebGraphicsMemo
// bytes. This will happen when the memory manager thinks that the renderer
// is not visible (which the renderer knows better).
if (allocation.gpuResourceSizeInBytes)
- m_client->setMemoryAllocationLimitBytes(allocation.gpuResourceSizeInBytes);
+ m_client->setManagedMemoryPolicy(ManagedMemoryPolicy(allocation.gpuResourceSizeInBytes));
enforceMemoryPolicy();
}
diff --git a/cc/gl_renderer_unittest.cc b/cc/gl_renderer_unittest.cc
index 33bf8c7..5505278 100644
--- a/cc/gl_renderer_unittest.cc
+++ b/cc/gl_renderer_unittest.cc
@@ -74,7 +74,8 @@ public:
virtual void didLoseContext() OVERRIDE { }
virtual void onSwapBuffersComplete() OVERRIDE { }
virtual void setFullRootLayerDamage() OVERRIDE { m_setFullRootLayerDamageCount++; }
- virtual void setMemoryAllocationLimitBytes(size_t bytes) OVERRIDE { m_memoryAllocationLimitBytes = bytes; }
+ virtual void setManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE { m_memoryAllocationLimitBytes = policy.bytesLimitWhenVisible; }
+ virtual void enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE { }
// Methods added for test.
int setFullRootLayerDamageCount() const { return m_setFullRootLayerDamageCount; }
diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc
index d762b0c..aa1b9db 100644
--- a/cc/layer_tree_host_impl.cc
+++ b/cc/layer_tree_host_impl.cc
@@ -223,7 +223,10 @@ CCLayerTreeHostImpl::CCLayerTreeHostImpl(const CCLayerTreeSettings& settings, CC
, m_deviceScaleFactor(1)
, m_visible(true)
, m_contentsTexturesPurged(false)
- , m_memoryAllocationLimitBytes(CCPrioritizedTextureManager::defaultMemoryAllocationLimit())
+ , m_managedMemoryPolicy(CCPrioritizedTextureManager::defaultMemoryAllocationLimit(),
+ CCPriorityCalculator::allowEverythingCutoff(),
+ 0,
+ CCPriorityCalculator::allowNothingCutoff())
, m_backgroundColor(0)
, m_hasTransparentBackground(false)
, m_needsAnimateLayers(false)
@@ -634,9 +637,11 @@ bool CCLayerTreeHostImpl::prepareToDraw(FrameData& frame)
return true;
}
-void CCLayerTreeHostImpl::reduceContentsTextureMemoryOnImplThread(size_t limitBytes)
+void CCLayerTreeHostImpl::enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
{
- bool evictedResources = m_client->reduceContentsTextureMemoryOnImplThread(limitBytes);
+ bool evictedResources = m_client->reduceContentsTextureMemoryOnImplThread(
+ m_visible ? policy.bytesLimitWhenVisible : policy.bytesLimitWhenNotVisible,
+ m_visible ? policy.priorityCutoffWhenVisible : policy.priorityCutoffWhenNotVisible);
if (evictedResources) {
setContentsTexturesPurged();
m_client->setNeedsCommitOnImplThread();
@@ -644,13 +649,14 @@ void CCLayerTreeHostImpl::reduceContentsTextureMemoryOnImplThread(size_t limitBy
}
}
-void CCLayerTreeHostImpl::setMemoryAllocationLimitBytes(size_t bytes)
+void CCLayerTreeHostImpl::setManagedMemoryPolicy(const ManagedMemoryPolicy& policy)
{
- DCHECK(bytes);
- if (m_memoryAllocationLimitBytes == bytes)
+ if (m_managedMemoryPolicy == policy)
return;
- m_memoryAllocationLimitBytes = bytes;
- reduceContentsTextureMemoryOnImplThread(m_visible ? m_memoryAllocationLimitBytes : 0);
+ m_managedMemoryPolicy = policy;
+ enforceManagedMemoryPolicy(m_managedMemoryPolicy);
+ // We always need to commit after changing the memory policy because the new
+ // limit can result in more or less content having texture allocated for it.
m_client->setNeedsCommitOnImplThread();
}
@@ -817,7 +823,7 @@ void CCLayerTreeHostImpl::setVisible(bool visible)
return;
m_visible = visible;
didVisibilityChange(this, m_visible);
- reduceContentsTextureMemoryOnImplThread(m_visible ? m_memoryAllocationLimitBytes : 0);
+ enforceManagedMemoryPolicy(m_managedMemoryPolicy);
if (!m_renderer)
return;
diff --git a/cc/layer_tree_host_impl.h b/cc/layer_tree_host_impl.h
index bcdc355..076dedf 100644
--- a/cc/layer_tree_host_impl.h
+++ b/cc/layer_tree_host_impl.h
@@ -42,7 +42,7 @@ public:
virtual void setNeedsCommitOnImplThread() = 0;
virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<CCAnimationEventsVector>, double wallClockTime) = 0;
// Returns true if resources were deleted by this call.
- virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes) = 0;
+ virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) = 0;
};
// CCPinchZoomViewport models the bounds and offset of the viewport that is used during a pinch-zoom operation.
@@ -150,7 +150,8 @@ public:
virtual void didLoseContext() OVERRIDE;
virtual void onSwapBuffersComplete() OVERRIDE;
virtual void setFullRootLayerDamage() OVERRIDE;
- virtual void setMemoryAllocationLimitBytes(size_t) OVERRIDE;
+ virtual void setManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE;
+ virtual void enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE;
// WebCompositorOutputSurfaceClient implementation.
virtual void onVSyncParametersChanged(double monotonicTimebase, double intervalInSeconds) OVERRIDE;
@@ -194,8 +195,7 @@ public:
bool contentsTexturesPurged() const { return m_contentsTexturesPurged; }
void setContentsTexturesPurged();
void resetContentsTexturesPurged();
- size_t memoryAllocationLimitBytes() const { return m_memoryAllocationLimitBytes; }
- void reduceContentsTextureMemoryOnImplThread(size_t limitBytes);
+ size_t memoryAllocationLimitBytes() const { return m_managedMemoryPolicy.bytesLimitWhenVisible; }
void setViewportSize(const IntSize& layoutViewportSize, const IntSize& deviceViewportSize);
const IntSize& layoutViewportSize() const { return m_layoutViewportSize; }
@@ -319,7 +319,7 @@ private:
float m_deviceScaleFactor;
bool m_visible;
bool m_contentsTexturesPurged;
- size_t m_memoryAllocationLimitBytes;
+ ManagedMemoryPolicy m_managedMemoryPolicy;
SkColor m_backgroundColor;
bool m_hasTransparentBackground;
diff --git a/cc/layer_tree_host_impl_unittest.cc b/cc/layer_tree_host_impl_unittest.cc
index 5029de2..f8e7385 100644
--- a/cc/layer_tree_host_impl_unittest.cc
+++ b/cc/layer_tree_host_impl_unittest.cc
@@ -87,7 +87,7 @@ public:
virtual void setNeedsRedrawOnImplThread() OVERRIDE { m_didRequestRedraw = true; }
virtual void setNeedsCommitOnImplThread() OVERRIDE { m_didRequestCommit = true; }
virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE { }
- virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes) OVERRIDE { return m_reduceMemoryResult; }
+ virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE { return m_reduceMemoryResult; }
void setReduceMemoryResult(bool reduceMemoryResult) { m_reduceMemoryResult = reduceMemoryResult; }
@@ -236,16 +236,16 @@ TEST_P(CCLayerTreeHostImplTest, notifyIfCanDrawChanged)
// Toggle contents textures purged without causing any evictions,
// and make sure that it does not change canDraw.
setReduceMemoryResult(false);
- m_hostImpl->setMemoryAllocationLimitBytes(
- m_hostImpl->memoryAllocationLimitBytes() - 1);
+ m_hostImpl->setManagedMemoryPolicy(ManagedMemoryPolicy(
+ m_hostImpl->memoryAllocationLimitBytes() - 1));
EXPECT_TRUE(m_hostImpl->canDraw());
EXPECT_FALSE(m_onCanDrawStateChangedCalled);
m_onCanDrawStateChangedCalled = false;
// Toggle contents textures purged to make sure it toggles canDraw.
setReduceMemoryResult(true);
- m_hostImpl->setMemoryAllocationLimitBytes(
- m_hostImpl->memoryAllocationLimitBytes() - 1);
+ m_hostImpl->setManagedMemoryPolicy(ManagedMemoryPolicy(
+ m_hostImpl->memoryAllocationLimitBytes() - 1));
EXPECT_FALSE(m_hostImpl->canDraw());
EXPECT_TRUE(m_onCanDrawStateChangedCalled);
m_onCanDrawStateChangedCalled = false;
@@ -4030,23 +4030,23 @@ TEST_P(CCLayerTreeHostImplTest, releaseContentsTextureShouldTriggerCommit)
// evicted, we need to re-commit because the new value may result in us
// drawing something different than before.
setReduceMemoryResult(false);
- m_hostImpl->setMemoryAllocationLimitBytes(
- m_hostImpl->memoryAllocationLimitBytes() - 1);
+ m_hostImpl->setManagedMemoryPolicy(ManagedMemoryPolicy(
+ m_hostImpl->memoryAllocationLimitBytes() - 1));
EXPECT_TRUE(m_didRequestCommit);
m_didRequestCommit = false;
// Especially if changing the memory limit caused evictions, we need
// to re-commit.
setReduceMemoryResult(true);
- m_hostImpl->setMemoryAllocationLimitBytes(
- m_hostImpl->memoryAllocationLimitBytes() - 1);
+ m_hostImpl->setManagedMemoryPolicy(ManagedMemoryPolicy(
+ m_hostImpl->memoryAllocationLimitBytes() - 1));
EXPECT_TRUE(m_didRequestCommit);
m_didRequestCommit = false;
// But if we set it to the same value that it was before, we shouldn't
// re-commit.
- m_hostImpl->setMemoryAllocationLimitBytes(
- m_hostImpl->memoryAllocationLimitBytes());
+ m_hostImpl->setManagedMemoryPolicy(ManagedMemoryPolicy(
+ m_hostImpl->memoryAllocationLimitBytes()));
EXPECT_FALSE(m_didRequestCommit);
}
@@ -4077,7 +4077,8 @@ public:
virtual void didLoseContext() OVERRIDE { }
virtual void onSwapBuffersComplete() OVERRIDE { }
virtual void setFullRootLayerDamage() OVERRIDE { }
- virtual void setMemoryAllocationLimitBytes(size_t) OVERRIDE { }
+ virtual void setManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE { }
+ virtual void enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE { }
protected:
CCTestRenderer(CCResourceProvider* resourceProvider) : CCRendererGL(this, resourceProvider) { }
diff --git a/cc/layer_tree_host_unittest.cc b/cc/layer_tree_host_unittest.cc
index 1de5332..da27070 100644
--- a/cc/layer_tree_host_unittest.cc
+++ b/cc/layer_tree_host_unittest.cc
@@ -2566,7 +2566,7 @@ public:
// Reduce the memory limit to only fit the root layer and one render surface. This
// prevents any contents drawing into surfaces from being allocated.
- hostImpl->setMemoryAllocationLimitBytes(100 * 100 * 4 * 2);
+ hostImpl->setManagedMemoryPolicy(ManagedMemoryPolicy(100 * 100 * 4 * 2));
break;
case 1:
EXPECT_FALSE(renderer->haveCachedResourcesForRenderPassId(surface1RenderPassId));
@@ -2716,7 +2716,7 @@ public:
virtual void run() OVERRIDE
{
DCHECK(m_test->m_implForEvictTextures);
- m_test->m_implForEvictTextures->reduceContentsTextureMemoryOnImplThread(0);
+ m_test->m_implForEvictTextures->enforceManagedMemoryPolicy(ManagedMemoryPolicy(0));
}
private:
@@ -2875,7 +2875,7 @@ public:
void evictTexturesOnImplThread()
{
DCHECK(m_implForEvictTextures);
- m_implForEvictTextures->reduceContentsTextureMemoryOnImplThread(0);
+ m_implForEvictTextures->enforceManagedMemoryPolicy(ManagedMemoryPolicy(0));
}
// Commit 1: Just commit and draw normally, then at the end, set ourselves
diff --git a/cc/managed_memory_policy.cc b/cc/managed_memory_policy.cc
new file mode 100644
index 0000000..29f1170
--- /dev/null
+++ b/cc/managed_memory_policy.cc
@@ -0,0 +1,45 @@
+// Copyright 2011 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 "config.h"
+
+#include "managed_memory_policy.h"
+
+#include "priority_calculator.h"
+
+namespace cc {
+
+ManagedMemoryPolicy::ManagedMemoryPolicy(size_t bytesLimitWhenVisible)
+ : bytesLimitWhenVisible(bytesLimitWhenVisible)
+ , priorityCutoffWhenVisible(CCPriorityCalculator::allowEverythingCutoff())
+ , bytesLimitWhenNotVisible(0)
+ , priorityCutoffWhenNotVisible(CCPriorityCalculator::allowNothingCutoff())
+{
+}
+
+ManagedMemoryPolicy::ManagedMemoryPolicy(size_t bytesLimitWhenVisible,
+ int priorityCutoffWhenVisible,
+ size_t bytesLimitWhenNotVisible,
+ int priorityCutoffWhenNotVisible)
+ : bytesLimitWhenVisible(bytesLimitWhenVisible)
+ , priorityCutoffWhenVisible(priorityCutoffWhenVisible)
+ , bytesLimitWhenNotVisible(bytesLimitWhenNotVisible)
+ , priorityCutoffWhenNotVisible(priorityCutoffWhenNotVisible)
+{
+}
+
+bool ManagedMemoryPolicy::operator==(const ManagedMemoryPolicy& other) const
+{
+ return bytesLimitWhenVisible == other.bytesLimitWhenVisible &&
+ priorityCutoffWhenVisible == other.priorityCutoffWhenVisible &&
+ bytesLimitWhenNotVisible == other.bytesLimitWhenNotVisible &&
+ priorityCutoffWhenNotVisible == other.priorityCutoffWhenNotVisible;
+}
+
+bool ManagedMemoryPolicy::operator!=(const ManagedMemoryPolicy& other) const
+{
+ return !(*this == other);
+}
+
+} // namespace cc
diff --git a/cc/managed_memory_policy.h b/cc/managed_memory_policy.h
new file mode 100644
index 0000000..eba13c3
--- /dev/null
+++ b/cc/managed_memory_policy.h
@@ -0,0 +1,29 @@
+// Copyright 2011 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.
+
+#ifndef managed_memory_policy_h
+#define managed_memory_policy_h
+
+#include "base/basictypes.h"
+
+namespace cc {
+
+struct ManagedMemoryPolicy {
+ ManagedMemoryPolicy(size_t bytesLimitWhenVisible);
+ ManagedMemoryPolicy(size_t bytesLimitWhenVisible,
+ int priorityCutoffWhenVisible,
+ size_t bytesLimitWhenNotVisible,
+ int priorityCutoffWhenNotVisible);
+ bool operator==(const ManagedMemoryPolicy&) const;
+ bool operator!=(const ManagedMemoryPolicy&) const;
+
+ size_t bytesLimitWhenVisible;
+ int priorityCutoffWhenVisible;
+ size_t bytesLimitWhenNotVisible;
+ int priorityCutoffWhenNotVisible;
+};
+
+} // namespace cc
+
+#endif
diff --git a/cc/prioritized_texture_manager.cc b/cc/prioritized_texture_manager.cc
index 1b18be2..900a1da 100644
--- a/cc/prioritized_texture_manager.cc
+++ b/cc/prioritized_texture_manager.cc
@@ -19,6 +19,7 @@ namespace cc {
CCPrioritizedTextureManager::CCPrioritizedTextureManager(size_t maxMemoryLimitBytes, int, int pool)
: m_maxMemoryLimitBytes(maxMemoryLimitBytes)
+ , m_externalPriorityCutoff(CCPriorityCalculator::allowEverythingCutoff())
, m_memoryUseBytes(0)
, m_memoryAboveCutoffBytes(0)
, m_memoryAvailableBytes(0)
@@ -56,13 +57,11 @@ void CCPrioritizedTextureManager::prioritizeTextures()
sortedTextures.push_back(*it);
std::sort(sortedTextures.begin(), sortedTextures.end(), compareTextures);
+ // Compute a priority cutoff based on memory pressure
m_memoryAvailableBytes = m_maxMemoryLimitBytes;
- m_priorityCutoff = CCPriorityCalculator::lowestPriority();
+ m_priorityCutoff = m_externalPriorityCutoff;
size_t memoryBytes = 0;
for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextures.end(); ++it) {
- if ((*it)->requestPriority() == CCPriorityCalculator::lowestPriority())
- break;
-
if ((*it)->isSelfManaged()) {
// Account for self-managed memory immediately by reducing the memory
// available (since it never gets acquired).
@@ -83,6 +82,16 @@ void CCPrioritizedTextureManager::prioritizeTextures()
}
}
+ // Disallow any textures with priority below the external cutoff to have backings.
+ size_t memoryLinkedTexturesBytes = 0;
+ for (TextureVector::iterator it = sortedTextures.begin(); it != sortedTextures.end(); ++it) {
+ CCPrioritizedTexture* texture = (*it);
+ if (!CCPriorityCalculator::priorityIsHigher(texture->requestPriority(), m_externalPriorityCutoff) &&
+ texture->haveBackingTexture())
+ texture->unlink();
+ }
+ DCHECK(memoryLinkedTexturesBytes <= m_memoryAvailableBytes);
+
// Only allow textures if they are higher than the cutoff. All textures
// of the same priority are accepted or rejected together, rather than
// being partially allowed randomly.
@@ -155,9 +164,14 @@ bool CCPrioritizedTextureManager::requestLate(CCPrioritizedTexture* texture)
if (texture->isAbovePriorityCutoff())
return true;
+ // Allow textures that have priority equal to the cutoff, but not strictly lower.
if (CCPriorityCalculator::priorityIsLower(texture->requestPriority(), m_priorityCutoff))
return false;
+ // Disallow textures that do not have a priority strictly higher than the external cutoff.
+ if (!CCPriorityCalculator::priorityIsHigher(texture->requestPriority(), m_externalPriorityCutoff))
+ return false;
+
size_t newMemoryBytes = m_memoryAboveCutoffBytes + texture->bytes();
if (newMemoryBytes > m_memoryAvailableBytes)
return false;
@@ -191,7 +205,7 @@ void CCPrioritizedTextureManager::acquireBackingTextureIfNeeded(CCPrioritizedTex
// Otherwise reduce memory and just allocate a new backing texures.
if (!backing) {
- evictBackingsToReduceMemory(m_memoryAvailableBytes - texture->bytes(), RespectManagerPriorityCutoff, resourceProvider);
+ evictBackingsToReduceMemory(m_memoryAvailableBytes - texture->bytes(), CCPriorityCalculator::allowEverythingCutoff(), EvictOnlyRecyclable, resourceProvider);
backing = createBacking(texture->size(), texture->format(), resourceProvider);
}
@@ -207,19 +221,21 @@ void CCPrioritizedTextureManager::acquireBackingTextureIfNeeded(CCPrioritizedTex
backing->updatePriority();
}
-bool CCPrioritizedTextureManager::evictBackingsToReduceMemory(size_t limitBytes, EvictionPriorityPolicy evictionPolicy, CCResourceProvider* resourceProvider)
+bool CCPrioritizedTextureManager::evictBackingsToReduceMemory(size_t limitBytes, int priorityCutoff, EvictionPolicy evictionPolicy, CCResourceProvider* resourceProvider)
{
DCHECK(CCProxy::isImplThread());
- if (memoryUseBytes() <= limitBytes)
+ if (memoryUseBytes() <= limitBytes && CCPriorityCalculator::allowEverythingCutoff() == priorityCutoff)
return false;
// Destroy backings until we are below the limit,
// or until all backings remaining are above the cutoff.
- while (memoryUseBytes() > limitBytes && m_backings.size() > 0) {
+ while (m_backings.size() > 0) {
CCPrioritizedTexture::Backing* backing = m_backings.front();
- if (evictionPolicy == RespectManagerPriorityCutoff)
- if (backing->wasAbovePriorityCutoffAtLastPriorityUpdate())
- break;
+ if (memoryUseBytes() <= limitBytes &&
+ CCPriorityCalculator::priorityIsHigher(backing->requestPriorityAtLastPriorityUpdate(), priorityCutoff))
+ break;
+ if (evictionPolicy == EvictOnlyRecyclable && !backing->canBeRecycled())
+ break;
evictFirstBackingResource(resourceProvider);
}
return true;
@@ -229,7 +245,7 @@ void CCPrioritizedTextureManager::reduceMemory(CCResourceProvider* resourceProvi
{
DCHECK(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked());
- evictBackingsToReduceMemory(m_memoryAvailableBytes, RespectManagerPriorityCutoff, resourceProvider);
+ evictBackingsToReduceMemory(m_memoryAvailableBytes, CCPriorityCalculator::allowEverythingCutoff(), EvictOnlyRecyclable, resourceProvider);
DCHECK(memoryUseBytes() <= maxMemoryLimitBytes());
// We currently collect backings from deleted textures for later recycling.
@@ -245,7 +261,7 @@ void CCPrioritizedTextureManager::reduceMemory(CCResourceProvider* resourceProvi
}
size_t tenPercentOfMemory = m_memoryAvailableBytes / 10;
if (wastedMemory > tenPercentOfMemory)
- evictBackingsToReduceMemory(memoryUseBytes() - (wastedMemory - tenPercentOfMemory), RespectManagerPriorityCutoff, resourceProvider);
+ evictBackingsToReduceMemory(memoryUseBytes() - (wastedMemory - tenPercentOfMemory), CCPriorityCalculator::allowEverythingCutoff(), EvictOnlyRecyclable, resourceProvider);
// Unlink all evicted backings
for (BackingList::const_iterator it = m_evictedBackings.begin(); it != m_evictedBackings.end(); ++it) {
@@ -261,10 +277,10 @@ void CCPrioritizedTextureManager::clearAllMemory(CCResourceProvider* resourcePro
{
DCHECK(CCProxy::isImplThread() && CCProxy::isMainThreadBlocked());
DCHECK(resourceProvider);
- evictBackingsToReduceMemory(0, DoNotRespectManagerPriorityCutoff, resourceProvider);
+ evictBackingsToReduceMemory(0, CCPriorityCalculator::allowEverythingCutoff(), EvictAnything, resourceProvider);
}
-bool CCPrioritizedTextureManager::reduceMemoryOnImplThread(size_t limitBytes, CCResourceProvider* resourceProvider)
+bool CCPrioritizedTextureManager::reduceMemoryOnImplThread(size_t limitBytes, int priorityCutoff, CCResourceProvider* resourceProvider)
{
DCHECK(CCProxy::isImplThread());
DCHECK(resourceProvider);
@@ -272,7 +288,7 @@ bool CCPrioritizedTextureManager::reduceMemoryOnImplThread(size_t limitBytes, CC
// the list are not sorted by priority. Sort them before doing the eviction.
if (m_backingsTailNotSorted)
sortBackings();
- return evictBackingsToReduceMemory(limitBytes, DoNotRespectManagerPriorityCutoff, resourceProvider);
+ return evictBackingsToReduceMemory(limitBytes, priorityCutoff, EvictAnything, resourceProvider);
}
void CCPrioritizedTextureManager::getEvictedBackings(BackingList& evictedBackings)
diff --git a/cc/prioritized_texture_manager.h b/cc/prioritized_texture_manager.h
index 439fe81..cbf3c49 100644
--- a/cc/prioritized_texture_manager.h
+++ b/cc/prioritized_texture_manager.h
@@ -65,13 +65,17 @@ public:
void setMaxMemoryLimitBytes(size_t bytes) { m_maxMemoryLimitBytes = bytes; }
size_t maxMemoryLimitBytes() const { return m_maxMemoryLimitBytes; }
+ // Sepecify a external priority cutoff. Only textures that have a strictly higher priority
+ // than this cutoff will be allowed.
+ void setExternalPriorityCutoff(int priorityCutoff) { m_externalPriorityCutoff = priorityCutoff; }
+
void prioritizeTextures();
void clearPriorities();
// Delete contents textures' backing resources until they use only bytesLimit bytes. This may
// be called on the impl thread while the main thread is running. Returns true if resources are
// indeed evicted as a result of this call.
- bool reduceMemoryOnImplThread(size_t limitBytes, CCResourceProvider*);
+ bool reduceMemoryOnImplThread(size_t limitBytes, int priorityCutoff, CCResourceProvider*);
// Returns true if there exist any textures that are linked to backings that have had their
// resources evicted. Only when we commit a tree that has no textures linked to evicted backings
// may we allow drawing.
@@ -103,9 +107,9 @@ public:
private:
friend class CCPrioritizedTextureTest;
- enum EvictionPriorityPolicy {
- RespectManagerPriorityCutoff,
- DoNotRespectManagerPriorityCutoff,
+ enum EvictionPolicy {
+ EvictOnlyRecyclable,
+ EvictAnything,
};
// Compare textures. Highest priority first.
@@ -136,7 +140,7 @@ private:
CCPrioritizedTextureManager(size_t maxMemoryLimitBytes, int maxTextureSize, int pool);
- bool evictBackingsToReduceMemory(size_t limitBytes, EvictionPriorityPolicy, CCResourceProvider*);
+ bool evictBackingsToReduceMemory(size_t limitBytes, int priorityCutoff, EvictionPolicy, CCResourceProvider*);
CCPrioritizedTexture::Backing* createBacking(IntSize, GLenum format, CCResourceProvider*);
void evictFirstBackingResource(CCResourceProvider*);
void deleteUnlinkedEvictedBackings();
@@ -145,7 +149,13 @@ private:
void assertInvariants();
size_t m_maxMemoryLimitBytes;
- unsigned m_priorityCutoff;
+ // The priority cutoff based on memory pressure. This is not a strict
+ // cutoff -- requestLate allows textures with priority equal to this
+ // cutoff to be allowed.
+ int m_priorityCutoff;
+ // The priority cutoff based on external memory policy. This is a strict
+ // cutoff -- no textures with priority equal to this cutoff will be allowed.
+ int m_externalPriorityCutoff;
size_t m_memoryUseBytes;
size_t m_memoryAboveCutoffBytes;
size_t m_memoryAvailableBytes;
diff --git a/cc/prioritized_texture_unittest.cc b/cc/prioritized_texture_unittest.cc
index ccad1cc..69796cb 100644
--- a/cc/prioritized_texture_unittest.cc
+++ b/cc/prioritized_texture_unittest.cc
@@ -196,6 +196,71 @@ TEST_F(CCPrioritizedTextureTest, changeMemoryLimits)
textureManager->clearAllMemory(resourceProvider());
}
+TEST_F(CCPrioritizedTextureTest, changePriorityCutoff)
+{
+ const size_t maxTextures = 8;
+ scoped_ptr<CCPrioritizedTextureManager> textureManager = createManager(maxTextures);
+ scoped_ptr<CCPrioritizedTexture> textures[maxTextures];
+
+ for (size_t i = 0; i < maxTextures; ++i)
+ textures[i] = textureManager->createTexture(m_textureSize, m_textureFormat);
+ for (size_t i = 0; i < maxTextures; ++i)
+ textures[i]->setRequestPriority(100 + i);
+
+ // Set the cutoff to drop two textures. Try to requestLate on all textures, and
+ // make sure that requestLate doesn't work on a texture with equal priority to
+ // the cutoff.
+ textureManager->setMaxMemoryLimitBytes(texturesMemorySize(8));
+ textureManager->setExternalPriorityCutoff(106);
+ prioritizeTexturesAndBackings(textureManager.get());
+ for (size_t i = 0; i < maxTextures; ++i)
+ EXPECT_EQ(validateTexture(textures[i], true), i < 6);
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked;
+ textureManager->reduceMemory(resourceProvider());
+ }
+ EXPECT_EQ(texturesMemorySize(6), textureManager->memoryAboveCutoffBytes());
+ EXPECT_LE(textureManager->memoryUseBytes(), textureManager->memoryAboveCutoffBytes());
+
+ // Set the cutoff to drop two more textures.
+ textureManager->setExternalPriorityCutoff(104);
+ prioritizeTexturesAndBackings(textureManager.get());
+ for (size_t i = 0; i < maxTextures; ++i)
+ EXPECT_EQ(validateTexture(textures[i], false), i < 4);
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked;
+ textureManager->reduceMemory(resourceProvider());
+ }
+ EXPECT_EQ(texturesMemorySize(4), textureManager->memoryAboveCutoffBytes());
+
+ // Do a one-time eviction for one more texture based on priority cutoff
+ CCPrioritizedTextureManager::BackingList evictedBackings;
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked;
+ textureManager->reduceMemoryOnImplThread(texturesMemorySize(8), 104, resourceProvider());
+ textureManager->getEvictedBackings(evictedBackings);
+ EXPECT_EQ(0, evictedBackings.size());
+ textureManager->reduceMemoryOnImplThread(texturesMemorySize(8), 103, resourceProvider());
+ textureManager->getEvictedBackings(evictedBackings);
+ EXPECT_EQ(1, evictedBackings.size());
+ }
+ textureManager->unlinkEvictedBackings(evictedBackings);
+ EXPECT_EQ(texturesMemorySize(3), textureManager->memoryUseBytes());
+
+ // Re-allocate the the texture after the one-time drop.
+ prioritizeTexturesAndBackings(textureManager.get());
+ for (size_t i = 0; i < maxTextures; ++i)
+ EXPECT_EQ(validateTexture(textures[i], false), i < 4);
+ {
+ DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked;
+ textureManager->reduceMemory(resourceProvider());
+ }
+ EXPECT_EQ(texturesMemorySize(4), textureManager->memoryAboveCutoffBytes());
+
+ DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked;
+ textureManager->clearAllMemory(resourceProvider());
+}
+
TEST_F(CCPrioritizedTextureTest, textureManagerPartialUpdateTextures)
{
const size_t maxTextures = 4;
@@ -567,11 +632,11 @@ TEST_F(CCPrioritizedTextureTest, clearUploadsToEvictedResources)
EXPECT_EQ(4, queue.fullUploadSize());
textureManager->reduceMemoryOnImplThread(
- texturesMemorySize(1), resourceProvider());
+ texturesMemorySize(1), CCPriorityCalculator::allowEverythingCutoff(), resourceProvider());
queue.clearUploadsToEvictedResources();
EXPECT_EQ(1, queue.fullUploadSize());
- textureManager->reduceMemoryOnImplThread(0, resourceProvider());
+ textureManager->reduceMemoryOnImplThread(0, CCPriorityCalculator::allowEverythingCutoff(), resourceProvider());
queue.clearUploadsToEvictedResources();
EXPECT_EQ(0, queue.fullUploadSize());
diff --git a/cc/priority_calculator.cc b/cc/priority_calculator.cc
index 0d527e0..9818716 100644
--- a/cc/priority_calculator.cc
+++ b/cc/priority_calculator.cc
@@ -10,12 +10,18 @@ using namespace std;
namespace cc {
+static const int nothingPriorityCutoff = -3;
+
+static const int mostHighPriority = -2;
+
static const int uiDrawsToRootSurfacePriority = -1;
static const int visibleDrawsToRootSurfacePriority = 0;
static const int renderSurfacesPriority = 1;
static const int uiDoesNotDrawToRootSurfacePriority = 2;
static const int visibleDoesNotDrawToRootSurfacePriority = 3;
+static const int visibleOnlyPriorityCutoff = 4;
+
// The lower digits are how far from being visible the texture is,
// in pixels.
static const int notVisibleBasePriority = 1000000;
@@ -28,6 +34,10 @@ static const int smallAnimatedLayerPriority = notVisibleBasePriority + 512;
static const int lingeringBasePriority = 2000000;
static const int lingeringLimitPriority = 2900000;
+static const int mostLowPriority = 3000000;
+
+static const int everythingPriorityCutoff = 3000001;
+
// static
int CCPriorityCalculator::uiPriority(bool drawsToRootSurface)
{
@@ -81,4 +91,34 @@ int CCPriorityCalculator::smallAnimatedLayerMinPriority()
return smallAnimatedLayerPriority;
}
+// static
+int CCPriorityCalculator::highestPriority()
+{
+ return mostHighPriority;
+}
+
+// static
+int CCPriorityCalculator::lowestPriority()
+{
+ return mostLowPriority;
+}
+
+// static
+int CCPriorityCalculator::allowNothingCutoff()
+{
+ return nothingPriorityCutoff;
+}
+
+// static
+int CCPriorityCalculator::allowVisibleOnlyCutoff()
+{
+ return visibleOnlyPriorityCutoff;
+}
+
+// static
+int CCPriorityCalculator::allowEverythingCutoff()
+{
+ return everythingPriorityCutoff;
+}
+
} // cc
diff --git a/cc/priority_calculator.h b/cc/priority_calculator.h
index 2d0f5ba..cab581b 100644
--- a/cc/priority_calculator.h
+++ b/cc/priority_calculator.h
@@ -19,11 +19,15 @@ public:
static int priorityFromDistance(const IntRect& visibleRect, const IntRect& textureRect, bool drawsToRootSurface);
static int smallAnimatedLayerMinPriority();
- static inline int highestPriority() { return std::numeric_limits<int>::min(); }
- static inline int lowestPriority() { return std::numeric_limits<int>::max(); }
+ static int highestPriority();
+ static int lowestPriority();
static inline bool priorityIsLower(int a, int b) { return a > b; }
static inline bool priorityIsHigher(int a, int b) { return a < b; }
- static inline bool maxPriority(int a, int b) { return priorityIsHigher(a, b) ? a : b; }
+ static inline int maxPriority(int a, int b) { return priorityIsHigher(a, b) ? a : b; }
+
+ static int allowNothingCutoff();
+ static int allowVisibleOnlyCutoff();
+ static int allowEverythingCutoff();
};
}
diff --git a/cc/renderer.h b/cc/renderer.h
index 6ac38e2..a1cb51d 100644
--- a/cc/renderer.h
+++ b/cc/renderer.h
@@ -6,6 +6,7 @@
#define CCRenderer_h
#include "CCLayerTreeHost.h"
+#include "managed_memory_policy.h"
#include "FloatQuad.h"
#include "base/basictypes.h"
#include "cc/render_pass.h"
@@ -21,7 +22,8 @@ public:
virtual void didLoseContext() = 0;
virtual void onSwapBuffersComplete() = 0;
virtual void setFullRootLayerDamage() = 0;
- virtual void setMemoryAllocationLimitBytes(size_t) = 0;
+ virtual void setManagedMemoryPolicy(const ManagedMemoryPolicy& policy) = 0;
+ virtual void enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy) = 0;
protected:
virtual ~CCRendererClient() { }
};
diff --git a/cc/single_thread_proxy.cc b/cc/single_thread_proxy.cc
index af9232f..d43606b 100644
--- a/cc/single_thread_proxy.cc
+++ b/cc/single_thread_proxy.cc
@@ -277,13 +277,13 @@ void CCSingleThreadProxy::postAnimationEventsToMainThreadOnImplThread(scoped_ptr
m_layerTreeHost->setAnimationEvents(events.Pass(), wallClockTime);
}
-bool CCSingleThreadProxy::reduceContentsTextureMemoryOnImplThread(size_t limitBytes)
+bool CCSingleThreadProxy::reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff)
{
DCHECK(isImplThread());
if (!m_layerTreeHost->contentsTextureManager())
return false;
- return m_layerTreeHost->contentsTextureManager()->reduceMemoryOnImplThread(limitBytes, m_layerTreeHostImpl->resourceProvider());
+ return m_layerTreeHost->contentsTextureManager()->reduceMemoryOnImplThread(limitBytes, priorityCutoff, m_layerTreeHostImpl->resourceProvider());
}
// Called by the legacy scheduling path (e.g. where render_widget does the scheduling)
diff --git a/cc/single_thread_proxy.h b/cc/single_thread_proxy.h
index 67c7faa..8c7661a 100644
--- a/cc/single_thread_proxy.h
+++ b/cc/single_thread_proxy.h
@@ -53,7 +53,7 @@ public:
virtual void setNeedsRedrawOnImplThread() OVERRIDE;
virtual void setNeedsCommitOnImplThread() OVERRIDE;
virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE;
- virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes) OVERRIDE;
+ virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE;
// Called by the legacy path where RenderWidget does the scheduling.
void compositeImmediately();
diff --git a/cc/software_renderer_unittest.cc b/cc/software_renderer_unittest.cc
index fa45efe..8601e3f 100644
--- a/cc/software_renderer_unittest.cc
+++ b/cc/software_renderer_unittest.cc
@@ -48,7 +48,8 @@ public:
virtual void didLoseContext() OVERRIDE { }
virtual void onSwapBuffersComplete() OVERRIDE { }
virtual void setFullRootLayerDamage() OVERRIDE { }
- virtual void setMemoryAllocationLimitBytes(size_t) OVERRIDE { }
+ virtual void setManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE { };
+ virtual void enforceManagedMemoryPolicy(const ManagedMemoryPolicy& policy) OVERRIDE { };
protected:
DebugScopedSetImplThread m_alwaysImplThread;
diff --git a/cc/thread_proxy.cc b/cc/thread_proxy.cc
index c4caa4d..54a11b3 100644
--- a/cc/thread_proxy.cc
+++ b/cc/thread_proxy.cc
@@ -348,14 +348,14 @@ void CCThreadProxy::postAnimationEventsToMainThreadOnImplThread(scoped_ptr<CCAni
m_mainThreadProxy->postTask(createCCThreadTask(this, &CCThreadProxy::setAnimationEvents, events.release(), wallClockTime));
}
-bool CCThreadProxy::reduceContentsTextureMemoryOnImplThread(size_t limitBytes)
+bool CCThreadProxy::reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff)
{
DCHECK(isImplThread());
if (!m_layerTreeHost->contentsTextureManager())
return false;
- if (!m_layerTreeHost->contentsTextureManager()->reduceMemoryOnImplThread(limitBytes, m_layerTreeHostImpl->resourceProvider()))
+ if (!m_layerTreeHost->contentsTextureManager()->reduceMemoryOnImplThread(limitBytes, priorityCutoff, m_layerTreeHostImpl->resourceProvider()))
return false;
// The texture upload queue may reference textures that were just purged, clear
diff --git a/cc/thread_proxy.h b/cc/thread_proxy.h
index c6c3a16..29b2549 100644
--- a/cc/thread_proxy.h
+++ b/cc/thread_proxy.h
@@ -61,7 +61,7 @@ public:
virtual void setNeedsRedrawOnImplThread() OVERRIDE;
virtual void setNeedsCommitOnImplThread() OVERRIDE;
virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<CCAnimationEventsVector>, double wallClockTime) OVERRIDE;
- virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes) OVERRIDE;
+ virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE;
// CCSchedulerClient implementation
virtual void scheduledActionBeginFrame() OVERRIDE;