https://bugs.webkit.org/show_bug.cgi?id=76740
Patch by David Reveman <reveman@chromium.org> on 2012-02-08
Reviewed by James Robinson.
Source/WebCore:
Allow the final batch of texture uploads to be performed without
allocating new textures and re-painting complete tiles.
This patch is tested by the following unit test:
- CCLayerTreeHostTestAtomicCommitWithPartialUpdate.runMultiThread
- TiledLayerChromiumTest.partialUpdates
* platform/graphics/chromium/TiledLayerChromium.cpp:
(WebCore::UpdatableTile::UpdatableTile):
(UpdatableTile):
(WebCore::TiledLayerChromium::updateCompositorResources):
(WebCore):
(WebCore::TiledLayerChromium::tileOnlyNeedsPartialUpdate):
(WebCore::TiledLayerChromium::tileNeedsBufferedUpdate):
(WebCore::TiledLayerChromium::prepareToUpdateTiles):
* platform/graphics/chromium/TiledLayerChromium.h:
(TiledLayerChromium):
* platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
(WebCore::CCLayerTreeHost::CCLayerTreeHost):
(WebCore::CCLayerTreeHost::initializeLayerRenderer):
(WebCore::CCLayerTreeHost::updateLayers):
(WebCore::CCLayerTreeHost::requestPartialTextureUpdate):
(WebCore):
* platform/graphics/chromium/cc/CCLayerTreeHost.h:
(WebCore::CCSettings::CCSettings):
(CCSettings):
(CCLayerTreeHost):
* platform/graphics/chromium/cc/CCProxy.h:
(CCProxy):
* platform/graphics/chromium/cc/CCSingleThreadProxy.cpp:
(WebCore::CCSingleThreadProxy::doCommit):
* platform/graphics/chromium/cc/CCSingleThreadProxy.h:
(WebCore::CCSingleThreadProxy::maxPartialTextureUpdates):
* platform/graphics/chromium/cc/CCTextureUpdater.cpp:
(WebCore::CCTextureUpdater::append):
(WebCore):
(WebCore::CCTextureUpdater::appendPartial):
(WebCore::CCTextureUpdater::hasMoreUpdates):
(WebCore::CCTextureUpdater::update):
(WebCore::CCTextureUpdater::clear):
* platform/graphics/chromium/cc/CCTextureUpdater.h:
(CCTextureUpdater):
* platform/graphics/chromium/cc/CCThreadProxy.cpp:
(WTF):
(WebCore::CCThreadProxy::scheduledActionUpdateMoreResources):
(WebCore::CCThreadProxy::maxPartialTextureUpdates):
* platform/graphics/chromium/cc/CCThreadProxy.h:
(CCThreadProxy):
Source/WebKit/chromium:
Add CCLayerTreeHostTestAtomicCommitWithPartialUpdate and
TiledLayerChromiumTest.partialUpdates tests that verifies
atomicity of commits with partial updates.
* tests/CCLayerTreeHostTest.cpp:
(WTF::CCLayerTreeHostTestAtomicCommit::CCLayerTreeHostTestAtomicCommit):
(WTF::CCLayerTreeHostTestAtomicCommit::beginTest):
(WTF::CCLayerTreeHostTestAtomicCommit::commitCompleteOnCCThread):
(WTF::CCLayerTreeHostTestAtomicCommit::layout):
(CCLayerTreeHostTestAtomicCommit):
(CCLayerTreeHostTestAtomicCommitWithPartialUpdate):
(WTF::CCLayerTreeHostTestAtomicCommitWithPartialUpdate::CCLayerTreeHostTestAtomicCommitWithPartialUpdate):
(WTF::CCLayerTreeHostTestAtomicCommitWithPartialUpdate::beginTest):
(WTF::CCLayerTreeHostTestAtomicCommitWithPartialUpdate::commitCompleteOnCCThread):
(WTF::CCLayerTreeHostTestAtomicCommitWithPartialUpdate::drawLayersOnCCThread):
(WTF::CCLayerTreeHostTestAtomicCommitWithPartialUpdate::layout):
(WTF::CCLayerTreeHostTestAtomicCommitWithPartialUpdate::afterTest):
(WTF):
(WTF::TEST_F):
* tests/TiledLayerChromiumTest.cpp:
(WTF::FakeLayerTextureUpdater::Texture::Texture):
(WTF::FakeLayerTextureUpdater::Texture::updateRect):
(Texture):
(WTF::FakeLayerTextureUpdater::FakeLayerTextureUpdater):
(FakeLayerTextureUpdater):
(WTF::FakeLayerTextureUpdater::updateCount):
(WTF::FakeLayerTextureUpdater::clearUpdateCount):
(WTF::FakeLayerTextureUpdater::updateRect):
(WTF::FakeLayerTextureUpdater::createTexture):
(FakeTiledLayerChromium):
(WTF::TEST):
(WTF):
git-svn-id: http://svn.webkit.org/repository/webkit/trunk@107177
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-02-08 David Reveman <reveman@chromium.org>
+
+ [Chromium] Avoid unnecessary full tile updates without breaking atomicity of commits.
+ https://bugs.webkit.org/show_bug.cgi?id=76740
+
+ Reviewed by James Robinson.
+
+ Allow the final batch of texture uploads to be performed without
+ allocating new textures and re-painting complete tiles.
+
+ This patch is tested by the following unit test:
+ - CCLayerTreeHostTestAtomicCommitWithPartialUpdate.runMultiThread
+ - TiledLayerChromiumTest.partialUpdates
+
+ * platform/graphics/chromium/TiledLayerChromium.cpp:
+ (WebCore::UpdatableTile::UpdatableTile):
+ (UpdatableTile):
+ (WebCore::TiledLayerChromium::updateCompositorResources):
+ (WebCore):
+ (WebCore::TiledLayerChromium::tileOnlyNeedsPartialUpdate):
+ (WebCore::TiledLayerChromium::tileNeedsBufferedUpdate):
+ (WebCore::TiledLayerChromium::prepareToUpdateTiles):
+ * platform/graphics/chromium/TiledLayerChromium.h:
+ (TiledLayerChromium):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.cpp:
+ (WebCore::CCLayerTreeHost::CCLayerTreeHost):
+ (WebCore::CCLayerTreeHost::initializeLayerRenderer):
+ (WebCore::CCLayerTreeHost::updateLayers):
+ (WebCore::CCLayerTreeHost::requestPartialTextureUpdate):
+ (WebCore):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.h:
+ (WebCore::CCSettings::CCSettings):
+ (CCSettings):
+ (CCLayerTreeHost):
+ * platform/graphics/chromium/cc/CCProxy.h:
+ (CCProxy):
+ * platform/graphics/chromium/cc/CCSingleThreadProxy.cpp:
+ (WebCore::CCSingleThreadProxy::doCommit):
+ * platform/graphics/chromium/cc/CCSingleThreadProxy.h:
+ (WebCore::CCSingleThreadProxy::maxPartialTextureUpdates):
+ * platform/graphics/chromium/cc/CCTextureUpdater.cpp:
+ (WebCore::CCTextureUpdater::append):
+ (WebCore):
+ (WebCore::CCTextureUpdater::appendPartial):
+ (WebCore::CCTextureUpdater::hasMoreUpdates):
+ (WebCore::CCTextureUpdater::update):
+ (WebCore::CCTextureUpdater::clear):
+ * platform/graphics/chromium/cc/CCTextureUpdater.h:
+ (CCTextureUpdater):
+ * platform/graphics/chromium/cc/CCThreadProxy.cpp:
+ (WTF):
+ (WebCore::CCThreadProxy::scheduledActionUpdateMoreResources):
+ (WebCore::CCThreadProxy::maxPartialTextureUpdates):
+ * platform/graphics/chromium/cc/CCThreadProxy.h:
+ (CCThreadProxy):
+
2012-02-07 MORITA Hajime <morrita@google.com>
Replacement text should be available from the marker.
class UpdatableTile : public CCLayerTilingData::Tile {
WTF_MAKE_NONCOPYABLE(UpdatableTile);
public:
- explicit UpdatableTile(PassOwnPtr<LayerTextureUpdater::Texture> texture) : m_texture(texture) { }
+ explicit UpdatableTile(PassOwnPtr<LayerTextureUpdater::Texture> texture)
+ : m_partialUpdate(false)
+ , m_texture(texture)
+ {
+ }
LayerTextureUpdater::Texture* texture() { return m_texture.get(); }
ManagedTexture* managedTexture() { return m_texture->texture(); }
IntRect m_dirtyRect;
IntRect m_updateRect;
IntRect m_opaqueRect;
+ bool m_partialUpdate;
private:
OwnPtr<LayerTextureUpdater::Texture> m_texture;
};
if (paintOffset.y() + destRect.height() > m_paintRect.height())
CRASH();
- updater.append(tile->texture(), sourceRect, destRect);
+ if (tile->m_partialUpdate)
+ updater.appendPartial(tile->texture(), sourceRect, destRect);
+ else
+ updater.append(tile->texture(), sourceRect, destRect);
}
}
}
}
+// Returns true if tile is dirty and only part of it needs to be updated.
+bool TiledLayerChromium::tileOnlyNeedsPartialUpdate(UpdatableTile* tile)
+{
+ if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat))
+ return false;
+
+ if (!tile->isDirty())
+ return false;
+
+ return !tile->m_dirtyRect.contains(m_tiler->tileRect(tile));
+}
+
+// Dirty tiles with valid textures needs buffered update to guarantee that
+// we don't modify textures currently used for drawing by the impl thread.
+bool TiledLayerChromium::tileNeedsBufferedUpdate(UpdatableTile* tile)
+{
+ // No impl thread?.
+ if (!CCProxy::hasImplThread())
+ return false;
+
+ if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat))
+ return false;
+
+ if (!tile->isDirty())
+ return false;
+
+ return true;
+}
+
void TiledLayerChromium::prepareToUpdateTiles(bool idle, int left, int top, int right, int bottom)
{
// Reset m_updateRect for all tiles.
for (CCLayerTilingData::TileMap::const_iterator iter = m_tiler->tiles().begin(); iter != m_tiler->tiles().end(); ++iter) {
UpdatableTile* tile = static_cast<UpdatableTile*>(iter->second.get());
tile->m_updateRect = IntRect();
+ tile->m_partialUpdate = false;
}
createTextureUpdaterIfNeeded();
if (!tile)
tile = createTile(i, j);
- // Do post commit deletion of current texture when partial texture
- // updates are not used.
- if (tile->isDirty() && layerTreeHost() && !layerTreeHost()->settings().partialTextureUpdates)
+ // FIXME: Decide if partial update should be allowed based on cost
+ // of update. https://bugs.webkit.org/show_bug.cgi?id=77376
+ if (tileOnlyNeedsPartialUpdate(tile) && layerTreeHost() && layerTreeHost()->requestPartialTextureUpdate())
+ tile->m_partialUpdate = true;
+ else if (tileNeedsBufferedUpdate(tile) && layerTreeHost())
layerTreeHost()->deleteTextureAfterCommit(tile->managedTexture()->steal());
if (!tile->managedTexture()->isValid(m_tiler->tileSize(), m_textureFormat))
void createTilerIfNeeded();
void setTilingOption(TilingOption);
+ bool tileOnlyNeedsPartialUpdate(UpdatableTile*);
+ bool tileNeedsBufferedUpdate(UpdatableTile*);
+
void prepareToUpdateTiles(bool idle, int left, int top, int right, int bottom);
IntRect idlePaintRect(const IntRect& visibleLayerRect);
#include "cc/CCThread.h"
#include "cc/CCThreadProxy.h"
+using namespace std;
+
namespace {
static int numLayerTreeInstances;
}
, m_minPageScale(1)
, m_maxPageScale(1)
, m_triggerIdlePaints(true)
+ , m_partialTextureUpdateRequests(0)
{
ASSERT(CCProxy::isMainThread());
numLayerTreeInstances++;
m_settings.acceleratePainting = m_proxy->layerRendererCapabilities().usingAcceleratedPainting;
// Update m_settings based on partial update capability.
- m_settings.partialTextureUpdates = m_settings.partialTextureUpdates && m_proxy->partialTextureUpdateCapability();
+ m_settings.maxPartialTextureUpdates = min(m_settings.maxPartialTextureUpdates, m_proxy->maxPartialTextureUpdates());
m_contentsTextureManager = TextureManager::create(TextureManager::highLimitBytes(viewportSize()),
TextureManager::reclaimLimitBytes(viewportSize()),
CCLayerTreeHostCommon::calculateDrawTransformsAndVisibility(rootLayer, rootLayer, identityMatrix, identityMatrix, m_updateList, rootRenderSurface->layerList(), layerRendererCapabilities().maxTextureSize);
}
+ // Reset partial texture update requests.
+ m_partialTextureUpdateRequests = 0;
+
reserveTextures();
paintLayerContents(m_updateList, PaintVisible);
}
}
+bool CCLayerTreeHost::requestPartialTextureUpdate()
+{
+ if (m_partialTextureUpdateRequests >= m_settings.maxPartialTextureUpdates)
+ return false;
+
+ m_partialTextureUpdateRequests++;
+ return true;
+}
+
void CCLayerTreeHost::deleteTextureAfterCommit(PassOwnPtr<ManagedTexture> texture)
{
m_deleteTextureAfterCommitList.append(texture);
#include "cc/CCLayerTreeHostCommon.h"
#include "cc/CCProxy.h"
+#include <limits>
#include <wtf/HashMap.h>
#include <wtf/PassOwnPtr.h>
#include <wtf/PassRefPtr.h>
, refreshRate(0)
, perTilePainting(false)
, partialSwapEnabled(false)
- , partialTextureUpdates(true) { }
+ , maxPartialTextureUpdates(std::numeric_limits<size_t>::max()) { }
bool acceleratePainting;
bool compositeOffscreen;
double refreshRate;
bool perTilePainting;
bool partialSwapEnabled;
- bool partialTextureUpdates;
+ size_t maxPartialTextureUpdates;
};
// Provides information on an Impl's rendering capabilities back to the CCLayerTreeHost
void startRateLimiter(GraphicsContext3D*);
void stopRateLimiter(GraphicsContext3D*);
+ bool requestPartialTextureUpdate();
void deleteTextureAfterCommit(PassOwnPtr<ManagedTexture>);
protected:
bool m_triggerIdlePaints;
TextureList m_deleteTextureAfterCommitList;
+ size_t m_partialTextureUpdateRequests;
};
}
virtual void start() = 0; // Must be called before using the proxy.
virtual void stop() = 0; // Must be called before deleting the proxy.
- // Whether sub-regions of textures can be updated or if complete texture
- // updates are required.
- virtual bool partialTextureUpdateCapability() const = 0;
+ // Maximum number of sub-region texture updates supported for each commit.
+ virtual size_t maxPartialTextureUpdates() const = 0;
// Debug hooks
#ifndef NDEBUG
#include "cc/CCTextureUpdater.h"
#include <wtf/CurrentTime.h>
+using namespace std;
using namespace WTF;
namespace WebCore {
m_layerTreeHost->beginCommitOnImplThread(m_layerTreeHostImpl.get());
CCTextureUpdater updater(m_layerTreeHostImpl->contentsTextureAllocator());
m_layerTreeHost->updateCompositorResources(m_layerTreeHostImpl->context(), updater);
- while (updater.update(m_layerTreeHostImpl->context(), 1)) { }
+ updater.update(m_layerTreeHostImpl->context(), numeric_limits<size_t>::max());
+ ASSERT(!updater.hasMoreUpdates());
m_layerTreeHostImpl->setVisible(m_layerTreeHost->visible());
m_layerTreeHost->finishCommitOnImplThread(m_layerTreeHostImpl.get());
#include "cc/CCCompletionEvent.h"
#include "cc/CCLayerTreeHostImpl.h"
#include "cc/CCProxy.h"
+#include <limits>
#include <wtf/OwnPtr.h>
namespace WebCore {
virtual void setVisible(bool);
virtual void start();
virtual void stop();
- virtual bool partialTextureUpdateCapability() const { return true; }
+ virtual size_t maxPartialTextureUpdates() const { return std::numeric_limits<size_t>::max(); }
// CCLayerTreeHostImplClient implementation
virtual void onSwapBuffersCompleteOnImplThread() { ASSERT_NOT_REACHED(); }
{
}
-void CCTextureUpdater::append(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect)
+void CCTextureUpdater::append(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect, Vector<UpdateEntry>& entries)
{
ASSERT(texture);
entry.m_texture = texture;
entry.m_sourceRect = sourceRect;
entry.m_destRect = destRect;
- m_entries.append(entry);
+ entries.append(entry);
+}
+
+void CCTextureUpdater::append(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect)
+{
+ append(texture, sourceRect, destRect, m_entries);
+}
+
+void CCTextureUpdater::appendPartial(LayerTextureUpdater::Texture* texture, const IntRect& sourceRect, const IntRect& destRect)
+{
+ append(texture, sourceRect, destRect, m_partialEntries);
}
bool CCTextureUpdater::hasMoreUpdates() const
{
- return m_entries.size();
+ return m_entries.size() || m_partialEntries.size();
}
bool CCTextureUpdater::update(GraphicsContext3D* context, size_t count)
{
+ size_t index;
size_t maxIndex = min(m_entryIndex + count, m_entries.size());
- for (; m_entryIndex < maxIndex; ++m_entryIndex) {
- UpdateEntry& entry = m_entries[m_entryIndex];
+ for (index = m_entryIndex; index < maxIndex; ++index) {
+ UpdateEntry& entry = m_entries[index];
entry.m_texture->updateRect(context, m_allocator, entry.m_sourceRect, entry.m_destRect);
}
- if (maxIndex < m_entries.size())
+ bool moreUpdates = maxIndex < m_entries.size();
+
+ ASSERT(m_partialEntries.size() <= count);
+ // Make sure the number of updates including partial updates are not more
+ // than |count|.
+ if ((count - (index - m_entryIndex)) < m_partialEntries.size())
+ moreUpdates = true;
+
+ if (moreUpdates) {
+ m_entryIndex = index;
return true;
+ }
+
+ for (index = 0; index < m_partialEntries.size(); ++index) {
+ UpdateEntry& entry = m_partialEntries[index];
+ entry.m_texture->updateRect(context, m_allocator, entry.m_sourceRect, entry.m_destRect);
+ }
// If no entries left to process, auto-clear.
clear();
{
m_entryIndex = 0;
m_entries.clear();
+ m_partialEntries.clear();
}
}
~CCTextureUpdater();
void append(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect);
+ void appendPartial(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect);
bool hasMoreUpdates() const;
IntRect m_destRect;
};
+ static void append(LayerTextureUpdater::Texture*, const IntRect& sourceRect, const IntRect& destRect, Vector<UpdateEntry>&);
+
TextureAllocator* m_allocator;
size_t m_entryIndex;
Vector<UpdateEntry> m_entries;
+ Vector<UpdateEntry> m_partialEntries;
};
}
namespace {
-static const size_t textureUpdatesPerFrame = 0;
+// Number of textures to update with each call to
+// scheduledActionUpdateMoreResources().
+static const size_t textureUpdatesPerFrame = 5;
} // anonymous namespace
{
TRACE_EVENT("CCThreadProxy::scheduledActionUpdateMoreResources", this, 0);
ASSERT(m_currentTextureUpdaterOnImplThread);
- m_currentTextureUpdaterOnImplThread->update(m_layerTreeHostImpl->context(), textureUpdatesPerFrame > 0 ? textureUpdatesPerFrame : 99999);
+ m_currentTextureUpdaterOnImplThread->update(m_layerTreeHostImpl->context(), textureUpdatesPerFrame);
}
void CCThreadProxy::scheduledActionCommit()
completion->signal();
}
-bool CCThreadProxy::partialTextureUpdateCapability() const
+size_t CCThreadProxy::maxPartialTextureUpdates() const
{
- return !textureUpdatesPerFrame;
+ return textureUpdatesPerFrame;
}
} // namespace WebCore
virtual void setVisible(bool);
virtual void start();
virtual void stop();
- virtual bool partialTextureUpdateCapability() const;
+ virtual size_t maxPartialTextureUpdates() const;
// CCLayerTreeHostImplClient implementation
virtual void onSwapBuffersCompleteOnImplThread();
+2012-02-08 David Reveman <reveman@chromium.org>
+
+ [Chromium] Avoid unnecessary full tile updates without breaking atomicity of commits.
+ https://bugs.webkit.org/show_bug.cgi?id=76740
+
+ Reviewed by James Robinson.
+
+ Add CCLayerTreeHostTestAtomicCommitWithPartialUpdate and
+ TiledLayerChromiumTest.partialUpdates tests that verifies
+ atomicity of commits with partial updates.
+
+ * tests/CCLayerTreeHostTest.cpp:
+ (WTF::CCLayerTreeHostTestAtomicCommit::CCLayerTreeHostTestAtomicCommit):
+ (WTF::CCLayerTreeHostTestAtomicCommit::beginTest):
+ (WTF::CCLayerTreeHostTestAtomicCommit::commitCompleteOnCCThread):
+ (WTF::CCLayerTreeHostTestAtomicCommit::layout):
+ (CCLayerTreeHostTestAtomicCommit):
+ (CCLayerTreeHostTestAtomicCommitWithPartialUpdate):
+ (WTF::CCLayerTreeHostTestAtomicCommitWithPartialUpdate::CCLayerTreeHostTestAtomicCommitWithPartialUpdate):
+ (WTF::CCLayerTreeHostTestAtomicCommitWithPartialUpdate::beginTest):
+ (WTF::CCLayerTreeHostTestAtomicCommitWithPartialUpdate::commitCompleteOnCCThread):
+ (WTF::CCLayerTreeHostTestAtomicCommitWithPartialUpdate::drawLayersOnCCThread):
+ (WTF::CCLayerTreeHostTestAtomicCommitWithPartialUpdate::layout):
+ (WTF::CCLayerTreeHostTestAtomicCommitWithPartialUpdate::afterTest):
+ (WTF):
+ (WTF::TEST_F):
+ * tests/TiledLayerChromiumTest.cpp:
+ (WTF::FakeLayerTextureUpdater::Texture::Texture):
+ (WTF::FakeLayerTextureUpdater::Texture::updateRect):
+ (Texture):
+ (WTF::FakeLayerTextureUpdater::FakeLayerTextureUpdater):
+ (FakeLayerTextureUpdater):
+ (WTF::FakeLayerTextureUpdater::updateCount):
+ (WTF::FakeLayerTextureUpdater::clearUpdateCount):
+ (WTF::FakeLayerTextureUpdater::updateRect):
+ (WTF::FakeLayerTextureUpdater::createTexture):
+ (FakeTiledLayerChromium):
+ (WTF::TEST):
+ (WTF):
+
2012-02-07 MORITA Hajime <morrita@google.com>
Replacement text should be available from the marker.
class CCLayerTreeHostTestAtomicCommit : public CCLayerTreeHostTest {
public:
CCLayerTreeHostTestAtomicCommit()
- : m_updateCheckLayer(ContentLayerChromiumWithUpdateTracking::create(&m_delegate))
- , m_numCommits(0)
+ : m_layer(ContentLayerChromiumWithUpdateTracking::create(&m_delegate))
{
// Make sure partial texture updates are turned off.
- m_settings.partialTextureUpdates = false;
+ m_settings.maxPartialTextureUpdates = 0;
}
virtual void beginTest()
{
- m_layerTreeHost->setRootLayer(m_updateCheckLayer);
+ m_layerTreeHost->setRootLayer(m_layer);
m_layerTreeHost->setViewportSize(IntSize(10, 10));
postSetNeedsCommitToMainThread();
EXPECT_EQ(1, context->numTextures());
// Number of textures used for commit should be one.
EXPECT_EQ(1, context->numUsedTextures());
- // Verify used texture is correct.
+ // Verify that used texture is correct.
EXPECT_TRUE(context->usedTexture(context->texture(0)));
context->resetUsedTextures();
virtual void layout()
{
- m_updateCheckLayer->setNeedsDisplay();
+ m_layer->setNeedsDisplay();
}
virtual void afterTest()
private:
MockContentLayerDelegate m_delegate;
- RefPtr<ContentLayerChromiumWithUpdateTracking> m_updateCheckLayer;
- int m_numCommits;
+ RefPtr<ContentLayerChromiumWithUpdateTracking> m_layer;
};
TEST_F(CCLayerTreeHostTestAtomicCommit, runMultiThread)
runTest(true);
}
+class CCLayerTreeHostTestAtomicCommitWithPartialUpdate : public CCLayerTreeHostTest {
+public:
+ CCLayerTreeHostTestAtomicCommitWithPartialUpdate()
+ : m_parent(ContentLayerChromiumWithUpdateTracking::create(&m_delegate))
+ , m_child(ContentLayerChromiumWithUpdateTracking::create(&m_delegate))
+ , m_numCommits(0)
+ {
+ // Allow one partial texture update.
+ m_settings.maxPartialTextureUpdates = 1;
+ }
+
+ virtual void beginTest()
+ {
+ m_layerTreeHost->setRootLayer(m_parent);
+ m_layerTreeHost->setViewportSize(IntSize(10, 10));
+ m_parent->addChild(m_child);
+ m_child->setOpacity(0.5);
+ m_child->setBounds(IntSize(20, 20));
+
+ postSetNeedsCommitToMainThread();
+ postSetNeedsRedrawToMainThread();
+ }
+
+ virtual void commitCompleteOnCCThread(CCLayerTreeHostImpl* impl)
+ {
+ CompositorFakeWebGraphicsContext3DWithTextureTracking* context = static_cast<CompositorFakeWebGraphicsContext3DWithTextureTracking*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(impl->context()));
+
+ switch (impl->frameNumber()) {
+ case 0:
+ // Number of textures should be two.
+ EXPECT_EQ(2, context->numTextures());
+ // Number of textures used for commit should be two.
+ EXPECT_EQ(2, context->numUsedTextures());
+ // Verify that used textures are correct.
+ EXPECT_TRUE(context->usedTexture(context->texture(0)));
+ EXPECT_TRUE(context->usedTexture(context->texture(1)));
+
+ context->resetUsedTextures();
+ break;
+ case 1:
+ // Number of textures should be four as the first two
+ // textures are used by the impl thread.
+ EXPECT_EQ(4, context->numTextures());
+ // Number of textures used for commit should still be two.
+ EXPECT_EQ(2, context->numUsedTextures());
+ // First two textures should not have been used.
+ EXPECT_FALSE(context->usedTexture(context->texture(0)));
+ EXPECT_FALSE(context->usedTexture(context->texture(1)));
+ // New textures should have been used.
+ EXPECT_TRUE(context->usedTexture(context->texture(2)));
+ EXPECT_TRUE(context->usedTexture(context->texture(3)));
+
+ context->resetUsedTextures();
+ break;
+ case 2:
+ // Number of textures should be three as we allow one
+ // partial update and the first two textures are used by
+ // the impl thread.
+ EXPECT_EQ(3, context->numTextures());
+ // Number of textures used for commit should still be two.
+ EXPECT_EQ(2, context->numUsedTextures());
+ // First texture should not have been used.
+ EXPECT_FALSE(context->usedTexture(context->texture(0)));
+ // Second texture should have been used.
+ EXPECT_TRUE(context->usedTexture(context->texture(1)));
+ // New textures should have been used.
+ EXPECT_TRUE(context->usedTexture(context->texture(2)));
+
+ context->resetUsedTextures();
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+
+ virtual void drawLayersOnCCThread(CCLayerTreeHostImpl* impl)
+ {
+ CompositorFakeWebGraphicsContext3DWithTextureTracking* context = static_cast<CompositorFakeWebGraphicsContext3DWithTextureTracking*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(impl->context()));
+
+ // Number of textures used for drawing should always be two.
+ EXPECT_EQ(2, context->numUsedTextures());
+
+ if (impl->frameNumber() < 3) {
+ context->resetUsedTextures();
+ postSetNeedsAnimateAndCommitToMainThread();
+ postSetNeedsRedrawToMainThread();
+ } else
+ endTest();
+ }
+
+ virtual void layout()
+ {
+ switch (m_numCommits++) {
+ case 0:
+ case 1:
+ m_parent->setNeedsDisplay();
+ m_child->setNeedsDisplay();
+ break;
+ case 2:
+ // Damage part of layers.
+ m_parent->setNeedsDisplayRect(FloatRect(0, 0, 5, 5));
+ m_child->setNeedsDisplayRect(FloatRect(0, 0, 5, 5));
+ break;
+ default:
+ ASSERT_NOT_REACHED();
+ break;
+ }
+ }
+
+ virtual void afterTest()
+ {
+ }
+
+private:
+ MockContentLayerDelegate m_delegate;
+ RefPtr<ContentLayerChromiumWithUpdateTracking> m_parent;
+ RefPtr<ContentLayerChromiumWithUpdateTracking> m_child;
+ int m_numCommits;
+};
+
+TEST_F(CCLayerTreeHostTestAtomicCommitWithPartialUpdate, runMultiThread)
+{
+ runTest(true);
+}
+
#define EXPECT_EQ_RECT(a, b) \
EXPECT_EQ(a.x(), b.x()); \
EXPECT_EQ(a.y(), b.y()); \
public:
class Texture : public LayerTextureUpdater::Texture {
public:
- Texture(PassOwnPtr<ManagedTexture> texture) : LayerTextureUpdater::Texture(texture) { }
+ Texture(FakeLayerTextureUpdater* layer, PassOwnPtr<ManagedTexture> texture)
+ : LayerTextureUpdater::Texture(texture)
+ , m_layer(layer)
+ {
+ }
virtual ~Texture() { }
- virtual void updateRect(GraphicsContext3D*, TextureAllocator*, const IntRect&, const IntRect&) { }
+ virtual void updateRect(GraphicsContext3D*, TextureAllocator*, const IntRect&, const IntRect&) { m_layer->updateRect(); }
+
+ private:
+ FakeLayerTextureUpdater* m_layer;
};
- FakeLayerTextureUpdater() : m_prepareCount(0) { }
+ FakeLayerTextureUpdater()
+ : m_prepareCount(0)
+ , m_updateCount(0)
+ {
+ }
virtual ~FakeLayerTextureUpdater() { }
// Sets the rect to invalidate during the next call to prepareToUpdate(). After the next
int prepareCount() const { return m_prepareCount; }
void clearPrepareCount() { m_prepareCount = 0; }
+ // Number of times updateRect has been invoked.
+ int updateCount() const { return m_updateCount; }
+ void clearUpdateCount() { m_updateCount = 0; }
+ void updateRect() { m_updateCount++; }
+
void setOpaquePaintRect(const IntRect& opaquePaintRect) { m_opaquePaintRect = opaquePaintRect; }
// Last rect passed to prepareToUpdate().
const IntRect& lastUpdateRect() const { return m_lastUpdateRect; }
- virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager* manager) { return adoptPtr(new Texture(ManagedTexture::create(manager))); }
+ virtual PassOwnPtr<LayerTextureUpdater::Texture> createTexture(TextureManager* manager) { return adoptPtr(new Texture(this, ManagedTexture::create(manager))); }
virtual SampledTexelFormat sampledTexelFormat(GC3Denum) { return SampledTexelFormatRGBA; }
virtual void prepareToUpdate(const IntRect& contentRect, const IntSize&, int, float, IntRect* resultingOpaqueRect);
private:
int m_prepareCount;
+ int m_updateCount;
IntRect m_rectToInvalidate;
IntRect m_lastUpdateRect;
IntRect m_opaquePaintRect;
}
private:
- virtual void createTextureUpdater(const CCLayerTreeHost*) { }
-
virtual LayerTextureUpdater* textureUpdater() const
{
return m_fakeTextureUpdater.get();
layer->invalidateRect(IntRect(0, 0, 200, 200));
}
+TEST(TiledLayerChromiumTest, partialUpdates)
+{
+ CCSettings settings;
+ settings.maxPartialTextureUpdates = 4;
+ // Initialize without threading support.
+ WebKit::WebCompositor::initialize(0);
+ FakeCCLayerTreeHostClient fakeCCLayerTreeHostClient;
+ RefPtr<CCLayerTreeHost> ccLayerTreeHost = CCLayerTreeHost::create(&fakeCCLayerTreeHostClient, settings);
+
+ // Create one 500 x 300 tiled layer.
+ IntSize contentBounds(300, 200);
+ IntRect contentRect(IntPoint::zero(), contentBounds);
+
+ OwnPtr<TextureManager> textureManager = TextureManager::create(60*1024*1024, 60*1024*1024, 1024);
+ RefPtr<FakeTiledLayerChromium> layer = adoptRef(new FakeTiledLayerChromium(textureManager.get()));
+ layer->setBounds(contentBounds);
+ layer->setPosition(FloatPoint(150, 150));
+ layer->invalidateRect(contentRect);
+
+ FakeTextureAllocator textureAllocator;
+ CCTextureUpdater updater(&textureAllocator);
+
+ ccLayerTreeHost->setRootLayer(layer);
+ ccLayerTreeHost->setViewportSize(IntSize(300, 200));
+
+ // Full update of all 6 tiles.
+ ccLayerTreeHost->updateLayers();
+ ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
+ updater.update(0, 4);
+ EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_TRUE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ updater.update(0, 4);
+ EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_FALSE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ ccLayerTreeHost->commitComplete();
+
+ // Full update of 3 tiles and partial update of 3 tiles.
+ layer->invalidateRect(IntRect(0, 0, 300, 150));
+ ccLayerTreeHost->updateLayers();
+ ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
+ updater.update(0, 4);
+ EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_TRUE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ updater.update(0, 4);
+ EXPECT_EQ(3, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_FALSE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ ccLayerTreeHost->commitComplete();
+
+ // Partial update of 6 tiles.
+ layer->invalidateRect(IntRect(50, 50, 200, 100));
+ ccLayerTreeHost->updateLayers();
+ ccLayerTreeHost->updateCompositorResources(ccLayerTreeHost->context(), updater);
+ updater.update(0, 4);
+ EXPECT_EQ(2, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_TRUE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ updater.update(0, 4);
+ EXPECT_EQ(4, layer->fakeLayerTextureUpdater()->updateCount());
+ EXPECT_FALSE(updater.hasMoreUpdates());
+ layer->fakeLayerTextureUpdater()->clearUpdateCount();
+ ccLayerTreeHost->commitComplete();
+
+ ccLayerTreeHost->setRootLayer(0);
+ ccLayerTreeHost.clear();
+ WebKit::WebCompositor::shutdown();
+}
+
} // namespace