Diff
Modified: trunk/Source/WebCore/ChangeLog (111776 => 111777)
--- trunk/Source/WebCore/ChangeLog 2012-03-22 22:43:16 UTC (rev 111776)
+++ trunk/Source/WebCore/ChangeLog 2012-03-22 22:43:19 UTC (rev 111777)
@@ -1,3 +1,46 @@
+2012-03-22 Michal Mocny <mmo...@google.com>
+
+ [chromium] LayerRendererChromium should use GpuMemoryAllocationChanged callback to explicitly manage framebuffer.
+ https://bugs.webkit.org/show_bug.cgi?id=81823
+
+ Reviewed by Adrienne Walker.
+
+ New UnitTests: LayerRendererChromiumTest
+
+ * platform/graphics/chromium/LayerRendererChromium.cpp:
+ (LayerRendererGpuMemoryAllocationChangedCallbackAdapter):
+ (WebCore::LayerRendererGpuMemoryAllocationChangedCallbackAdapter::create):
+ (WebCore::LayerRendererGpuMemoryAllocationChangedCallbackAdapter::~LayerRendererGpuMemoryAllocationChangedCallbackAdapter):
+ (WebCore::LayerRendererGpuMemoryAllocationChangedCallbackAdapter::onGpuMemoryAllocationChanged):
+ (WebCore::LayerRendererGpuMemoryAllocationChangedCallbackAdapter::LayerRendererGpuMemoryAllocationChangedCallbackAdapter):
+ (WebCore):
+ (WebCore::LayerRendererChromium::LayerRendererChromium):
+ (WebCore::LayerRendererChromium::initialize):
+ (WebCore::LayerRendererChromium::~LayerRendererChromium):
+ (WebCore::LayerRendererChromium::setVisible):
+ (WebCore::LayerRendererChromium::swapBuffers):
+ (WebCore::LayerRendererChromium::discardFramebuffer):
+ (WebCore::LayerRendererChromium::ensureFramebuffer):
+ * platform/graphics/chromium/LayerRendererChromium.h:
+ (WebCore):
+ (LayerRendererChromiumClient):
+ (LayerRendererChromium):
+ (WebCore::LayerRendererChromium::isFramebufferDiscarded):
+ (ScopedEnsureFramebufferAllocation):
+ (WebCore::ScopedEnsureFramebufferAllocation::ScopedEnsureFramebufferAllocation):
+ (WebCore::ScopedEnsureFramebufferAllocation::~ScopedEnsureFramebufferAllocation):
+ * platform/graphics/chromium/cc/CCLayerTreeHost.h:
+ (WebCore::LayerRendererCapabilities::LayerRendererCapabilities):
+ (LayerRendererCapabilities):
+ * platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp:
+ (WebCore::CCLayerTreeHostImpl::setVisible):
+ * platform/graphics/chromium/cc/CCLayerTreeHostImpl.h:
+ (CCLayerTreeHostImpl):
+ * platform/graphics/chromium/cc/CCSingleThreadProxy.cpp:
+ (WebCore::CCSingleThreadProxy::compositeAndReadback):
+ * platform/graphics/chromium/cc/CCThreadProxy.cpp:
+ (WebCore::CCThreadProxy::compositeAndReadback):
+
2012-03-22 Adam Barth <aba...@webkit.org>
ContainerNode::insertedIntoTree and removedFromTree use weak iteration patterns
Modified: trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp (111776 => 111777)
--- trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp 2012-03-22 22:43:16 UTC (rev 111776)
+++ trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp 2012-03-22 22:43:19 UTC (rev 111777)
@@ -165,7 +165,32 @@
LayerRendererChromium* m_layerRenderer;
};
+class LayerRendererGpuMemoryAllocationChangedCallbackAdapter : public Extensions3DChromium::GpuMemoryAllocationChangedCallbackCHROMIUM {
+public:
+ static PassOwnPtr<LayerRendererGpuMemoryAllocationChangedCallbackAdapter> create(LayerRendererChromium* layerRenderer)
+ {
+ return adoptPtr(new LayerRendererGpuMemoryAllocationChangedCallbackAdapter(layerRenderer));
+ }
+ virtual ~LayerRendererGpuMemoryAllocationChangedCallbackAdapter() { }
+ virtual void onGpuMemoryAllocationChanged(Extensions3DChromium::GpuMemoryAllocationCHROMIUM allocation)
+ {
+ if (!allocation.suggestHaveBackbuffer)
+ m_layerRenderer->discardFramebuffer();
+ else
+ m_layerRenderer->ensureFramebuffer();
+ }
+
+private:
+ explicit LayerRendererGpuMemoryAllocationChangedCallbackAdapter(LayerRendererChromium* layerRenderer)
+ : m_layerRenderer(layerRenderer)
+ {
+ }
+
+ LayerRendererChromium* m_layerRenderer;
+};
+
+
PassOwnPtr<LayerRendererChromium> LayerRendererChromium::create(LayerRendererChromiumClient* client, PassRefPtr<GraphicsContext3D> context)
{
OwnPtr<LayerRendererChromium> layerRenderer(adoptPtr(new LayerRendererChromium(client, context)));
@@ -184,6 +209,7 @@
, m_defaultRenderSurface(0)
, m_sharedGeometryQuad(FloatRect(-0.5f, -0.5f, 1.0f, 1.0f))
, m_isViewportChanged(false)
+ , m_isFramebufferDiscarded(false)
{
}
@@ -259,6 +285,17 @@
if (m_capabilities.usingTextureStorageExtension)
extensions->ensureEnabled("GL_EXT_texture_storage");
+ m_capabilities.usingGpuMemoryManager = extensions->supports("GL_CHROMIUM_gpu_memory_manager");
+ if (m_capabilities.usingGpuMemoryManager) {
+ extensions->ensureEnabled("GL_CHROMIUM_gpu_memory_manager");
+ Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
+ extensions3DChromium->setGpuMemoryAllocationChangedCallbackCHROMIUM(LayerRendererGpuMemoryAllocationChangedCallbackAdapter::create(this));
+ }
+
+ m_capabilities.usingDiscardFramebuffer = extensions->supports("GL_CHROMIUM_discard_framebuffer");
+ if (m_capabilities.usingDiscardFramebuffer)
+ extensions->ensureEnabled("GL_CHROMIUM_discard_framebuffer");
+
GLC(m_context.get(), m_context->getIntegerv(GraphicsContext3D::MAX_TEXTURE_SIZE, &m_capabilities.maxTextureSize));
m_capabilities.bestTextureFormat = PlatformColor::bestTextureFormat(m_context.get());
@@ -277,6 +314,7 @@
ASSERT(CCProxy::isImplThread());
Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(m_context->getExtensions());
extensions3DChromium->setSwapBuffersCompleteCallbackCHROMIUM(nullptr);
+ extensions3DChromium->setGpuMemoryAllocationChangedCallbackCHROMIUM(nullptr);
m_headsUpDisplay.clear(); // Explicitly destroy the HUD before the TextureManager dies.
cleanupSharedObjects();
}
@@ -311,6 +349,10 @@
if (!visible)
releaseRenderSurfaceTextures();
+ // FIXME: Remove this once framebuffer is automatically recreated on first use
+ if (visible)
+ ensureFramebuffer();
+
// TODO: Replace setVisibilityCHROMIUM with an extension to explicitly manage front/backbuffers
// crbug.com/116049
if (m_capabilities.usingSetVisibility) {
@@ -1031,6 +1073,13 @@
void LayerRendererChromium::swapBuffers(const IntRect& subBuffer)
{
+ // FIXME: Remove this once gpu process supports ignoring swap buffers command while framebuffer is discarded.
+ // Alternatively (preferably?), protect all cc code so as not to attempt a swap after a framebuffer discard.
+ if (m_isFramebufferDiscarded) {
+ m_client->setFullRootLayerDamage();
+ return;
+ }
+
TRACE_EVENT("LayerRendererChromium::swapBuffers", this, 0);
// We're done! Time to swapbuffers!
@@ -1054,6 +1103,38 @@
m_client->onSwapBuffersComplete();
}
+void LayerRendererChromium::discardFramebuffer()
+{
+ if (m_isFramebufferDiscarded)
+ return;
+
+ if (!m_capabilities.usingDiscardFramebuffer)
+ return;
+
+ Extensions3D* extensions = m_context->getExtensions();
+ Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
+ // FIXME: Update attachments argument to appropriate values once they are no longer ignored.
+ extensions3DChromium->discardFramebufferEXT(GraphicsContext3D::TEXTURE_2D, 0, 0);
+ m_isFramebufferDiscarded = true;
+
+ // Damage tracker needs a full reset every time framebuffer is discarded.
+ m_client->setFullRootLayerDamage();
+}
+
+void LayerRendererChromium::ensureFramebuffer()
+{
+ if (!m_isFramebufferDiscarded)
+ return;
+
+ if (!m_capabilities.usingDiscardFramebuffer)
+ return;
+
+ Extensions3D* extensions = m_context->getExtensions();
+ Extensions3DChromium* extensions3DChromium = static_cast<Extensions3DChromium*>(extensions);
+ extensions3DChromium->ensureFramebufferCHROMIUM();
+ m_isFramebufferDiscarded = false;
+}
+
void LayerRendererChromium::getFramebufferPixels(void *pixels, const IntRect& rect)
{
ASSERT(rect.maxX() <= viewportWidth() && rect.maxY() <= viewportHeight());
Modified: trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h (111776 => 111777)
--- trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h 2012-03-22 22:43:16 UTC (rev 111776)
+++ trunk/Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h 2012-03-22 22:43:19 UTC (rev 111777)
@@ -61,6 +61,7 @@
class GraphicsContext3D;
class TrackingTextureAllocator;
class LayerRendererSwapBuffersCompleteCallbackAdapter;
+class ScopedEnsureFramebufferAllocation;
class LayerRendererChromiumClient {
public:
@@ -70,6 +71,7 @@
virtual const CCLayerImpl* rootLayer() const = 0;
virtual void didLoseContext() = 0;
virtual void onSwapBuffersComplete() = 0;
+ virtual void setFullRootLayerDamage() = 0;
};
// Class that handles drawing of composited render layers using GL.
@@ -160,10 +162,15 @@
float width, float height, float opacity, const FloatQuad&,
int matrixLocation, int alphaLocation, int quadLocation);
-private:
+ void discardFramebuffer();
+ void ensureFramebuffer();
+ bool isFramebufferDiscarded() const { return m_isFramebufferDiscarded; }
+
+protected:
LayerRendererChromium(LayerRendererChromiumClient*, PassRefPtr<GraphicsContext3D>);
bool initialize();
+private:
void drawQuad(const CCDrawQuad*, const FloatRect& surfaceDamageRect);
void drawDebugBorderQuad(const CCDebugBorderDrawQuad*);
void drawRenderSurfaceQuad(const CCRenderSurfaceDrawQuad*);
@@ -254,8 +261,37 @@
FloatQuad m_sharedGeometryQuad;
bool m_isViewportChanged;
+ bool m_isFramebufferDiscarded;
};
+// The purpose of this helper is twofold:
+// 1. To ensure that a framebuffer is available for scope lifetime, and
+// 2. To reset framebuffer allocation to previous state on scope exit.
+// If the framebuffer is recreated, its contents are undefined.
+// FIXME: Prevent/delay discarding framebuffer via any means while any
+// instance of this is alive. At the moment, this isn't an issue.
+class ScopedEnsureFramebufferAllocation {
+public:
+ explicit ScopedEnsureFramebufferAllocation(LayerRendererChromium* layerRenderer)
+ : m_layerRenderer(layerRenderer)
+ , m_framebufferWasInitiallyDiscarded(layerRenderer->isFramebufferDiscarded())
+ {
+ if (m_framebufferWasInitiallyDiscarded)
+ m_layerRenderer->ensureFramebuffer();
+ }
+
+ ~ScopedEnsureFramebufferAllocation()
+ {
+ if (m_framebufferWasInitiallyDiscarded)
+ m_layerRenderer->discardFramebuffer();
+ }
+
+private:
+ LayerRendererChromium* m_layerRenderer;
+ bool m_framebufferWasInitiallyDiscarded;
+};
+
+
// Setting DEBUG_GL_CALLS to 1 will call glGetError() after almost every GL
// call made by the compositor. Useful for debugging rendering issues but
// will significantly degrade performance.
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h (111776 => 111777)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h 2012-03-22 22:43:16 UTC (rev 111776)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h 2012-03-22 22:43:19 UTC (rev 111777)
@@ -102,6 +102,8 @@
, usingSwapCompleteCallback(false)
, usingTextureUsageHint(false)
, usingTextureStorageExtension(false)
+ , usingGpuMemoryManager(false)
+ , usingDiscardFramebuffer(false)
, maxTextureSize(0) { }
GC3Denum bestTextureFormat;
@@ -113,6 +115,8 @@
bool usingSwapCompleteCallback;
bool usingTextureUsageHint;
bool usingTextureStorageExtension;
+ bool usingGpuMemoryManager;
+ bool usingDiscardFramebuffer;
int maxTextureSize;
};
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp (111776 => 111777)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp 2012-03-22 22:43:16 UTC (rev 111776)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp 2012-03-22 22:43:19 UTC (rev 111777)
@@ -480,11 +480,6 @@
m_layerRenderer->setVisible(visible);
- // Reset the damage tracker because the front/back buffers may have been damaged by the GPU
- // process on visibility change.
- if (visible && m_layerRenderer->capabilities().usingPartialSwap)
- setFullRootLayerDamage();
-
const bool shouldTickInBackground = !visible && m_needsAnimateLayers;
m_timeSourceClientAdapter->setActive(shouldTickInBackground);
}
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h (111776 => 111777)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h 2012-03-22 22:43:16 UTC (rev 111776)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h 2012-03-22 22:43:19 UTC (rev 111777)
@@ -98,6 +98,7 @@
virtual const CCLayerImpl* rootLayer() const { return m_rootLayerImpl.get(); }
virtual void didLoseContext();
virtual void onSwapBuffersComplete();
+ virtual void setFullRootLayerDamage();
// Implementation
bool canDraw();
@@ -134,10 +135,6 @@
PassOwnPtr<CCScrollAndScaleSet> processScrollDeltas();
- // Where possible, redraws are scissored to a damage region calculated from changes to
- // layer properties. This function overrides the damage region for the next draw cycle.
- void setFullRootLayerDamage();
-
void startPageScaleAnimation(const IntSize& tragetPosition, bool useAnchor, float scale, double durationSec);
bool needsAnimateLayers() const { return m_needsAnimateLayers; }
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp (111776 => 111777)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp 2012-03-22 22:43:16 UTC (rev 111776)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp 2012-03-22 22:43:19 UTC (rev 111777)
@@ -72,6 +72,8 @@
TRACE_EVENT("CCSingleThreadProxy::compositeAndReadback", this, 0);
ASSERT(CCProxy::isMainThread());
+ ScopedEnsureFramebufferAllocation ensureFramebuffer(m_layerTreeHostImpl->layerRenderer());
+
if (!commitIfNeeded())
return false;
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp (111776 => 111777)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp 2012-03-22 22:43:16 UTC (rev 111776)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp 2012-03-22 22:43:19 UTC (rev 111777)
@@ -91,6 +91,8 @@
ASSERT(isMainThread());
ASSERT(m_layerTreeHost);
+ ScopedEnsureFramebufferAllocation ensureFramebuffer(m_layerTreeHostImpl->layerRenderer());
+
if (!m_layerRendererInitialized) {
TRACE_EVENT("compositeAndReadback_EarlyOut_LR_Uninitialized", this, 0);
return false;
Modified: trunk/Source/WebKit/chromium/ChangeLog (111776 => 111777)
--- trunk/Source/WebKit/chromium/ChangeLog 2012-03-22 22:43:16 UTC (rev 111776)
+++ trunk/Source/WebKit/chromium/ChangeLog 2012-03-22 22:43:19 UTC (rev 111777)
@@ -1,3 +1,36 @@
+2012-03-22 Michal Mocny <mmo...@google.com>
+
+ [chromium] LayerRendererChromium should use GpuMemoryAllocationChanged callback to explicitly manage framebuffer.
+ https://bugs.webkit.org/show_bug.cgi?id=81823
+
+ Reviewed by Adrienne Walker.
+
+ * WebKit.gypi:
+ * tests/LayerRendererChromiumTest.cpp: Added.
+ (FrameCountingMemoryAllocationSettingContext):
+ (FrameCountingMemoryAllocationSettingContext::FrameCountingMemoryAllocationSettingContext):
+ (FrameCountingMemoryAllocationSettingContext::prepareTexture):
+ (FrameCountingMemoryAllocationSettingContext::setMemoryAllocationChangedCallbackCHROMIUM):
+ (FrameCountingMemoryAllocationSettingContext::getString):
+ (FrameCountingMemoryAllocationSettingContext::frameCount):
+ (FrameCountingMemoryAllocationSettingContext::setMemoryAllocation):
+ (FakeLayerRendererChromiumClient):
+ (FakeLayerRendererChromiumClient::FakeLayerRendererChromiumClient):
+ (FakeLayerRendererChromiumClient::viewportSize):
+ (FakeLayerRendererChromiumClient::settings):
+ (FakeLayerRendererChromiumClient::rootLayer):
+ (FakeLayerRendererChromiumClient::didLoseContext):
+ (FakeLayerRendererChromiumClient::onSwapBuffersComplete):
+ (FakeLayerRendererChromiumClient::setFullRootLayerDamage):
+ (FakeLayerRendererChromiumClient::setFullRootLayerDamageCount):
+ (FakeLayerRendererChromium):
+ (FakeLayerRendererChromium::FakeLayerRendererChromium):
+ (LayerRendererChromiumTest):
+ (LayerRendererChromiumTest::LayerRendererChromiumTest):
+ (LayerRendererChromiumTest::SetUp):
+ (LayerRendererChromiumTest::swapBuffers):
+ (TEST_F):
+
2012-03-22 Shawn Singh <shawnsi...@chromium.org>
[chromium] Make CCDamageTracker robust to empty layer lists
Modified: trunk/Source/WebKit/chromium/WebKit.gypi (111776 => 111777)
--- trunk/Source/WebKit/chromium/WebKit.gypi 2012-03-22 22:43:16 UTC (rev 111776)
+++ trunk/Source/WebKit/chromium/WebKit.gypi 2012-03-22 22:43:19 UTC (rev 111777)
@@ -105,6 +105,7 @@
'tests/KeyboardTest.cpp',
'tests/KURLTest.cpp',
'tests/LayerChromiumTest.cpp',
+ 'tests/LayerRendererChromiumTest.cpp',
'tests/LayerTextureUpdaterTest.cpp',
'tests/LevelDBTest.cpp',
'tests/LocalizedNumberICUTest.cpp',
Added: trunk/Source/WebKit/chromium/tests/LayerRendererChromiumTest.cpp (0 => 111777)
--- trunk/Source/WebKit/chromium/tests/LayerRendererChromiumTest.cpp (rev 0)
+++ trunk/Source/WebKit/chromium/tests/LayerRendererChromiumTest.cpp 2012-03-22 22:43:19 UTC (rev 111777)
@@ -0,0 +1,226 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "LayerRendererChromium.h"
+
+#include "FakeWebGraphicsContext3D.h"
+#include "GraphicsContext3D.h"
+#include "GraphicsContext3DPrivate.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+using namespace WebCore;
+using namespace WebKit;
+
+class FrameCountingMemoryAllocationSettingContext : public FakeWebGraphicsContext3D {
+public:
+ FrameCountingMemoryAllocationSettingContext() : m_frame(0) { }
+
+ // WebGraphicsContext3D methods.
+
+ // This method would normally do a glSwapBuffers under the hood.
+ virtual void prepareTexture() { m_frame++; }
+ virtual void setMemoryAllocationChangedCallbackCHROMIUM(WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* callback) { m_memoryAllocationChangedCallback = callback; }
+ virtual WebString getString(WebKit::WGC3Denum name)
+ {
+ if (name == GraphicsContext3D::EXTENSIONS)
+ return WebString("GL_CHROMIUM_set_visibility GL_CHROMIUM_gpu_memory_manager GL_CHROMIUM_discard_framebuffer");
+ return WebString();
+ }
+
+ // Methods added for test.
+ int frameCount() { return m_frame; }
+ void setMemoryAllocation(WebGraphicsMemoryAllocation allocation) { m_memoryAllocationChangedCallback->onMemoryAllocationChanged(allocation); }
+
+private:
+ int m_frame;
+ WebGraphicsMemoryAllocationChangedCallbackCHROMIUM* m_memoryAllocationChangedCallback;
+};
+
+class FakeLayerRendererChromiumClient : public LayerRendererChromiumClient {
+public:
+ FakeLayerRendererChromiumClient() : m_setFullRootLayerDamageCount(0) { }
+
+ // LayerRendererChromiumClient methods.
+ virtual const IntSize& viewportSize() const { static IntSize fakeSize; return fakeSize; }
+ virtual const CCSettings& settings() const { static CCSettings fakeSettings; return fakeSettings; }
+ virtual CCLayerImpl* rootLayer() { return 0; }
+ virtual const CCLayerImpl* rootLayer() const { return 0; }
+ virtual void didLoseContext() { }
+ virtual void onSwapBuffersComplete() { }
+ virtual void setFullRootLayerDamage() { m_setFullRootLayerDamageCount++; }
+
+ // Methods added for test.
+ int setFullRootLayerDamageCount() const { return m_setFullRootLayerDamageCount; }
+
+private:
+ int m_setFullRootLayerDamageCount;
+};
+
+class FakeLayerRendererChromium : public LayerRendererChromium {
+public:
+ FakeLayerRendererChromium(LayerRendererChromiumClient* client, PassRefPtr<GraphicsContext3D> context) : LayerRendererChromium(client, context) { }
+
+ // LayerRendererChromium methods.
+
+ // Changing visibility to public.
+ using LayerRendererChromium::initialize;
+};
+
+class LayerRendererChromiumTest : public testing::Test {
+protected:
+ LayerRendererChromiumTest()
+ : m_suggestHaveBackbufferYes(1, true)
+ , m_suggestHaveBackbufferNo(1, false)
+ , m_context(GraphicsContext3DPrivate::createGraphicsContextFromWebContext(adoptPtr(new FrameCountingMemoryAllocationSettingContext()), GraphicsContext3D::RenderDirectlyToHostWindow))
+ , m_mockContext(*static_cast<FrameCountingMemoryAllocationSettingContext*>(GraphicsContext3DPrivate::extractWebGraphicsContext3D(m_context.get())))
+ , m_layerRendererChromium(&m_mockClient, m_context.release())
+ {
+ }
+
+ virtual void SetUp()
+ {
+ m_layerRendererChromium.initialize();
+ }
+
+ void swapBuffers()
+ {
+ m_layerRendererChromium.swapBuffers(IntRect());
+ }
+
+ WebGraphicsMemoryAllocation m_suggestHaveBackbufferYes;
+ WebGraphicsMemoryAllocation m_suggestHaveBackbufferNo;
+
+ RefPtr<GraphicsContext3D> m_context;
+ FrameCountingMemoryAllocationSettingContext& m_mockContext;
+ FakeLayerRendererChromiumClient m_mockClient;
+ FakeLayerRendererChromium m_layerRendererChromium;
+};
+
+// Test LayerRendererChromium discardFramebuffer functionality:
+// Suggest recreating framebuffer when one already exists.
+// Expected: it does nothing.
+TEST_F(LayerRendererChromiumTest, SuggestBackbufferYesWhenItAlreadyExistsShouldDoNothing)
+{
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferYes);
+ EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount());
+ EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
+
+ swapBuffers();
+ EXPECT_EQ(1, m_mockContext.frameCount());
+}
+
+// Test LayerRendererChromium discardFramebuffer functionality:
+// Suggest discarding framebuffer when one exists.
+// Expected: it is discarded and damage tracker is reset.
+TEST_F(LayerRendererChromiumTest, SuggestBackbufferNoShouldDiscardBackbufferAndDamageRootLayer)
+{
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferNo);
+ EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
+ EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
+}
+
+// Test LayerRendererChromium discardFramebuffer functionality:
+// Suggest discarding framebuffer when one does not exist.
+// Expected: it does nothing.
+TEST_F(LayerRendererChromiumTest, SuggestBackbufferNoWhenItDoesntExistShouldDoNothing)
+{
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferNo);
+ EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
+ EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
+
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferNo);
+ EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
+ EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
+}
+
+// Test LayerRendererChromium discardFramebuffer functionality:
+// Suggest discarding framebuffer, then try to swapBuffers.
+// Expected: framebuffer is discarded, swaps are ignored, and damage is reset after discard and after each swap.
+TEST_F(LayerRendererChromiumTest, SwapBuffersWhileBackbufferDiscardedShouldIgnoreSwapAndDamageRootLayer)
+{
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferNo);
+ EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
+ EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
+
+ swapBuffers();
+ EXPECT_EQ(0, m_mockContext.frameCount());
+ EXPECT_EQ(2, m_mockClient.setFullRootLayerDamageCount());
+
+ swapBuffers();
+ EXPECT_EQ(0, m_mockContext.frameCount());
+ EXPECT_EQ(3, m_mockClient.setFullRootLayerDamageCount());
+}
+
+// Test LayerRendererChromium discardFramebuffer functionality:
+// Discard framebuffer, then set visibility to true.
+// Expected: recreates the framebuffer.
+TEST_F(LayerRendererChromiumTest, SetVisibilityTrueShouldRecreateBackbuffer)
+{
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferNo);
+ EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
+
+ m_layerRendererChromium.setVisible(true);
+ EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
+}
+
+// Test LayerRendererChromium discardFramebuffer functionality:
+// Create a ScopedEnsureFramebufferAllocation while a framebuffer was discarded and then swapBuffers.
+// Expected: will recreate framebuffer scope duration, during which swaps will work fine, and discard on scope exit.
+TEST_F(LayerRendererChromiumTest, DiscardedBackbufferIsRecreatredForScopeDuration)
+{
+ m_mockContext.setMemoryAllocation(m_suggestHaveBackbufferNo);
+ EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
+ EXPECT_EQ(1, m_mockClient.setFullRootLayerDamageCount());
+ {
+ ScopedEnsureFramebufferAllocation ensureFramebuffer(&m_layerRendererChromium);
+ EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
+
+ swapBuffers();
+ EXPECT_EQ(1, m_mockContext.frameCount());
+ }
+ EXPECT_TRUE(m_layerRendererChromium.isFramebufferDiscarded());
+ EXPECT_EQ(2, m_mockClient.setFullRootLayerDamageCount());
+}
+
+// Test LayerRendererChromium discardFramebuffer functionality:
+// Create a ScopedEnsureFramebufferAllocation while a framebuffer was not discarded and then swapBuffers.
+// Expected: will have no effect.
+TEST_F(LayerRendererChromiumTest, EnsuringBackbufferForScopeDurationDoesNothingIfAlreadyExists)
+{
+ EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
+ EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount());
+ {
+ ScopedEnsureFramebufferAllocation ensureFramebuffer(&m_layerRendererChromium);
+ EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
+ EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount());
+
+ swapBuffers();
+ EXPECT_EQ(1, m_mockContext.frameCount());
+ }
+ EXPECT_FALSE(m_layerRendererChromium.isFramebufferDiscarded());
+ EXPECT_EQ(0, m_mockClient.setFullRootLayerDamageCount());
+}