[GTK] Do not release OpenGL resource immediately when leaving accelerated compositing...
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 Jan 2017 16:42:12 +0000 (16:42 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 30 Jan 2017 16:42:12 +0000 (16:42 +0000)
https://bugs.webkit.org/show_bug.cgi?id=167544

Reviewed by Michael Catanzaro.

Sometimes the conditions to be in AC mode or not change quickly, and then we leave AC mode just enter it again
after a very short period of time. In those cases we are dropping all the GL resources and the compositor
thread, and creating it again. We could keep the layer tree host alive for a while when exiting AC mode, and
reuse it if we enter AC mode before the previous one has been discarded. While the previous layer tree host is
alive we still need to keep it up to date, for example if the web view is resized or contents size change, and
synchronize with the threaded compositor when it becomes the layer tree host again.

* WebProcess/WebPage/AcceleratedDrawingArea.cpp:
(WebKit::AcceleratedDrawingArea::~AcceleratedDrawingArea): Discard the previous layer tree host.
(WebKit::AcceleratedDrawingArea::AcceleratedDrawingArea): Initialize the timer to discard the previous layer
tree host.
(WebKit::AcceleratedDrawingArea::pageBackgroundTransparencyChanged): Notify the previous layer tree host if needed.
(WebKit::AcceleratedDrawingArea::mainFrameContentSizeChanged): Ditto.
(WebKit::AcceleratedDrawingArea::updateBackingStoreState): Ditto.
(WebKit::AcceleratedDrawingArea::enterAcceleratedCompositingMode): Reuse the previous layer tree host if possible.
(WebKit::AcceleratedDrawingArea::exitAcceleratedCompositingModeNow): Exit AC mode and save the layer tree host
starting a timer of 5 seconds to discard it if not reused.
(WebKit::AcceleratedDrawingArea::discardPreviousLayerTreeHost): Invalidate and destroy the previous layer tree host.
(WebKit::AcceleratedDrawingArea::didChangeViewportAttributes): Notify the previous layer tree host if needed.
(WebKit::AcceleratedDrawingArea::deviceOrPageScaleFactorChanged): Ditto.
* WebProcess/WebPage/AcceleratedDrawingArea.h:
* WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.cpp:
(WebKit::ThreadedCoordinatedLayerTreeHost::scrollNonCompositedContents): If it's discardable add the action to
be synchronized instead.
(WebKit::ThreadedCoordinatedLayerTreeHost::contentsSizeChanged): Ditto.
(WebKit::ThreadedCoordinatedLayerTreeHost::deviceOrPageScaleFactorChanged): Ditto.
(WebKit::ThreadedCoordinatedLayerTreeHost::pageBackgroundTransparencyChanged): Ditto.
(WebKit::ThreadedCoordinatedLayerTreeHost::sizeDidChange): Ditto.
(WebKit::ThreadedCoordinatedLayerTreeHost::didChangeViewportAttributes): Ditto.
(WebKit::ThreadedCoordinatedLayerTreeHost::setIsDiscardable): When the layer tree host becomes discardable,
reset the sync actions and return. When it becomes the real layer tree host again, apply all pending actions to
synchronize with the threaded compositor.
* WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.h:
* WebProcess/WebPage/DrawingAreaImpl.cpp:
(WebKit::DrawingAreaImpl::scroll): Notify the previous layer tree host if needed.
(WebKit::DrawingAreaImpl::mainFrameContentSizeChanged): Ditto.
(WebKit::DrawingAreaImpl::exitAcceleratedCompositingMode): Use AcceleratedDrawingArea::exitAcceleratedCompositingModeNow().
* WebProcess/WebPage/LayerTreeHost.h:
(WebKit::LayerTreeHost::setIsDiscardable): Added.

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

Source/WebKit2/ChangeLog
Source/WebKit2/WebProcess/WebPage/AcceleratedDrawingArea.cpp
Source/WebKit2/WebProcess/WebPage/AcceleratedDrawingArea.h
Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.cpp
Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.h
Source/WebKit2/WebProcess/WebPage/DrawingAreaImpl.cpp
Source/WebKit2/WebProcess/WebPage/LayerTreeHost.h

index 53dcaee..3aeaa62 100644 (file)
@@ -1,3 +1,50 @@
+2017-01-30  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK] Do not release OpenGL resource immediately when leaving accelerated compositing mode
+        https://bugs.webkit.org/show_bug.cgi?id=167544
+
+        Reviewed by Michael Catanzaro.
+
+        Sometimes the conditions to be in AC mode or not change quickly, and then we leave AC mode just enter it again
+        after a very short period of time. In those cases we are dropping all the GL resources and the compositor
+        thread, and creating it again. We could keep the layer tree host alive for a while when exiting AC mode, and
+        reuse it if we enter AC mode before the previous one has been discarded. While the previous layer tree host is
+        alive we still need to keep it up to date, for example if the web view is resized or contents size change, and
+        synchronize with the threaded compositor when it becomes the layer tree host again.
+
+        * WebProcess/WebPage/AcceleratedDrawingArea.cpp:
+        (WebKit::AcceleratedDrawingArea::~AcceleratedDrawingArea): Discard the previous layer tree host.
+        (WebKit::AcceleratedDrawingArea::AcceleratedDrawingArea): Initialize the timer to discard the previous layer
+        tree host.
+        (WebKit::AcceleratedDrawingArea::pageBackgroundTransparencyChanged): Notify the previous layer tree host if needed.
+        (WebKit::AcceleratedDrawingArea::mainFrameContentSizeChanged): Ditto.
+        (WebKit::AcceleratedDrawingArea::updateBackingStoreState): Ditto.
+        (WebKit::AcceleratedDrawingArea::enterAcceleratedCompositingMode): Reuse the previous layer tree host if possible.
+        (WebKit::AcceleratedDrawingArea::exitAcceleratedCompositingModeNow): Exit AC mode and save the layer tree host
+        starting a timer of 5 seconds to discard it if not reused.
+        (WebKit::AcceleratedDrawingArea::discardPreviousLayerTreeHost): Invalidate and destroy the previous layer tree host.
+        (WebKit::AcceleratedDrawingArea::didChangeViewportAttributes): Notify the previous layer tree host if needed.
+        (WebKit::AcceleratedDrawingArea::deviceOrPageScaleFactorChanged): Ditto.
+        * WebProcess/WebPage/AcceleratedDrawingArea.h:
+        * WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.cpp:
+        (WebKit::ThreadedCoordinatedLayerTreeHost::scrollNonCompositedContents): If it's discardable add the action to
+        be synchronized instead.
+        (WebKit::ThreadedCoordinatedLayerTreeHost::contentsSizeChanged): Ditto.
+        (WebKit::ThreadedCoordinatedLayerTreeHost::deviceOrPageScaleFactorChanged): Ditto.
+        (WebKit::ThreadedCoordinatedLayerTreeHost::pageBackgroundTransparencyChanged): Ditto.
+        (WebKit::ThreadedCoordinatedLayerTreeHost::sizeDidChange): Ditto.
+        (WebKit::ThreadedCoordinatedLayerTreeHost::didChangeViewportAttributes): Ditto.
+        (WebKit::ThreadedCoordinatedLayerTreeHost::setIsDiscardable): When the layer tree host becomes discardable,
+        reset the sync actions and return. When it becomes the real layer tree host again, apply all pending actions to
+        synchronize with the threaded compositor.
+        * WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.h:
+        * WebProcess/WebPage/DrawingAreaImpl.cpp:
+        (WebKit::DrawingAreaImpl::scroll): Notify the previous layer tree host if needed.
+        (WebKit::DrawingAreaImpl::mainFrameContentSizeChanged): Ditto.
+        (WebKit::DrawingAreaImpl::exitAcceleratedCompositingMode): Use AcceleratedDrawingArea::exitAcceleratedCompositingModeNow().
+        * WebProcess/WebPage/LayerTreeHost.h:
+        (WebKit::LayerTreeHost::setIsDiscardable): Added.
+
 2017-01-30  Manuel Rego Casasnovas  <rego@igalia.com>
 
         [GTK] Remove support to enable/disable experimental features
index fd9d308..94ec336 100644 (file)
@@ -44,6 +44,7 @@ namespace WebKit {
 
 AcceleratedDrawingArea::~AcceleratedDrawingArea()
 {
+    discardPreviousLayerTreeHost();
     if (m_layerTreeHost)
         m_layerTreeHost->invalidate();
 }
@@ -55,6 +56,7 @@ AcceleratedDrawingArea::AcceleratedDrawingArea(WebPage& webPage, const WebPageCr
     : DrawingArea(DrawingAreaTypeImpl, webPage)
 #endif
     , m_exitCompositingTimer(RunLoop::main(), this, &AcceleratedDrawingArea::exitAcceleratedCompositingMode)
+    , m_discardPreviousLayerTreeHostTimer(RunLoop::main(), this, &AcceleratedDrawingArea::discardPreviousLayerTreeHost)
 {
     if (!m_webPage.isVisible())
         suspendPainting();
@@ -91,6 +93,8 @@ void AcceleratedDrawingArea::pageBackgroundTransparencyChanged()
 {
     if (m_layerTreeHost)
         m_layerTreeHost->pageBackgroundTransparencyChanged();
+    else if (m_previousLayerTreeHost)
+        m_previousLayerTreeHost->pageBackgroundTransparencyChanged();
 }
 
 void AcceleratedDrawingArea::setLayerTreeStateIsFrozen(bool isFrozen)
@@ -150,8 +154,12 @@ void AcceleratedDrawingArea::updatePreferences(const WebPreferencesStore& store)
 
 void AcceleratedDrawingArea::mainFrameContentSizeChanged(const IntSize& size)
 {
-    if (m_webPage.useFixedLayout() && m_layerTreeHost)
-        m_layerTreeHost->sizeDidChange(size);
+    if (m_webPage.useFixedLayout()) {
+        if (m_layerTreeHost)
+            m_layerTreeHost->sizeDidChange(size);
+        else if (m_previousLayerTreeHost)
+            m_previousLayerTreeHost->sizeDidChange(size);
+    }
     m_webPage.mainFrame()->pageOverlayController().didChangeDocumentSize();
 }
 
@@ -234,6 +242,8 @@ void AcceleratedDrawingArea::updateBackingStoreState(uint64_t stateID, bool resp
 #else
         if (m_layerTreeHost)
             m_layerTreeHost->sizeDidChange(m_webPage.size());
+        else if (m_previousLayerTreeHost)
+            m_previousLayerTreeHost->sizeDidChange(m_webPage.size());
 #endif
     } else {
         ASSERT(size == m_webPage.size());
@@ -317,19 +327,32 @@ void AcceleratedDrawingArea::resumePainting()
 
 void AcceleratedDrawingArea::enterAcceleratedCompositingMode(GraphicsLayer* graphicsLayer)
 {
+    m_discardPreviousLayerTreeHostTimer.stop();
+
     m_exitCompositingTimer.stop();
     m_wantsToExitAcceleratedCompositingMode = false;
 
     ASSERT(!m_layerTreeHost);
-    m_layerTreeHost = LayerTreeHost::create(m_webPage);
+    if (m_previousLayerTreeHost) {
+        m_layerTreeHost = WTFMove(m_previousLayerTreeHost);
+        m_layerTreeHost->setIsDiscardable(false);
+        if (!m_isPaintingSuspended)
+            m_layerTreeHost->resumeRendering();
+        if (!m_layerTreeStateIsFrozen)
+            m_layerTreeHost->setLayerFlushSchedulingEnabled(true);
+    } else {
+        m_layerTreeHost = LayerTreeHost::create(m_webPage);
+
+        if (m_isPaintingSuspended)
+            m_layerTreeHost->pauseRendering();
+    }
+
 #if USE(TEXTURE_MAPPER_GL) && PLATFORM(GTK) && PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
     if (m_nativeSurfaceHandleForCompositing)
         m_layerTreeHost->setNativeSurfaceHandleForCompositing(m_nativeSurfaceHandleForCompositing);
 #endif
     if (!m_inUpdateBackingStoreState)
         m_layerTreeHost->setShouldNotifyAfterNextScheduledLayerFlush(true);
-    if (m_isPaintingSuspended)
-        m_layerTreeHost->pauseRendering();
 
     m_layerTreeHost->setRootCompositingLayer(graphicsLayer);
 }
@@ -347,6 +370,32 @@ void AcceleratedDrawingArea::exitAcceleratedCompositingModeSoon()
     m_exitCompositingTimer.startOneShot(0);
 }
 
+void AcceleratedDrawingArea::exitAcceleratedCompositingModeNow()
+{
+    ASSERT(!m_alwaysUseCompositing);
+    ASSERT(!m_layerTreeStateIsFrozen);
+
+    m_exitCompositingTimer.stop();
+    m_wantsToExitAcceleratedCompositingMode = false;
+
+    ASSERT(m_layerTreeHost);
+    m_previousLayerTreeHost = WTFMove(m_layerTreeHost);
+    m_previousLayerTreeHost->setIsDiscardable(true);
+    m_previousLayerTreeHost->pauseRendering();
+    m_previousLayerTreeHost->setLayerFlushSchedulingEnabled(false);
+    m_discardPreviousLayerTreeHostTimer.startOneShot(5);
+}
+
+void AcceleratedDrawingArea::discardPreviousLayerTreeHost()
+{
+    m_discardPreviousLayerTreeHostTimer.stop();
+    if (!m_previousLayerTreeHost)
+        return;
+
+    m_previousLayerTreeHost->invalidate();
+    m_previousLayerTreeHost = nullptr;
+}
+
 #if USE(COORDINATED_GRAPHICS_MULTIPROCESS)
 void AcceleratedDrawingArea::didReceiveCoordinatedLayerTreeHostMessage(IPC::Connection& connection, IPC::Decoder& decoder)
 {
@@ -376,6 +425,8 @@ void AcceleratedDrawingArea::didChangeViewportAttributes(ViewportAttributes&& at
 {
     if (m_layerTreeHost)
         m_layerTreeHost->didChangeViewportAttributes(WTFMove(attrs));
+    else if (m_previousLayerTreeHost)
+        m_previousLayerTreeHost->didChangeViewportAttributes(WTFMove(attrs));
 }
 #endif
 
@@ -384,6 +435,8 @@ void AcceleratedDrawingArea::deviceOrPageScaleFactorChanged()
 {
     if (m_layerTreeHost)
         m_layerTreeHost->deviceOrPageScaleFactorChanged();
+    else if (m_previousLayerTreeHost)
+        m_previousLayerTreeHost->deviceOrPageScaleFactorChanged();
 }
 #endif
 
index 4f9754f..f0b789a 100644 (file)
@@ -86,6 +86,8 @@ protected:
 
     void exitAcceleratedCompositingModeSoon();
     bool exitAcceleratedCompositingModePending() const { return m_exitCompositingTimer.isActive(); }
+    void exitAcceleratedCompositingModeNow();
+    void discardPreviousLayerTreeHost();
 
     virtual void suspendPainting();
     virtual void resumePainting();
@@ -127,6 +129,9 @@ protected:
 
     // The layer tree host that handles accelerated compositing.
     RefPtr<LayerTreeHost> m_layerTreeHost;
+
+    RefPtr<LayerTreeHost> m_previousLayerTreeHost;
+    RunLoop::Timer<AcceleratedDrawingArea> m_discardPreviousLayerTreeHostTimer;
 };
 
 } // namespace WebKit
index 48928b7..281353b 100644 (file)
@@ -102,17 +102,28 @@ void ThreadedCoordinatedLayerTreeHost::scrollNonCompositedContents(const IntRect
         return;
 
     m_viewportController.didScroll(rect.location());
-    didChangeViewport();
+    if (m_isDiscardable)
+        m_discardableSyncActions |= DiscardableSyncActions::UpdateViewport;
+    else
+        didChangeViewport();
 }
 
 void ThreadedCoordinatedLayerTreeHost::contentsSizeChanged(const IntSize& newSize)
 {
     m_viewportController.didChangeContentsSize(newSize);
-    didChangeViewport();
+    if (m_isDiscardable)
+        m_discardableSyncActions |= DiscardableSyncActions::UpdateViewport;
+    else
+        didChangeViewport();
 }
 
 void ThreadedCoordinatedLayerTreeHost::deviceOrPageScaleFactorChanged()
 {
+    if (m_isDiscardable) {
+        m_discardableSyncActions |= DiscardableSyncActions::UpdateScale;
+        return;
+    }
+
     if (m_surface && m_surface->resize(m_webPage.size()))
         m_layerTreeContext.contextID = m_surface->surfaceID();
 
@@ -122,12 +133,23 @@ void ThreadedCoordinatedLayerTreeHost::deviceOrPageScaleFactorChanged()
 
 void ThreadedCoordinatedLayerTreeHost::pageBackgroundTransparencyChanged()
 {
+    if (m_isDiscardable) {
+        m_discardableSyncActions |= DiscardableSyncActions::UpdateBackground;
+        return;
+    }
+
     CoordinatedLayerTreeHost::pageBackgroundTransparencyChanged();
     m_compositor->setDrawsBackground(m_webPage.drawsBackground());
 }
 
 void ThreadedCoordinatedLayerTreeHost::sizeDidChange(const IntSize& size)
 {
+    if (m_isDiscardable) {
+        m_discardableSyncActions |= DiscardableSyncActions::UpdateSize;
+        m_viewportController.didChangeViewportSize(size);
+        return;
+    }
+
     if (m_surface && m_surface->resize(size))
         m_layerTreeContext.contextID = m_surface->surfaceID();
 
@@ -142,7 +164,10 @@ void ThreadedCoordinatedLayerTreeHost::sizeDidChange(const IntSize& size)
 void ThreadedCoordinatedLayerTreeHost::didChangeViewportAttributes(ViewportAttributes&& attr)
 {
     m_viewportController.didChangeViewportAttributes(WTFMove(attr));
-    didChangeViewport();
+    if (m_isDiscardable)
+        m_discardableSyncActions |= DiscardableSyncActions::UpdateViewport;
+    else
+        didChangeViewport();
 }
 
 #if PLATFORM(GTK) && PLATFORM(X11) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
@@ -195,6 +220,33 @@ void ThreadedCoordinatedLayerTreeHost::commitSceneState(const CoordinatedGraphic
     m_compositor->updateSceneState(state);
 }
 
+void ThreadedCoordinatedLayerTreeHost::setIsDiscardable(bool discardable)
+{
+    m_isDiscardable = discardable;
+    if (m_isDiscardable) {
+        m_discardableSyncActions = OptionSet<DiscardableSyncActions>();
+        return;
+    }
+
+    if (m_discardableSyncActions.isEmpty())
+        return;
+
+    if (m_discardableSyncActions.contains(DiscardableSyncActions::UpdateBackground))
+        pageBackgroundTransparencyChanged();
+
+    if (m_discardableSyncActions.contains(DiscardableSyncActions::UpdateSize)) {
+        // Size changes already sets the scale factor and updates the viewport.
+        sizeDidChange(m_webPage.size());
+        return;
+    }
+
+    if (m_discardableSyncActions.contains(DiscardableSyncActions::UpdateScale))
+        deviceOrPageScaleFactorChanged();
+
+    if (m_discardableSyncActions.contains(DiscardableSyncActions::UpdateViewport))
+        didChangeViewport();
+}
+
 } // namespace WebKit
 
 #endif // USE(COORDINATED_GRAPHICS)
index 85ccde1..ca8aeac 100644 (file)
@@ -33,6 +33,7 @@
 #include "CoordinatedLayerTreeHost.h"
 #include "SimpleViewportController.h"
 #include "ThreadedCompositor.h"
+#include <wtf/OptionSet.h>
 
 namespace WebCore {
 class GraphicsContext;
@@ -66,6 +67,8 @@ private:
     void forceRepaint() override;
     bool forceRepaintAsync(uint64_t callbackID) override { return false; }
 
+    void setIsDiscardable(bool) override;
+
 #if PLATFORM(GTK) && PLATFORM(X11) &&  !USE(REDIRECTED_XCOMPOSITE_WINDOW)
     void setNativeSurfaceHandleForCompositing(uint64_t) override;
 #endif
@@ -98,12 +101,21 @@ private:
     void didFlushRootLayer(const WebCore::FloatRect&) override { }
     void commitSceneState(const WebCore::CoordinatedGraphicsState&) override;
 
+    enum class DiscardableSyncActions {
+        UpdateSize = 1 << 1,
+        UpdateViewport = 1 << 2,
+        UpdateScale = 1 << 3,
+        UpdateBackground = 1 << 4
+    };
+
     CompositorClient m_compositorClient;
     std::unique_ptr<AcceleratedSurface> m_surface;
     RefPtr<ThreadedCompositor> m_compositor;
     SimpleViewportController m_viewportController;
     float m_lastPageScaleFactor { 1 };
     WebCore::IntPoint m_lastScrollPosition;
+    bool m_isDiscardable { false };
+    OptionSet<DiscardableSyncActions> m_discardableSyncActions;
 };
 
 } // namespace WebKit
index 99917dd..a2da574 100644 (file)
@@ -98,6 +98,9 @@ void DrawingAreaImpl::scroll(const IntRect& scrollRect, const IntSize& scrollDel
     if (scrollRect.isEmpty())
         return;
 
+    if (m_previousLayerTreeHost)
+        m_previousLayerTreeHost->scrollNonCompositedContents(scrollRect);
+
     if (!m_scrollRect.isEmpty() && scrollRect != m_scrollRect) {
         unsigned scrollArea = scrollRect.width() * scrollRect.height();
         unsigned currentScrollArea = m_scrollRect.width() * m_scrollRect.height();
@@ -164,6 +167,8 @@ void DrawingAreaImpl::mainFrameContentSizeChanged(const WebCore::IntSize& newSiz
 #if USE(COORDINATED_GRAPHICS_THREADED)
     if (m_layerTreeHost)
         m_layerTreeHost->contentsSizeChanged(newSize);
+    else if (m_previousLayerTreeHost)
+        m_previousLayerTreeHost->contentsSizeChanged(newSize);
 #else
     UNUSED_PARAM(newSize);
 #endif
@@ -289,15 +294,7 @@ void DrawingAreaImpl::exitAcceleratedCompositingMode()
     if (m_alwaysUseCompositing)
         return;
 
-    ASSERT(!m_layerTreeStateIsFrozen);
-
-    m_exitCompositingTimer.stop();
-    m_wantsToExitAcceleratedCompositingMode = false;
-
-    ASSERT(m_layerTreeHost);
-
-    m_layerTreeHost->invalidate();
-    m_layerTreeHost = nullptr;
+    AcceleratedDrawingArea::exitAcceleratedCompositingModeNow();
     m_dirtyRegion = m_webPage.bounds();
 
     if (m_inUpdateBackingStoreState)
index 3c64686..70ee437 100644 (file)
@@ -89,6 +89,7 @@ public:
 
 #if USE(COORDINATED_GRAPHICS)
     virtual void scheduleAnimation() = 0;
+    virtual void setIsDiscardable(bool) { };
 #endif
 
 #if USE(TEXTURE_MAPPER_GL) && PLATFORM(GTK)