diff options
-rw-r--r-- | cc/delegated_renderer_layer_impl_unittest.cc | 1 | ||||
-rw-r--r-- | cc/gl_renderer.cc | 5 | ||||
-rw-r--r-- | cc/gl_renderer.h | 2 | ||||
-rw-r--r-- | cc/layer_tree_host_impl.cc | 2 | ||||
-rw-r--r-- | cc/layer_tree_host_impl.h | 1 | ||||
-rw-r--r-- | cc/layer_tree_host_impl_unittest.cc | 1 | ||||
-rw-r--r-- | cc/prioritized_texture_manager.cc | 34 | ||||
-rw-r--r-- | cc/prioritized_texture_manager.h | 12 | ||||
-rw-r--r-- | cc/prioritized_texture_unittest.cc | 63 | ||||
-rw-r--r-- | cc/priority_calculator.cc | 10 | ||||
-rw-r--r-- | cc/priority_calculator.h | 1 | ||||
-rw-r--r-- | cc/renderer.h | 2 | ||||
-rw-r--r-- | cc/single_thread_proxy.cc | 10 | ||||
-rw-r--r-- | cc/single_thread_proxy.h | 1 | ||||
-rw-r--r-- | cc/software_renderer.h | 2 | ||||
-rw-r--r-- | cc/thread_proxy.cc | 10 | ||||
-rw-r--r-- | cc/thread_proxy.h | 1 |
17 files changed, 155 insertions, 3 deletions
diff --git a/cc/delegated_renderer_layer_impl_unittest.cc b/cc/delegated_renderer_layer_impl_unittest.cc index 8e3b43e..c8ecda0 100644 --- a/cc/delegated_renderer_layer_impl_unittest.cc +++ b/cc/delegated_renderer_layer_impl_unittest.cc @@ -52,6 +52,7 @@ public: virtual void setNeedsCommitOnImplThread() OVERRIDE { } virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector>, double wallClockTime) OVERRIDE { } virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE { return true; } + virtual void sendManagedMemoryStats() OVERRIDE { } protected: scoped_ptr<GraphicsContext> createContext() diff --git a/cc/gl_renderer.cc b/cc/gl_renderer.cc index b059d76..f287aec 100644 --- a/cc/gl_renderer.cc +++ b/cc/gl_renderer.cc @@ -184,6 +184,11 @@ void GLRenderer::setVisible(bool visible) enforceMemoryPolicy(); } +void GLRenderer::sendManagedMemoryStats(size_t bytesVisible, size_t bytesVisibleAndNearby, size_t bytesAllocated) +{ + // This message cannot reach the GPU process until WebKit changes land. +} + void GLRenderer::releaseRenderPassTextures() { m_renderPassTextures.clear(); diff --git a/cc/gl_renderer.h b/cc/gl_renderer.h index 0a5ec31..fc6810f 100644 --- a/cc/gl_renderer.h +++ b/cc/gl_renderer.h @@ -56,6 +56,8 @@ public: virtual void setVisible(bool) OVERRIDE; + virtual void sendManagedMemoryStats(size_t bytesVisible, size_t bytesVisibleAndNearby, size_t bytesAllocated) OVERRIDE; + protected: GLRenderer(RendererClient*, ResourceProvider*); diff --git a/cc/layer_tree_host_impl.cc b/cc/layer_tree_host_impl.cc index d228ba1..eca5aa2 100644 --- a/cc/layer_tree_host_impl.cc +++ b/cc/layer_tree_host_impl.cc @@ -259,6 +259,7 @@ void LayerTreeHostImpl::commitComplete() // Recompute max scroll position; must be after layer content bounds are // updated. updateMaxScrollPosition(); + m_client->sendManagedMemoryStats(); } bool LayerTreeHostImpl::canDraw() @@ -648,6 +649,7 @@ void LayerTreeHostImpl::enforceManagedMemoryPolicy(const ManagedMemoryPolicy& po m_client->setNeedsCommitOnImplThread(); m_client->onCanDrawStateChanged(canDraw()); } + m_client->sendManagedMemoryStats(); } void LayerTreeHostImpl::setManagedMemoryPolicy(const ManagedMemoryPolicy& policy) diff --git a/cc/layer_tree_host_impl.h b/cc/layer_tree_host_impl.h index 7ce1d31..1dc750d 100644 --- a/cc/layer_tree_host_impl.h +++ b/cc/layer_tree_host_impl.h @@ -43,6 +43,7 @@ public: virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector>, double wallClockTime) = 0; // Returns true if resources were deleted by this call. virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) = 0; + virtual void sendManagedMemoryStats() = 0; }; // PinchZoomViewport models the bounds and offset of the viewport that is used during a pinch-zoom operation. diff --git a/cc/layer_tree_host_impl_unittest.cc b/cc/layer_tree_host_impl_unittest.cc index 68a4b7f..106a702 100644 --- a/cc/layer_tree_host_impl_unittest.cc +++ b/cc/layer_tree_host_impl_unittest.cc @@ -88,6 +88,7 @@ public: virtual void setNeedsCommitOnImplThread() OVERRIDE { m_didRequestCommit = true; } virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector>, double wallClockTime) OVERRIDE { } virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE { return m_reduceMemoryResult; } + virtual void sendManagedMemoryStats() OVERRIDE { } void setReduceMemoryResult(bool reduceMemoryResult) { m_reduceMemoryResult = reduceMemoryResult; } diff --git a/cc/prioritized_texture_manager.cc b/cc/prioritized_texture_manager.cc index 6ad408e..c41b347 100644 --- a/cc/prioritized_texture_manager.cc +++ b/cc/prioritized_texture_manager.cc @@ -25,6 +25,10 @@ PrioritizedTextureManager::PrioritizedTextureManager(size_t maxMemoryLimitBytes, , m_memoryAvailableBytes(0) , m_pool(pool) , m_backingsTailNotSorted(false) + , m_memoryVisibleBytes(0) + , m_memoryVisibleAndNearbyBytes(0) + , m_memoryVisibleLastPushedBytes(0) + , m_memoryVisibleAndNearbyLastPushedBytes(0) { } @@ -40,6 +44,18 @@ PrioritizedTextureManager::~PrioritizedTextureManager() DCHECK(m_backings.empty()); } +size_t PrioritizedTextureManager::memoryVisibleBytes() const +{ + DCHECK(Proxy::isImplThread()); + return m_memoryVisibleLastPushedBytes; +} + +size_t PrioritizedTextureManager::memoryVisibleAndNearbyBytes() const +{ + DCHECK(Proxy::isImplThread()); + return m_memoryVisibleAndNearbyLastPushedBytes; +} + void PrioritizedTextureManager::prioritizeTextures() { TRACE_EVENT0("cc", "PrioritizedTextureManager::prioritizeTextures"); @@ -52,9 +68,17 @@ void PrioritizedTextureManager::prioritizeTextures() TextureVector& sortedTextures = m_tempTextureVector; sortedTextures.clear(); - // Copy all textures into a vector and sort them. - for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) - sortedTextures.push_back(*it); + // Copy all textures into a vector, sort them, and collect memory requirements statistics. + m_memoryVisibleBytes = 0; + m_memoryVisibleAndNearbyBytes = 0; + for (TextureSet::iterator it = m_textures.begin(); it != m_textures.end(); ++it) { + PrioritizedTexture* texture = (*it); + sortedTextures.push_back(texture); + if (PriorityCalculator::priorityIsHigher(texture->requestPriority(), PriorityCalculator::allowVisibleOnlyCutoff())) + m_memoryVisibleBytes += texture->bytes(); + if (PriorityCalculator::priorityIsHigher(texture->requestPriority(), PriorityCalculator::allowVisibleAndNearbyCutoff())) + m_memoryVisibleAndNearbyBytes += texture->bytes(); + } std::sort(sortedTextures.begin(), sortedTextures.end(), compareTextures); // Compute a priority cutoff based on memory pressure @@ -118,6 +142,10 @@ void PrioritizedTextureManager::pushTexturePrioritiesToBackings() (*it)->updatePriority(); sortBackings(); assertInvariants(); + + // Push memory requirements to the impl thread structure. + m_memoryVisibleLastPushedBytes = m_memoryVisibleBytes; + m_memoryVisibleAndNearbyLastPushedBytes = m_memoryVisibleAndNearbyBytes; } void PrioritizedTextureManager::updateBackingsInDrawingImplTree() diff --git a/cc/prioritized_texture_manager.h b/cc/prioritized_texture_manager.h index 47f283a..952b584 100644 --- a/cc/prioritized_texture_manager.h +++ b/cc/prioritized_texture_manager.h @@ -69,6 +69,10 @@ public: // than this cutoff will be allowed. void setExternalPriorityCutoff(int priorityCutoff) { m_externalPriorityCutoff = priorityCutoff; } + // Return the amount of texture memory required at particular cutoffs. + size_t memoryVisibleBytes() const; + size_t memoryVisibleAndNearbyBytes() const; + void prioritizeTextures(); void clearPriorities(); @@ -174,6 +178,14 @@ private: TextureVector m_tempTextureVector; + // Statistics about memory usage at priority cutoffs, computed at prioritizeTextures. + size_t m_memoryVisibleBytes; + size_t m_memoryVisibleAndNearbyBytes; + + // Statistics copied at the time of pushTexturePrioritiesToBackings. + size_t m_memoryVisibleLastPushedBytes; + size_t m_memoryVisibleAndNearbyLastPushedBytes; + DISALLOW_COPY_AND_ASSIGN(PrioritizedTextureManager); }; diff --git a/cc/prioritized_texture_unittest.cc b/cc/prioritized_texture_unittest.cc index c223870..61c80d3 100644 --- a/cc/prioritized_texture_unittest.cc +++ b/cc/prioritized_texture_unittest.cc @@ -642,4 +642,67 @@ TEST_F(PrioritizedTextureTest, clearUploadsToEvictedResources) } +TEST_F(PrioritizedTextureTest, usageStatistics) +{ + const size_t maxTextures = 5; + scoped_ptr<PrioritizedTextureManager> textureManager = createManager(maxTextures); + scoped_ptr<PrioritizedTexture> textures[maxTextures]; + + for (size_t i = 0; i < maxTextures; ++i) + textures[i] = textureManager->createTexture(m_textureSize, m_textureFormat); + + textures[0]->setRequestPriority(PriorityCalculator::allowVisibleOnlyCutoff() - 1); + textures[1]->setRequestPriority(PriorityCalculator::allowVisibleOnlyCutoff()); + textures[2]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff() - 1); + textures[3]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff()); + textures[4]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff() + 1); + + // Set max limit to 2 textures. + textureManager->setMaxMemoryLimitBytes(texturesMemorySize(2)); + prioritizeTexturesAndBackings(textureManager.get()); + + // The first two textures should be available, others should not. + for (size_t i = 0; i < 2; ++i) + EXPECT_TRUE(validateTexture(textures[i], false)); + for (size_t i = 2; i < maxTextures; ++i) + EXPECT_FALSE(validateTexture(textures[i], false)); + + // Validate the statistics. + { + DebugScopedSetImplThread implThread; + EXPECT_EQ(texturesMemorySize(2), textureManager->memoryUseBytes()); + EXPECT_EQ(texturesMemorySize(1), textureManager->memoryVisibleBytes()); + EXPECT_EQ(texturesMemorySize(3), textureManager->memoryVisibleAndNearbyBytes()); + } + + // Re-prioritize the textures, but do not push the values to backings. + textures[0]->setRequestPriority(PriorityCalculator::allowVisibleOnlyCutoff() - 1); + textures[1]->setRequestPriority(PriorityCalculator::allowVisibleOnlyCutoff() - 1); + textures[2]->setRequestPriority(PriorityCalculator::allowVisibleOnlyCutoff() - 1); + textures[3]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff() - 1); + textures[4]->setRequestPriority(PriorityCalculator::allowVisibleAndNearbyCutoff()); + textureManager->prioritizeTextures(); + + // Verify that we still see the old values. + { + DebugScopedSetImplThread implThread; + EXPECT_EQ(texturesMemorySize(2), textureManager->memoryUseBytes()); + EXPECT_EQ(texturesMemorySize(1), textureManager->memoryVisibleBytes()); + EXPECT_EQ(texturesMemorySize(3), textureManager->memoryVisibleAndNearbyBytes()); + } + + // Push priorities to backings, and verify we see the new values. + { + DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked; + textureManager->pushTexturePrioritiesToBackings(); + EXPECT_EQ(texturesMemorySize(2), textureManager->memoryUseBytes()); + EXPECT_EQ(texturesMemorySize(3), textureManager->memoryVisibleBytes()); + EXPECT_EQ(texturesMemorySize(4), textureManager->memoryVisibleAndNearbyBytes()); + } + + DebugScopedSetImplThreadAndMainThreadBlocked implThreadAndMainThreadBlocked; + textureManager->clearAllMemory(resourceProvider()); +} + + } // namespace diff --git a/cc/priority_calculator.cc b/cc/priority_calculator.cc index e2bb0c7..fc250d9 100644 --- a/cc/priority_calculator.cc +++ b/cc/priority_calculator.cc @@ -27,6 +27,10 @@ static const int visibleOnlyPriorityCutoff = 4; static const int notVisibleBasePriority = 1000000; static const int notVisibleLimitPriority = 1900000; +// Arbitrarily define "nearby" to be 2000 pixels. A better estimate +// would be percent-of-viewport or percent-of-screen. +static const int visibleAndNearbyPriorityCutoff = notVisibleBasePriority + 2000; + // Small animated layers are treated as though they are 512 pixels // from being visible. static const int smallAnimatedLayerPriority = notVisibleBasePriority + 512; @@ -116,6 +120,12 @@ int PriorityCalculator::allowVisibleOnlyCutoff() } // static +int PriorityCalculator::allowVisibleAndNearbyCutoff() +{ + return visibleAndNearbyPriorityCutoff; +} + +// static int PriorityCalculator::allowEverythingCutoff() { return everythingPriorityCutoff; diff --git a/cc/priority_calculator.h b/cc/priority_calculator.h index e8daa90..761b6d5 100644 --- a/cc/priority_calculator.h +++ b/cc/priority_calculator.h @@ -27,6 +27,7 @@ public: static int allowNothingCutoff(); static int allowVisibleOnlyCutoff(); + static int allowVisibleAndNearbyCutoff(); static int allowEverythingCutoff(); }; diff --git a/cc/renderer.h b/cc/renderer.h index 5edd957..dfb6a87 100644 --- a/cc/renderer.h +++ b/cc/renderer.h @@ -67,6 +67,8 @@ public: virtual void setVisible(bool) = 0; + virtual void sendManagedMemoryStats(size_t bytesVisible, size_t bytesVisibleAndNearby, size_t bytesAllocated) = 0; + protected: explicit Renderer(RendererClient* client) : m_client(client) diff --git a/cc/single_thread_proxy.cc b/cc/single_thread_proxy.cc index 9667e75..d9918fa 100644 --- a/cc/single_thread_proxy.cc +++ b/cc/single_thread_proxy.cc @@ -286,6 +286,16 @@ bool SingleThreadProxy::reduceContentsTextureMemoryOnImplThread(size_t limitByte return m_layerTreeHost->contentsTextureManager()->reduceMemoryOnImplThread(limitBytes, priorityCutoff, m_layerTreeHostImpl->resourceProvider()); } +void SingleThreadProxy::sendManagedMemoryStats() +{ + DCHECK(Proxy::isImplThread()); + if (m_layerTreeHostImpl.get() && m_layerTreeHostImpl->renderer()) + m_layerTreeHostImpl->renderer()->sendManagedMemoryStats( + m_layerTreeHost->contentsTextureManager()->memoryVisibleBytes(), + m_layerTreeHost->contentsTextureManager()->memoryVisibleAndNearbyBytes(), + m_layerTreeHost->contentsTextureManager()->memoryUseBytes()); +} + // Called by the legacy scheduling path (e.g. where render_widget does the scheduling) void SingleThreadProxy::compositeImmediately() { diff --git a/cc/single_thread_proxy.h b/cc/single_thread_proxy.h index 5b5e208..9ade5f8 100644 --- a/cc/single_thread_proxy.h +++ b/cc/single_thread_proxy.h @@ -54,6 +54,7 @@ public: virtual void setNeedsCommitOnImplThread() OVERRIDE; virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector>, double wallClockTime) OVERRIDE; virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE; + virtual void sendManagedMemoryStats() OVERRIDE; // Called by the legacy path where RenderWidget does the scheduling. void compositeImmediately(); diff --git a/cc/software_renderer.h b/cc/software_renderer.h index 92961ca..1f1604b 100644 --- a/cc/software_renderer.h +++ b/cc/software_renderer.h @@ -36,6 +36,8 @@ public: virtual void setVisible(bool) OVERRIDE; + virtual void sendManagedMemoryStats(size_t bytesVisible, size_t bytesVisibleAndNearby, size_t bytesAllocated) OVERRIDE { } + protected: virtual void bindFramebufferToOutputSurface(DrawingFrame&) OVERRIDE; virtual bool bindFramebufferToTexture(DrawingFrame&, const ScopedTexture*, const gfx::Rect& framebufferRect) OVERRIDE; diff --git a/cc/thread_proxy.cc b/cc/thread_proxy.cc index 94685da..ace26b5 100644 --- a/cc/thread_proxy.cc +++ b/cc/thread_proxy.cc @@ -368,6 +368,16 @@ bool ThreadProxy::reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int return true; } +void ThreadProxy::sendManagedMemoryStats() +{ + DCHECK(isImplThread()); + if (m_layerTreeHostImpl.get() && m_layerTreeHostImpl->renderer()) + m_layerTreeHostImpl->renderer()->sendManagedMemoryStats( + m_layerTreeHost->contentsTextureManager()->memoryVisibleBytes(), + m_layerTreeHost->contentsTextureManager()->memoryVisibleAndNearbyBytes(), + m_layerTreeHost->contentsTextureManager()->memoryUseBytes()); +} + void ThreadProxy::setNeedsRedraw() { DCHECK(isMainThread()); diff --git a/cc/thread_proxy.h b/cc/thread_proxy.h index aab144a..58c8fd4 100644 --- a/cc/thread_proxy.h +++ b/cc/thread_proxy.h @@ -62,6 +62,7 @@ public: virtual void setNeedsCommitOnImplThread() OVERRIDE; virtual void postAnimationEventsToMainThreadOnImplThread(scoped_ptr<AnimationEventsVector>, double wallClockTime) OVERRIDE; virtual bool reduceContentsTextureMemoryOnImplThread(size_t limitBytes, int priorityCutoff) OVERRIDE; + virtual void sendManagedMemoryStats() OVERRIDE; // SchedulerClient implementation virtual void scheduledActionBeginFrame() OVERRIDE; |