[chromium] LayerRendererChromium should use GpuMemoryAllocationChanged callback to...
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Mar 2012 22:43:19 +0000 (22:43 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Mar 2012 22:43:19 +0000 (22:43 +0000)
https://bugs.webkit.org/show_bug.cgi?id=81823

Patch by Michal Mocny <mmocny@google.com> on 2012-03-22
Reviewed by Adrienne Walker.

Source/WebCore:

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):

Source/WebKit/chromium:

* 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):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@111777 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebCore/ChangeLog
Source/WebCore/platform/graphics/chromium/LayerRendererChromium.cpp
Source/WebCore/platform/graphics/chromium/LayerRendererChromium.h
Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHost.h
Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.cpp
Source/WebCore/platform/graphics/chromium/cc/CCLayerTreeHostImpl.h
Source/WebCore/platform/graphics/chromium/cc/CCSingleThreadProxy.cpp
Source/WebCore/platform/graphics/chromium/cc/CCThreadProxy.cpp
Source/WebKit/chromium/ChangeLog
Source/WebKit/chromium/WebKit.gypi
Source/WebKit/chromium/tests/LayerRendererChromiumTest.cpp [new file with mode: 0644]

index e1e2f7dfd29cdd56b796425090c26f6540fb40cc..5ba8017cb7f353fa19ba5a9c98174e1647647773 100644 (file)
@@ -1,3 +1,46 @@
+2012-03-22  Michal Mocny  <mmocny@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  <abarth@webkit.org>
 
         ContainerNode::insertedIntoTree and removedFromTree use weak iteration patterns
index 27b3ede513257a7a9f46b9ae2492196a6c963990..88b66d6640d2f16bb88b506eaf3cf0894cf6fcbd 100644 (file)
@@ -165,6 +165,31 @@ private:
     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)
 {
@@ -184,6 +209,7 @@ LayerRendererChromium::LayerRendererChromium(LayerRendererChromiumClient* client
     , m_defaultRenderSurface(0)
     , m_sharedGeometryQuad(FloatRect(-0.5f, -0.5f, 1.0f, 1.0f))
     , m_isViewportChanged(false)
+    , m_isFramebufferDiscarded(false)
 {
 }
 
@@ -259,6 +285,17 @@ bool LayerRendererChromium::initialize()
     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 @@ LayerRendererChromium::~LayerRendererChromium()
     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 @@ void LayerRendererChromium::setVisible(bool visible)
     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::finish()
 
 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 @@ void LayerRendererChromium::onSwapBuffersComplete()
     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());
index 52ea87c133b157f1a5e0a8820addf63161f08d63..61c1d4a877bebccfa5da1fd1deb64231922a2c71 100644 (file)
@@ -61,6 +61,7 @@ class GeometryBinding;
 class GraphicsContext3D;
 class TrackingTextureAllocator;
 class LayerRendererSwapBuffersCompleteCallbackAdapter;
+class ScopedEnsureFramebufferAllocation;
 
 class LayerRendererChromiumClient {
 public:
@@ -70,6 +71,7 @@ public:
     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 @@ public:
                           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 @@ private:
     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.
index 9f780a7ae77aa1e8e15137a1db8f9f0f90bf8cab..7390ec34a9e7b8d0306b3d6694611e00a4d72764 100644 (file)
@@ -102,6 +102,8 @@ struct LayerRendererCapabilities {
         , usingSwapCompleteCallback(false)
         , usingTextureUsageHint(false)
         , usingTextureStorageExtension(false)
+        , usingGpuMemoryManager(false)
+        , usingDiscardFramebuffer(false)
         , maxTextureSize(0) { }
 
     GC3Denum bestTextureFormat;
@@ -113,6 +115,8 @@ struct LayerRendererCapabilities {
     bool usingSwapCompleteCallback;
     bool usingTextureUsageHint;
     bool usingTextureStorageExtension;
+    bool usingGpuMemoryManager;
+    bool usingDiscardFramebuffer;
     int maxTextureSize;
 };
 
index 9c7c3edc65ce16437d2655601d53bfd0feabe139..4f6ec7398772c8e03c009677999e8810aa9b6b5b 100644 (file)
@@ -480,11 +480,6 @@ void CCLayerTreeHostImpl::setVisible(bool visible)
 
     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);
 }
index e0c6e73a33420dd47d09542862cb9a48a0ad1cb0..77eb892fbe98ecfea2eb8e11918382de5f7cdae7 100644 (file)
@@ -98,6 +98,7 @@ public:
     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 @@ public:
 
     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; }
index 607b38af7a22cc774ff6a172793d3de59e40368b..2d9e0f341fe7257d34798f6cf1b8d4df859d20b0 100644 (file)
@@ -72,6 +72,8 @@ bool CCSingleThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect
     TRACE_EVENT("CCSingleThreadProxy::compositeAndReadback", this, 0);
     ASSERT(CCProxy::isMainThread());
 
+    ScopedEnsureFramebufferAllocation ensureFramebuffer(m_layerTreeHostImpl->layerRenderer());
+
     if (!commitIfNeeded())
         return false;
 
index e4173a8ad6113f7edc4b902ab0a7f850863a145f..8270740d0069d81a43ed063674931edbc133d41d 100644 (file)
@@ -91,6 +91,8 @@ bool CCThreadProxy::compositeAndReadback(void *pixels, const IntRect& rect)
     ASSERT(isMainThread());
     ASSERT(m_layerTreeHost);
 
+    ScopedEnsureFramebufferAllocation ensureFramebuffer(m_layerTreeHostImpl->layerRenderer());
+
     if (!m_layerRendererInitialized) {
         TRACE_EVENT("compositeAndReadback_EarlyOut_LR_Uninitialized", this, 0);
         return false;
index 65e0f88ec68de2e49ba6ca3d497378a2c7d848f7..042de716aff18283582eeccecd924a39a5c7b975 100644 (file)
@@ -1,3 +1,36 @@
+2012-03-22  Michal Mocny  <mmocny@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  <shawnsingh@chromium.org>
 
         [chromium] Make CCDamageTracker robust to empty layer lists
index e267a5bd3db93cdb2c7f892c216b8972f3337f2a..889429bd923801d63176fbd012670546e2688e4e 100644 (file)
             'tests/KeyboardTest.cpp',
             'tests/KURLTest.cpp',
             'tests/LayerChromiumTest.cpp',
+            'tests/LayerRendererChromiumTest.cpp',
             'tests/LayerTextureUpdaterTest.cpp',
             'tests/LevelDBTest.cpp',
             'tests/LocalizedNumberICUTest.cpp',
diff --git a/Source/WebKit/chromium/tests/LayerRendererChromiumTest.cpp b/Source/WebKit/chromium/tests/LayerRendererChromiumTest.cpp
new file mode 100644 (file)
index 0000000..7fa37a2
--- /dev/null
@@ -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());
+}