Add a way to tell the web process to perform a full backing store update on its next...
authoraroben@apple.com <aroben@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Mar 2011 01:36:29 +0000 (01:36 +0000)
committeraroben@apple.com <aroben@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Mar 2011 01:36:29 +0000 (01:36 +0000)
Messages::DrawingArea::UpdateBackingStoreState now takes a boolean specifying whether the
full backing store update should happen immediately or should be deferred until the next
paint or compositing mode change occurs. The deferred update isn't used yet, but will be
used when we start throwing away backing stores to save memory.

Fixes <http://webkit.org/b/55730> UI process needs a way to tell the web process its backing
store needs a full update on the next paint

Reviewed by Anders Carlsson.

* UIProcess/DrawingAreaProxyImpl.cpp:
(WebKit::DrawingAreaProxyImpl::paint): If we have an outstanding backing store state change
request, tell the web process to perform the backing store update right away, in case we
previously told it it could defer the update.
(WebKit::DrawingAreaProxyImpl::sizeDidChange): Specify that we need an immediate backing
store update.
(WebKit::DrawingAreaProxyImpl::didUpdateBackingStoreState): We can no longer assert that we
were waiting for a DidUpdateBackingStoreState message when we receive one, as it's possible
for the web process to decide to send us this message on its own (if we asked it to do a
deferred backing store update and then it needed to paint some part of the page). Specify
that we need an immediate backing store update if the web process hasn't updated to our
latest state, as we're about to draw potentially out-of-date bits to the screen and want to
get the right bits as soon as possible. Also added a FIXME about a potential optimization.
(WebKit::DrawingAreaProxyImpl::backingStoreStateDidChange): Added a RespondImmediatelyOrNot
parameter, which is just passed through to sendUpdateBackingStoreState.
(WebKit::DrawingAreaProxyImpl::sendUpdateBackingStoreState): Added a RespondImmediatelyOrNot
parameter that is used to specify to the web process whether to perform the full backing
store update immediately. We now only wait for a DidUpdateBackingStoreState message (and
thus suppress any more UpdateBackingStoreState messages until one is received) when we ask
the web process for an immediate response; otherwise we could end up accidentally calling
waitForAndDispatchDidUpdateBackingStoreState when the web process hasn't been told to send
us such a message.

* UIProcess/DrawingAreaProxyImpl.h: Added RespondImmediatelyOrNot.

* WebProcess/WebPage/DrawingArea.h:
(WebKit::DrawingArea::updateBackingStoreState): Added respondImmediately argument.

* WebProcess/WebPage/DrawingArea.messages.in: Added respondImmediately argument to
UpdateBackingStoreState message.

* WebProcess/WebPage/DrawingAreaImpl.cpp:
(WebKit::DrawingAreaImpl::DrawingAreaImpl): Initialize new member that's used to track
whether we should send a DidUpdateBackingStoreState message instead of an Update or
compositing mode change message. This will be set to true when a deferred backing store
update is pending.
(WebKit::DrawingAreaImpl::layerHostDidFlushLayers): If a deferred update is pending, send a
DidUpdateBackingStoreState message instead of a compositing mode change message.
(WebKit::DrawingAreaImpl::updateBackingStoreState): Added respondImmediately argument. If
we've already been told about this state ID (as can happen when the UI process decides it
needs an immediate update to a state that it previously requested a deferred update to),
don't bother updating the page's size, etc. In addition, if we've already sent a
DidUpdateBackingStoreState message for this state, we don't have to do anything at all.
Moved code to send the DidUpdateBackingStoreState message from here...
(WebKit::DrawingAreaImpl::sendDidUpdateBackingStoreState): ...to here.
(WebKit::DrawingAreaImpl::exitAcceleratedCompositingMode): Always update our dirty region,
even if painting is suspended or we're in the process of updating the backing store state.
It causes no harm and simplifies the code. If a deferred update is pending, send a
DidUpdateBackingStoreState message instead of a compositing mode change message. Also
removed a redundant if.
(WebKit::DrawingAreaImpl::display): Added an assertion that this isn't called while updating
backing store state, as otherwise we might end up sending two DidUpdateBackingStoreState
messages. If a deferred update is pending, send a DidUpdateBackingStoreState message instead
of an Update message.

* WebProcess/WebPage/DrawingAreaImpl.h: Updated updateBackingStoreState to match the base
class. Added sendDidUpdateBackingStoreState and m_shouldSendDidUpdateBackingStoreState.

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

Source/WebKit2/ChangeLog
Source/WebKit2/UIProcess/DrawingAreaProxyImpl.cpp
Source/WebKit2/UIProcess/DrawingAreaProxyImpl.h
Source/WebKit2/WebProcess/WebPage/DrawingArea.h
Source/WebKit2/WebProcess/WebPage/DrawingArea.messages.in
Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp
Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.h

index 9bcd497..0b1d18d 100644 (file)
@@ -1,3 +1,75 @@
+2011-03-03  Adam Roben  <aroben@apple.com>
+
+        Add a way to tell the web process to perform a full backing store update on its next paint
+
+        Messages::DrawingArea::UpdateBackingStoreState now takes a boolean specifying whether the
+        full backing store update should happen immediately or should be deferred until the next
+        paint or compositing mode change occurs. The deferred update isn't used yet, but will be
+        used when we start throwing away backing stores to save memory.
+
+        Fixes <http://webkit.org/b/55730> UI process needs a way to tell the web process its backing
+        store needs a full update on the next paint
+
+        Reviewed by Anders Carlsson.
+
+        * UIProcess/DrawingAreaProxyImpl.cpp:
+        (WebKit::DrawingAreaProxyImpl::paint): If we have an outstanding backing store state change
+        request, tell the web process to perform the backing store update right away, in case we
+        previously told it it could defer the update.
+        (WebKit::DrawingAreaProxyImpl::sizeDidChange): Specify that we need an immediate backing
+        store update.
+        (WebKit::DrawingAreaProxyImpl::didUpdateBackingStoreState): We can no longer assert that we
+        were waiting for a DidUpdateBackingStoreState message when we receive one, as it's possible
+        for the web process to decide to send us this message on its own (if we asked it to do a
+        deferred backing store update and then it needed to paint some part of the page). Specify
+        that we need an immediate backing store update if the web process hasn't updated to our
+        latest state, as we're about to draw potentially out-of-date bits to the screen and want to
+        get the right bits as soon as possible. Also added a FIXME about a potential optimization.
+        (WebKit::DrawingAreaProxyImpl::backingStoreStateDidChange): Added a RespondImmediatelyOrNot
+        parameter, which is just passed through to sendUpdateBackingStoreState.
+        (WebKit::DrawingAreaProxyImpl::sendUpdateBackingStoreState): Added a RespondImmediatelyOrNot
+        parameter that is used to specify to the web process whether to perform the full backing
+        store update immediately. We now only wait for a DidUpdateBackingStoreState message (and
+        thus suppress any more UpdateBackingStoreState messages until one is received) when we ask
+        the web process for an immediate response; otherwise we could end up accidentally calling
+        waitForAndDispatchDidUpdateBackingStoreState when the web process hasn't been told to send
+        us such a message.
+
+        * UIProcess/DrawingAreaProxyImpl.h: Added RespondImmediatelyOrNot.
+
+        * WebProcess/WebPage/DrawingArea.h:
+        (WebKit::DrawingArea::updateBackingStoreState): Added respondImmediately argument.
+
+        * WebProcess/WebPage/DrawingArea.messages.in: Added respondImmediately argument to
+        UpdateBackingStoreState message.
+
+        * WebProcess/WebPage/DrawingAreaImpl.cpp:
+        (WebKit::DrawingAreaImpl::DrawingAreaImpl): Initialize new member that's used to track
+        whether we should send a DidUpdateBackingStoreState message instead of an Update or
+        compositing mode change message. This will be set to true when a deferred backing store
+        update is pending.
+        (WebKit::DrawingAreaImpl::layerHostDidFlushLayers): If a deferred update is pending, send a
+        DidUpdateBackingStoreState message instead of a compositing mode change message.
+        (WebKit::DrawingAreaImpl::updateBackingStoreState): Added respondImmediately argument. If
+        we've already been told about this state ID (as can happen when the UI process decides it
+        needs an immediate update to a state that it previously requested a deferred update to),
+        don't bother updating the page's size, etc. In addition, if we've already sent a
+        DidUpdateBackingStoreState message for this state, we don't have to do anything at all.
+        Moved code to send the DidUpdateBackingStoreState message from here...
+        (WebKit::DrawingAreaImpl::sendDidUpdateBackingStoreState): ...to here.
+        (WebKit::DrawingAreaImpl::exitAcceleratedCompositingMode): Always update our dirty region,
+        even if painting is suspended or we're in the process of updating the backing store state.
+        It causes no harm and simplifies the code. If a deferred update is pending, send a
+        DidUpdateBackingStoreState message instead of a compositing mode change message. Also
+        removed a redundant if.
+        (WebKit::DrawingAreaImpl::display): Added an assertion that this isn't called while updating
+        backing store state, as otherwise we might end up sending two DidUpdateBackingStoreState
+        messages. If a deferred update is pending, send a DidUpdateBackingStoreState message instead
+        of an Update message.
+
+        * WebProcess/WebPage/DrawingAreaImpl.h: Updated updateBackingStoreState to match the base
+        class. Added sendDidUpdateBackingStoreState and m_shouldSendDidUpdateBackingStoreState.
+
 2011-03-03  Andy Estes  <aestes@apple.com>
 
         Reviewed by Darin Adler.
index 87cc205..81dca28 100644 (file)
@@ -71,15 +71,25 @@ void DrawingAreaProxyImpl::paint(BackingStore::PlatformGraphicsContext context,
 
     ASSERT(!isInAcceleratedCompositingMode());
 
-    if (m_isWaitingForDidUpdateBackingStoreState) {
-        // Wait for a DidUpdateBackingStoreState message that contains the new bits before we paint
-        // what's currently in the backing store.
-        waitForAndDispatchDidUpdateBackingStoreState();
+    ASSERT(m_currentBackingStoreStateID <= m_nextBackingStoreStateID);
+    if (m_currentBackingStoreStateID < m_nextBackingStoreStateID) {
+        // Tell the web process to do a full backing store update now, in case we previously told
+        // it about our next state but didn't request an immediate update.
+        sendUpdateBackingStoreState(RespondImmediately);
+
+        if (m_isWaitingForDidUpdateBackingStoreState) {
+            // Wait for a DidUpdateBackingStoreState message that contains the new bits before we paint
+            // what's currently in the backing store.
+            waitForAndDispatchDidUpdateBackingStoreState();
+        }
 
-        // Dispatching DidUpdateBackingStoreState could destroy our backing store or change the compositing mode.
+        // Dispatching DidUpdateBackingStoreState (either beneath sendUpdateBackingStoreState or
+        // beneath waitForAndDispatchDidUpdateBackingStoreState) could destroy our backing store or
+        // change the compositing mode.
         if (!m_backingStore || isInAcceleratedCompositingMode())
             return;
-    }
+    } else
+        ASSERT(!m_isWaitingForDidUpdateBackingStoreState);
 
     m_backingStore->paint(context, rect);
     unpaintedRegion.subtract(IntRect(IntPoint(), m_backingStore->size()));
@@ -103,7 +113,7 @@ bool DrawingAreaProxyImpl::paint(const WebCore::IntRect&, PlatformDrawingContext
 
 void DrawingAreaProxyImpl::sizeDidChange()
 {
-    backingStoreStateDidChange();
+    backingStoreStateDidChange(RespondImmediately);
 }
 
 void DrawingAreaProxyImpl::visibilityDidChange()
@@ -140,11 +150,10 @@ void DrawingAreaProxyImpl::didUpdateBackingStoreState(uint64_t backingStoreState
     ASSERT_ARG(backingStoreStateID, backingStoreStateID > m_currentBackingStoreStateID);
     m_currentBackingStoreStateID = backingStoreStateID;
 
-    ASSERT(m_isWaitingForDidUpdateBackingStoreState);
     m_isWaitingForDidUpdateBackingStoreState = false;
 
     if (m_nextBackingStoreStateID != m_currentBackingStoreStateID)
-        sendUpdateBackingStoreState();
+        sendUpdateBackingStoreState(RespondImmediately);
 
     if (layerTreeContext != m_layerTreeContext) {
         if (!m_layerTreeContext.isEmpty()) {
@@ -163,6 +172,8 @@ void DrawingAreaProxyImpl::didUpdateBackingStoreState(uint64_t backingStoreState
         return;
     }
 
+    // FIXME: We could just reuse our existing backing store if it's the same size as
+    // updateInfo.viewSize.
     m_backingStore = nullptr;
     incorporateUpdate(updateInfo);
 }
@@ -214,13 +225,13 @@ void DrawingAreaProxyImpl::incorporateUpdate(const UpdateInfo& updateInfo)
         m_webPageProxy->displayView();
 }
 
-void DrawingAreaProxyImpl::backingStoreStateDidChange()
+void DrawingAreaProxyImpl::backingStoreStateDidChange(RespondImmediatelyOrNot respondImmediatelyOrNot)
 {
     ++m_nextBackingStoreStateID;
-    sendUpdateBackingStoreState();
+    sendUpdateBackingStoreState(respondImmediatelyOrNot);
 }
 
-void DrawingAreaProxyImpl::sendUpdateBackingStoreState()
+void DrawingAreaProxyImpl::sendUpdateBackingStoreState(RespondImmediatelyOrNot respondImmediatelyOrNot)
 {
     ASSERT(m_currentBackingStoreStateID < m_nextBackingStoreStateID);
 
@@ -230,11 +241,11 @@ void DrawingAreaProxyImpl::sendUpdateBackingStoreState()
     if (m_isWaitingForDidUpdateBackingStoreState)
         return;
 
-    m_isWaitingForDidUpdateBackingStoreState = true;
-    m_webPageProxy->process()->send(Messages::DrawingArea::UpdateBackingStoreState(m_nextBackingStoreStateID, m_size, m_scrollOffset), m_webPageProxy->pageID());
+    m_isWaitingForDidUpdateBackingStoreState = respondImmediatelyOrNot == RespondImmediately;
+    m_webPageProxy->process()->send(Messages::DrawingArea::UpdateBackingStoreState(m_nextBackingStoreStateID, respondImmediatelyOrNot == RespondImmediately, m_size, m_scrollOffset), m_webPageProxy->pageID());
     m_scrollOffset = IntSize();
 
-    if (!m_layerTreeContext.isEmpty()) {
+    if (m_isWaitingForDidUpdateBackingStoreState && !m_layerTreeContext.isEmpty()) {
         // Wait for the DidUpdateBackingStoreState message. Normally we don this in DrawingAreaProxyImpl::paint, but that
         // function is never called when in accelerated compositing mode.
         waitForAndDispatchDidUpdateBackingStoreState();
index 3c47dd3..3054d31 100644 (file)
@@ -62,8 +62,9 @@ private:
 
     void incorporateUpdate(const UpdateInfo&);
 
-    void backingStoreStateDidChange();
-    void sendUpdateBackingStoreState();
+    enum RespondImmediatelyOrNot { DoNotRespondImmediately, RespondImmediately };
+    void backingStoreStateDidChange(RespondImmediatelyOrNot);
+    void sendUpdateBackingStoreState(RespondImmediatelyOrNot);
     void waitForAndDispatchDidUpdateBackingStoreState();
 
     void enterAcceleratedCompositingMode(const LayerTreeContext&);
index d71a18f..a94d66c 100644 (file)
@@ -86,7 +86,7 @@ protected:
 private:
     // CoreIPC message handlers.
     // FIXME: These should be pure virtual.
-    virtual void updateBackingStoreState(uint64_t backingStoreStateID, const WebCore::IntSize& size, const WebCore::IntSize& scrollOffset) { }
+    virtual void updateBackingStoreState(uint64_t backingStoreStateID, bool respondImmediately, const WebCore::IntSize& size, const WebCore::IntSize& scrollOffset) { }
     virtual void didUpdate() { }
     virtual void suspendPainting() { }
     virtual void resumePainting() { }
index e0507b3..30186f2 100644 (file)
@@ -21,7 +21,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 messages -> DrawingArea {
-    UpdateBackingStoreState(uint64_t backingStoreStateID, WebCore::IntSize size, WebCore::IntSize scrollOffset)
+    UpdateBackingStoreState(uint64_t backingStoreStateID, bool respondImmediately, WebCore::IntSize size, WebCore::IntSize scrollOffset)
     DidUpdate()
     SuspendPainting()
     ResumePainting()
index 58001b3..0a18256 100644 (file)
@@ -60,6 +60,7 @@ DrawingAreaImpl::DrawingAreaImpl(WebPage* webPage, const WebPageCreationParamete
     : DrawingArea(DrawingAreaTypeImpl, webPage)
     , m_backingStoreStateID(0)
     , m_inUpdateBackingStoreState(false)
+    , m_shouldSendDidUpdateBackingStoreState(false)
     , m_isWaitingForDidUpdate(false)
     , m_isPaintingSuspended(!parameters.isVisible)
     , m_alwaysUseCompositing(false)
@@ -188,6 +189,11 @@ void DrawingAreaImpl::layerHostDidFlushLayers()
 
     m_layerTreeHost->forceRepaint();
 
+    if (m_shouldSendDidUpdateBackingStoreState) {
+        sendDidUpdateBackingStoreState();
+        return;
+    }
+
     if (!m_layerTreeHost)
         return;
 
@@ -237,47 +243,74 @@ void DrawingAreaImpl::didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID
 {
 }
 
-void DrawingAreaImpl::updateBackingStoreState(uint64_t stateID, const WebCore::IntSize& size, const WebCore::IntSize& scrollOffset)
+void DrawingAreaImpl::updateBackingStoreState(uint64_t stateID, bool respondImmediately, const WebCore::IntSize& size, const WebCore::IntSize& scrollOffset)
 {
     ASSERT(!m_inUpdateBackingStoreState);
     m_inUpdateBackingStoreState = true;
 
-    ASSERT_ARG(stateID, stateID > m_backingStoreStateID);
-    m_backingStoreStateID = stateID;
+    ASSERT_ARG(stateID, stateID >= m_backingStoreStateID);
+    if (stateID != m_backingStoreStateID) {
+        m_backingStoreStateID = stateID;
+        m_shouldSendDidUpdateBackingStoreState = true;
+
+        m_webPage->setSize(size);
+        m_webPage->layoutIfNeeded();
+        m_webPage->scrollMainFrameIfNotAtMaxScrollPosition(scrollOffset);
+
+        if (m_layerTreeHost)
+            m_layerTreeHost->sizeDidChange(size);
+        else
+            m_dirtyRegion = m_webPage->bounds();
+    } else {
+        ASSERT(size == m_webPage->size());
+        if (!m_shouldSendDidUpdateBackingStoreState) {
+            // We've already sent a DidUpdateBackingStoreState message for this state. We have nothing more to do.
+            m_inUpdateBackingStoreState = false;
+            return;
+        }
+    }
 
-    // Set this to false since we're about to call display().
+    // The UI process has updated to a new backing store state. Any Update messages we sent before
+    // this point will be ignored. We wait to set this to false until after updating the page's
+    // size so that any displays triggered by the relayout will be ignored. If we're supposed to
+    // respond to the UpdateBackingStoreState message immediately, we'll do a display anyway in
+    // sendDidUpdateBackingStoreState; otherwise we shouldn't do one right now.
     m_isWaitingForDidUpdate = false;
 
-    m_webPage->setSize(size);
-    m_webPage->layoutIfNeeded();
-    m_webPage->scrollMainFrameIfNotAtMaxScrollPosition(scrollOffset);
+    if (respondImmediately)
+        sendDidUpdateBackingStoreState();
+
+    m_inUpdateBackingStoreState = false;
+}
+
+void DrawingAreaImpl::sendDidUpdateBackingStoreState()
+{
+    ASSERT(!m_isWaitingForDidUpdate);
+    ASSERT(m_shouldSendDidUpdateBackingStoreState);
+
+    m_shouldSendDidUpdateBackingStoreState = false;
 
     UpdateInfo updateInfo;
     LayerTreeContext layerTreeContext;
 
-    if (m_layerTreeHost) {
-        m_layerTreeHost->sizeDidChange(size);
-        layerTreeContext = m_layerTreeHost->layerTreeContext();
-
-        // We don't want the layer tree host to notify after the next scheduled
-        // layer flush because that might end up sending an EnterAcceleratedCompositingMode
-        // message back to the UI process, but the updated layer tree context
-        // will be sent back in the DidUpdateBackingStoreState message.
-        m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush(false);
-    } else
-        m_dirtyRegion = m_webPage->bounds();
-
-    if (m_isPaintingSuspended || m_layerTreeHost)
-        updateInfo.viewSize = m_webPage->size();
-    else {
-        // The display here should not cause layout to happen, so we can't enter accelerated compositing mode here.
+    if (!m_isPaintingSuspended && !m_layerTreeHost)
         display(updateInfo);
-        ASSERT(!m_layerTreeHost);
+
+    if (m_isPaintingSuspended || m_layerTreeHost) {
+        updateInfo.viewSize = m_webPage->size();
+
+        if (m_layerTreeHost) {
+            layerTreeContext = m_layerTreeHost->layerTreeContext();
+
+            // We don't want the layer tree host to notify after the next scheduled
+            // layer flush because that might end up sending an EnterAcceleratedCompositingMode
+            // message back to the UI process, but the updated layer tree context
+            // will be sent back in the DidUpdateBackingStoreState message.
+            m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush(false);
+        }
     }
 
     m_webPage->send(Messages::DrawingAreaProxy::DidUpdateBackingStoreState(m_backingStoreStateID, updateInfo, layerTreeContext));
-
-    m_inUpdateBackingStoreState = false;
 }
 
 void DrawingAreaImpl::didUpdate()
@@ -342,22 +375,25 @@ void DrawingAreaImpl::exitAcceleratedCompositingMode()
 
     m_layerTreeHost->invalidate();
     m_layerTreeHost = nullptr;
+    m_dirtyRegion = m_webPage->bounds();
 
     if (m_inUpdateBackingStoreState)
         return;
 
+    if (m_shouldSendDidUpdateBackingStoreState) {
+        sendDidUpdateBackingStoreState();
+        return;
+    }
+
     UpdateInfo updateInfo;
     if (m_isPaintingSuspended)
         updateInfo.viewSize = m_webPage->size();
-    else {
-        m_dirtyRegion = m_webPage->bounds();
+    else
         display(updateInfo);
-    }
 
     // Send along a complete update of the page so we can paint the contents right after we exit the
     // accelerated compositing mode, eliminiating flicker.
-    if (!m_inUpdateBackingStoreState)
-        m_webPage->send(Messages::DrawingAreaProxy::ExitAcceleratedCompositingMode(m_backingStoreStateID, updateInfo));
+    m_webPage->send(Messages::DrawingAreaProxy::ExitAcceleratedCompositingMode(m_backingStoreStateID, updateInfo));
 }
 
 void DrawingAreaImpl::exitAcceleratedCompositingModeSoon()
@@ -389,6 +425,7 @@ void DrawingAreaImpl::display()
 {
     ASSERT(!m_layerTreeHost);
     ASSERT(!m_isWaitingForDidUpdate);
+    ASSERT(!m_inUpdateBackingStoreState);
 
     if (m_isPaintingSuspended)
         return;
@@ -396,6 +433,11 @@ void DrawingAreaImpl::display()
     if (m_dirtyRegion.isEmpty())
         return;
 
+    if (m_shouldSendDidUpdateBackingStoreState) {
+        sendDidUpdateBackingStoreState();
+        return;
+    }
+
     UpdateInfo updateInfo;
     display(updateInfo);
 
index 7e64f99..8d85200 100644 (file)
@@ -60,11 +60,13 @@ private:
     virtual void didReceiveMessage(CoreIPC::Connection*, CoreIPC::MessageID, CoreIPC::ArgumentDecoder*);
 
     // CoreIPC message handlers.
-    virtual void updateBackingStoreState(uint64_t backingStoreStateID, const WebCore::IntSize&, const WebCore::IntSize& scrollOffset);
+    virtual void updateBackingStoreState(uint64_t backingStoreStateID, bool respondImmediately, const WebCore::IntSize&, const WebCore::IntSize& scrollOffset);
     virtual void didUpdate();
     virtual void suspendPainting();
     virtual void resumePainting();
 
+    void sendDidUpdateBackingStoreState();
+
     void enterAcceleratedCompositingMode(WebCore::GraphicsLayer*);
     void exitAcceleratedCompositingModeSoon();
     void exitAcceleratedCompositingMode();
@@ -82,6 +84,10 @@ private:
     // Whether we're currently processing an UpdateBackingStoreState message.
     bool m_inUpdateBackingStoreState;
 
+    // When true, we should send an UpdateBackingStoreState message instead of any other messages
+    // we normally send to the UI process.
+    bool m_shouldSendDidUpdateBackingStoreState;
+
     // Whether we're waiting for a DidUpdate message. Used for throttling paints so that the 
     // web process won't paint more frequent than the UI process can handle.
     bool m_isWaitingForDidUpdate;