[Nicosia] Add SceneIntegration
authorzandobersek@gmail.com <zandobersek@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 13 Jun 2019 14:05:39 +0000 (14:05 +0000)
committerzandobersek@gmail.com <zandobersek@gmail.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 13 Jun 2019 14:05:39 +0000 (14:05 +0000)
https://bugs.webkit.org/show_bug.cgi?id=198791

Reviewed by Carlos Garcia Campos.

Source/WebCore:

Add the SceneIntegration class to the Nicosia namespace, primarily for
the purpose of being able to conveniently trigger scene updates whenever
changes are done to the state of layers that are included in that scene.
Initially this would be used for layer changes done on a
scrolling-dedicated thread.

Each Nicosia::PlatformLayer can have a SceneIntegration object reference
associated. Helper createUpdateScope() method returns a
SceneIntegration::UpdateScope instance that triggers an update for the
scene when that instance is destroyed (normally when it goes out of the
scope).

* platform/TextureMapper.cmake:
* platform/graphics/nicosia/NicosiaPlatformLayer.h:
(Nicosia::PlatformLayer::setSceneIntegration):
(Nicosia::PlatformLayer::createUpdateScope):
* platform/graphics/nicosia/NicosiaSceneIntegration.cpp: Added.
(Nicosia::SceneIntegration::SceneIntegration):
(Nicosia::SceneIntegration::~SceneIntegration):
(Nicosia::SceneIntegration::setClient):
(Nicosia::SceneIntegration::invalidate):
(Nicosia::SceneIntegration::requestUpdate):
(Nicosia::SceneIntegration::createUpdateScope):
(Nicosia::SceneIntegration::UpdateScope::UpdateScope):
(Nicosia::SceneIntegration::UpdateScope::~UpdateScope):
* platform/graphics/nicosia/NicosiaSceneIntegration.h: Added.

Source/WebKit:

Have the LayerTreeHost own the SceneIntegration object that's to be
associated with layers used inside the LayerTreeHost's scene. The
class now also inherits the SceneIntegration::Client interface, with the
requestUpdate() method scheduling a scene update in ThreadedCompositor.

CompositingCoordinator now retrieves the SceneIntegration object from
the LayerTreeHost instance and manages association to that object for
layers under the coordinator's control.

ThreadedCompositor class gets a new public updateScene() method that
schedules an update, enabling the SceneIntegration class to invoke
scene updates.

* Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp:
(WebKit::ThreadedCompositor::updateScene):
* Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h:
* WebProcess/WebPage/CoordinatedGraphics/CompositingCoordinator.cpp:
(WebKit::CompositingCoordinator::createGraphicsLayer):
(WebKit::CompositingCoordinator::detachLayer):
(WebKit::CompositingCoordinator::attachLayer):
* WebProcess/WebPage/CoordinatedGraphics/CompositingCoordinator.h:
* WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:
(WebKit::LayerTreeHost::LayerTreeHost):
(WebKit::LayerTreeHost::sceneIntegration):
(WebKit::LayerTreeHost::requestUpdate):
* WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h:

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

12 files changed:
Source/WebCore/ChangeLog
Source/WebCore/platform/TextureMapper.cmake
Source/WebCore/platform/graphics/nicosia/NicosiaPlatformLayer.h
Source/WebCore/platform/graphics/nicosia/NicosiaSceneIntegration.cpp [new file with mode: 0644]
Source/WebCore/platform/graphics/nicosia/NicosiaSceneIntegration.h [new file with mode: 0644]
Source/WebKit/ChangeLog
Source/WebKit/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp
Source/WebKit/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h
Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/CompositingCoordinator.cpp
Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/CompositingCoordinator.h
Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp
Source/WebKit/WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h

index b84bf5e..7a38ddc 100644 (file)
@@ -1,3 +1,37 @@
+2019-06-13  Zan Dobersek  <zdobersek@igalia.com>
+
+        [Nicosia] Add SceneIntegration
+        https://bugs.webkit.org/show_bug.cgi?id=198791
+
+        Reviewed by Carlos Garcia Campos.
+
+        Add the SceneIntegration class to the Nicosia namespace, primarily for
+        the purpose of being able to conveniently trigger scene updates whenever
+        changes are done to the state of layers that are included in that scene.
+        Initially this would be used for layer changes done on a
+        scrolling-dedicated thread.
+
+        Each Nicosia::PlatformLayer can have a SceneIntegration object reference
+        associated. Helper createUpdateScope() method returns a
+        SceneIntegration::UpdateScope instance that triggers an update for the
+        scene when that instance is destroyed (normally when it goes out of the
+        scope).
+
+        * platform/TextureMapper.cmake:
+        * platform/graphics/nicosia/NicosiaPlatformLayer.h:
+        (Nicosia::PlatformLayer::setSceneIntegration):
+        (Nicosia::PlatformLayer::createUpdateScope):
+        * platform/graphics/nicosia/NicosiaSceneIntegration.cpp: Added.
+        (Nicosia::SceneIntegration::SceneIntegration):
+        (Nicosia::SceneIntegration::~SceneIntegration):
+        (Nicosia::SceneIntegration::setClient):
+        (Nicosia::SceneIntegration::invalidate):
+        (Nicosia::SceneIntegration::requestUpdate):
+        (Nicosia::SceneIntegration::createUpdateScope):
+        (Nicosia::SceneIntegration::UpdateScope::UpdateScope):
+        (Nicosia::SceneIntegration::UpdateScope::~UpdateScope):
+        * platform/graphics/nicosia/NicosiaSceneIntegration.h: Added.
+
 2019-06-13  Philippe Normand  <pnormand@igalia.com>
 
         [GStreamer] HLS stream slow start
index 28b7e17..9198e20 100644 (file)
@@ -82,6 +82,7 @@ if (USE_COORDINATED_GRAPHICS)
         platform/graphics/nicosia/NicosiaPaintingEngineThreaded.cpp
         platform/graphics/nicosia/NicosiaPlatformLayer.cpp
         platform/graphics/nicosia/NicosiaScene.cpp
+        platform/graphics/nicosia/NicosiaSceneIntegration.cpp
 
         platform/graphics/nicosia/cairo/NicosiaCairoOperationRecorder.cpp
         platform/graphics/nicosia/cairo/NicosiaPaintingContextCairo.cpp
@@ -100,6 +101,7 @@ if (USE_COORDINATED_GRAPHICS)
         platform/graphics/nicosia/NicosiaPaintingEngine.h
         platform/graphics/nicosia/NicosiaPlatformLayer.h
         platform/graphics/nicosia/NicosiaScene.h
+        platform/graphics/nicosia/NicosiaSceneIntegration.h
 
         platform/graphics/nicosia/texmap/NicosiaBackingStoreTextureMapperImpl.h
         platform/graphics/nicosia/texmap/NicosiaCompositionLayerTextureMapperImpl.h
index be3a525..a3bf287 100644 (file)
@@ -34,6 +34,7 @@
 #include "FloatPoint3D.h"
 #include "FloatRect.h"
 #include "FloatSize.h"
+#include "NicosiaSceneIntegration.h"
 #include "TextureMapperAnimation.h"
 #include "TransformationMatrix.h"
 #include <wtf/Function.h>
@@ -53,6 +54,20 @@ public:
     using LayerID = uint64_t;
     LayerID id() const { return m_id; }
 
+    void setSceneIntegration(RefPtr<SceneIntegration>&& sceneIntegration)
+    {
+        LockHolder locker(m_state.lock);
+        m_state.sceneIntegration = WTFMove(sceneIntegration);
+    }
+
+    std::unique_ptr<SceneIntegration::UpdateScope> createUpdateScope()
+    {
+        LockHolder locker(m_state.lock);
+        if (m_state.sceneIntegration)
+            return m_state.sceneIntegration->createUpdateScope();
+        return nullptr;
+    }
+
 protected:
     explicit PlatformLayer(uint64_t);
 
@@ -60,6 +75,7 @@ protected:
 
     struct {
         Lock lock;
+        RefPtr<SceneIntegration> sceneIntegration;
     } m_state;
 };
 
diff --git a/Source/WebCore/platform/graphics/nicosia/NicosiaSceneIntegration.cpp b/Source/WebCore/platform/graphics/nicosia/NicosiaSceneIntegration.cpp
new file mode 100644 (file)
index 0000000..109c2c5
--- /dev/null
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 Metrological Group B.V.
+ * Copyright (C) 2019 Igalia S.L.
+ *
+ * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * HOLDER OR 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 "NicosiaSceneIntegration.h"
+
+namespace Nicosia {
+
+SceneIntegration::SceneIntegration(Client& client)
+{
+    m_client.object = &client;
+}
+
+SceneIntegration::~SceneIntegration()
+{
+    ASSERT(!m_client.object);
+}
+
+void SceneIntegration::setClient(Client& client)
+{
+    LockHolder locker(m_client.lock);
+    m_client.object = &client;
+}
+
+void SceneIntegration::invalidate()
+{
+    LockHolder locker(m_client.lock);
+    m_client.object = nullptr;
+}
+
+void SceneIntegration::requestUpdate()
+{
+    LockHolder locker(m_client.lock);
+    if (m_client.object)
+        m_client.object->requestUpdate();
+}
+
+std::unique_ptr<SceneIntegration::UpdateScope> SceneIntegration::createUpdateScope()
+{
+    return std::make_unique<UpdateScope>(makeRef(*this));
+}
+
+SceneIntegration::Client::~Client() = default;
+
+SceneIntegration::UpdateScope::UpdateScope(Ref<SceneIntegration>&& sceneIntegration)
+    : m_sceneIntegration(WTFMove(sceneIntegration))
+    , m_locker(m_sceneIntegration->m_client.lock)
+{
+}
+
+SceneIntegration::UpdateScope::~UpdateScope()
+{
+    auto& sceneIntegrationObj = m_sceneIntegration.get();
+    if (sceneIntegrationObj.m_client.object)
+        sceneIntegrationObj.m_client.object->requestUpdate();
+}
+
+} // namespace Nicosia
diff --git a/Source/WebCore/platform/graphics/nicosia/NicosiaSceneIntegration.h b/Source/WebCore/platform/graphics/nicosia/NicosiaSceneIntegration.h
new file mode 100644 (file)
index 0000000..4050b01
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2019 Metrological Group B.V.
+ * Copyright (C) 2019 Igalia S.L.
+ *
+ * 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * HOLDER OR 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.
+ */
+
+#pragma once
+
+#include <memory>
+#include <wtf/Lock.h>
+#include <wtf/Ref.h>
+#include <wtf/ThreadSafeRefCounted.h>
+
+namespace Nicosia {
+
+class SceneIntegration : public ThreadSafeRefCounted<SceneIntegration> {
+public:
+    class Client {
+    public:
+        virtual ~Client();
+
+        virtual void requestUpdate() = 0;
+    };
+
+    static Ref<SceneIntegration> create(Client& client)
+    {
+        return adoptRef(*new SceneIntegration(client));
+    }
+    ~SceneIntegration();
+
+    void setClient(Client&);
+    void invalidate();
+
+    void requestUpdate();
+
+    class UpdateScope {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        explicit UpdateScope(Ref<SceneIntegration>&&);
+        ~UpdateScope();
+
+    private:
+        Ref<SceneIntegration> m_sceneIntegration;
+        LockHolder m_locker;
+    };
+
+    std::unique_ptr<UpdateScope> createUpdateScope();
+
+private:
+    explicit SceneIntegration(Client&);
+
+    struct {
+        Lock lock;
+        Client* object { nullptr };
+    } m_client;
+};
+
+} // namespace Nicosia
index 80a2155..027e9ab 100644 (file)
@@ -1,3 +1,37 @@
+2019-06-13  Zan Dobersek  <zdobersek@igalia.com>
+
+        [Nicosia] Add SceneIntegration
+        https://bugs.webkit.org/show_bug.cgi?id=198791
+
+        Reviewed by Carlos Garcia Campos.
+
+        Have the LayerTreeHost own the SceneIntegration object that's to be
+        associated with layers used inside the LayerTreeHost's scene. The
+        class now also inherits the SceneIntegration::Client interface, with the
+        requestUpdate() method scheduling a scene update in ThreadedCompositor.
+
+        CompositingCoordinator now retrieves the SceneIntegration object from
+        the LayerTreeHost instance and manages association to that object for
+        layers under the coordinator's control.
+
+        ThreadedCompositor class gets a new public updateScene() method that
+        schedules an update, enabling the SceneIntegration class to invoke
+        scene updates.
+
+        * Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp:
+        (WebKit::ThreadedCompositor::updateScene):
+        * Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h:
+        * WebProcess/WebPage/CoordinatedGraphics/CompositingCoordinator.cpp:
+        (WebKit::CompositingCoordinator::createGraphicsLayer):
+        (WebKit::CompositingCoordinator::detachLayer):
+        (WebKit::CompositingCoordinator::attachLayer):
+        * WebProcess/WebPage/CoordinatedGraphics/CompositingCoordinator.h:
+        * WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.cpp:
+        (WebKit::LayerTreeHost::LayerTreeHost):
+        (WebKit::LayerTreeHost::sceneIntegration):
+        (WebKit::LayerTreeHost::requestUpdate):
+        * WebProcess/WebPage/CoordinatedGraphics/LayerTreeHost.h:
+
 2019-06-13  Ludovico de Nittis  <ludovico.denittis@collabora.com>
 
         [GTK] gdk_display_get_device_manager and gdk_screen_get_width/height are deprecated
index e84d52f..cd3e57c 100644 (file)
@@ -269,6 +269,11 @@ void ThreadedCompositor::updateSceneState(const CoordinatedGraphicsState& state)
     m_compositingRunLoop->scheduleUpdate();
 }
 
+void ThreadedCompositor::updateScene()
+{
+    m_compositingRunLoop->scheduleUpdate();
+}
+
 #if USE(REQUEST_ANIMATION_FRAME_DISPLAY_MONITOR)
 RefPtr<WebCore::DisplayRefreshMonitor> ThreadedCompositor::displayRefreshMonitor(PlatformDisplayID)
 {
index 66fe3f1..490640d 100644 (file)
@@ -69,6 +69,7 @@ public:
     void setViewportSize(const WebCore::IntSize&, float scale);
 
     void updateSceneState(const WebCore::CoordinatedGraphicsState&);
+    void updateScene();
 
     void invalidate();
 
index be640e9..9e56dce 100644 (file)
@@ -235,7 +235,11 @@ Ref<GraphicsLayer> CompositingCoordinator::createGraphicsLayer(GraphicsLayer::Ty
 {
     auto layer = adoptRef(*new CoordinatedGraphicsLayer(layerType, client));
     layer->setCoordinator(this);
-    m_nicosia.state.layers.add(layer->compositionLayer());
+    {
+        auto& compositionLayer = layer->compositionLayer();
+        m_nicosia.state.layers.add(compositionLayer);
+        compositionLayer->setSceneIntegration(m_client.sceneIntegration());
+    }
     m_registeredLayers.add(layer->id(), layer.ptr());
     layer->setNeedsVisibleRectAdjustment();
     notifyFlushRequired(layer.ptr());
@@ -275,7 +279,11 @@ void CompositingCoordinator::detachLayer(CoordinatedGraphicsLayer* layer)
     if (m_isPurging)
         return;
 
-    m_nicosia.state.layers.remove(layer->compositionLayer());
+    {
+        auto& compositionLayer = layer->compositionLayer();
+        m_nicosia.state.layers.remove(compositionLayer);
+        compositionLayer->setSceneIntegration(nullptr);
+    }
     m_registeredLayers.remove(layer->id());
     notifyFlushRequired(layer);
 }
@@ -283,7 +291,11 @@ void CompositingCoordinator::detachLayer(CoordinatedGraphicsLayer* layer)
 void CompositingCoordinator::attachLayer(CoordinatedGraphicsLayer* layer)
 {
     layer->setCoordinator(this);
-    m_nicosia.state.layers.add(layer->compositionLayer());
+    {
+        auto& compositionLayer = layer->compositionLayer();
+        m_nicosia.state.layers.add(compositionLayer);
+        compositionLayer->setSceneIntegration(m_client.sceneIntegration());
+    }
     m_registeredLayers.add(layer->id(), layer);
     layer->setNeedsVisibleRectAdjustment();
     notifyFlushRequired(layer);
index b4a0d15..79ccccb 100644 (file)
@@ -40,6 +40,7 @@
 
 namespace Nicosia {
 class PaintingEngine;
+class SceneIntegration;
 }
 
 namespace WebCore {
@@ -60,6 +61,7 @@ public:
         virtual void didFlushRootLayer(const WebCore::FloatRect& visibleContentRect) = 0;
         virtual void notifyFlushRequired() = 0;
         virtual void commitSceneState(const WebCore::CoordinatedGraphicsState&) = 0;
+        virtual RefPtr<Nicosia::SceneIntegration> sceneIntegration() = 0;
     };
 
     CompositingCoordinator(WebCore::Page*, CompositingCoordinator::Client&);
index 880c4e3..6935a16 100644 (file)
@@ -53,6 +53,7 @@ LayerTreeHost::LayerTreeHost(WebPage& webPage)
     , m_surface(AcceleratedSurface::create(webPage, *this))
     , m_viewportController(webPage.size())
     , m_layerFlushTimer(RunLoop::main(), this, &LayerTreeHost::layerFlushTimerFired)
+    , m_sceneIntegration(Nicosia::SceneIntegration::create(*this))
 {
 #if USE(GLIB_EVENT_LOOP)
     m_layerFlushTimer.setPriority(RunLoopSourcePriority::LayerFlushTimer);
@@ -366,11 +367,21 @@ void LayerTreeHost::commitSceneState(const CoordinatedGraphicsState& state)
     m_compositor->updateSceneState(state);
 }
 
+RefPtr<Nicosia::SceneIntegration> LayerTreeHost::sceneIntegration()
+{
+    return m_sceneIntegration.copyRef();
+}
+
 void LayerTreeHost::frameComplete()
 {
     m_compositor->frameComplete();
 }
 
+void LayerTreeHost::requestUpdate()
+{
+    m_compositor->updateScene();
+}
+
 uint64_t LayerTreeHost::nativeSurfaceHandleForCompositing()
 {
     m_surface->initialize();
index cc3b691..54ede6c 100644 (file)
 #include <wtf/OptionSet.h>
 #include <wtf/RunLoop.h>
 
+#if USE(COORDINATED_GRAPHICS)
+#include <WebCore/NicosiaSceneIntegration.h>
+#endif
+
 namespace WebCore {
 class IntRect;
 class IntSize;
@@ -54,7 +58,7 @@ class WebPage;
 
 class LayerTreeHost
 #if USE(COORDINATED_GRAPHICS)
-    final : public CompositingCoordinator::Client, public AcceleratedSurface::Client
+    final : public CompositingCoordinator::Client, public AcceleratedSurface::Client, public Nicosia::SceneIntegration::Client
 #endif
 {
     WTF_MAKE_FAST_ALLOCATED;
@@ -103,10 +107,14 @@ private:
     void didFlushRootLayer(const WebCore::FloatRect& visibleContentRect) override;
     void notifyFlushRequired() override { scheduleLayerFlush(); };
     void commitSceneState(const WebCore::CoordinatedGraphicsState&) override;
+    RefPtr<Nicosia::SceneIntegration> sceneIntegration() override;
 
     // AcceleratedSurface::Client
     void frameComplete() override;
 
+    // Nicosia::SceneIntegration::Client
+    void requestUpdate() override;
+
     uint64_t nativeSurfaceHandleForCompositing();
     void didDestroyGLContext();
     void willRenderFrame();
@@ -193,6 +201,7 @@ private:
         bool needsFreshFlush { false };
     } m_forceRepaintAsync;
     RunLoop::Timer<LayerTreeHost> m_layerFlushTimer;
+    Ref<Nicosia::SceneIntegration> m_sceneIntegration;
 #endif // USE(COORDINATED_GRAPHICS)
 };