[GTK] Accelerated compositing does not work in Wayland
authorcarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 29 Aug 2016 09:33:40 +0000 (09:33 +0000)
committercarlosgc@webkit.org <carlosgc@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 29 Aug 2016 09:33:40 +0000 (09:33 +0000)
https://bugs.webkit.org/show_bug.cgi?id=115803

Reviewed by Michael Catanzaro.

Source/WebCore:

The Wayland implementation in WebKit2 uses a nested display running in the UI process so that GL contexts created
in the web process need to be created in the nested display. We currently have a shared platform display that
should represent the connection to the actual display all applications connect to. This patch refactors the
GLContext API to ensure that GL contexts are always attached to a particular platform display. The create
methods receive an optional PlatformDisplay that will be used as the display of all GL operations of the created
GL context. The sharing GL context should also share the same display, it can't be global to the process, but to
the display, so it's now created on demand by the PlatformDisplay. In addition to the global shared display,
it's now possible to set a shared display for compositing that can be used when creating GL contexts. This makes
it possible to use a different display for compositing, connected to the nested display in wayland, even in non
wayland environments.
The patch also adds support for surfaceless EGL contexts that can be used for offscreen contexts. It also adds
support for offscreen wayland contexts, as a fallback in wayland in case surfaceless is not supported.
Some wayland code that is specific to the WebKit2 implementation has been moved to the WebKit2 layer.

* PlatformGTK.cmake:
* platform/graphics/GLContext.cpp:
(WebCore::initializeOpenGLShimsIfNeeded):
(WebCore::GLContext::createContextForWindow):
(WebCore::GLContext::createOffscreenContext):
(WebCore::GLContext::createSharingContext):
(WebCore::GLContext::GLContext):
(WebCore::GLContext::~GLContext):
(WebCore::GLContext::current):
(WebCore::activeContextList): Deleted.
* platform/graphics/GLContext.h:
(WebCore::GLContext::display):
* platform/graphics/GraphicsContext3DPrivate.cpp:
(WebCore::GraphicsContext3DPrivate::GraphicsContext3DPrivate):
(WebCore::GraphicsContext3DPrivate::platformContext):
(WebCore::GraphicsContext3DPrivate::paintToTextureMapper):
* platform/graphics/PlatformDisplay.cpp:
(WebCore::PlatformDisplay::createPlatformDisplay): Always use the default wayland display created by GTK+ for
the global shared display.
(WebCore::PlatformDisplay::sharedDisplayForCompositing):
(WebCore::PlatformDisplay::setSharedDisplayForCompositing):
(WebCore::PlatformDisplay::sharingGLContext):
(WebCore::eglDisplays): Helper HashSet to keep track of all PlatformDisplays with an EGL display intialized to
properly termimate them at exit.
(WebCore::PlatformDisplay::initializeEGLDisplay): Remove eglBindAPI() from display initialization, since it's
not a display initialization and it's thread specific, so it needs to be called on every thread where EGL is used.
(WebCore::PlatformDisplay::terminateEGLDisplay):
(WebCore::PlatformDisplay::eglDisplay): Deleted.
* platform/graphics/PlatformDisplay.h:
* platform/graphics/cairo/ImageBufferCairo.cpp:
(WebCore::ImageBufferData::~ImageBufferData):
(WebCore::ImageBufferData::createCompositorBuffer):
(WebCore::ImageBufferData::swapBuffersIfNeeded):
(WebCore::ImageBufferData::createCairoGLSurface):
(WebCore::ImageBufferData::paintToTextureMapper):
(WebCore::ImageBuffer::copyToPlatformTexture):
* platform/graphics/egl/GLContextEGL.cpp:
(WebCore::GLContextEGL::getEGLConfig):
(WebCore::GLContextEGL::createWindowContext):
(WebCore::GLContextEGL::createPbufferContext):
(WebCore::GLContextEGL::createSurfacelessContext):
(WebCore::GLContextEGL::createPixmapContext):
(WebCore::GLContextEGL::createWaylandContext):
(WebCore::GLContextEGL::createContext):
(WebCore::GLContextEGL::createSharingContext):
(WebCore::GLContextEGL::GLContextEGL):
(WebCore::GLContextEGL::~GLContextEGL):
(WebCore::GLContextEGL::defaultFrameBufferSize):
(WebCore::GLContextEGL::makeContextCurrent):
(WebCore::GLContextEGL::swapBuffers):
(WebCore::GLContextEGL::cairoDevice):
* platform/graphics/egl/GLContextEGL.h:
* platform/graphics/glx/GLContextGLX.cpp:
(WebCore::GLContextGLX::createWindowContext):
(WebCore::GLContextGLX::createPbufferContext):
(WebCore::GLContextGLX::createPixmapContext):
(WebCore::GLContextGLX::createContext):
(WebCore::GLContextGLX::createSharingContext):
(WebCore::GLContextGLX::GLContextGLX):
(WebCore::GLContextGLX::~GLContextGLX):
(WebCore::GLContextGLX::defaultFrameBufferSize):
(WebCore::GLContextGLX::makeContextCurrent):
(WebCore::GLContextGLX::swapBuffers):
(WebCore::GLContextGLX::cairoDevice):
(WebCore::GLContextGLX::waitNative): Deleted.
* platform/graphics/glx/GLContextGLX.h:
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
(WebCore::MediaPlayerPrivateGStreamerBase::ensureGstGLContext):
(WebCore::MediaPlayerPrivateGStreamerBase::nativeImageForCurrentTime):
* platform/graphics/wayland/PlatformDisplayWayland.cpp:
(WebCore::PlatformDisplayWayland::PlatformDisplayWayland):
(WebCore::PlatformDisplayWayland::~PlatformDisplayWayland):
(WebCore::PlatformDisplayWayland::initialize):
(WebCore::PlatformDisplayWayland::registryGlobal):
(WebCore::PlatformDisplayWayland::createSurface):
* platform/graphics/wayland/PlatformDisplayWayland.h:
(WebCore::PlatformDisplayWayland::native): Deleted.
* platform/graphics/wayland/WaylandEventSource.cpp: Removed.
* platform/graphics/wayland/WaylandSurface.cpp: Removed.
* platform/graphics/wayland/WebKitGtkWaylandClientProtocol.xml: Removed.
* platform/graphics/wayland/WlUniquePtr.h: Make it possible to use std::unique_ptr with Wayland objects.
(WebCore::WlPtrDeleter::operator()):

Source/WebKit/win:

Update to the new GLContext API.

* WebCoreSupport/AcceleratedCompositingContext.cpp:
(AcceleratedCompositingContext::initialize):
(AcceleratedCompositingContext::acceleratedCompositingAvailable):

Source/WebKit2:

This is the initial implementation of accelerated compositing support in Wayland for the GTK+ port. It's based
on previous patches written by Iago Toral, Žan Doberšek, Emanuele Aina and Emilio Pozuelo Monfort.

The existing WebKitGTK+ Wayland interface previously added for this to WebCore has been moved to the WebKit2
layer, since it's actually specific to WebKit2, and it's now actually used. The UI process runs a nested Wayland
compositor that web processes connect to. Web processes create a Wayland surface in the nested compositor for
the web page, and using the WebKitGTK+ Wayland protocol interface they tell the nested compositor the web page
associated to the surface. A Wayland window is created for that surface that is then used as the native window
handle for compositing. To communicate with the nested compositor and to ensure all GL operations happen in the
nested compositor display, the web process creates a Wayland display that connects to the nested compositor,
uses the WebKitGTK+ Wayland interface and it's set as the global shared display for compositing.

The nested Wayland compositor creates a new display with a unique name that is sent to the web processes at
start up. It implements the Wayland surface interface to handle the Wayland buffers created for every surface
and scheduling redraws on the web pages when updates are available. It uses the WebKitGTK+ Wayland interface to
associate the surfaces to a particular web page. A texture is created for every surface and updated with the
Wayland buffer contents using an EGLImageKHR and eglImageTargetTexture2d API.

To abstract the platform differences and avoid ifdefs as much as possible, new abstract classes have been added
to represent the surfaces used in accelerated compositing. AcceleratedSurface is used by the web process and
represents the surface where contents are rendered into. The X11 implementation is the redirected XComposite
window, and the Wayland implementation is equivalent to the previous Wayland surface added to WebCore but never
used. In the UI process the web view creates an abstract AcceleratedBackingStore that is used to render the
AcceleratedSurface into the web view using cairo. The X11 implementation creates the cairo surface for the
redirected XComposite window pixmap and uses XDamage extension to schedule redraws. The Wayland implementation
asks the nested Wayland compositor for the texture associated to the web view page.

Accelerated compositing is now always enabled by default in both X11 and Wayland, unless it's explicitly
disabled by the user using the WEBKIT_DISABLE_COMPOSITING_MODE environment variable, or if any extension or
feature required by X11 or Wayland implementations are not available.

* PlatformGTK.cmake:
* Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp:
(WebKit::ThreadedCompositor::glContext): Pass the shared display for compositing to GLContext::createContextForWindow()
* Shared/WebProcessCreationParameters.cpp:
(WebKit::WebProcessCreationParameters::encode): Encode wayland compositor display name.
(WebKit::WebProcessCreationParameters::decode): Decode wayland compositor display name.
* Shared/WebProcessCreationParameters.h: Add wayland compositor display name initial parameter.
* UIProcess/API/gtk/WebKitWebViewBase.cpp:
(webkitWebViewBaseDispose):
(webkitWebViewBaseDraw):
(webkitWebViewBaseCreateWebPage):
(webkitWebViewBaseEnterAcceleratedCompositingMode):
(webkitWebViewBaseUpdateAcceleratedCompositingMode):
(webkitWebViewBaseExitAcceleratedCompositingMode):
(webkitWebViewBasePageClosed):
* UIProcess/WebProcessPool.cpp:
(WebKit::WebProcessPool::createNewWebProcess): Initialize the wayland compositor display name initial parameter.
* UIProcess/gtk/AcceleratedBackingStore.cpp: Added.
(WebKit::AcceleratedBackingStore::create):
(WebKit::AcceleratedBackingStore::AcceleratedBackingStore):
(WebKit::AcceleratedBackingStore::~AcceleratedBackingStore):
(WebKit::AcceleratedBackingStore::paint):
* UIProcess/gtk/AcceleratedBackingStore.h: Added.
(WebKit::AcceleratedBackingStore::update):
* UIProcess/gtk/AcceleratedBackingStoreWayland.cpp: Added.
(WebKit::AcceleratedBackingStoreWayland::create):
(WebKit::AcceleratedBackingStoreWayland::AcceleratedBackingStoreWayland):
(WebKit::AcceleratedBackingStoreWayland::~AcceleratedBackingStoreWayland):
(WebKit::AcceleratedBackingStoreWayland::paint):
* UIProcess/gtk/AcceleratedBackingStoreWayland.h: Added.
* UIProcess/gtk/AcceleratedBackingStoreX11.cpp: Added.
(WebKit::XDamageNotifier::singleton):
(WebKit::XDamageNotifier::add):
(WebKit::XDamageNotifier::remove):
(WebKit::XDamageNotifier::filterXDamageEvent):
(WebKit::XDamageNotifier::notify):
(WebKit::AcceleratedBackingStoreX11::create):
(WebKit::AcceleratedBackingStoreX11::AcceleratedBackingStoreX11):
(WebKit::AcceleratedBackingStoreX11::~AcceleratedBackingStoreX11):
(WebKit::AcceleratedBackingStoreX11::update):
(WebKit::AcceleratedBackingStoreX11::paint):
* UIProcess/gtk/AcceleratedBackingStoreX11.h: Added.
* UIProcess/gtk/WaylandCompositor.cpp: Added.
(WebKit::WaylandCompositor::singleton):
(WebKit::WaylandCompositor::Buffer::getOrCreate):
(WebKit::WaylandCompositor::Buffer::Buffer):
(WebKit::WaylandCompositor::Buffer::~Buffer):
(WebKit::WaylandCompositor::Buffer::destroyListenerCallback):
(WebKit::WaylandCompositor::Buffer::use):
(WebKit::WaylandCompositor::Buffer::unuse):
(WebKit::WaylandCompositor::Buffer::createImage):
(WebKit::WaylandCompositor::Buffer::size):
(WebKit::WaylandCompositor::Surface::Surface):
(WebKit::WaylandCompositor::Surface::~Surface):
(WebKit::WaylandCompositor::Surface::makePendingBufferCurrent):
(WebKit::WaylandCompositor::Surface::attachBuffer):
(WebKit::WaylandCompositor::Surface::requestFrame):
(WebKit::WaylandCompositor::Surface::prepareTextureForPainting):
(WebKit::WaylandCompositor::Surface::commit):
(WebKit::WaylandCompositor::initializeEGL):
(WebKit::createWaylandLoopSource):
(WebKit::WaylandCompositor::WaylandCompositor):
(WebKit::WaylandCompositor::getTexture):
(WebKit::WaylandCompositor::bindSurfaceToWebPage):
(WebKit::WaylandCompositor::registerWebPage):
(WebKit::WaylandCompositor::unregisterWebPage):
* UIProcess/gtk/WaylandCompositor.h: Added.
(WebKit::WaylandCompositor::Buffer::createWeakPtr):
(WebKit::WaylandCompositor::Surface::setWebPage):
(WebKit::WaylandCompositor::isRunning):
(WebKit::WaylandCompositor::displayName):
* UIProcess/gtk/WebPreferencesGtk.cpp:
(WebKit::WebPreferences::platformInitializeStore):
* UIProcess/gtk/XDamageNotifier.cpp: Removed.
* WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.cpp:
(WebKit::ThreadedCoordinatedLayerTreeHost::ThreadedCoordinatedLayerTreeHost):
(WebKit::ThreadedCoordinatedLayerTreeHost::invalidate):
(WebKit::ThreadedCoordinatedLayerTreeHost::deviceOrPageScaleFactorChanged):
(WebKit::ThreadedCoordinatedLayerTreeHost::sizeDidChange):
* WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.h:
* WebProcess/WebPage/gtk/AcceleratedSurface.cpp: Added.
(WebKit::AcceleratedSurface::create):
(WebKit::AcceleratedSurface::AcceleratedSurface):
(WebKit::AcceleratedSurface::~AcceleratedSurface):
(WebKit::AcceleratedSurface::resize):
* WebProcess/WebPage/gtk/AcceleratedSurface.h: Added.
(WebKit::AcceleratedSurface::window):
(WebKit::AcceleratedSurface::surfaceID):
* WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp: Added.
(WebKit::waylandCompositorDisplay):
(WebKit::AcceleratedSurfaceWayland::create):
(WebKit::AcceleratedSurfaceWayland::AcceleratedSurfaceWayland):
(WebKit::AcceleratedSurfaceWayland::~AcceleratedSurfaceWayland):
(WebKit::AcceleratedSurfaceWayland::resize):
* WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h: Added.
* WebProcess/WebPage/gtk/AcceleratedSurfaceX11.cpp: Renamed from Source/WebKit2/WebProcess/WebPage/gtk/RedirectedXCompositeWindow.cpp.
(WebKit::AcceleratedSurfaceX11::create):
(WebKit::AcceleratedSurfaceX11::AcceleratedSurfaceX11):
(WebKit::AcceleratedSurfaceX11::~AcceleratedSurfaceX11):
(WebKit::AcceleratedSurfaceX11::resize):
* WebProcess/WebPage/gtk/AcceleratedSurfaceX11.h: Renamed from Source/WebKit2/WebProcess/WebPage/gtk/RedirectedXCompositeWindow.h.
* WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp:
(WebKit::LayerTreeHostGtk::LayerTreeHostGtk):
(WebKit::LayerTreeHostGtk::makeContextCurrent):
(WebKit::LayerTreeHostGtk::invalidate):
(WebKit::LayerTreeHostGtk::sizeDidChange):
(WebKit::LayerTreeHostGtk::deviceOrPageScaleFactorChanged):
(WebKit::LayerTreeHostGtk::RenderFrameScheduler::RenderFrameScheduler): Deleted.
* WebProcess/WebPage/gtk/LayerTreeHostGtk.h:
* WebProcess/WebProcess.cpp:
(WebKit::WebProcess::initializeWebProcess): Initialize the wayland compositor display name.
* WebProcess/WebProcess.h:
(WebKit::WebProcess::waylandCompositorDisplayName): Return the wayland compositor display name.

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

53 files changed:
Source/WebCore/ChangeLog
Source/WebCore/PlatformGTK.cmake
Source/WebCore/platform/graphics/GLContext.cpp
Source/WebCore/platform/graphics/GLContext.h
Source/WebCore/platform/graphics/GraphicsContext3DPrivate.cpp
Source/WebCore/platform/graphics/PlatformDisplay.cpp
Source/WebCore/platform/graphics/PlatformDisplay.h
Source/WebCore/platform/graphics/cairo/ImageBufferCairo.cpp
Source/WebCore/platform/graphics/egl/GLContextEGL.cpp
Source/WebCore/platform/graphics/egl/GLContextEGL.h
Source/WebCore/platform/graphics/glx/GLContextGLX.cpp
Source/WebCore/platform/graphics/glx/GLContextGLX.h
Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp
Source/WebCore/platform/graphics/wayland/PlatformDisplayWayland.cpp
Source/WebCore/platform/graphics/wayland/PlatformDisplayWayland.h
Source/WebCore/platform/graphics/wayland/WaylandEventSource.cpp [deleted file]
Source/WebCore/platform/graphics/wayland/WaylandSurface.cpp [deleted file]
Source/WebCore/platform/graphics/wayland/WlUniquePtr.h [new file with mode: 0644]
Source/WebKit/win/ChangeLog
Source/WebKit/win/WebCoreSupport/AcceleratedCompositingContext.cpp
Source/WebKit2/ChangeLog
Source/WebKit2/PlatformGTK.cmake
Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp
Source/WebKit2/Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.h
Source/WebKit2/Shared/WebProcessCreationParameters.cpp
Source/WebKit2/Shared/WebProcessCreationParameters.h
Source/WebKit2/Shared/gtk/WebKit2WaylandProtocol.xml [moved from Source/WebCore/platform/graphics/wayland/WebKitGtkWaylandClientProtocol.xml with 94% similarity]
Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp
Source/WebKit2/UIProcess/AcceleratedDrawingAreaProxy.cpp
Source/WebKit2/UIProcess/WebProcessPool.cpp
Source/WebKit2/UIProcess/gtk/AcceleratedBackingStore.cpp [new file with mode: 0644]
Source/WebKit2/UIProcess/gtk/AcceleratedBackingStore.h [moved from Source/WebCore/platform/graphics/wayland/WaylandSurface.h with 64% similarity]
Source/WebKit2/UIProcess/gtk/AcceleratedBackingStoreWayland.cpp [new file with mode: 0644]
Source/WebKit2/UIProcess/gtk/AcceleratedBackingStoreWayland.h [moved from Source/WebCore/platform/graphics/wayland/WaylandEventSource.h with 68% similarity]
Source/WebKit2/UIProcess/gtk/AcceleratedBackingStoreX11.cpp [new file with mode: 0644]
Source/WebKit2/UIProcess/gtk/AcceleratedBackingStoreX11.h [new file with mode: 0644]
Source/WebKit2/UIProcess/gtk/WaylandCompositor.cpp [new file with mode: 0644]
Source/WebKit2/UIProcess/gtk/WaylandCompositor.h [new file with mode: 0644]
Source/WebKit2/UIProcess/gtk/WebPreferencesGtk.cpp
Source/WebKit2/UIProcess/gtk/XDamageNotifier.cpp [deleted file]
Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.cpp
Source/WebKit2/WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.h
Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurface.cpp [new file with mode: 0644]
Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurface.h [moved from Source/WebKit2/UIProcess/gtk/XDamageNotifier.h with 68% similarity]
Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp [new file with mode: 0644]
Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h [new file with mode: 0644]
Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceX11.cpp [moved from Source/WebKit2/WebProcess/WebPage/gtk/RedirectedXCompositeWindow.cpp with 87% similarity]
Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceX11.h [moved from Source/WebKit2/WebProcess/WebPage/gtk/RedirectedXCompositeWindow.h with 77% similarity]
Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp
Source/WebKit2/WebProcess/WebPage/gtk/LayerTreeHostGtk.h
Source/WebKit2/WebProcess/WebProcess.cpp
Source/WebKit2/WebProcess/WebProcess.h
Source/cmake/OptionsGTK.cmake

index d475081..06d2495 100644 (file)
@@ -1,3 +1,107 @@
+2016-08-16  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK] Accelerated compositing does not work in Wayland
+        https://bugs.webkit.org/show_bug.cgi?id=115803
+
+        Reviewed by Michael Catanzaro.
+
+        The Wayland implementation in WebKit2 uses a nested display running in the UI process so that GL contexts created
+        in the web process need to be created in the nested display. We currently have a shared platform display that
+        should represent the connection to the actual display all applications connect to. This patch refactors the
+        GLContext API to ensure that GL contexts are always attached to a particular platform display. The create
+        methods receive an optional PlatformDisplay that will be used as the display of all GL operations of the created
+        GL context. The sharing GL context should also share the same display, it can't be global to the process, but to
+        the display, so it's now created on demand by the PlatformDisplay. In addition to the global shared display,
+        it's now possible to set a shared display for compositing that can be used when creating GL contexts. This makes
+        it possible to use a different display for compositing, connected to the nested display in wayland, even in non
+        wayland environments.
+        The patch also adds support for surfaceless EGL contexts that can be used for offscreen contexts. It also adds
+        support for offscreen wayland contexts, as a fallback in wayland in case surfaceless is not supported.
+        Some wayland code that is specific to the WebKit2 implementation has been moved to the WebKit2 layer.
+
+        * PlatformGTK.cmake:
+        * platform/graphics/GLContext.cpp:
+        (WebCore::initializeOpenGLShimsIfNeeded):
+        (WebCore::GLContext::createContextForWindow):
+        (WebCore::GLContext::createOffscreenContext):
+        (WebCore::GLContext::createSharingContext):
+        (WebCore::GLContext::GLContext):
+        (WebCore::GLContext::~GLContext):
+        (WebCore::GLContext::current):
+        (WebCore::activeContextList): Deleted.
+        * platform/graphics/GLContext.h:
+        (WebCore::GLContext::display):
+        * platform/graphics/GraphicsContext3DPrivate.cpp:
+        (WebCore::GraphicsContext3DPrivate::GraphicsContext3DPrivate):
+        (WebCore::GraphicsContext3DPrivate::platformContext):
+        (WebCore::GraphicsContext3DPrivate::paintToTextureMapper):
+        * platform/graphics/PlatformDisplay.cpp:
+        (WebCore::PlatformDisplay::createPlatformDisplay): Always use the default wayland display created by GTK+ for
+        the global shared display.
+        (WebCore::PlatformDisplay::sharedDisplayForCompositing):
+        (WebCore::PlatformDisplay::setSharedDisplayForCompositing):
+        (WebCore::PlatformDisplay::sharingGLContext):
+        (WebCore::eglDisplays): Helper HashSet to keep track of all PlatformDisplays with an EGL display intialized to
+        properly termimate them at exit.
+        (WebCore::PlatformDisplay::initializeEGLDisplay): Remove eglBindAPI() from display initialization, since it's
+        not a display initialization and it's thread specific, so it needs to be called on every thread where EGL is used.
+        (WebCore::PlatformDisplay::terminateEGLDisplay):
+        (WebCore::PlatformDisplay::eglDisplay): Deleted.
+        * platform/graphics/PlatformDisplay.h:
+        * platform/graphics/cairo/ImageBufferCairo.cpp:
+        (WebCore::ImageBufferData::~ImageBufferData):
+        (WebCore::ImageBufferData::createCompositorBuffer):
+        (WebCore::ImageBufferData::swapBuffersIfNeeded):
+        (WebCore::ImageBufferData::createCairoGLSurface):
+        (WebCore::ImageBufferData::paintToTextureMapper):
+        (WebCore::ImageBuffer::copyToPlatformTexture):
+        * platform/graphics/egl/GLContextEGL.cpp:
+        (WebCore::GLContextEGL::getEGLConfig):
+        (WebCore::GLContextEGL::createWindowContext):
+        (WebCore::GLContextEGL::createPbufferContext):
+        (WebCore::GLContextEGL::createSurfacelessContext):
+        (WebCore::GLContextEGL::createPixmapContext):
+        (WebCore::GLContextEGL::createWaylandContext):
+        (WebCore::GLContextEGL::createContext):
+        (WebCore::GLContextEGL::createSharingContext):
+        (WebCore::GLContextEGL::GLContextEGL):
+        (WebCore::GLContextEGL::~GLContextEGL):
+        (WebCore::GLContextEGL::defaultFrameBufferSize):
+        (WebCore::GLContextEGL::makeContextCurrent):
+        (WebCore::GLContextEGL::swapBuffers):
+        (WebCore::GLContextEGL::cairoDevice):
+        * platform/graphics/egl/GLContextEGL.h:
+        * platform/graphics/glx/GLContextGLX.cpp:
+        (WebCore::GLContextGLX::createWindowContext):
+        (WebCore::GLContextGLX::createPbufferContext):
+        (WebCore::GLContextGLX::createPixmapContext):
+        (WebCore::GLContextGLX::createContext):
+        (WebCore::GLContextGLX::createSharingContext):
+        (WebCore::GLContextGLX::GLContextGLX):
+        (WebCore::GLContextGLX::~GLContextGLX):
+        (WebCore::GLContextGLX::defaultFrameBufferSize):
+        (WebCore::GLContextGLX::makeContextCurrent):
+        (WebCore::GLContextGLX::swapBuffers):
+        (WebCore::GLContextGLX::cairoDevice):
+        (WebCore::GLContextGLX::waitNative): Deleted.
+        * platform/graphics/glx/GLContextGLX.h:
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
+        (WebCore::MediaPlayerPrivateGStreamerBase::ensureGstGLContext):
+        (WebCore::MediaPlayerPrivateGStreamerBase::nativeImageForCurrentTime):
+        * platform/graphics/wayland/PlatformDisplayWayland.cpp:
+        (WebCore::PlatformDisplayWayland::PlatformDisplayWayland):
+        (WebCore::PlatformDisplayWayland::~PlatformDisplayWayland):
+        (WebCore::PlatformDisplayWayland::initialize):
+        (WebCore::PlatformDisplayWayland::registryGlobal):
+        (WebCore::PlatformDisplayWayland::createSurface):
+        * platform/graphics/wayland/PlatformDisplayWayland.h:
+        (WebCore::PlatformDisplayWayland::native): Deleted.
+        * platform/graphics/wayland/WaylandEventSource.cpp: Removed.
+        * platform/graphics/wayland/WaylandSurface.cpp: Removed.
+        * platform/graphics/wayland/WebKitGtkWaylandClientProtocol.xml: Removed.
+        * platform/graphics/wayland/WlUniquePtr.h: Make it possible to use std::unique_ptr with Wayland objects.
+        (WebCore::WlPtrDeleter::operator()):
+
 2016-08-29  Youenn Fablet  <youenn@apple.com>
 
         [Fetch API] Add support for BufferSource bodies
index 9334cfb..e323dba 100644 (file)
@@ -144,6 +144,8 @@ list(APPEND WebCore_SOURCES
 
     platform/graphics/opentype/OpenTypeVerticalData.cpp
 
+    platform/graphics/wayland/PlatformDisplayWayland.cpp
+
     platform/graphics/x11/PlatformDisplayX11.cpp
     platform/graphics/x11/XUniqueResource.cpp
 
@@ -348,24 +350,6 @@ if (ENABLE_PLUGIN_PROCESS_GTK2)
 endif ()
 
 if (ENABLE_WAYLAND_TARGET)
-    # Wayland protocol extension.
-    add_custom_command(
-        OUTPUT ${DERIVED_SOURCES_WEBCORE_DIR}/WebKitGtkWaylandClientProtocol.c
-        DEPENDS ${WEBCORE_DIR}/platform/graphics/wayland/WebKitGtkWaylandClientProtocol.xml
-        COMMAND wayland-scanner server-header < ${WEBCORE_DIR}/platform/graphics/wayland/WebKitGtkWaylandClientProtocol.xml > ${DERIVED_SOURCES_WEBCORE_DIR}/WebKitGtkWaylandServerProtocol.h
-        COMMAND wayland-scanner client-header < ${WEBCORE_DIR}/platform/graphics/wayland/WebKitGtkWaylandClientProtocol.xml > ${DERIVED_SOURCES_WEBCORE_DIR}/WebKitGtkWaylandClientProtocol.h
-        COMMAND wayland-scanner code < ${WEBCORE_DIR}/platform/graphics/wayland/WebKitGtkWaylandClientProtocol.xml > ${DERIVED_SOURCES_WEBCORE_DIR}/WebKitGtkWaylandClientProtocol.c
-    )
-
-    list(APPEND WebCore_SOURCES
-        platform/graphics/wayland/PlatformDisplayWayland.cpp
-        platform/graphics/wayland/WaylandEventSource.cpp
-        platform/graphics/wayland/WaylandSurface.cpp
-    )
-    list(APPEND WebCore_DERIVED_SOURCES
-        ${DERIVED_SOURCES_WEBCORE_DIR}/WebKitGtkWaylandClientProtocol.c
-    )
-
     list(APPEND WebCore_SYSTEM_INCLUDE_DIRECTORIES
         ${WAYLAND_INCLUDE_DIRS}
     )
index de61248..e9303ed 100644 (file)
 #include "config.h"
 
 #if ENABLE(GRAPHICS_CONTEXT_3D)
-
 #include "GLContext.h"
-
-#include "PlatformDisplay.h"
 #include <wtf/ThreadSpecific.h>
 
 #if USE(EGL)
@@ -57,12 +54,6 @@ inline ThreadGlobalGLContext* currentContext()
     return *ThreadGlobalGLContext::staticGLContext;
 }
 
-GLContext* GLContext::sharingContext()
-{
-    DEPRECATED_DEFINE_STATIC_LOCAL(std::unique_ptr<GLContext>, sharing, (createOffscreenContext()));
-    return sharing.get();
-}
-
 #if PLATFORM(X11)
 // Because of driver bugs, exiting the program when there are active pbuffers
 // can crash the X server (this has been observed with the official Nvidia drivers).
@@ -111,12 +102,30 @@ void GLContext::cleanupActiveContextsAtExit()
 }
 #endif // PLATFORM(X11)
 
+static bool initializeOpenGLShimsIfNeeded()
+{
+#if USE(OPENGL_ES_2)
+    return true;
+#else
+    static bool initialized = false;
+    static bool success = true;
+    if (!initialized) {
+        success = initializeOpenGLShims();
+        initialized = true;
+    }
+    return success;
+#endif
+}
 
-std::unique_ptr<GLContext> GLContext::createContextForWindow(GLNativeWindowType windowHandle, GLContext* sharingContext)
+std::unique_ptr<GLContext> GLContext::createContextForWindow(GLNativeWindowType windowHandle, PlatformDisplay* platformDisplay)
 {
-#if PLATFORM(WAYLAND) && USE(EGL)
-    if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland) {
-        if (auto eglContext = GLContextEGL::createContext(windowHandle, sharingContext))
+    if (!initializeOpenGLShimsIfNeeded())
+        return nullptr;
+
+    PlatformDisplay& display = platformDisplay ? *platformDisplay : PlatformDisplay::sharedDisplay();
+#if PLATFORM(WAYLAND)
+    if (display.type() == PlatformDisplay::Type::Wayland) {
+        if (auto eglContext = GLContextEGL::createContext(windowHandle, display))
             return WTFMove(eglContext);
         return nullptr;
     }
@@ -128,34 +137,60 @@ std::unique_ptr<GLContext> GLContext::createContextForWindow(GLNativeWindowType
 #else
     XID GLXWindowHandle = static_cast<XID>(windowHandle);
 #endif
-    if (auto glxContext = GLContextGLX::createContext(GLXWindowHandle, sharingContext))
+    if (auto glxContext = GLContextGLX::createContext(GLXWindowHandle, display))
         return WTFMove(glxContext);
 #endif
 #if USE(EGL)
-    if (auto eglContext = GLContextEGL::createContext(windowHandle, sharingContext))
+    if (auto eglContext = GLContextEGL::createContext(windowHandle, display))
         return WTFMove(eglContext);
 #endif
     return nullptr;
 }
 
-GLContext::GLContext()
+std::unique_ptr<GLContext> GLContext::createOffscreenContext(PlatformDisplay* platformDisplay)
 {
-#if PLATFORM(X11)
-    addActiveContext(this);
+    if (!initializeOpenGLShimsIfNeeded())
+        return nullptr;
+
+    return createContextForWindow(0, platformDisplay ? platformDisplay : &PlatformDisplay::sharedDisplay());
+}
+
+std::unique_ptr<GLContext> GLContext::createSharingContext(PlatformDisplay& display)
+{
+    if (!initializeOpenGLShimsIfNeeded())
+        return nullptr;
+
+#if USE(GLX)
+    if (display.type() == PlatformDisplay::Type::X11) {
+        if (auto glxContext = GLContextGLX::createSharingContext(display))
+            return WTFMove(glxContext);
+    }
 #endif
+
+#if USE(EGL) || PLATFORM(WAYLAND)
+    if (auto eglContext = GLContextEGL::createSharingContext(display))
+        return WTFMove(eglContext);
+#endif
+
+    return nullptr;
 }
 
-std::unique_ptr<GLContext> GLContext::createOffscreenContext(GLContext* sharingContext)
+GLContext::GLContext(PlatformDisplay& display)
+    : m_display(display)
 {
-    return createContextForWindow(0, sharingContext);
+#if PLATFORM(X11)
+    if (display.type() == PlatformDisplay::Type::X11)
+        addActiveContext(this);
+#endif
 }
 
 GLContext::~GLContext()
 {
     if (this == currentContext()->context())
-        currentContext()->setContext(0);
+        currentContext()->setContext(nullptr);
 #if PLATFORM(X11)
-    removeActiveContext(this);
+    if (m_display.type() == PlatformDisplay::Type::X11)
+        removeActiveContext(this);
 #endif
 }
 
@@ -165,7 +200,7 @@ bool GLContext::makeContextCurrent()
     return true;
 }
 
-GLContext* GLContext::getCurrent()
+GLContext* GLContext::current()
 {
     return currentContext()->context();
 }
index d439454..c82f098 100644 (file)
@@ -21,7 +21,7 @@
 #define GLContext_h
 
 #include "GraphicsContext3D.h"
-#include "Widget.h"
+#include "PlatformDisplay.h"
 #include <wtf/Noncopyable.h>
 
 #if USE(EGL) && !PLATFORM(GTK)
@@ -39,27 +39,25 @@ typedef uint64_t GLNativeWindowType;
 typedef struct _cairo_device cairo_device_t;
 #endif
 
-#if PLATFORM(X11)
-typedef struct _XDisplay Display;
-#endif
-
 namespace WebCore {
 
 class GLContext {
-    WTF_MAKE_NONCOPYABLE(GLContext);
+    WTF_MAKE_NONCOPYABLE(GLContext); WTF_MAKE_FAST_ALLOCATED;
 public:
-    static std::unique_ptr<GLContext> createContextForWindow(GLNativeWindowType windowHandle, GLContext* sharingContext);
-    static std::unique_ptr<GLContext> createOffscreenContext(GLContext* sharing = 0);
-    static GLContext* getCurrent();
-    static GLContext* sharingContext();
+    static std::unique_ptr<GLContext> createContextForWindow(GLNativeWindowType windowHandle, PlatformDisplay* = nullptr);
+    static std::unique_ptr<GLContext> createOffscreenContext(PlatformDisplay* = nullptr);
+    static std::unique_ptr<GLContext> createSharingContext(PlatformDisplay&);
+    static GLContext* current();
+
+    PlatformDisplay& display() const { return m_display; }
 
-    GLContext();
     virtual ~GLContext();
     virtual bool makeContextCurrent();
     virtual void swapBuffers() = 0;
     virtual void waitNative() = 0;
     virtual bool canRenderToDefaultFramebuffer() = 0;
     virtual IntSize defaultFrameBufferSize() = 0;
+    virtual void swapInterval(int) = 0;
 
     virtual bool isEGLContext() const = 0;
 
@@ -67,26 +65,21 @@ public:
     virtual cairo_device_t* cairoDevice() = 0;
 #endif
 
-#if PLATFORM(X11)
-    static Display* sharedX11Display();
-    static void cleanupSharedX11Display();
+#if ENABLE(GRAPHICS_CONTEXT_3D)
+    virtual PlatformGraphicsContext3D platformContext() = 0;
 #endif
 
+#if PLATFORM(X11)
+private:
     static void addActiveContext(GLContext*);
     static void removeActiveContext(GLContext*);
     static void cleanupActiveContextsAtExit();
-
-#if ENABLE(GRAPHICS_CONTEXT_3D)
-    virtual PlatformGraphicsContext3D platformContext() = 0;
 #endif
 
-    class Data {
-    public:
-        virtual ~Data() = default;
-    };
-
 protected:
-    std::unique_ptr<Data> m_contextData;
+    GLContext(PlatformDisplay&);
+
+    PlatformDisplay& m_display;
 };
 
 } // namespace WebCore
index 15cd4df..6a73022 100644 (file)
@@ -55,7 +55,7 @@ GraphicsContext3DPrivate::GraphicsContext3DPrivate(GraphicsContext3D* context, G
 {
     switch (renderStyle) {
     case GraphicsContext3D::RenderOffscreen:
-        m_glContext = GLContext::createOffscreenContext(GLContext::sharingContext());
+        m_glContext = GLContext::createOffscreenContext(&PlatformDisplay::sharedDisplayForCompositing());
         break;
     case GraphicsContext3D::RenderToCurrentGLContext:
         break;
@@ -85,7 +85,7 @@ bool GraphicsContext3DPrivate::makeContextCurrent()
 
 PlatformGraphicsContext3D GraphicsContext3DPrivate::platformContext()
 {
-    return m_glContext ? m_glContext->platformContext() : GLContext::getCurrent()->platformContext();
+    return m_glContext ? m_glContext->platformContext() : GLContext::current()->platformContext();
 }
 
 #if USE(COORDINATED_GRAPHICS_THREADED)
@@ -123,7 +123,7 @@ void GraphicsContext3DPrivate::paintToTextureMapper(TextureMapper& textureMapper
 
 #if USE(TEXTURE_MAPPER_GL)
     if (m_context->m_attrs.antialias && m_context->m_state.boundFBO == m_context->m_multisampleFBO) {
-        GLContext* previousActiveContext = GLContext::getCurrent();
+        GLContext* previousActiveContext = GLContext::current();
         if (previousActiveContext != m_glContext.get())
             m_context->makeContextCurrent();
 
index 2e91aa3..18517d2 100644 (file)
@@ -26,6 +26,7 @@
 #include "config.h"
 #include "PlatformDisplay.h"
 
+#include "GLContext.h"
 #include <cstdlib>
 #include <mutex>
 
@@ -59,6 +60,8 @@
 
 #if USE(EGL)
 #include <EGL/egl.h>
+#include <wtf/HashSet.h>
+#include <wtf/NeverDestroyed.h>
 #endif
 
 namespace WebCore {
@@ -76,7 +79,7 @@ std::unique_ptr<PlatformDisplay> PlatformDisplay::createPlatformDisplay()
 #endif
 #if PLATFORM(WAYLAND)
     if (GDK_IS_WAYLAND_DISPLAY(display))
-        return PlatformDisplayWayland::create();
+        return std::make_unique<PlatformDisplayWayland>(gdk_wayland_display_get_wl_display(display));
 #endif
 #endif
 #elif PLATFORM(EFL) && defined(HAVE_ECORE_X)
@@ -103,6 +106,18 @@ PlatformDisplay& PlatformDisplay::sharedDisplay()
     return *display;
 }
 
+static PlatformDisplay* s_sharedDisplayForCompositing;
+
+PlatformDisplay& PlatformDisplay::sharedDisplayForCompositing()
+{
+    return s_sharedDisplayForCompositing ? *s_sharedDisplayForCompositing : sharedDisplay();
+}
+
+void PlatformDisplay::setSharedDisplayForCompositing(PlatformDisplay& display)
+{
+    s_sharedDisplayForCompositing = &display;
+}
+
 PlatformDisplay::PlatformDisplay()
 #if USE(EGL)
     : m_eglDisplay(EGL_NO_DISPLAY)
@@ -117,7 +132,22 @@ PlatformDisplay::~PlatformDisplay()
 #endif
 }
 
+#if !PLATFORM(EFL)
+GLContext* PlatformDisplay::sharingGLContext()
+{
+    if (!m_sharingGLContext)
+        m_sharingGLContext = GLContext::createSharingContext(*this);
+    return m_sharingGLContext.get();
+}
+#endif
+
 #if USE(EGL)
+static HashSet<PlatformDisplay*>& eglDisplays()
+{
+    static NeverDestroyed<HashSet<PlatformDisplay*>> displays;
+    return displays;
+}
+
 EGLDisplay PlatformDisplay::eglDisplay() const
 {
     if (!m_eglDisplayInitialized)
@@ -125,12 +155,20 @@ EGLDisplay PlatformDisplay::eglDisplay() const
     return m_eglDisplay;
 }
 
+bool PlatformDisplay::eglCheckVersion(int major, int minor) const
+{
+    if (!m_eglDisplayInitialized)
+        const_cast<PlatformDisplay*>(this)->initializeEGLDisplay();
+
+    return (m_eglMajorVersion > major) || ((m_eglMajorVersion == major) && (m_eglMinorVersion >= minor));
+}
+
 void PlatformDisplay::initializeEGLDisplay()
 {
     m_eglDisplayInitialized = true;
 
     if (m_eglDisplay == EGL_NO_DISPLAY) {
-// EGL is optionally soft linked on Windows.
+        // EGL is optionally soft linked on Windows.
 #if PLATFORM(WIN)
         auto eglGetDisplay = eglGetDisplayPtr();
         if (!eglGetDisplay)
@@ -141,36 +179,41 @@ void PlatformDisplay::initializeEGLDisplay()
             return;
     }
 
-    if (eglInitialize(m_eglDisplay, 0, 0) == EGL_FALSE) {
+    EGLint majorVersion, minorVersion;
+    if (eglInitialize(m_eglDisplay, &majorVersion, &minorVersion) == EGL_FALSE) {
         LOG_ERROR("EGLDisplay Initialization failed.");
         terminateEGLDisplay();
         return;
     }
 
-#if USE(OPENGL_ES_2)
-    static const EGLenum eglAPIVersion = EGL_OPENGL_ES_API;
-#else
-    static const EGLenum eglAPIVersion = EGL_OPENGL_API;
-#endif
-    if (eglBindAPI(eglAPIVersion) == EGL_FALSE) {
-        LOG_ERROR("Failed to set EGL API(%d).", eglGetError());
-        terminateEGLDisplay();
-        return;
+    m_eglMajorVersion = majorVersion;
+    m_eglMinorVersion = minorVersion;
+
+    eglDisplays().add(this);
+
+    static bool eglAtexitHandlerInitialized = false;
+    if (!eglAtexitHandlerInitialized) {
+        // EGL registers atexit handlers to cleanup its global display list.
+        // Since the global PlatformDisplay instance is created before,
+        // when the PlatformDisplay destructor is called, EGL has already removed the
+        // display from the list, causing eglTerminate() to crash. So, here we register
+        // our own atexit handler, after EGL has been initialized and after the global
+        // instance has been created to ensure we call eglTerminate() before the other
+        // EGL atexit handlers and the PlatformDisplay destructor.
+        // See https://bugs.webkit.org/show_bug.cgi?id=157973.
+        eglAtexitHandlerInitialized = true;
+        std::atexit([] {
+            while (!eglDisplays().isEmpty()) {
+                auto* display = eglDisplays().takeAny();
+                display->terminateEGLDisplay();
+            }
+        });
     }
-
-    // EGL registers atexit handlers to cleanup its global display list.
-    // Since the global PlatformDisplay instance is created before,
-    // when the PlatformDisplay destructor is called, EGL has already removed the
-    // display from the list, causing eglTerminate() to crash. So, here we register
-    // our own atexit handler, after EGL has been initialized and after the global
-    // instance has been created to ensure we call eglTerminate() before the other
-    // EGL atexit handlers and the PlatformDisplay destructor.
-    // See https://bugs.webkit.org/show_bug.cgi?id=157973.
-    std::atexit([] { PlatformDisplay::sharedDisplay().terminateEGLDisplay(); });
 }
 
 void PlatformDisplay::terminateEGLDisplay()
 {
+    m_sharingGLContext = nullptr;
     ASSERT(m_eglDisplayInitialized);
     if (m_eglDisplay == EGL_NO_DISPLAY)
         return;
index 9209f45..700771c 100644 (file)
@@ -35,10 +35,13 @@ typedef void *EGLDisplay;
 
 namespace WebCore {
 
+class GLContext;
+
 class PlatformDisplay {
     WTF_MAKE_NONCOPYABLE(PlatformDisplay); WTF_MAKE_FAST_ALLOCATED;
 public:
     static PlatformDisplay& sharedDisplay();
+    static PlatformDisplay& sharedDisplayForCompositing();
     virtual ~PlatformDisplay();
 
     enum class Type {
@@ -55,13 +58,22 @@ public:
 
     virtual Type type() const = 0;
 
+#if !PLATFORM(EFL)
+    // FIXME: This should not have any platform ifdef, but EFL has its own EGLContext class
+    // instead of using the GLContext common API.
+    GLContext* sharingGLContext();
+#endif
+
 #if USE(EGL)
     EGLDisplay eglDisplay() const;
+    bool eglCheckVersion(int major, int minor) const;
 #endif
 
 protected:
     PlatformDisplay();
 
+    static void setSharedDisplayForCompositing(PlatformDisplay&);
+
 #if USE(EGL)
     virtual void initializeEGLDisplay();
 
@@ -75,7 +87,10 @@ private:
     void terminateEGLDisplay();
 
     bool m_eglDisplayInitialized { false };
+    int m_eglMajorVersion { 0 };
+    int m_eglMinorVersion { 0 };
 #endif
+    std::unique_ptr<GLContext> m_sharingGLContext;
 };
 
 } // namespace WebCore
index 8f48c20..3cd2ab0 100644 (file)
@@ -88,8 +88,8 @@ ImageBufferData::~ImageBufferData()
         return;
 
 #if ENABLE(ACCELERATED_2D_CANVAS)
-    GLContext* previousActiveContext = GLContext::getCurrent();
-    GLContext::sharingContext()->makeContextCurrent();
+    GLContext* previousActiveContext = GLContext::current();
+    PlatformDisplay::sharedDisplayForCompositing().sharingGLContext()->makeContextCurrent();
 
     if (m_texture)
         glDeleteTextures(1, &m_texture);
@@ -108,7 +108,8 @@ ImageBufferData::~ImageBufferData()
 #if USE(COORDINATED_GRAPHICS_THREADED)
 void ImageBufferData::createCompositorBuffer()
 {
-    GLContext::sharingContext()->makeContextCurrent();
+    auto* context = PlatformDisplay::sharedDisplayForCompositing().sharingGLContext();
+    context->makeContextCurrent();
 
     glGenTextures(1, &m_compositorTexture);
     glBindTexture(GL_TEXTURE_2D, m_compositorTexture);
@@ -119,15 +120,14 @@ void ImageBufferData::createCompositorBuffer()
     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     glTexImage2D(GL_TEXTURE_2D, 0 , GL_RGBA, m_size.width(), m_size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 
-    cairo_device_t* device = GLContext::sharingContext()->cairoDevice();
-    m_compositorSurface = adoptRef(cairo_gl_surface_create_for_texture(device, CAIRO_CONTENT_COLOR_ALPHA, m_compositorTexture, m_size.width(), m_size.height()));
+    m_compositorSurface = adoptRef(cairo_gl_surface_create_for_texture(context->cairoDevice(), CAIRO_CONTENT_COLOR_ALPHA, m_compositorTexture, m_size.width(), m_size.height()));
     m_compositorCr = adoptRef(cairo_create(m_compositorSurface.get()));
     cairo_set_antialias(m_compositorCr.get(), CAIRO_ANTIALIAS_NONE);
 }
 
 void ImageBufferData::swapBuffersIfNeeded()
 {
-    GLContext* previousActiveContext = GLContext::getCurrent();
+    GLContext* previousActiveContext = GLContext::current();
 
     if (!m_compositorTexture) {
         createCompositorBuffer();
@@ -159,7 +159,8 @@ void clearSurface(cairo_surface_t* surface)
 
 void ImageBufferData::createCairoGLSurface()
 {
-    GLContext::sharingContext()->makeContextCurrent();
+    auto* context = PlatformDisplay::sharedDisplayForCompositing().sharingGLContext();
+    context->makeContextCurrent();
 
     // We must generate the texture ourselves, because there is no Cairo API for extracting it
     // from a pre-existing surface.
@@ -174,7 +175,6 @@ void ImageBufferData::createCairoGLSurface()
 
     glTexImage2D(GL_TEXTURE_2D, 0 /* level */, GL_RGBA, m_size.width(), m_size.height(), 0 /* border */, GL_RGBA, GL_UNSIGNED_BYTE, 0);
 
-    GLContext* context = GLContext::sharingContext();
     cairo_device_t* device = context->cairoDevice();
 
     // Thread-awareness is a huge performance hit on non-Intel drivers.
@@ -563,7 +563,7 @@ void ImageBufferData::paintToTextureMapper(TextureMapper& textureMapper, const F
     ASSERT(m_texture);
 
     // Cairo may change the active context, so we make sure to change it back after flushing.
-    GLContext* previousActiveContext = GLContext::getCurrent();
+    GLContext* previousActiveContext = GLContext::current();
     cairo_surface_flush(m_surface.get());
     previousActiveContext->makeContextCurrent();
 
@@ -609,7 +609,7 @@ bool ImageBuffer::copyToPlatformTexture(GraphicsContext3D&, GC3Denum target, Pla
 
     cairo_surface_flush(m_data.m_surface.get());
 
-    std::unique_ptr<GLContext> context = GLContext::createContextForWindow(0, GLContext::sharingContext());
+    std::unique_ptr<GLContext> context = GLContext::createOffscreenContext(&PlatformDisplay::sharedDisplayForCompositing());
     context->makeContextCurrent();
     uint32_t fbo;
     glGenFramebuffers(1, &fbo);
index a2bc75b..7979968 100644 (file)
@@ -22,7 +22,6 @@
 #if USE(EGL)
 
 #include "GraphicsContext3D.h"
-#include "PlatformDisplay.h"
 
 #if USE(CAIRO)
 #include <cairo.h>
 #include <X11/Xlib.h>
 #endif
 
+#if PLATFORM(WAYLAND)
+#include "PlatformDisplayWayland.h"
+#include <wayland-egl.h>
+#endif
+
 #if ENABLE(ACCELERATED_2D_CANVAS)
 // cairo-gl.h includes some definitions from GLX that conflict with
 // the ones provided by us. Since GLContextEGL doesn't use any GLX
 
 namespace WebCore {
 
-static EGLDisplay sharedEGLDisplay()
-{
-    return PlatformDisplay::sharedDisplay().eglDisplay();
-}
-
 static const EGLint gContextAttributes[] = {
 #if USE(OPENGL_ES_2)
     EGL_CONTEXT_CLIENT_VERSION, 2,
@@ -62,7 +61,13 @@ static const EGLint gContextAttributes[] = {
     EGL_NONE
 };
 
-static bool getEGLConfig(EGLConfig* config, GLContextEGL::EGLSurfaceType surfaceType)
+#if USE(OPENGL_ES_2)
+static const EGLenum gEGLAPIVersion = EGL_OPENGL_ES_API;
+#else
+static const EGLenum gEGLAPIVersion = EGL_OPENGL_API;
+#endif
+
+bool GLContextEGL::getEGLConfig(EGLDisplay display, EGLConfig* config, EGLSurfaceType surfaceType)
 {
     EGLint attributeList[] = {
 #if USE(OPENGL_ES_2)
@@ -87,27 +92,23 @@ static bool getEGLConfig(EGLConfig* config, GLContextEGL::EGLSurfaceType surface
         attributeList[13] = EGL_PIXMAP_BIT;
         break;
     case GLContextEGL::WindowSurface:
+    case GLContextEGL::Surfaceless:
         attributeList[13] = EGL_WINDOW_BIT;
         break;
     }
 
     EGLint numberConfigsReturned;
-    return eglChooseConfig(sharedEGLDisplay(), attributeList, config, 1, &numberConfigsReturned) && numberConfigsReturned;
+    return eglChooseConfig(display, attributeList, config, 1, &numberConfigsReturned) && numberConfigsReturned;
 }
 
-std::unique_ptr<GLContextEGL> GLContextEGL::createWindowContext(EGLNativeWindowType window, GLContext* sharingContext, std::unique_ptr<GLContext::Data>&& contextData)
+std::unique_ptr<GLContextEGL> GLContextEGL::createWindowContext(EGLNativeWindowType window, PlatformDisplay& platformDisplay, EGLContext sharingContext)
 {
-    EGLContext eglSharingContext = sharingContext ? static_cast<GLContextEGL*>(sharingContext)->m_context : 0;
-
-    EGLDisplay display = sharedEGLDisplay();
-    if (display == EGL_NO_DISPLAY)
-        return nullptr;
-
+    EGLDisplay display = platformDisplay.eglDisplay();
     EGLConfig config;
-    if (!getEGLConfig(&config, WindowSurface))
+    if (!getEGLConfig(display, &config, WindowSurface))
         return nullptr;
 
-    EGLContext context = eglCreateContext(display, config, eglSharingContext, gContextAttributes);
+    EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes);
     if (context == EGL_NO_CONTEXT)
         return nullptr;
 
@@ -117,19 +118,14 @@ std::unique_ptr<GLContextEGL> GLContextEGL::createWindowContext(EGLNativeWindowT
         return nullptr;
     }
 
-    auto glContext = std::make_unique<GLContextEGL>(context, surface, WindowSurface);
-    glContext->m_contextData = WTFMove(contextData);
-    return glContext;
+    return std::unique_ptr<GLContextEGL>(new GLContextEGL(platformDisplay, context, surface, WindowSurface));
 }
 
-std::unique_ptr<GLContextEGL> GLContextEGL::createPbufferContext(EGLContext sharingContext)
+std::unique_ptr<GLContextEGL> GLContextEGL::createPbufferContext(PlatformDisplay& platformDisplay, EGLContext sharingContext)
 {
-    EGLDisplay display = sharedEGLDisplay();
-    if (display == EGL_NO_DISPLAY)
-        return nullptr;
-
+    EGLDisplay display = platformDisplay.eglDisplay();
     EGLConfig config;
-    if (!getEGLConfig(&config, PbufferSurface))
+    if (!getEGLConfig(display, &config, PbufferSurface))
         return nullptr;
 
     EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes);
@@ -143,18 +139,36 @@ std::unique_ptr<GLContextEGL> GLContextEGL::createPbufferContext(EGLContext shar
         return nullptr;
     }
 
-    return std::make_unique<GLContextEGL>(context, surface, PbufferSurface);
+    return std::unique_ptr<GLContextEGL>(new GLContextEGL(platformDisplay, context, surface, PbufferSurface));
 }
 
-#if PLATFORM(X11)
-std::unique_ptr<GLContextEGL> GLContextEGL::createPixmapContext(EGLContext sharingContext)
+std::unique_ptr<GLContextEGL> GLContextEGL::createSurfacelessContext(PlatformDisplay& platformDisplay, EGLContext sharingContext)
 {
-    EGLDisplay display = sharedEGLDisplay();
+    EGLDisplay display = platformDisplay.eglDisplay();
     if (display == EGL_NO_DISPLAY)
         return nullptr;
 
+    const char* extensions = eglQueryString(display, EGL_EXTENSIONS);
+    if (!strstr(extensions, "EGL_KHR_surfaceless_context") && !strstr(extensions, "EGL_KHR_surfaceless_opengl"))
+        return nullptr;
+
     EGLConfig config;
-    if (!getEGLConfig(&config, PixmapSurface))
+    if (!getEGLConfig(display, &config, Surfaceless))
+        return nullptr;
+
+    EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes);
+    if (context == EGL_NO_CONTEXT)
+        return nullptr;
+
+    return std::unique_ptr<GLContextEGL>(new GLContextEGL(platformDisplay, context, EGL_NO_SURFACE, Surfaceless));
+}
+
+#if PLATFORM(X11)
+std::unique_ptr<GLContextEGL> GLContextEGL::createPixmapContext(PlatformDisplay& platformDisplay, EGLContext sharingContext)
+{
+    EGLDisplay display = platformDisplay.eglDisplay();
+    EGLConfig config;
+    if (!getEGLConfig(display, &config, PixmapSurface))
         return nullptr;
 
     EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes);
@@ -167,7 +181,7 @@ std::unique_ptr<GLContextEGL> GLContextEGL::createPixmapContext(EGLContext shari
         return nullptr;
     }
 
-    Display* x11Display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
+    Display* x11Display = downcast<PlatformDisplayX11>(platformDisplay).native();
     XUniquePixmap pixmap = XCreatePixmap(x11Display, DefaultRootWindow(x11Display), 1, 1, depth);
     if (!pixmap) {
         eglDestroyContext(display, context);
@@ -180,49 +194,107 @@ std::unique_ptr<GLContextEGL> GLContextEGL::createPixmapContext(EGLContext shari
         return nullptr;
     }
 
-    return std::make_unique<GLContextEGL>(context, surface, WTFMove(pixmap));
+    return std::unique_ptr<GLContextEGL>(new GLContextEGL(platformDisplay, context, surface, WTFMove(pixmap)));
 }
 #endif // PLATFORM(X11)
 
-std::unique_ptr<GLContextEGL> GLContextEGL::createContext(EGLNativeWindowType window, GLContext* sharingContext)
+#if PLATFORM(WAYLAND)
+std::unique_ptr<GLContextEGL> GLContextEGL::createWaylandContext(PlatformDisplay& platformDisplay, EGLContext sharingContext)
 {
-    if (!sharedEGLDisplay())
+    EGLDisplay display = platformDisplay.eglDisplay();
+    EGLConfig config;
+    if (!getEGLConfig(display, &config, WindowSurface))
         return nullptr;
 
-    static bool initialized = false;
-    static bool success = true;
-    if (!initialized) {
-#if !USE(OPENGL_ES_2)
-        success = initializeOpenGLShims();
-#endif
-        initialized = true;
+    EGLContext context = eglCreateContext(display, config, sharingContext, gContextAttributes);
+    if (context == EGL_NO_CONTEXT)
+        return nullptr;
+
+    WlUniquePtr<struct wl_surface> wlSurface(downcast<PlatformDisplayWayland>(platformDisplay).createSurface());
+    if (!wlSurface) {
+        eglDestroyContext(display, context);
+        return nullptr;
     }
-    if (!success)
+
+    EGLNativeWindowType window = wl_egl_window_create(wlSurface.get(), 1, 1);
+    EGLSurface surface = eglCreateWindowSurface(display, config, window, 0);
+    if (surface == EGL_NO_SURFACE) {
+        eglDestroyContext(display, context);
+        wl_egl_window_destroy(window);
+        return nullptr;
+    }
+
+    return std::unique_ptr<GLContextEGL>(new GLContextEGL(platformDisplay, context, surface, WTFMove(wlSurface), window));
+}
+#endif
+
+std::unique_ptr<GLContextEGL> GLContextEGL::createContext(EGLNativeWindowType window, PlatformDisplay& platformDisplay)
+{
+    if (platformDisplay.eglDisplay() == EGL_NO_DISPLAY)
         return nullptr;
 
-    EGLContext eglSharingContext = sharingContext ? static_cast<GLContextEGL*>(sharingContext)->m_context : 0;
-    auto context = window ? createWindowContext(window, sharingContext) : nullptr;
+    if (eglBindAPI(gEGLAPIVersion) == EGL_FALSE)
+        return nullptr;
+
+    EGLContext eglSharingContext = platformDisplay.sharingGLContext() ? static_cast<GLContextEGL*>(platformDisplay.sharingGLContext())->m_context : EGL_NO_CONTEXT;
+    auto context = window ? createWindowContext(window, platformDisplay, eglSharingContext) : nullptr;
+    if (!context)
+        context = createSurfacelessContext(platformDisplay, eglSharingContext);
+    if (!context) {
 #if PLATFORM(X11)
+        if (platformDisplay.type() == PlatformDisplay::Type::X11)
+            context = createPixmapContext(platformDisplay, eglSharingContext);
+#endif
+#if PLATFORM(WAYLAND)
+        if (platformDisplay.type() == PlatformDisplay::Type::Wayland)
+            context = createWaylandContext(platformDisplay, eglSharingContext);
+#endif
+    }
     if (!context)
-        context = createPixmapContext(eglSharingContext);
+        context = createPbufferContext(platformDisplay, eglSharingContext);
+
+    return context;
+}
+
+std::unique_ptr<GLContextEGL> GLContextEGL::createSharingContext(PlatformDisplay& platformDisplay)
+{
+    if (platformDisplay.eglDisplay() == EGL_NO_DISPLAY)
+        return nullptr;
+
+    if (eglBindAPI(gEGLAPIVersion) == EGL_FALSE)
+        return nullptr;
+
+    auto context = createSurfacelessContext(platformDisplay);
+    if (!context) {
+#if PLATFORM(X11)
+        if (platformDisplay.type() == PlatformDisplay::Type::X11)
+            context = createPixmapContext(platformDisplay);
+#endif
+#if PLATFORM(WAYLAND)
+        if (platformDisplay.type() == PlatformDisplay::Type::Wayland)
+            context = createWaylandContext(platformDisplay);
 #endif
+    }
     if (!context)
-        context = createPbufferContext(eglSharingContext);
+        context = createPbufferContext(platformDisplay);
 
     return context;
 }
 
-GLContextEGL::GLContextEGL(EGLContext context, EGLSurface surface, EGLSurfaceType type)
-    : m_context(context)
+GLContextEGL::GLContextEGL(PlatformDisplay& display, EGLContext context, EGLSurface surface, EGLSurfaceType type)
+    : GLContext(display)
+    , m_context(context)
     , m_surface(surface)
     , m_type(type)
 {
     ASSERT(type != PixmapSurface);
+    ASSERT(type == Surfaceless || surface != EGL_NO_SURFACE);
 }
 
 #if PLATFORM(X11)
-GLContextEGL::GLContextEGL(EGLContext context, EGLSurface surface, XUniquePixmap&& pixmap)
-    : m_context(context)
+GLContextEGL::GLContextEGL(PlatformDisplay& display, EGLContext context, EGLSurface surface, XUniquePixmap&& pixmap)
+    : GLContext(display)
+    , m_context(context)
     , m_surface(surface)
     , m_type(PixmapSurface)
     , m_pixmap(WTFMove(pixmap))
@@ -230,6 +302,18 @@ GLContextEGL::GLContextEGL(EGLContext context, EGLSurface surface, XUniquePixmap
 }
 #endif
 
+#if PLATFORM(WAYLAND)
+GLContextEGL::GLContextEGL(PlatformDisplay& display, EGLContext context, EGLSurface surface, WlUniquePtr<struct wl_surface>&& wlSurface, EGLNativeWindowType wlWindow)
+    : GLContext(display)
+    , m_context(context)
+    , m_surface(surface)
+    , m_type(WindowSurface)
+    , m_wlSurface(WTFMove(wlSurface))
+    , m_wlWindow(wlWindow)
+{
+}
+#endif
+
 GLContextEGL::~GLContextEGL()
 {
 #if USE(CAIRO)
@@ -237,7 +321,7 @@ GLContextEGL::~GLContextEGL()
         cairo_device_destroy(m_cairoDevice);
 #endif
 
-    EGLDisplay display = sharedEGLDisplay();
+    EGLDisplay display = m_display.eglDisplay();
     if (m_context) {
         glBindFramebuffer(GL_FRAMEBUFFER, 0);
         eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
@@ -246,6 +330,11 @@ GLContextEGL::~GLContextEGL()
 
     if (m_surface)
         eglDestroySurface(display, m_surface);
+
+#if PLATFORM(WAYLAND)
+    if (m_wlWindow)
+        wl_egl_window_destroy(m_wlWindow);
+#endif
 }
 
 bool GLContextEGL::canRenderToDefaultFramebuffer()
@@ -258,9 +347,10 @@ IntSize GLContextEGL::defaultFrameBufferSize()
     if (!canRenderToDefaultFramebuffer())
         return IntSize();
 
+    EGLDisplay display = m_display.eglDisplay();
     EGLint width, height;
-    if (!eglQuerySurface(sharedEGLDisplay(), m_surface, EGL_WIDTH, &width)
-        || !eglQuerySurface(sharedEGLDisplay(), m_surface, EGL_HEIGHT, &height))
+    if (!eglQuerySurface(display, m_surface, EGL_WIDTH, &width)
+        || !eglQuerySurface(display, m_surface, EGL_HEIGHT, &height))
         return IntSize();
 
     return IntSize(width, height);
@@ -268,19 +358,19 @@ IntSize GLContextEGL::defaultFrameBufferSize()
 
 bool GLContextEGL::makeContextCurrent()
 {
-    ASSERT(m_context && m_surface);
+    ASSERT(m_context);
 
     GLContext::makeContextCurrent();
     if (eglGetCurrentContext() == m_context)
         return true;
 
-    return eglMakeCurrent(sharedEGLDisplay(), m_surface, m_surface, m_context);
+    return eglMakeCurrent(m_display.eglDisplay(), m_surface, m_surface, m_context);
 }
 
 void GLContextEGL::swapBuffers()
 {
     ASSERT(m_surface);
-    eglSwapBuffers(sharedEGLDisplay(), m_surface);
+    eglSwapBuffers(m_display.eglDisplay(), m_surface);
 }
 
 void GLContextEGL::waitNative()
@@ -288,6 +378,12 @@ void GLContextEGL::waitNative()
     eglWaitNative(EGL_CORE_NATIVE_ENGINE);
 }
 
+void GLContextEGL::swapInterval(int interval)
+{
+    ASSERT(m_surface);
+    eglSwapInterval(m_display.eglDisplay(), interval);
+}
+
 #if USE(CAIRO)
 cairo_device_t* GLContextEGL::cairoDevice()
 {
@@ -295,7 +391,7 @@ cairo_device_t* GLContextEGL::cairoDevice()
         return m_cairoDevice;
 
 #if ENABLE(ACCELERATED_2D_CANVAS)
-    m_cairoDevice = cairo_egl_device_create(sharedEGLDisplay(), m_context);
+    m_cairoDevice = cairo_egl_device_create(m_display.eglDisplay(), m_context);
 #endif
 
     return m_cairoDevice;
index 86575a9..702535c 100644 (file)
 #include "XUniqueResource.h"
 #endif
 
+#if PLATFORM(WAYLAND)
+#include "WlUniquePtr.h"
+#endif
+
 namespace WebCore {
 
-class GLContextEGL : public GLContext {
+class GLContextEGL final : public GLContext {
     WTF_MAKE_NONCOPYABLE(GLContextEGL);
 public:
-    enum EGLSurfaceType { PbufferSurface, WindowSurface, PixmapSurface };
-    static std::unique_ptr<GLContextEGL> createContext(EGLNativeWindowType, GLContext* sharingContext = 0);
-    static std::unique_ptr<GLContextEGL> createWindowContext(EGLNativeWindowType, GLContext* sharingContext, std::unique_ptr<GLContext::Data>&& = nullptr);
+    static std::unique_ptr<GLContextEGL> createContext(EGLNativeWindowType, PlatformDisplay&);
+    static std::unique_ptr<GLContextEGL> createSharingContext(PlatformDisplay&);
 
-    GLContextEGL(EGLContext, EGLSurface, EGLSurfaceType);
-#if PLATFORM(X11)
-    GLContextEGL(EGLContext, EGLSurface, XUniquePixmap&&);
-#endif
     virtual ~GLContextEGL();
-    virtual bool makeContextCurrent();
-    virtual void swapBuffers();
-    virtual void waitNative();
-    virtual bool canRenderToDefaultFramebuffer();
-    virtual IntSize defaultFrameBufferSize();
+
+    bool makeContextCurrent() override;
+    void swapBuffers() override;
+    void waitNative() override;
+    bool canRenderToDefaultFramebuffer() override;
+    IntSize defaultFrameBufferSize() override;
+    void swapInterval(int) override;
 #if USE(CAIRO)
-    virtual cairo_device_t* cairoDevice();
+    cairo_device_t* cairoDevice() override;
 #endif
-    virtual bool isEGLContext() const { return true; }
+    bool isEGLContext() const override { return true; }
 
 #if ENABLE(GRAPHICS_CONTEXT_3D)
-    virtual PlatformGraphicsContext3D platformContext();
+    PlatformGraphicsContext3D platformContext() override;
 #endif
 
 private:
-    static std::unique_ptr<GLContextEGL> createPbufferContext(EGLContext sharingContext);
+    enum EGLSurfaceType { PbufferSurface, WindowSurface, PixmapSurface, Surfaceless };
+
+    GLContextEGL(PlatformDisplay&, EGLContext, EGLSurface, EGLSurfaceType);
 #if PLATFORM(X11)
-    static std::unique_ptr<GLContextEGL> createPixmapContext(EGLContext sharingContext);
+    GLContextEGL(PlatformDisplay&, EGLContext, EGLSurface, XUniquePixmap&&);
+#endif
+#if PLATFORM(WAYLAND)
+    GLContextEGL(PlatformDisplay&, EGLContext, EGLSurface, WlUniquePtr<struct wl_surface>&&, EGLNativeWindowType);
+#endif
+
+    static std::unique_ptr<GLContextEGL> createWindowContext(EGLNativeWindowType, PlatformDisplay&, EGLContext sharingContext = EGL_NO_CONTEXT);
+    static std::unique_ptr<GLContextEGL> createPbufferContext(PlatformDisplay&, EGLContext sharingContext = EGL_NO_CONTEXT);
+    static std::unique_ptr<GLContextEGL> createSurfacelessContext(PlatformDisplay&, EGLContext sharingContext = EGL_NO_CONTEXT);
+#if PLATFORM(X11)
+    static std::unique_ptr<GLContextEGL> createPixmapContext(PlatformDisplay&, EGLContext sharingContext = EGL_NO_CONTEXT);
+#endif
+#if PLATFORM(WAYLAND)
+    static std::unique_ptr<GLContextEGL> createWaylandContext(PlatformDisplay&, EGLContext sharingContext = EGL_NO_CONTEXT);
 #endif
 
-    static void addActiveContext(GLContextEGL*);
-    static void cleanupSharedEGLDisplay(void);
+    static bool getEGLConfig(EGLDisplay, EGLConfig*, EGLSurfaceType);
 
-    EGLContext m_context;
-    EGLSurface m_surface;
+    EGLContext m_context { EGL_NO_CONTEXT };
+    EGLSurface m_surface { EGL_NO_SURFACE };
     EGLSurfaceType m_type;
 #if PLATFORM(X11)
     XUniquePixmap m_pixmap;
 #endif
+#if PLATFORM(WAYLAND)
+    WlUniquePtr<struct wl_surface> m_wlSurface;
+    struct wl_egl_window* m_wlWindow { nullptr };
+#endif
 #if USE(CAIRO)
     cairo_device_t* m_cairoDevice { nullptr };
 #endif
index 14bb539..dfbb965 100644 (file)
 
 namespace WebCore {
 
-std::unique_ptr<GLContextGLX> GLContextGLX::createWindowContext(XID window, GLContext* sharingContext)
+#if !defined(PFNGLXSWAPINTERVALSGIPROC)
+typedef int (*PFNGLXSWAPINTERVALSGIPROC) (int);
+#endif
+
+static PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI;
+
+static bool hasSGISwapControlExtension(Display* display)
+{
+    static bool initialized = false;
+    if (initialized)
+        return !!glXSwapIntervalSGI;
+
+    initialized = true;
+    const char* extensions = glXQueryExtensionsString(display, 0);
+    if (!strstr(extensions, "GLX_SGI_swap_control"))
+        return false;
+
+    glXSwapIntervalSGI = reinterpret_cast<PFNGLXSWAPINTERVALSGIPROC>(glXGetProcAddress(reinterpret_cast<const unsigned char*>("glXSwapIntervalSGI")));
+    return !!glXSwapIntervalSGI;
+}
+
+std::unique_ptr<GLContextGLX> GLContextGLX::createWindowContext(XID window, PlatformDisplay& platformDisplay, GLXContext sharingContext)
 {
-    Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
+    Display* display = downcast<PlatformDisplayX11>(platformDisplay).native();
     XWindowAttributes attributes;
     if (!XGetWindowAttributes(display, window, &attributes))
         return nullptr;
@@ -45,15 +66,14 @@ std::unique_ptr<GLContextGLX> GLContextGLX::createWindowContext(XID window, GLCo
     int numReturned = 0;
     XUniquePtr<XVisualInfo> visualInfoList(XGetVisualInfo(display, VisualIDMask, &visualInfo, &numReturned));
 
-    GLXContext glxSharingContext = sharingContext ? static_cast<GLContextGLX*>(sharingContext)->m_context.get() : nullptr;
-    XUniqueGLXContext context(glXCreateContext(display, visualInfoList.get(), glxSharingContext, True));
+    XUniqueGLXContext context(glXCreateContext(display, visualInfoList.get(), sharingContext, True));
     if (!context)
         return nullptr;
 
-    return std::make_unique<GLContextGLX>(WTFMove(context), window);
+    return std::unique_ptr<GLContextGLX>(new GLContextGLX(platformDisplay, WTFMove(context), window));
 }
 
-std::unique_ptr<GLContextGLX> GLContextGLX::createPbufferContext(GLXContext sharingContext)
+std::unique_ptr<GLContextGLX> GLContextGLX::createPbufferContext(PlatformDisplay& platformDisplay, GLXContext sharingContext)
 {
     static const int fbConfigAttributes[] = {
         GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
@@ -67,7 +87,7 @@ std::unique_ptr<GLContextGLX> GLContextGLX::createPbufferContext(GLXContext shar
     };
 
     int returnedElements;
-    Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
+    Display* display = downcast<PlatformDisplayX11>(platformDisplay).native();
     XUniquePtr<GLXFBConfig> configs(glXChooseFBConfig(display, 0, fbConfigAttributes, &returnedElements));
     if (!returnedElements)
         return nullptr;
@@ -82,10 +102,10 @@ std::unique_ptr<GLContextGLX> GLContextGLX::createPbufferContext(GLXContext shar
     if (!context)
         return nullptr;
 
-    return std::make_unique<GLContextGLX>(WTFMove(context), WTFMove(pbuffer));
+    return std::unique_ptr<GLContextGLX>(new GLContextGLX(platformDisplay, WTFMove(context), WTFMove(pbuffer)));
 }
 
-std::unique_ptr<GLContextGLX> GLContextGLX::createPixmapContext(GLXContext sharingContext)
+std::unique_ptr<GLContextGLX> GLContextGLX::createPixmapContext(PlatformDisplay& platformDisplay, GLXContext sharingContext)
 {
     static int visualAttributes[] = {
         GLX_RGBA,
@@ -96,7 +116,7 @@ std::unique_ptr<GLContextGLX> GLContextGLX::createPixmapContext(GLXContext shari
         0
     };
 
-    Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
+    Display* display = downcast<PlatformDisplayX11>(platformDisplay).native();
     XUniquePtr<XVisualInfo> visualInfo(glXChooseVisual(display, DefaultScreen(display), visualAttributes));
     if (!visualInfo)
         return nullptr;
@@ -113,46 +133,46 @@ std::unique_ptr<GLContextGLX> GLContextGLX::createPixmapContext(GLXContext shari
     if (!glxPixmap)
         return nullptr;
 
-    return std::make_unique<GLContextGLX>(WTFMove(context), WTFMove(pixmap), WTFMove(glxPixmap));
+    return std::unique_ptr<GLContextGLX>(new GLContextGLX(platformDisplay, WTFMove(context), WTFMove(pixmap), WTFMove(glxPixmap)));
 }
 
-std::unique_ptr<GLContextGLX> GLContextGLX::createContext(XID window, GLContext* sharingContext)
+std::unique_ptr<GLContextGLX> GLContextGLX::createContext(XID window, PlatformDisplay& platformDisplay)
 {
-    static bool initialized = false;
-    static bool success = true;
-    if (!initialized) {
-        success = initializeOpenGLShims();
-        initialized = true;
-    }
-    if (!success)
-        return nullptr;
-
-    GLXContext glxSharingContext = sharingContext ? static_cast<GLContextGLX*>(sharingContext)->m_context.get() : nullptr;
-    auto context = window ? createWindowContext(window, sharingContext) : nullptr;
-    if (!context)
-        context = createPbufferContext(glxSharingContext);
+    GLXContext glxSharingContext = platformDisplay.sharingGLContext() ? static_cast<GLContextGLX*>(platformDisplay.sharingGLContext())->m_context.get() : nullptr;
+    auto context = window ? createWindowContext(window, platformDisplay, glxSharingContext) : nullptr;
     if (!context)
-        context = createPixmapContext(glxSharingContext);
+        context = createPbufferContext(platformDisplay, glxSharingContext);
     if (!context)
-        return nullptr;
+        context = createPixmapContext(platformDisplay, glxSharingContext);
 
     return context;
 }
 
-GLContextGLX::GLContextGLX(XUniqueGLXContext&& context, XID window)
-    : m_context(WTFMove(context))
+std::unique_ptr<GLContextGLX> GLContextGLX::createSharingContext(PlatformDisplay& platformDisplay)
+{
+    auto context = createPbufferContext(platformDisplay);
+    if (!context)
+        context = createPixmapContext(platformDisplay);
+    return context;
+}
+
+GLContextGLX::GLContextGLX(PlatformDisplay& display, XUniqueGLXContext&& context, XID window)
+    : GLContext(display)
+    , m_context(WTFMove(context))
     , m_window(window)
 {
 }
 
-GLContextGLX::GLContextGLX(XUniqueGLXContext&& context, XUniqueGLXPbuffer&& pbuffer)
-    : m_context(WTFMove(context))
+GLContextGLX::GLContextGLX(PlatformDisplay& display, XUniqueGLXContext&& context, XUniqueGLXPbuffer&& pbuffer)
+    : GLContext(display)
+    , m_context(WTFMove(context))
     , m_pbuffer(WTFMove(pbuffer))
 {
 }
 
-GLContextGLX::GLContextGLX(XUniqueGLXContext&& context, XUniquePixmap&& pixmap, XUniqueGLXPixmap&& glxPixmap)
-    : m_context(WTFMove(context))
+GLContextGLX::GLContextGLX(PlatformDisplay& display, XUniqueGLXContext&& context, XUniquePixmap&& pixmap, XUniqueGLXPixmap&& glxPixmap)
+    : GLContext(display)
+    , m_context(WTFMove(context))
     , m_pixmap(WTFMove(pixmap))
     , m_glxPixmap(WTFMove(glxPixmap))
 {
@@ -166,9 +186,8 @@ GLContextGLX::~GLContextGLX()
     if (m_context) {
         // This may be necessary to prevent crashes with NVidia's closed source drivers. Originally
         // from Mozilla's 3D canvas implementation at: http://bitbucket.org/ilmari/canvas3d/
-        Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
         glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
-        glXMakeCurrent(display, None, None);
+        glXMakeCurrent(downcast<PlatformDisplayX11>(m_display).native(), None, None);
     }
 }
 
@@ -185,8 +204,7 @@ IntSize GLContextGLX::defaultFrameBufferSize()
     int x, y;
     Window rootWindow;
     unsigned int width, height, borderWidth, depth;
-    Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
-    if (!XGetGeometry(display, m_window, &rootWindow, &x, &y, &width, &height, &borderWidth, &depth))
+    if (!XGetGeometry(downcast<PlatformDisplayX11>(m_display).native(), m_window, &rootWindow, &x, &y, &width, &height, &borderWidth, &depth))
         return IntSize();
 
     return IntSize(width, height);
@@ -200,7 +218,7 @@ bool GLContextGLX::makeContextCurrent()
     if (glXGetCurrentContext() == m_context.get())
         return true;
 
-    Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
+    Display* display = downcast<PlatformDisplayX11>(m_display).native();
     if (m_window)
         return glXMakeCurrent(display, m_window, m_context.get());
 
@@ -213,7 +231,7 @@ bool GLContextGLX::makeContextCurrent()
 void GLContextGLX::swapBuffers()
 {
     if (m_window)
-        glXSwapBuffers(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native(), m_window);
+        glXSwapBuffers(downcast<PlatformDisplayX11>(m_display).native(), m_window);
 }
 
 void GLContextGLX::waitNative()
@@ -221,13 +239,20 @@ void GLContextGLX::waitNative()
     glXWaitX();
 }
 
+void GLContextGLX::swapInterval(int interval)
+{
+    if (!hasSGISwapControlExtension(downcast<PlatformDisplayX11>(m_display).native()))
+        return;
+    glXSwapIntervalSGI(interval);
+}
+
 cairo_device_t* GLContextGLX::cairoDevice()
 {
     if (m_cairoDevice)
         return m_cairoDevice;
 
 #if ENABLE(ACCELERATED_2D_CANVAS) && CAIRO_HAS_GLX_FUNCTIONS
-    m_cairoDevice = cairo_glx_device_create(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native(), m_context.get());
+    m_cairoDevice = cairo_glx_device_create(downcast<PlatformDisplayX11>(m_display).native(), m_context.get());
 #endif
 
     return m_cairoDevice;
index 647f998..19fc374 100644 (file)
@@ -32,31 +32,35 @@ typedef void* ContextKeyType;
 
 namespace WebCore {
 
-class GLContextGLX : public GLContext {
+class GLContextGLX final : public GLContext {
     WTF_MAKE_NONCOPYABLE(GLContextGLX);
 public:
-    static std::unique_ptr<GLContextGLX> createContext(XID window, GLContext* sharingContext);
-    static std::unique_ptr<GLContextGLX> createWindowContext(XID window, GLContext* sharingContext);
+    static std::unique_ptr<GLContextGLX> createContext(XID window, PlatformDisplay&);
+    static std::unique_ptr<GLContextGLX> createSharingContext(PlatformDisplay&);
 
-    GLContextGLX(XUniqueGLXContext&&, XID);
-    GLContextGLX(XUniqueGLXContext&&, XUniqueGLXPbuffer&&);
-    GLContextGLX(XUniqueGLXContext&&, XUniquePixmap&&, XUniqueGLXPixmap&&);
     virtual ~GLContextGLX();
-    virtual bool makeContextCurrent();
-    virtual void swapBuffers();
-    virtual void waitNative();
-    virtual bool canRenderToDefaultFramebuffer();
-    virtual IntSize defaultFrameBufferSize();
-    virtual cairo_device_t* cairoDevice();
-    virtual bool isEGLContext() const { return false; }
+
+    bool makeContextCurrent() override;
+    void swapBuffers() override;
+    void waitNative() override;
+    bool canRenderToDefaultFramebuffer() override;
+    IntSize defaultFrameBufferSize() override;
+    void swapInterval(int) override;
+    cairo_device_t* cairoDevice() override;
+    bool isEGLContext() const override { return false; }
 
 #if ENABLE(GRAPHICS_CONTEXT_3D)
-    virtual PlatformGraphicsContext3D platformContext();
+    PlatformGraphicsContext3D platformContext() override;
 #endif
 
 private:
-    static std::unique_ptr<GLContextGLX> createPbufferContext(GLXContext sharingContext);
-    static std::unique_ptr<GLContextGLX> createPixmapContext(GLXContext sharingContext);
+    GLContextGLX(PlatformDisplay&, XUniqueGLXContext&&, XID);
+    GLContextGLX(PlatformDisplay&, XUniqueGLXContext&&, XUniqueGLXPbuffer&&);
+    GLContextGLX(PlatformDisplay&, XUniqueGLXContext&&, XUniquePixmap&&, XUniqueGLXPixmap&&);
+
+    static std::unique_ptr<GLContextGLX> createWindowContext(XID window, PlatformDisplay&, GLXContext sharingContext = nullptr);
+    static std::unique_ptr<GLContextGLX> createPbufferContext(PlatformDisplay&, GLXContext sharingContext = nullptr);
+    static std::unique_ptr<GLContextGLX> createPixmapContext(PlatformDisplay&, GLXContext sharingContext = nullptr);
 
     XUniqueGLXContext m_context;
     XID m_window { 0 };
index b29239e..fcff428 100644 (file)
@@ -235,8 +235,8 @@ bool MediaPlayerPrivateGStreamerBase::ensureGstGLContext()
     if (m_glContext)
         return true;
 
+    const auto& sharedDisplay = PlatformDisplay::sharedDisplayForCompositing();
     if (!m_glDisplay) {
-        const auto& sharedDisplay = PlatformDisplay::sharedDisplay();
 #if PLATFORM(X11)
         m_glDisplay = GST_GL_DISPLAY(gst_gl_display_x11_new_with_display(downcast<PlatformDisplayX11>(sharedDisplay).native()));
 #elif PLATFORM(WAYLAND)
@@ -244,7 +244,7 @@ bool MediaPlayerPrivateGStreamerBase::ensureGstGLContext()
 #endif
     }
 
-    GLContext* webkitContext = GLContext::sharingContext();
+    GLContext* webkitContext = sharedDisplay.sharingGLContext();
     // EGL and GLX are mutually exclusive, no need for ifdefs here.
     GstGLPlatform glPlatform = webkitContext->isEGLContext() ? GST_GL_PLATFORM_EGL : GST_GL_PLATFORM_GLX;
 
@@ -702,7 +702,7 @@ NativeImagePtr MediaPlayerPrivateGStreamerBase::nativeImageForCurrentTime()
     if (!gst_video_frame_map(&videoFrame, &videoInfo, buffer, static_cast<GstMapFlags>(GST_MAP_READ | GST_MAP_GL)))
         return nullptr;
 
-    GLContext* context = GLContext::sharingContext();
+    GLContext* context = PlatformDisplay::sharedDisplayForCompositing().sharingGLContext();
     context->makeContextCurrent();
     cairo_device_t* device = context->cairoDevice();
 
index d3305e1..47924a7 100644 (file)
 #if PLATFORM(WAYLAND)
 
 #include "GLContextEGL.h"
-#include "WaylandSurface.h"
 #include <cstring>
-#include <glib.h>
+#include <wayland-egl.h>
 #include <wtf/Assertions.h>
 
 namespace WebCore {
 
-const struct wl_registry_listener PlatformDisplayWayland::m_registryListener = {
-    PlatformDisplayWayland::globalCallback,
-    PlatformDisplayWayland::globalRemoveCallback
+const struct wl_registry_listener PlatformDisplayWayland::s_registryListener = {
+    // globalCallback
+    [](void* data, struct wl_registry*, uint32_t name, const char* interface, uint32_t) {
+        static_cast<PlatformDisplayWayland*>(data)->registryGlobal(interface, name);
+    },
+    // globalRemoveCallback
+    [](void*, struct wl_registry*, uint32_t)
+    {
+    }
 };
 
-void PlatformDisplayWayland::globalCallback(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t)
+PlatformDisplayWayland::PlatformDisplayWayland(struct wl_display* display)
 {
-    auto display = static_cast<PlatformDisplayWayland*>(data);
-    if (!std::strcmp(interface, "wl_compositor"))
-        display->m_compositor = static_cast<struct wl_compositor*>(wl_registry_bind(registry, name, &wl_compositor_interface, 1));
-    else if (!std::strcmp(interface, "wl_webkitgtk"))
-        display->m_webkitgtk = static_cast<struct wl_webkitgtk*>(wl_registry_bind(registry, name, &wl_webkitgtk_interface, 1));
+    initialize(display);
 }
 
-void PlatformDisplayWayland::globalRemoveCallback(void*, struct wl_registry*, uint32_t)
-{
-    // FIXME: if this can happen without the UI Process getting shut down
-    // we should probably destroy our cached display instance.
-}
-
-std::unique_ptr<PlatformDisplayWayland> PlatformDisplayWayland::create()
+PlatformDisplayWayland::~PlatformDisplayWayland()
 {
-    struct wl_display* wlDisplay = wl_display_connect(nullptr);
-    if (!wlDisplay) {
-        WTFLogAlways("PlatformDisplayWayland initialization: failed to connect to the Wayland server socket. Check your WAYLAND_DISPLAY or WAYLAND_SOCKET environment variables.");
-        return nullptr;
-    }
-
-    auto display = std::unique_ptr<PlatformDisplayWayland>(new PlatformDisplayWayland(wlDisplay));
-    if (!display->isInitialized()) {
-        WTFLogAlways("PlatformDisplayWayland initialization: failed to complete the initialization of the display.");
-        return nullptr;
-    }
-
-    return display;
 }
 
-PlatformDisplayWayland::PlatformDisplayWayland(struct wl_display* wlDisplay)
-    : m_display(wlDisplay)
-    , m_registry(wl_display_get_registry(m_display))
-    , m_eglConfigChosen(false)
+void PlatformDisplayWayland::initialize(wl_display* display)
 {
-    wl_registry_add_listener(m_registry, &m_registryListener, this);
+    m_display = display;
+    m_registry.reset(wl_display_get_registry(m_display));
+    wl_registry_add_listener(m_registry.get(), &s_registryListener, this);
     wl_display_roundtrip(m_display);
 
-    static const EGLint configAttributes[] = {
-        EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
-        EGL_RED_SIZE, 1,
-        EGL_GREEN_SIZE, 1,
-        EGL_BLUE_SIZE, 1,
-        EGL_ALPHA_SIZE, 1,
-        EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-        EGL_NONE
-    };
-
     m_eglDisplay = eglGetDisplay(m_display);
     PlatformDisplay::initializeEGLDisplay();
-    if (m_eglDisplay == EGL_NO_DISPLAY)
-        return;
-
-    EGLint numberOfConfigs;
-    if (!eglChooseConfig(m_eglDisplay, configAttributes, &m_eglConfig, 1, &numberOfConfigs) || numberOfConfigs != 1) {
-        g_warning("PlatformDisplayWayland initialization: failed to find the desired EGL configuration.");
-        return;
-    }
-
-    m_eglConfigChosen = true;
 }
 
-PlatformDisplayWayland::~PlatformDisplayWayland()
+void PlatformDisplayWayland::registryGlobal(const char* interface, uint32_t name)
 {
-    if (m_webkitgtk)
-        wl_webkitgtk_destroy(m_webkitgtk);
-    if (m_compositor)
-        wl_compositor_destroy(m_compositor);
-    if (m_registry)
-        wl_registry_destroy(m_registry);
-    if (m_display)
-        wl_display_disconnect(m_display);
-}
-
-std::unique_ptr<WaylandSurface> PlatformDisplayWayland::createSurface(const IntSize& size, int widgetId)
-{
-    struct wl_surface* wlSurface = wl_compositor_create_surface(m_compositor);
-    // We keep the minimum size at 1x1px since Mesa returns null values in wl_egl_window_create() for zero width or height.
-    EGLNativeWindowType nativeWindow = wl_egl_window_create(wlSurface, std::max(1, size.width()), std::max(1, size.height()));
-
-    wl_webkitgtk_set_surface_for_widget(m_webkitgtk, wlSurface, widgetId);
-    wl_display_roundtrip(m_display);
-
-    return std::make_unique<WaylandSurface>(wlSurface, nativeWindow);
+    if (!std::strcmp(interface, "wl_compositor"))
+        m_compositor.reset(static_cast<struct wl_compositor*>(wl_registry_bind(m_registry.get(), name, &wl_compositor_interface, 1)));
 }
 
-std::unique_ptr<GLContextEGL> PlatformDisplayWayland::createSharingGLContext()
+WlUniquePtr<struct wl_surface> PlatformDisplayWayland::createSurface() const
 {
-    class OffscreenContextData : public GLContext::Data {
-    public:
-        virtual ~OffscreenContextData()
-        {
-            wl_egl_window_destroy(nativeWindow);
-            wl_surface_destroy(surface);
-        }
-
-        struct wl_surface* surface;
-        EGLNativeWindowType nativeWindow;
-    };
-
-    auto contextData = std::make_unique<OffscreenContextData>();
-    contextData->surface = wl_compositor_create_surface(m_compositor);
-    contextData->nativeWindow = wl_egl_window_create(contextData->surface, 1, 1);
+    if (!m_compositor)
+        return nullptr;
 
-    auto nativeWindow = contextData->nativeWindow;
-    return GLContextEGL::createWindowContext(nativeWindow, nullptr, WTFMove(contextData));
+    return WlUniquePtr<struct wl_surface>(wl_compositor_create_surface(m_compositor.get()));
 }
 
 } // namespace WebCore
index 4cc9044..c16582a 100644 (file)
 #if PLATFORM(WAYLAND)
 
 #include "PlatformDisplay.h"
-#include "WebKitGtkWaylandClientProtocol.h"
-#include <memory>
+#include "WlUniquePtr.h"
 #include <wayland-client.h>
-#include <wayland-egl.h>
-#include <EGL/egl.h>
 
 namespace WebCore {
 
-class GLContextEGL;
-class IntSize;
-class WaylandSurface;
-
-class PlatformDisplayWayland final: public PlatformDisplay {
+class PlatformDisplayWayland : public PlatformDisplay {
 public:
-    static std::unique_ptr<PlatformDisplayWayland> create();
+    PlatformDisplayWayland(struct wl_display*);
     virtual ~PlatformDisplayWayland();
 
     struct wl_display* native() const { return m_display; }
 
-    std::unique_ptr<WaylandSurface> createSurface(const IntSize&, int widgetID);
-
-    std::unique_ptr<GLContextEGL> createSharingGLContext();
+    WlUniquePtr<struct wl_surface> createSurface() const;
 
 private:
-    static const struct wl_registry_listener m_registryListener;
-    static void globalCallback(void* data, struct wl_registry*, uint32_t name, const char* interface, uint32_t version);
-    static void globalRemoveCallback(void* data, struct wl_registry*, uint32_t name);
+    static const struct wl_registry_listener s_registryListener;
 
-    PlatformDisplayWayland(struct wl_display*);
+    Type type() const override { return PlatformDisplay::Type::Wayland; }
 
-    // FIXME: This should check also for m_webkitgtk once the UIProcess embedded Wayland subcompositer is implemented.
-    bool isInitialized() { return m_compositor && m_eglDisplay != EGL_NO_DISPLAY && m_eglConfigChosen; }
+protected:
+    PlatformDisplayWayland() = default;
+    void initialize(struct wl_display*);
 
-    Type type() const override { return PlatformDisplay::Type::Wayland; }
+    virtual void registryGlobal(const char* interface, uint32_t name);
 
     struct wl_display* m_display;
-    struct wl_registry* m_registry;
-    struct wl_compositor* m_compositor;
-    struct wl_webkitgtk* m_webkitgtk;
-
-    EGLConfig m_eglConfig;
-    bool m_eglConfigChosen;
+    WlUniquePtr<struct wl_registry> m_registry;
+    WlUniquePtr<struct wl_compositor> m_compositor;
 };
 
 } // namespace WebCore
diff --git a/Source/WebCore/platform/graphics/wayland/WaylandEventSource.cpp b/Source/WebCore/platform/graphics/wayland/WaylandEventSource.cpp
deleted file mode 100644 (file)
index 6b2ad2f..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * Copyright (C) 2014 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 APPLE COMPUTER, INC. ``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 COMPUTER, INC. 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 "WaylandEventSource.h"
-
-#if PLATFORM(WAYLAND)
-
-namespace WebCore {
-
-class GLibSource {
-public:
-    void initialize(struct wl_display*);
-
-    gboolean check();
-    gboolean dispatch();
-
-private:
-    GSource m_source;
-    GPollFD m_pollFileDescriptor;
-    struct wl_display* m_display;
-};
-
-void GLibSource::initialize(struct wl_display* display)
-{
-    m_display = display;
-    struct wl_event_loop* loop = wl_display_get_event_loop(display);
-    m_pollFileDescriptor.fd = wl_event_loop_get_fd(loop);
-    m_pollFileDescriptor.events = G_IO_IN | G_IO_ERR | G_IO_HUP;
-    g_source_add_poll(&m_source, &m_pollFileDescriptor);
-
-    g_source_set_name(&m_source, "Nested Wayland compositor display event source");
-    g_source_set_priority(&m_source, G_PRIORITY_DEFAULT);
-    g_source_set_can_recurse(&m_source, TRUE);
-    g_source_attach(&m_source, nullptr);
-}
-
-gboolean GLibSource::check()
-{
-    return m_pollFileDescriptor.revents;
-}
-
-gboolean GLibSource::dispatch()
-{
-    if (m_pollFileDescriptor.revents & G_IO_IN) {
-        struct wl_event_loop* loop = wl_display_get_event_loop(m_display);
-        wl_event_loop_dispatch(loop, -1);
-        wl_display_flush_clients(m_display);
-        m_pollFileDescriptor.revents = 0;
-    }
-
-    if (m_pollFileDescriptor.revents & (G_IO_ERR | G_IO_HUP))
-        g_warning("Wayland Display Event Source: lost connection to nested Wayland compositor");
-
-    return TRUE;
-}
-
-static gboolean prepareCallback(GSource*, gint* timeout)
-{
-    *timeout = -1;
-    return FALSE;
-}
-
-static gboolean checkCallback(GSource* base)
-{
-    auto source = reinterpret_cast<GLibSource*>(base);
-    return source->check();
-}
-
-static gboolean dispatchCallback(GSource* base, GSourceFunc, gpointer)
-{
-    auto source = reinterpret_cast<GLibSource*>(base);
-    return source->dispatch();
-}
-
-static GSourceFuncs waylandGLibSourceFuncs = {
-    prepareCallback,
-    checkCallback,
-    dispatchCallback,
-    nullptr, // finalize
-    nullptr, // closure_callback
-    nullptr, // closure_marshall
-};
-
-GSource* WaylandEventSource::createDisplayEventSource(struct wl_display* display)
-{
-    GSource* base = g_source_new(&waylandGLibSourceFuncs, sizeof(GLibSource));
-
-    auto source = reinterpret_cast<GLibSource*>(base);
-    source->initialize(display);
-
-    return base;
-}
-
-} // namespace WebCore
-
-#endif // PLATFORM(WAYLAND)
diff --git a/Source/WebCore/platform/graphics/wayland/WaylandSurface.cpp b/Source/WebCore/platform/graphics/wayland/WaylandSurface.cpp
deleted file mode 100644 (file)
index 971ab19..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2014 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 APPLE COMPUTER, INC. ``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 COMPUTER, INC. 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 "WaylandSurface.h"
-
-#if PLATFORM(WAYLAND)
-
-#include "GLContextEGL.h"
-#include "IntSize.h"
-#include "PlatformDisplayWayland.h"
-#include <EGL/egl.h>
-
-namespace WebCore {
-
-void frameCallback(void*, struct wl_callback* callback, uint32_t)
-{
-    if (callback)
-        wl_callback_destroy(callback);
-}
-
-static const struct wl_callback_listener frameListener = {
-    frameCallback
-};
-
-WaylandSurface::WaylandSurface(struct wl_surface* wlSurface, EGLNativeWindowType nativeWindow)
-    : m_wlSurface(wlSurface)
-    , m_nativeWindow(nativeWindow)
-{
-}
-
-WaylandSurface::~WaylandSurface()
-{
-    // The surface couldn't have been created in the first place if WaylandDisplay wasn't properly initialized.
-    const PlatformDisplayWayland& waylandDisplay = downcast<PlatformDisplayWayland>(PlatformDisplay::sharedDisplay());
-    ASSERT(waylandDisplay.native());
-    eglMakeCurrent(waylandDisplay.native(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
-
-    wl_egl_window_destroy(m_nativeWindow);
-    wl_surface_destroy(m_wlSurface);
-}
-
-void WaylandSurface::resize(const IntSize& size)
-{
-    wl_egl_window_resize(m_nativeWindow, size.width(), size.height(), 0, 0);
-}
-
-std::unique_ptr<GLContextEGL> WaylandSurface::createGLContext()
-{
-    return GLContextEGL::createWindowContext(m_nativeWindow, GLContext::sharingContext());
-}
-
-void WaylandSurface::requestFrame()
-{
-    struct wl_callback* frameCallback = wl_surface_frame(m_wlSurface);
-    wl_callback_add_listener(frameCallback, &frameListener, this);
-}
-
-} // namespace WebCore
-
-#endif // PLATFORM(WAYLAND)
diff --git a/Source/WebCore/platform/graphics/wayland/WlUniquePtr.h b/Source/WebCore/platform/graphics/wayland/WlUniquePtr.h
new file mode 100644 (file)
index 0000000..03d2dab
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2016 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 APPLE COMPUTER, INC. ``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 COMPUTER, INC. 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
+
+#if PLATFORM(WAYLAND)
+#include <wayland-client-protocol.h>
+#include <wayland-server.h>
+
+namespace WebCore {
+
+template<typename T>
+struct WlPtrDeleter {
+};
+
+template<typename T>
+using WlUniquePtr = std::unique_ptr<T, WlPtrDeleter<T>>;
+
+#define FOR_EACH_WAYLAND_DELETER(macro) \
+    macro(struct wl_display, wl_display_destroy) \
+    macro(struct wl_global, wl_global_destroy) \
+    macro(struct wl_surface, wl_surface_destroy) \
+    macro(struct wl_compositor, wl_compositor_destroy) \
+    macro(struct wl_registry, wl_registry_destroy) \
+    macro(struct wl_proxy, wl_proxy_destroy)
+
+#define DEFINE_WAYLAND_DELETER(typeName, deleterFunc) \
+    template<> struct WlPtrDeleter<typeName> \
+    { \
+        void operator() (typeName* ptr) const { deleterFunc(ptr); } \
+    };
+
+FOR_EACH_WAYLAND_DELETER(DEFINE_WAYLAND_DELETER)
+#undef FOR_EACH_WAYLAND_DELETER
+#undef DEFINE_WAYLAND_DELETER
+
+} // namespace WebCore
+
+#endif // PLATFORM(WAYLAND)
index 4b1cf6b..978b4eb 100644 (file)
@@ -1,3 +1,16 @@
+2016-08-16  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK] Accelerated compositing does not work in Wayland
+        https://bugs.webkit.org/show_bug.cgi?id=115803
+
+        Reviewed by Michael Catanzaro.
+
+        Update to the new GLContext API.
+
+        * WebCoreSupport/AcceleratedCompositingContext.cpp:
+        (AcceleratedCompositingContext::initialize):
+        (AcceleratedCompositingContext::acceleratedCompositingAvailable):
+
 2016-08-21  Alex Christensen  <achristensen@webkit.org>
 
         Use Document& instead of Document* when getting cookies
index 9a26d92..17817b9 100644 (file)
@@ -102,7 +102,7 @@ void AcceleratedCompositingContext::initialize()
 
     // The creation of the TextureMapper needs an active OpenGL context.
     if (!m_context)
-        m_context = GLContext::createContextForWindow(m_window, GLContext::sharingContext());
+        m_context = GLContext::createContextForWindow(m_window);
 
     if (!m_context)
         return;
@@ -282,7 +282,7 @@ bool AcceleratedCompositingContext::acceleratedCompositingAvailable()
         return false;
 
     // Create GL context.
-    std::unique_ptr<WebCore::GLContext> context = GLContext::createContextForWindow(testWindow, GLContext::sharingContext());
+    std::unique_ptr<WebCore::GLContext> context = GLContext::createContextForWindow(testWindow);
 
     if (!context) {
         ::DestroyWindow(testWindow);
index 6ccd5d5..4af5d27 100644 (file)
@@ -1,3 +1,155 @@
+2016-08-16  Carlos Garcia Campos  <cgarcia@igalia.com>
+
+        [GTK] Accelerated compositing does not work in Wayland
+        https://bugs.webkit.org/show_bug.cgi?id=115803
+
+        Reviewed by Michael Catanzaro.
+
+        This is the initial implementation of accelerated compositing support in Wayland for the GTK+ port. It's based
+        on previous patches written by Iago Toral, Žan Doberšek, Emanuele Aina and Emilio Pozuelo Monfort.
+
+        The existing WebKitGTK+ Wayland interface previously added for this to WebCore has been moved to the WebKit2
+        layer, since it's actually specific to WebKit2, and it's now actually used. The UI process runs a nested Wayland
+        compositor that web processes connect to. Web processes create a Wayland surface in the nested compositor for
+        the web page, and using the WebKitGTK+ Wayland protocol interface they tell the nested compositor the web page
+        associated to the surface. A Wayland window is created for that surface that is then used as the native window
+        handle for compositing. To communicate with the nested compositor and to ensure all GL operations happen in the
+        nested compositor display, the web process creates a Wayland display that connects to the nested compositor,
+        uses the WebKitGTK+ Wayland interface and it's set as the global shared display for compositing.
+
+        The nested Wayland compositor creates a new display with a unique name that is sent to the web processes at
+        start up. It implements the Wayland surface interface to handle the Wayland buffers created for every surface
+        and scheduling redraws on the web pages when updates are available. It uses the WebKitGTK+ Wayland interface to
+        associate the surfaces to a particular web page. A texture is created for every surface and updated with the
+        Wayland buffer contents using an EGLImageKHR and eglImageTargetTexture2d API.
+
+        To abstract the platform differences and avoid ifdefs as much as possible, new abstract classes have been added
+        to represent the surfaces used in accelerated compositing. AcceleratedSurface is used by the web process and
+        represents the surface where contents are rendered into. The X11 implementation is the redirected XComposite
+        window, and the Wayland implementation is equivalent to the previous Wayland surface added to WebCore but never
+        used. In the UI process the web view creates an abstract AcceleratedBackingStore that is used to render the
+        AcceleratedSurface into the web view using cairo. The X11 implementation creates the cairo surface for the
+        redirected XComposite window pixmap and uses XDamage extension to schedule redraws. The Wayland implementation
+        asks the nested Wayland compositor for the texture associated to the web view page.
+
+        Accelerated compositing is now always enabled by default in both X11 and Wayland, unless it's explicitly
+        disabled by the user using the WEBKIT_DISABLE_COMPOSITING_MODE environment variable, or if any extension or
+        feature required by X11 or Wayland implementations are not available.
+
+        * PlatformGTK.cmake:
+        * Shared/CoordinatedGraphics/threadedcompositor/ThreadedCompositor.cpp:
+        (WebKit::ThreadedCompositor::glContext): Pass the shared display for compositing to GLContext::createContextForWindow()
+        * Shared/WebProcessCreationParameters.cpp:
+        (WebKit::WebProcessCreationParameters::encode): Encode wayland compositor display name.
+        (WebKit::WebProcessCreationParameters::decode): Decode wayland compositor display name.
+        * Shared/WebProcessCreationParameters.h: Add wayland compositor display name initial parameter.
+        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
+        (webkitWebViewBaseDispose):
+        (webkitWebViewBaseDraw):
+        (webkitWebViewBaseCreateWebPage):
+        (webkitWebViewBaseEnterAcceleratedCompositingMode):
+        (webkitWebViewBaseUpdateAcceleratedCompositingMode):
+        (webkitWebViewBaseExitAcceleratedCompositingMode):
+        (webkitWebViewBasePageClosed):
+        * UIProcess/WebProcessPool.cpp:
+        (WebKit::WebProcessPool::createNewWebProcess): Initialize the wayland compositor display name initial parameter.
+        * UIProcess/gtk/AcceleratedBackingStore.cpp: Added.
+        (WebKit::AcceleratedBackingStore::create):
+        (WebKit::AcceleratedBackingStore::AcceleratedBackingStore):
+        (WebKit::AcceleratedBackingStore::~AcceleratedBackingStore):
+        (WebKit::AcceleratedBackingStore::paint):
+        * UIProcess/gtk/AcceleratedBackingStore.h: Added.
+        (WebKit::AcceleratedBackingStore::update):
+        * UIProcess/gtk/AcceleratedBackingStoreWayland.cpp: Added.
+        (WebKit::AcceleratedBackingStoreWayland::create):
+        (WebKit::AcceleratedBackingStoreWayland::AcceleratedBackingStoreWayland):
+        (WebKit::AcceleratedBackingStoreWayland::~AcceleratedBackingStoreWayland):
+        (WebKit::AcceleratedBackingStoreWayland::paint):
+        * UIProcess/gtk/AcceleratedBackingStoreWayland.h: Added.
+        * UIProcess/gtk/AcceleratedBackingStoreX11.cpp: Added.
+        (WebKit::XDamageNotifier::singleton):
+        (WebKit::XDamageNotifier::add):
+        (WebKit::XDamageNotifier::remove):
+        (WebKit::XDamageNotifier::filterXDamageEvent):
+        (WebKit::XDamageNotifier::notify):
+        (WebKit::AcceleratedBackingStoreX11::create):
+        (WebKit::AcceleratedBackingStoreX11::AcceleratedBackingStoreX11):
+        (WebKit::AcceleratedBackingStoreX11::~AcceleratedBackingStoreX11):
+        (WebKit::AcceleratedBackingStoreX11::update):
+        (WebKit::AcceleratedBackingStoreX11::paint):
+        * UIProcess/gtk/AcceleratedBackingStoreX11.h: Added.
+        * UIProcess/gtk/WaylandCompositor.cpp: Added.
+        (WebKit::WaylandCompositor::singleton):
+        (WebKit::WaylandCompositor::Buffer::getOrCreate):
+        (WebKit::WaylandCompositor::Buffer::Buffer):
+        (WebKit::WaylandCompositor::Buffer::~Buffer):
+        (WebKit::WaylandCompositor::Buffer::destroyListenerCallback):
+        (WebKit::WaylandCompositor::Buffer::use):
+        (WebKit::WaylandCompositor::Buffer::unuse):
+        (WebKit::WaylandCompositor::Buffer::createImage):
+        (WebKit::WaylandCompositor::Buffer::size):
+        (WebKit::WaylandCompositor::Surface::Surface):
+        (WebKit::WaylandCompositor::Surface::~Surface):
+        (WebKit::WaylandCompositor::Surface::makePendingBufferCurrent):
+        (WebKit::WaylandCompositor::Surface::attachBuffer):
+        (WebKit::WaylandCompositor::Surface::requestFrame):
+        (WebKit::WaylandCompositor::Surface::prepareTextureForPainting):
+        (WebKit::WaylandCompositor::Surface::commit):
+        (WebKit::WaylandCompositor::initializeEGL):
+        (WebKit::createWaylandLoopSource):
+        (WebKit::WaylandCompositor::WaylandCompositor):
+        (WebKit::WaylandCompositor::getTexture):
+        (WebKit::WaylandCompositor::bindSurfaceToWebPage):
+        (WebKit::WaylandCompositor::registerWebPage):
+        (WebKit::WaylandCompositor::unregisterWebPage):
+        * UIProcess/gtk/WaylandCompositor.h: Added.
+        (WebKit::WaylandCompositor::Buffer::createWeakPtr):
+        (WebKit::WaylandCompositor::Surface::setWebPage):
+        (WebKit::WaylandCompositor::isRunning):
+        (WebKit::WaylandCompositor::displayName):
+        * UIProcess/gtk/WebPreferencesGtk.cpp:
+        (WebKit::WebPreferences::platformInitializeStore):
+        * UIProcess/gtk/XDamageNotifier.cpp: Removed.
+        * WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.cpp:
+        (WebKit::ThreadedCoordinatedLayerTreeHost::ThreadedCoordinatedLayerTreeHost):
+        (WebKit::ThreadedCoordinatedLayerTreeHost::invalidate):
+        (WebKit::ThreadedCoordinatedLayerTreeHost::deviceOrPageScaleFactorChanged):
+        (WebKit::ThreadedCoordinatedLayerTreeHost::sizeDidChange):
+        * WebProcess/WebPage/CoordinatedGraphics/ThreadedCoordinatedLayerTreeHost.h:
+        * WebProcess/WebPage/gtk/AcceleratedSurface.cpp: Added.
+        (WebKit::AcceleratedSurface::create):
+        (WebKit::AcceleratedSurface::AcceleratedSurface):
+        (WebKit::AcceleratedSurface::~AcceleratedSurface):
+        (WebKit::AcceleratedSurface::resize):
+        * WebProcess/WebPage/gtk/AcceleratedSurface.h: Added.
+        (WebKit::AcceleratedSurface::window):
+        (WebKit::AcceleratedSurface::surfaceID):
+        * WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp: Added.
+        (WebKit::waylandCompositorDisplay):
+        (WebKit::AcceleratedSurfaceWayland::create):
+        (WebKit::AcceleratedSurfaceWayland::AcceleratedSurfaceWayland):
+        (WebKit::AcceleratedSurfaceWayland::~AcceleratedSurfaceWayland):
+        (WebKit::AcceleratedSurfaceWayland::resize):
+        * WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h: Added.
+        * WebProcess/WebPage/gtk/AcceleratedSurfaceX11.cpp: Renamed from Source/WebKit2/WebProcess/WebPage/gtk/RedirectedXCompositeWindow.cpp.
+        (WebKit::AcceleratedSurfaceX11::create):
+        (WebKit::AcceleratedSurfaceX11::AcceleratedSurfaceX11):
+        (WebKit::AcceleratedSurfaceX11::~AcceleratedSurfaceX11):
+        (WebKit::AcceleratedSurfaceX11::resize):
+        * WebProcess/WebPage/gtk/AcceleratedSurfaceX11.h: Renamed from Source/WebKit2/WebProcess/WebPage/gtk/RedirectedXCompositeWindow.h.
+        * WebProcess/WebPage/gtk/LayerTreeHostGtk.cpp:
+        (WebKit::LayerTreeHostGtk::LayerTreeHostGtk):
+        (WebKit::LayerTreeHostGtk::makeContextCurrent):
+        (WebKit::LayerTreeHostGtk::invalidate):
+        (WebKit::LayerTreeHostGtk::sizeDidChange):
+        (WebKit::LayerTreeHostGtk::deviceOrPageScaleFactorChanged):
+        (WebKit::LayerTreeHostGtk::RenderFrameScheduler::RenderFrameScheduler): Deleted.
+        * WebProcess/WebPage/gtk/LayerTreeHostGtk.h:
+        * WebProcess/WebProcess.cpp:
+        (WebKit::WebProcess::initializeWebProcess): Initialize the wayland compositor display name.
+        * WebProcess/WebProcess.h:
+        (WebKit::WebProcess::waylandCompositorDisplayName): Return the wayland compositor display name.
+
 2016-08-27  Jonathan Bedard  <jbedard@apple.com>
 
         WTR needs an implementation of setAutomaticLinkDetectionEnabled
index 343e96b..0980f55 100644 (file)
@@ -295,13 +295,16 @@ list(APPEND WebKit2_SOURCES
     UIProcess/gstreamer/InstallMissingMediaPluginsPermissionRequest.cpp
     UIProcess/gstreamer/WebPageProxyGStreamer.cpp
 
+    UIProcess/gtk/AcceleratedBackingStore.cpp
+    UIProcess/gtk/AcceleratedBackingStoreWayland.cpp
+    UIProcess/gtk/AcceleratedBackingStoreX11.cpp
     UIProcess/gtk/DragAndDropHandler.cpp
     UIProcess/gtk/ExperimentalFeatures.cpp
     UIProcess/gtk/GestureController.cpp
     UIProcess/gtk/InputMethodFilter.cpp
     UIProcess/gtk/KeyBindingTranslator.cpp
     UIProcess/gtk/TextCheckerGtk.cpp
-    UIProcess/gtk/XDamageNotifier.cpp
+    UIProcess/gtk/WaylandCompositor.cpp
     UIProcess/gtk/WebColorPickerGtk.cpp
     UIProcess/gtk/WebContextMenuProxyGtk.cpp
     UIProcess/gtk/WebFullScreenClientGtk.cpp
@@ -350,8 +353,10 @@ list(APPEND WebKit2_SOURCES
 
     WebProcess/WebPage/gstreamer/WebPageGStreamer.cpp
 
+    WebProcess/WebPage/gtk/AcceleratedSurface.cpp
+    WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp
+    WebProcess/WebPage/gtk/AcceleratedSurfaceX11.cpp
     WebProcess/WebPage/gtk/PrinterListGtk.cpp
-    WebProcess/WebPage/gtk/RedirectedXCompositeWindow.cpp
     WebProcess/WebPage/gtk/WebInspectorUIGtk.cpp
     WebProcess/WebPage/gtk/WebPageGtk.cpp
     WebProcess/WebPage/gtk/WebPrintOperationGtk.cpp
@@ -368,6 +373,7 @@ list(APPEND WebKit2_DERIVED_SOURCES
     ${DERIVED_SOURCES_WEBKIT2GTK_DIR}/InspectorGResourceBundle.c
     ${DERIVED_SOURCES_WEBKIT2GTK_DIR}/WebKit2InspectorGResourceBundle.c
     ${DERIVED_SOURCES_WEBKIT2GTK_DIR}/WebKit2ResourcesGResourceBundle.c
+    ${DERIVED_SOURCES_WEBKIT2GTK_DIR}/WebKit2WaylandClientProtocol.c
 
     ${DERIVED_SOURCES_WEBKIT2GTK_API_DIR}/WebKitEnumTypes.cpp
     ${DERIVED_SOURCES_WEBKIT2GTK_API_DIR}/WebKitMarshal.cpp
@@ -684,6 +690,17 @@ add_custom_command(
     VERBATIM
 )
 
+if (ENABLE_WAYLAND_TARGET)
+    # Wayland protocol extension.
+    add_custom_command(
+        OUTPUT ${DERIVED_SOURCES_WEBKIT2GTK_DIR}/WebKit2WaylandClientProtocol.c
+        DEPENDS ${WEBKIT2_DIR}/Shared/gtk/WebKit2WaylandProtocol.xml
+        COMMAND wayland-scanner server-header < ${WEBKIT2_DIR}/Shared/gtk/WebKit2WaylandProtocol.xml > ${DERIVED_SOURCES_WEBKIT2GTK_DIR}/WebKit2WaylandServerProtocol.h
+        COMMAND wayland-scanner client-header < ${WEBKIT2_DIR}/Shared/gtk/WebKit2WaylandProtocol.xml > ${DERIVED_SOURCES_WEBKIT2GTK_DIR}/WebKit2WaylandClientProtocol.h
+        COMMAND wayland-scanner code < ${WEBKIT2_DIR}/Shared/gtk/WebKit2WaylandProtocol.xml > ${DERIVED_SOURCES_WEBKIT2GTK_DIR}/WebKit2WaylandClientProtocol.c
+    )
+endif ()
+
 if (ENABLE_PLUGIN_PROCESS_GTK2)
     set(PluginProcessGTK2_EXECUTABLE_NAME WebKitPluginProcess2)
 
index 3452428..54a610c 100644 (file)
@@ -29,6 +29,7 @@
 #if USE(COORDINATED_GRAPHICS_THREADED)
 
 #include "CompositingRunLoop.h"
+#include <WebCore/PlatformDisplay.h>
 #include <WebCore/TransformationMatrix.h>
 
 #if USE(OPENGL_ES_2)
@@ -41,14 +42,15 @@ using namespace WebCore;
 
 namespace WebKit {
 
-Ref<ThreadedCompositor> ThreadedCompositor::create(Client* client, uint64_t nativeSurfaceHandle)
+Ref<ThreadedCompositor> ThreadedCompositor::create(Client* client, uint64_t nativeSurfaceHandle, ShouldDoFrameSync doFrameSync)
 {
-    return adoptRef(*new ThreadedCompositor(client, nativeSurfaceHandle));
+    return adoptRef(*new ThreadedCompositor(client, nativeSurfaceHandle, doFrameSync));
 }
 
-ThreadedCompositor::ThreadedCompositor(Client* client, uint64_t nativeSurfaceHandle)
+ThreadedCompositor::ThreadedCompositor(Client* client, uint64_t nativeSurfaceHandle, ShouldDoFrameSync doFrameSync)
     : m_client(client)
     , m_nativeSurfaceHandle(nativeSurfaceHandle)
+    , m_doFrameSync(doFrameSync)
     , m_compositingRunLoop(std::make_unique<CompositingRunLoop>([this] { renderLayerTree(); }))
 {
     m_compositingRunLoop->performTaskSync([this, protectedThis = makeRef(*this)] {
@@ -164,34 +166,25 @@ void ThreadedCompositor::scheduleDisplayImmediately()
     m_compositingRunLoop->startUpdateTimer(CompositingRunLoop::Immediate);
 }
 
-bool ThreadedCompositor::tryEnsureGLContext()
+bool ThreadedCompositor::makeContextCurrent()
 {
-    if (!glContext())
-        return false;
+    if (m_context)
+        return m_context->makeContextCurrent();
 
-    glContext()->makeContextCurrent();
-    // The window size may be out of sync with the page size at this point, and getting
-    // the viewport parameters incorrect, means that the content will be misplaced. Thus
-    // we set the viewport parameters directly from the window size.
-    IntSize contextSize = glContext()->defaultFrameBufferSize();
-    if (m_viewportSize != contextSize) {
-        glViewport(0, 0, contextSize.width(), contextSize.height());
-        m_viewportSize = contextSize;
-    }
+    if (!m_nativeSurfaceHandle)
+        return false;
 
-    return true;
-}
+    m_context = GLContext::createContextForWindow(reinterpret_cast<GLNativeWindowType>(m_nativeSurfaceHandle), &PlatformDisplay::sharedDisplayForCompositing());
+    if (!m_context)
+        return false;
 
-GLContext* ThreadedCompositor::glContext()
-{
-    if (m_context)
-        return m_context.get();
+    if (!m_context->makeContextCurrent())
+        return false;
 
-    if (!m_nativeSurfaceHandle)
-        return nullptr;
+    if (m_doFrameSync == ShouldDoFrameSync::No)
+        m_context->swapInterval(0);
 
-    m_context = GLContext::createContextForWindow(reinterpret_cast<GLNativeWindowType>(m_nativeSurfaceHandle), GLContext::sharingContext());
-    return m_context.get();
+    return true;
 }
 
 void ThreadedCompositor::forceRepaint()
@@ -216,9 +209,18 @@ void ThreadedCompositor::renderLayerTree()
     if (!m_scene || !m_scene->isActive())
         return;
 
-    if (!tryEnsureGLContext())
+    if (!makeContextCurrent())
         return;
 
+    // The window size may be out of sync with the page size at this point, and getting
+    // the viewport parameters incorrect, means that the content will be misplaced. Thus,
+    // we set the viewport parameters directly from the window size.
+    IntSize contextSize = m_context->defaultFrameBufferSize();
+    if (m_viewportSize != contextSize) {
+        glViewport(0, 0, contextSize.width(), contextSize.height());
+        m_viewportSize = contextSize;
+    }
+
     FloatRect clipRect(0, 0, m_viewportSize.width(), m_viewportSize.height());
 
     TransformationMatrix viewportTransform;
@@ -232,7 +234,7 @@ void ThreadedCompositor::renderLayerTree()
     }
     m_scene->paintToCurrentGLContext(viewportTransform, 1, clipRect, Color::transparent, !m_drawsBackground, scrollPostion);
 
-    glContext()->swapBuffers();
+    m_context->swapBuffers();
 }
 
 void ThreadedCompositor::updateSceneState(const CoordinatedGraphicsState& state)
index 042c69f..63684f8 100644 (file)
@@ -57,7 +57,9 @@ public:
         virtual void commitScrollOffset(uint32_t layerID, const WebCore::IntSize& offset) = 0;
     };
 
-    static Ref<ThreadedCompositor> create(Client*, uint64_t nativeSurfaceHandle = 0);
+    enum class ShouldDoFrameSync { No, Yes };
+
+    static Ref<ThreadedCompositor> create(Client*, uint64_t nativeSurfaceHandle = 0, ShouldDoFrameSync = ShouldDoFrameSync::Yes);
     virtual ~ThreadedCompositor();
 
     void setNativeSurfaceHandleForCompositing(uint64_t);
@@ -77,7 +79,7 @@ public:
     void forceRepaint();
 
 private:
-    ThreadedCompositor(Client*, uint64_t nativeSurfaceHandle);
+    ThreadedCompositor(Client*, uint64_t nativeSurfaceHandle, ShouldDoFrameSync);
 
     // CoordinatedGraphicsSceneClient
     void renderNextFrame() override;
@@ -90,8 +92,7 @@ private:
     void renderLayerTree();
     void scheduleDisplayImmediately();
 
-    bool tryEnsureGLContext();
-    WebCore::GLContext* glContext();
+    bool makeContextCurrent();
 
     Client* m_client { nullptr };
     RefPtr<CoordinatedGraphicsScene> m_scene;
@@ -102,6 +103,7 @@ private:
     float m_deviceScaleFactor { 1 };
     bool m_drawsBackground { true };
     uint64_t m_nativeSurfaceHandle;
+    ShouldDoFrameSync m_doFrameSync;
 
     std::unique_ptr<CompositingRunLoop> m_compositingRunLoop;
 };
index 9ebb43d..2198fc9 100644 (file)
@@ -145,6 +145,10 @@ void WebProcessCreationParameters::encode(IPC::Encoder& encoder) const
 #if OS(LINUX)
     encoder << memoryPressureMonitorHandle;
 #endif
+
+#if PLATFORM(WAYLAND)
+    encoder << waylandCompositorDisplayName;
+#endif
 }
 
 bool WebProcessCreationParameters::decode(IPC::Decoder& decoder, WebProcessCreationParameters& parameters)
@@ -305,6 +309,11 @@ bool WebProcessCreationParameters::decode(IPC::Decoder& decoder, WebProcessCreat
         return false;
 #endif
 
+#if PLATFORM(WAYLAND)
+    if (!decoder.decode(parameters.waylandCompositorDisplayName))
+        return false;
+#endif
+
     return true;
 }
 
index ff2005c..c26c4bf 100644 (file)
@@ -170,6 +170,10 @@ struct WebProcessCreationParameters {
 #if OS(LINUX)
     IPC::Attachment memoryPressureMonitorHandle;
 #endif
+
+#if PLATFORM(WAYLAND)
+    String waylandCompositorDisplayName;
+#endif
 };
 
 } // namespace WebKit
@@ -27,9 +27,9 @@
   </copyright>
 
   <interface name="wl_webkitgtk" version="1">
-    <request name="set_surface_for_widget">
+    <request name="bind_surface_to_page">
       <arg name="surface" type="object" interface="wl_surface"/>
-      <arg name="id" type="uint"/>
+      <arg name="page_id" type="uint"/>
     </request>
 
   </interface>
index ad38140..06af059 100644 (file)
@@ -30,6 +30,7 @@
 #include "WebKitWebViewBase.h"
 
 #include "APIPageConfiguration.h"
+#include "AcceleratedBackingStore.h"
 #include "DrawingAreaProxyImpl.h"
 #include "InputMethodFilter.h"
 #include "KeyBindingTranslator.h"
 #include "WebFullScreenManagerProxy.h"
 #endif
 
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-#include "XDamageNotifier.h"
-#include <WebCore/PlatformDisplayX11.h>
-#include <WebCore/XUniqueResource.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/Xdamage.h>
-#include <cairo-xlib.h>
-#endif
-
 #if PLATFORM(X11)
 #include <gdk/gdkx.h>
 #endif
 
-#if PLATFORM(WAYLAND)
-#include <gdk/gdkwayland.h>
-#endif
-
 // gtk_widget_get_scale_factor() appeared in GTK 3.10, but we also need
 // to make sure we have cairo new enough to support cairo_surface_set_device_scale
 #define HAVE_GTK_SCALE_FACTOR HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE && GTK_CHECK_VERSION(3, 10, 0)
@@ -211,10 +199,7 @@ struct _WebKitWebViewBasePrivate {
     unsigned screenSaverCookie;
 #endif
 
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    RefPtr<cairo_surface_t> acceleratedCompositingSurface;
-    XUniqueDamage acceleratedCompositingSurfaceDamage;
-#endif
+    std::unique_ptr<AcceleratedBackingStore> acceleratedBackingStore;
 
 #if ENABLE(DRAG_SUPPORT)
     std::unique_ptr<DragAndDropHandler> dragAndDropHandler;
@@ -351,50 +336,6 @@ static void webkitWebViewBaseSetToplevelOnScreenWindow(WebKitWebViewBase* webVie
         priv->toplevelWindowRealizedID = g_signal_connect_swapped(window, "realize", G_CALLBACK(toplevelWindowRealized), webViewBase);
 }
 
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-static void webkitWebViewBaseSetAcceleratedCompositingPixmap(WebKitWebViewBase* webView, Pixmap pixmap)
-{
-    if (PlatformDisplay::sharedDisplay().type() != PlatformDisplay::Type::X11)
-        return;
-
-    WebKitWebViewBasePrivate* priv = webView->priv;
-    if (priv->acceleratedCompositingSurface
-        && cairo_xlib_surface_get_drawable(priv->acceleratedCompositingSurface.get()) == pixmap)
-        return;
-
-    if (priv->acceleratedCompositingSurface) {
-        if (priv->acceleratedCompositingSurfaceDamage) {
-            XDamageNotifier::singleton().remove(priv->acceleratedCompositingSurfaceDamage.get());
-            priv->acceleratedCompositingSurfaceDamage.reset();
-        }
-        priv->acceleratedCompositingSurface = nullptr;
-    }
-
-    if (!pixmap)
-        return;
-
-    DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(priv->pageProxy->drawingArea());
-    if (!drawingArea)
-        return;
-
-    IntSize size = drawingArea->size();
-    float deviceScaleFactor = priv->pageProxy->deviceScaleFactor();
-    size.scale(deviceScaleFactor);
-
-    Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
-    ASSERT(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native() == GDK_DISPLAY_XDISPLAY(gdk_display_get_default()));
-    GdkVisual* visual = gdk_screen_get_rgba_visual(gdk_screen_get_default());
-    if (!visual)
-        visual = gdk_screen_get_system_visual(gdk_screen_get_default());
-    priv->acceleratedCompositingSurface = adoptRef(cairo_xlib_surface_create(display, pixmap, GDK_VISUAL_XVISUAL(visual), size.width(), size.height()));
-    cairoSurfaceSetDeviceScale(priv->acceleratedCompositingSurface.get(), deviceScaleFactor, deviceScaleFactor);
-    priv->acceleratedCompositingSurfaceDamage = XDamageCreate(display, pixmap, XDamageReportNonEmpty);
-    XDamageNotifier::singleton().add(priv->acceleratedCompositingSurfaceDamage.get(), [webView] {
-        gtk_widget_queue_draw(GTK_WIDGET(webView));
-    });
-}
-#endif
-
 static void webkitWebViewBaseRealize(GtkWidget* widget)
 {
     WebKitWebViewBase* webView = WEBKIT_WEB_VIEW_BASE(widget);
@@ -564,9 +505,7 @@ static void webkitWebViewBaseDispose(GObject* gobject)
     g_cancellable_cancel(webView->priv->screenSaverInhibitCancellable.get());
     webkitWebViewBaseSetToplevelOnScreenWindow(webView, nullptr);
     webView->priv->pageProxy->close();
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    webkitWebViewBaseSetAcceleratedCompositingPixmap(webView, 0);
-#endif
+    webView->priv->acceleratedBackingStore = nullptr;
     G_OBJECT_CLASS(webkit_web_view_base_parent_class)->dispose(gobject);
 }
 
@@ -585,55 +524,6 @@ static void webkitWebViewBaseConstructed(GObject* object)
     priv->authenticationDialog = 0;
 }
 
-static bool webkitWebViewRenderAcceleratedCompositingResults(WebKitWebViewBase* webViewBase, DrawingAreaProxyImpl* drawingArea, cairo_t* cr, GdkRectangle* clipRect)
-{
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    ASSERT(drawingArea);
-
-    if (!drawingArea->isInAcceleratedCompositingMode())
-        return false;
-
-    WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(webViewBase)->priv;
-    cairo_surface_t* surface = priv->acceleratedCompositingSurface.get();
-    cairo_save(cr);
-
-    if (!surface || !priv->pageProxy->drawsBackground()) {
-        const WebCore::Color& color = priv->pageProxy->backgroundColor();
-        if (color.hasAlpha()) {
-            cairo_rectangle(cr, clipRect->x, clipRect->y, clipRect->width, clipRect->height);
-            cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
-            cairo_fill(cr);
-        }
-
-        if (color.alpha() > 0) {
-            setSourceRGBAFromColor(cr, color);
-            cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
-            cairo_rectangle(cr, clipRect->x, clipRect->y, clipRect->width, clipRect->height);
-            cairo_fill(cr);
-        }
-    }
-
-    if (surface) {
-        // The surface can be modified by the web process at any time, so we mark it
-        // as dirty to ensure we always render the updated contents as soon as possible.
-        cairo_surface_mark_dirty(surface);
-        cairo_rectangle(cr, clipRect->x, clipRect->y, clipRect->width, clipRect->height);
-        cairo_set_source_surface(cr, surface, 0, 0);
-        cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
-        cairo_fill(cr);
-    }
-
-    cairo_restore(cr);
-
-    return true;
-#else
-    UNUSED_PARAM(webViewBase);
-    UNUSED_PARAM(cr);
-    UNUSED_PARAM(clipRect);
-    return false;
-#endif
-}
-
 static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr)
 {
     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
@@ -645,7 +535,9 @@ static gboolean webkitWebViewBaseDraw(GtkWidget* widget, cairo_t* cr)
     if (!gdk_cairo_get_clip_rectangle(cr, &clipRect))
         return FALSE;
 
-    if (!webkitWebViewRenderAcceleratedCompositingResults(webViewBase, drawingArea, cr, &clipRect)) {
+    if (webViewBase->priv->acceleratedBackingStore && drawingArea->isInAcceleratedCompositingMode())
+        webViewBase->priv->acceleratedBackingStore->paint(cr, clipRect);
+    else {
         WebCore::Region unpaintedRegion; // This is simply unused.
         drawingArea->paint(cr, clipRect, unpaintedRegion);
     }
@@ -1286,6 +1178,8 @@ void webkitWebViewBaseCreateWebPage(WebKitWebViewBase* webkitWebViewBase, Ref<AP
     priv->pageProxy = context->createWebPage(*priv->pageClient, WTFMove(configuration));
     priv->pageProxy->initializeWebPage();
 
+    priv->acceleratedBackingStore = AcceleratedBackingStore::create(*priv->pageProxy);
+
     priv->inputMethodFilter.setPage(priv->pageProxy.get());
 
 #if HAVE(GTK_SCALE_FACTOR)
@@ -1566,29 +1460,20 @@ void webkitWebViewBaseResetClickCounter(WebKitWebViewBase* webkitWebViewBase)
 
 void webkitWebViewBaseEnterAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext)
 {
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    webkitWebViewBaseSetAcceleratedCompositingPixmap(webkitWebViewBase, layerTreeContext.contextID);
-#else
-    UNUSED_PARAM(webkitWebViewBase);
-#endif
+    if (webkitWebViewBase->priv->acceleratedBackingStore)
+        webkitWebViewBase->priv->acceleratedBackingStore->update(layerTreeContext);
 }
 
 void webkitWebViewBaseUpdateAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase, const LayerTreeContext& layerTreeContext)
 {
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    webkitWebViewBaseSetAcceleratedCompositingPixmap(webkitWebViewBase, layerTreeContext.contextID);
-#else
-    UNUSED_PARAM(webkitWebViewBase);
-#endif
+    if (webkitWebViewBase->priv->acceleratedBackingStore)
+        webkitWebViewBase->priv->acceleratedBackingStore->update(layerTreeContext);
 }
 
 void webkitWebViewBaseExitAcceleratedCompositingMode(WebKitWebViewBase* webkitWebViewBase)
 {
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    webkitWebViewBaseSetAcceleratedCompositingPixmap(webkitWebViewBase, 0);
-#else
-    UNUSED_PARAM(webkitWebViewBase);
-#endif
+    if (webkitWebViewBase->priv->acceleratedBackingStore)
+        webkitWebViewBase->priv->acceleratedBackingStore->update(LayerTreeContext());
 }
 
 void webkitWebViewBaseDidRelaunchWebProcess(WebKitWebViewBase* webkitWebViewBase)
@@ -1616,9 +1501,9 @@ void webkitWebViewBaseDidRelaunchWebProcess(WebKitWebViewBase* webkitWebViewBase
 
 void webkitWebViewBasePageClosed(WebKitWebViewBase* webkitWebViewBase)
 {
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    webkitWebViewBaseSetAcceleratedCompositingPixmap(webkitWebViewBase, 0);
-#elif PLATFORM(X11) && USE(TEXTURE_MAPPER)
+    if (webkitWebViewBase->priv->acceleratedBackingStore)
+        webkitWebViewBase->priv->acceleratedBackingStore->update(LayerTreeContext());
+#if PLATFORM(X11) && USE(TEXTURE_MAPPER) && !USE(REDIRECTED_XCOMPOSITE_WINDOW)
     if (PlatformDisplay::sharedDisplay().type() != PlatformDisplay::Type::X11)
         return;
 
index d2b625b..180781e 100644 (file)
 #include "CoordinatedLayerTreeHostProxy.h"
 #endif
 
+#if PLATFORM(WAYLAND)
+#include "WaylandCompositor.h"
+#include <WebCore/PlatformDisplay.h>
+#endif
+
 using namespace WebCore;
 
 namespace WebKit {
@@ -216,6 +221,13 @@ void AcceleratedDrawingAreaProxy::waitForAndDispatchDidUpdateBackingStoreState()
     if (m_webPageProxy.process().state() == WebProcessProxy::State::Launching)
         return;
 
+#if PLATFORM(WAYLAND)
+    // Never block the UI process in Wayland when waiting for DidUpdateBackingStoreState after a resize,
+    // because the nested compositor needs to handle the web process requests that happens while resizing.
+    if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland && WaylandCompositor::singleton().isRunning())
+        return;
+#endif
+
     // FIXME: waitForAndDispatchImmediately will always return the oldest DidUpdateBackingStoreState message that
     // hasn't yet been processed. But it might be better to skip ahead to some other DidUpdateBackingStoreState
     // message, if multiple DidUpdateBackingStoreState messages are waiting to be processed. For instance, we could
index e56cf1e..fae4d16 100644 (file)
 #include "MemoryPressureMonitor.h"
 #endif
 
+#if PLATFORM(WAYLAND)
+#include "WaylandCompositor.h"
+#include <WebCore/PlatformDisplay.h>
+#endif
+
 #ifndef NDEBUG
 #include <wtf/RefCountedLeakCounter.h>
 #endif
@@ -639,6 +644,11 @@ WebProcessProxy& WebProcessPool::createNewWebProcess()
         parameters.memoryPressureMonitorHandle = MemoryPressureMonitor::singleton().createHandle();
 #endif
 
+#if PLATFORM(WAYLAND)
+    if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland)
+        parameters.waylandCompositorDisplayName = WaylandCompositor::singleton().displayName();
+#endif
+
     parameters.resourceLoadStatisticsEnabled = resourceLoadStatisticsEnabled();
 
     // Add any platform specific parameters
diff --git a/Source/WebKit2/UIProcess/gtk/AcceleratedBackingStore.cpp b/Source/WebKit2/UIProcess/gtk/AcceleratedBackingStore.cpp
new file mode 100644 (file)
index 0000000..c162a3b
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2016 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 APPLE COMPUTER, INC. ``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 COMPUTER, INC. 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 "AcceleratedBackingStore.h"
+
+#include "WebPageProxy.h"
+#include <WebCore/CairoUtilities.h>
+#include <WebCore/PlatformDisplay.h>
+
+#if PLATFORM(WAYLAND)
+#include "AcceleratedBackingStoreWayland.h"
+#endif
+
+#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
+#include "AcceleratedBackingStoreX11.h"
+#endif
+
+using namespace WebCore;
+
+namespace WebKit {
+
+std::unique_ptr<AcceleratedBackingStore> AcceleratedBackingStore::create(WebPageProxy& webPage)
+{
+#if PLATFORM(WAYLAND)
+    if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland)
+        return AcceleratedBackingStoreWayland::create(webPage);
+#endif
+#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
+    if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11)
+        return AcceleratedBackingStoreX11::create(webPage);
+#endif
+    return nullptr;
+}
+
+AcceleratedBackingStore::AcceleratedBackingStore(WebPageProxy& webPage)
+    : m_webPage(webPage)
+{
+}
+
+bool AcceleratedBackingStore::paint(cairo_t* cr, const IntRect& clipRect)
+{
+    if (m_webPage.drawsBackground())
+        return true;
+
+    const WebCore::Color& color = m_webPage.backgroundColor();
+    if (color.hasAlpha()) {
+        cairo_rectangle(cr, clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height());
+        cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
+        cairo_fill(cr);
+    }
+
+    if (color.alpha() > 0) {
+        setSourceRGBAFromColor(cr, color);
+        cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
+        cairo_rectangle(cr, clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height());
+        cairo_fill(cr);
+    }
+
+    return true;
+}
+
+} // namespace WebKit
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Igalia S.L.
+ * Copyright (C) 2016 Igalia S.L.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef  WaylandSurface_h
-#define  WaylandSurface_h
+#pragma once
 
-#if PLATFORM(WAYLAND)
+#include <wtf/Noncopyable.h>
 
-#include <wayland-client.h>
-
-#include <wayland-egl.h>
-#include <EGL/eglplatform.h>
+typedef struct _cairo cairo_t;
 
 namespace WebCore {
+class IntRect;
+}
 
-class GLContextEGL;
-class IntSize;
-
-class WaylandSurface {
-public:
-    WaylandSurface(struct wl_surface*, EGLNativeWindowType);
-    ~WaylandSurface();
+namespace WebKit {
 
-    struct wl_surface* surface() { return m_wlSurface; }
-    EGLNativeWindowType nativeWindowHandle() { return m_nativeWindow; }
+class LayerTreeContext;
+class WebPageProxy;
 
-    void resize(const IntSize&);
+class AcceleratedBackingStore {
+    WTF_MAKE_NONCOPYABLE(AcceleratedBackingStore); WTF_MAKE_FAST_ALLOCATED;
+public:
+    static std::unique_ptr<AcceleratedBackingStore> create(WebPageProxy&);
+    virtual ~AcceleratedBackingStore() = default;
 
-    std::unique_ptr<GLContextEGL> createGLContext();
+    virtual void update(const LayerTreeContext&) { }
+    virtual bool paint(cairo_t*, const WebCore::IntRect&);
 
-    void requestFrame();
+protected:
+    AcceleratedBackingStore(WebPageProxy&);
 
-private:
-    struct wl_surface* m_wlSurface;
-    EGLNativeWindowType m_nativeWindow;
+    WebPageProxy& m_webPage;
 };
 
-} // namespace WebCore
-
-#endif // PLATFORM(WAYLAND)
-
-#endif // WaylandSurface_h
+} // namespace WebKit
diff --git a/Source/WebKit2/UIProcess/gtk/AcceleratedBackingStoreWayland.cpp b/Source/WebKit2/UIProcess/gtk/AcceleratedBackingStoreWayland.cpp
new file mode 100644 (file)
index 0000000..2f6ba63
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2016 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 APPLE COMPUTER, INC. ``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 COMPUTER, INC. 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 "AcceleratedBackingStoreWayland.h"
+
+#if PLATFORM(WAYLAND)
+
+#include "WaylandCompositor.h"
+#include "WebPageProxy.h"
+#include <WebCore/CairoUtilities.h>
+#include <WebCore/RefPtrCairo.h>
+
+#if USE(OPENGL_ES_2)
+#include <GLES2/gl2.h>
+#else
+#include <WebCore/OpenGLShims.h>
+#endif
+
+using namespace WebCore;
+
+namespace WebKit {
+
+std::unique_ptr<AcceleratedBackingStoreWayland> AcceleratedBackingStoreWayland::create(WebPageProxy& webPage)
+{
+    if (!WaylandCompositor::singleton().isRunning())
+        return nullptr;
+    return std::unique_ptr<AcceleratedBackingStoreWayland>(new AcceleratedBackingStoreWayland(webPage));
+}
+
+AcceleratedBackingStoreWayland::AcceleratedBackingStoreWayland(WebPageProxy& webPage)
+    : AcceleratedBackingStore(webPage)
+{
+    WaylandCompositor::singleton().registerWebPage(m_webPage);
+}
+
+AcceleratedBackingStoreWayland::~AcceleratedBackingStoreWayland()
+{
+    WaylandCompositor::singleton().unregisterWebPage(m_webPage);
+}
+
+bool AcceleratedBackingStoreWayland::paint(cairo_t* cr, const IntRect& clipRect)
+{
+    GLuint texture;
+    IntSize textureSize;
+    if (!WaylandCompositor::singleton().getTexture(m_webPage, texture, textureSize))
+        return false;
+
+    cairo_save(cr);
+    AcceleratedBackingStore::paint(cr, clipRect);
+
+#if 0
+    // FIXME: Use this when GTK+ >= 3.16. GTK+ expects the Y axis to be inverted to what we get, so we need to flip it somehow.
+    gdk_cairo_draw_from_gl(cr, gtk_widget_get_window(m_webPage.viewWidget()), texture, GL_TEXTURE, 1, clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height());
+#else
+    IntSize size = textureSize;
+    float deviceScaleFactor = m_webPage.deviceScaleFactor();
+    size.scale(deviceScaleFactor);
+
+    if (!m_surface || cairo_image_surface_get_width(m_surface.get()) != size.width() || cairo_image_surface_get_height(m_surface.get()) != size.height())
+        m_surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, size.width(), size.height()));
+    cairoSurfaceSetDeviceScale(m_surface.get(), deviceScaleFactor, deviceScaleFactor);
+
+    GLuint fb;
+    glGenFramebuffers(1, &fb);
+    glBindFramebuffer(GL_FRAMEBUFFER, fb);
+    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
+
+    glPixelStorei(GL_PACK_ALIGNMENT, 4);
+    glPixelStorei(GL_PACK_ROW_LENGTH, cairo_image_surface_get_stride(m_surface.get()) / 4);
+#if USE(OPENGL_ES_2)
+    glReadPixels(0, 0, textureSize.width(), textureSize.height(), GL_RGBA, GL_UNSIGNED_BYTE, cairo_image_surface_get_data(m_surface.get()));
+#else
+    glReadPixels(0, 0, textureSize.width(), textureSize.height(), GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, cairo_image_surface_get_data(m_surface.get()));
+#endif
+    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glDeleteFramebuffers(1, &fb);
+
+    // The surface can be modified by the web process at any time, so we mark it
+    // as dirty to ensure we always render the updated contents as soon as possible.
+    cairo_surface_mark_dirty(m_surface.get());
+    cairo_rectangle(cr, clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height());
+    cairo_set_source_surface(cr, m_surface.get(), 0, 0);
+    cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+    cairo_fill(cr);
+#endif
+
+    cairo_restore(cr);
+
+    return true;
+}
+
+} // namespace WebKit
+
+#endif // PLATFORM(WAYLAND)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Igalia S.L.
+ * Copyright (C) 2016 Igalia S.L.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-#ifndef WaylandEventSource_h
-#define WaylandEventSource_h
+#pragma once
+
+#include "AcceleratedBackingStore.h"
 
 #if PLATFORM(WAYLAND)
 
-#include <glib.h>
-#include <wayland-server.h>
+#include <WebCore/RefPtrCairo.h>
+
+namespace WebKit {
 
-namespace WebCore {
+class WebPageProxy;
 
-class WaylandEventSource {
+class AcceleratedBackingStoreWayland final : public AcceleratedBackingStore {
+    WTF_MAKE_NONCOPYABLE(AcceleratedBackingStoreWayland); WTF_MAKE_FAST_ALLOCATED;
 public:
-    static GSource* createDisplayEventSource(struct wl_display*);
+    static std::unique_ptr<AcceleratedBackingStoreWayland> create(WebPageProxy&);
+    ~AcceleratedBackingStoreWayland();
+
+private:
+    AcceleratedBackingStoreWayland(WebPageProxy&);
+
+    bool paint(cairo_t*, const WebCore::IntRect&) override;
+
+    RefPtr<cairo_surface_t> m_surface;
 };
 
-} // namespace WebCore
+} // namespace WebKit
 
 #endif // PLATFORM(WAYLAND)
-
-#endif // WaylandEventSource_h
diff --git a/Source/WebKit2/UIProcess/gtk/AcceleratedBackingStoreX11.cpp b/Source/WebKit2/UIProcess/gtk/AcceleratedBackingStoreX11.cpp
new file mode 100644 (file)
index 0000000..9328301
--- /dev/null
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2016 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 APPLE COMPUTER, INC. ``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 COMPUTER, INC. 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 "AcceleratedBackingStoreX11.h"
+
+#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
+
+#include "DrawingAreaProxyImpl.h"
+#include "LayerTreeContext.h"
+#include "WebPageProxy.h"
+#include <WebCore/CairoUtilities.h>
+#include <WebCore/PlatformDisplayX11.h>
+#include <X11/Xlib.h>
+#include <X11/extensions/Xdamage.h>
+#include <cairo-xlib.h>
+#include <gdk/gdkx.h>
+#include <wtf/HashMap.h>
+#include <wtf/NeverDestroyed.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+static Optional<int> s_damageEventBase;
+
+class XDamageNotifier {
+    WTF_MAKE_NONCOPYABLE(XDamageNotifier);
+    friend class NeverDestroyed<XDamageNotifier>;
+public:
+    static XDamageNotifier& singleton()
+    {
+        static NeverDestroyed<XDamageNotifier> notifier;
+        return notifier;
+    }
+
+    void add(Damage damage, std::function<void()>&& notifyFunction)
+    {
+        if (m_notifyFunctions.isEmpty())
+            gdk_window_add_filter(nullptr, reinterpret_cast<GdkFilterFunc>(&filterXDamageEvent), this);
+        m_notifyFunctions.add(damage, WTFMove(notifyFunction));
+    }
+
+    void remove(Damage damage)
+    {
+        m_notifyFunctions.remove(damage);
+        if (m_notifyFunctions.isEmpty())
+            gdk_window_remove_filter(nullptr, reinterpret_cast<GdkFilterFunc>(&filterXDamageEvent), this);
+    }
+
+private:
+    XDamageNotifier() = default;
+
+    static GdkFilterReturn filterXDamageEvent(GdkXEvent* event, GdkEvent*, XDamageNotifier* notifier)
+    {
+        auto* xEvent = static_cast<XEvent*>(event);
+        if (xEvent->type != s_damageEventBase.value() + XDamageNotify)
+            return GDK_FILTER_CONTINUE;
+
+        auto* damageEvent = reinterpret_cast<XDamageNotifyEvent*>(xEvent);
+        if (notifier->notify(damageEvent->damage)) {
+            XDamageSubtract(xEvent->xany.display, damageEvent->damage, None, None);
+            return GDK_FILTER_REMOVE;
+        }
+
+        return GDK_FILTER_CONTINUE;
+    }
+
+    bool notify(Damage damage) const
+    {
+        if (const auto& notifyFunction = m_notifyFunctions.get(damage)) {
+            notifyFunction();
+            return true;
+        }
+        return false;
+    }
+
+    HashMap<Damage, std::function<void()>> m_notifyFunctions;
+};
+
+std::unique_ptr<AcceleratedBackingStoreX11> AcceleratedBackingStoreX11::create(WebPageProxy& webPage)
+{
+    auto& display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay());
+    if (!display.supportsXComposite() || !display.supportsXDamage(s_damageEventBase))
+        return nullptr;
+    return std::unique_ptr<AcceleratedBackingStoreX11>(new AcceleratedBackingStoreX11(webPage));
+}
+
+AcceleratedBackingStoreX11::AcceleratedBackingStoreX11(WebPageProxy& webPage)
+    : AcceleratedBackingStore(webPage)
+{
+}
+
+AcceleratedBackingStoreX11::~AcceleratedBackingStoreX11()
+{
+    if (m_damage) {
+        XDamageNotifier::singleton().remove(m_damage.get());
+        m_damage.reset();
+    }
+}
+
+void AcceleratedBackingStoreX11::update(const LayerTreeContext& layerTreeContext)
+{
+    Pixmap pixmap = layerTreeContext.contextID;
+    if (m_surface && cairo_xlib_surface_get_drawable(m_surface.get()) == pixmap)
+        return;
+
+    if (m_surface) {
+        if (m_damage) {
+            XDamageNotifier::singleton().remove(m_damage.get());
+            m_damage.reset();
+        }
+        m_surface = nullptr;
+    }
+
+    if (!pixmap)
+        return;
+
+    DrawingAreaProxyImpl* drawingArea = static_cast<DrawingAreaProxyImpl*>(m_webPage.drawingArea());
+    if (!drawingArea)
+        return;
+
+    IntSize size = drawingArea->size();
+    float deviceScaleFactor = m_webPage.deviceScaleFactor();
+    size.scale(deviceScaleFactor);
+
+    Display* display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native();
+    ASSERT(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native() == GDK_DISPLAY_XDISPLAY(gdk_display_get_default()));
+    GdkVisual* visual = gdk_screen_get_rgba_visual(gdk_screen_get_default());
+    if (!visual)
+        visual = gdk_screen_get_system_visual(gdk_screen_get_default());
+    m_surface = adoptRef(cairo_xlib_surface_create(display, pixmap, GDK_VISUAL_XVISUAL(visual), size.width(), size.height()));
+    cairoSurfaceSetDeviceScale(m_surface.get(), deviceScaleFactor, deviceScaleFactor);
+    m_damage = XDamageCreate(display, pixmap, XDamageReportNonEmpty);
+    XDamageNotifier::singleton().add(m_damage.get(), [this] {
+        gtk_widget_queue_draw(m_webPage.viewWidget());
+    });
+}
+
+bool AcceleratedBackingStoreX11::paint(cairo_t* cr, const IntRect& clipRect)
+{
+    if (!m_surface)
+        return false;
+
+    cairo_save(cr);
+    AcceleratedBackingStore::paint(cr, clipRect);
+
+    // The surface can be modified by the web process at any time, so we mark it
+    // as dirty to ensure we always render the updated contents as soon as possible.
+    cairo_surface_mark_dirty(m_surface.get());
+    cairo_rectangle(cr, clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height());
+    cairo_set_source_surface(cr, m_surface.get(), 0, 0);
+    cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
+    cairo_fill(cr);
+
+    cairo_restore(cr);
+
+    return true;
+}
+
+} // namespace WebKit
+
+#endif // USE(REDIRECTED_XCOMPOSITE_WINDOW)
diff --git a/Source/WebKit2/UIProcess/gtk/AcceleratedBackingStoreX11.h b/Source/WebKit2/UIProcess/gtk/AcceleratedBackingStoreX11.h
new file mode 100644 (file)
index 0000000..d9a7c2f
--- /dev/null
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2016 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 APPLE COMPUTER, INC. ``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 COMPUTER, INC. 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 "AcceleratedBackingStore.h"
+
+#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
+
+#include <WebCore/RefPtrCairo.h>
+#include <WebCore/XUniqueResource.h>
+
+namespace WebKit {
+
+class WebPageProxy;
+
+class AcceleratedBackingStoreX11 final : public AcceleratedBackingStore {
+    WTF_MAKE_NONCOPYABLE(AcceleratedBackingStoreX11); WTF_MAKE_FAST_ALLOCATED;
+public:
+    static std::unique_ptr<AcceleratedBackingStoreX11> create(WebPageProxy&);
+    ~AcceleratedBackingStoreX11();
+
+private:
+    AcceleratedBackingStoreX11(WebPageProxy&);
+
+    void update(const LayerTreeContext&) override;
+    bool paint(cairo_t*, const WebCore::IntRect&) override;
+
+    RefPtr<cairo_surface_t> m_surface;
+    WebCore::XUniqueDamage m_damage;
+};
+
+} // namespace WebKit
+
+#endif // USE(REDIRECTED_XCOMPOSITE_WINDOW)
diff --git a/Source/WebKit2/UIProcess/gtk/WaylandCompositor.cpp b/Source/WebKit2/UIProcess/gtk/WaylandCompositor.cpp
new file mode 100644 (file)
index 0000000..c07c734
--- /dev/null
@@ -0,0 +1,515 @@
+/*
+ * Copyright (C) 2016 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 APPLE COMPUTER, INC. ``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 COMPUTER, INC. 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 "WaylandCompositor.h"
+
+#if PLATFORM(WAYLAND)
+
+#include "WebKit2WaylandServerProtocol.h"
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <WebCore/GLContext.h>
+#include <WebCore/PlatformDisplayWayland.h>
+#include <WebCore/Region.h>
+#include <WebCore/UUID.h>
+#include <wayland-server-protocol.h>
+
+#if USE(OPENGL_ES_2)
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#else
+#include <WebCore/OpenGLShims.h>
+#endif
+
+using namespace WebCore;
+
+namespace WebKit {
+
+#if !defined(PFNEGLBINDWAYLANDDISPLAYWL)
+typedef EGLBoolean (*PFNEGLBINDWAYLANDDISPLAYWL) (EGLDisplay, struct wl_display*);
+#endif
+
+#if !defined(PFNEGLUNBINDWAYLANDDISPLAYWL)
+typedef EGLBoolean (*PFNEGLUNBINDWAYLANDDISPLAYWL) (EGLDisplay, struct wl_display*);
+#endif
+
+#if !defined(PFNEGLQUERYWAYLANDBUFFERWL)
+typedef EGLBoolean (*PFNEGLQUERYWAYLANDBUFFERWL) (EGLDisplay, struct wl_resource*, EGLint attribute, EGLint* value);
+#endif
+
+#if !defined(PFNEGLCREATEIMAGEKHRPROC)
+typedef EGLImageKHR (*PFNEGLCREATEIMAGEKHRPROC) (EGLDisplay, EGLContext, EGLenum target, EGLClientBuffer, const EGLint* attribList);
+#endif
+
+#if !defined(PFNEGLDESTROYIMAGEKHRPROC)
+typedef EGLBoolean (*PFNEGLDESTROYIMAGEKHRPROC) (EGLDisplay, EGLImageKHR);
+#endif
+
+#if !defined(PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)
+typedef void (*PFNGLEGLIMAGETARGETTEXTURE2DOESPROC) (GLenum target, GLeglImageOES);
+#endif
+
+static PFNEGLBINDWAYLANDDISPLAYWL eglBindWaylandDisplay;
+static PFNEGLUNBINDWAYLANDDISPLAYWL eglUnbindWaylandDisplay;
+static PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBuffer;
+static PFNEGLCREATEIMAGEKHRPROC eglCreateImage;
+static PFNEGLDESTROYIMAGEKHRPROC eglDestroyImage;
+static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC eglImageTargetTexture2D;
+
+WaylandCompositor& WaylandCompositor::singleton()
+{
+    static NeverDestroyed<WaylandCompositor> waylandCompositor;
+    return waylandCompositor;
+}
+
+WaylandCompositor::Buffer* WaylandCompositor::Buffer::getOrCreate(struct wl_resource* resource)
+{
+    if (struct wl_listener* listener = wl_resource_get_destroy_listener(resource, destroyListenerCallback)) {
+        WaylandCompositor::Buffer* buffer;
+        return wl_container_of(listener, buffer, m_destroyListener);
+    }
+
+    return new WaylandCompositor::Buffer(resource);
+}
+
+WaylandCompositor::Buffer::Buffer(struct wl_resource* resource)
+    : m_resource(resource)
+    , m_weakPtrFactory(this)
+{
+    wl_list_init(&m_destroyListener.link);
+    m_destroyListener.notify = destroyListenerCallback;
+    wl_resource_add_destroy_listener(m_resource, &m_destroyListener);
+}
+
+WaylandCompositor::Buffer::~Buffer()
+{
+    wl_list_remove(&m_destroyListener.link);
+}
+
+void WaylandCompositor::Buffer::destroyListenerCallback(struct wl_listener* listener, void*)
+{
+    WaylandCompositor::Buffer* buffer;
+    buffer = wl_container_of(listener, buffer, m_destroyListener);
+    delete buffer;
+}
+
+void WaylandCompositor::Buffer::use()
+{
+    m_busyCount++;
+}
+
+void WaylandCompositor::Buffer::unuse()
+{
+    m_busyCount--;
+    if (!m_busyCount)
+        wl_resource_queue_event(m_resource, WL_BUFFER_RELEASE);
+}
+
+EGLImageKHR WaylandCompositor::Buffer::createImage() const
+{
+    return static_cast<EGLImageKHR*>(eglCreateImage(PlatformDisplay::sharedDisplay().eglDisplay(), EGL_NO_CONTEXT, EGL_WAYLAND_BUFFER_WL, m_resource, nullptr));
+}
+
+IntSize WaylandCompositor::Buffer::size() const
+{
+    EGLDisplay eglDisplay = PlatformDisplay::sharedDisplay().eglDisplay();
+    int width, height;
+    eglQueryWaylandBuffer(eglDisplay, m_resource, EGL_WIDTH, &width);
+    eglQueryWaylandBuffer(eglDisplay, m_resource, EGL_HEIGHT, &height);
+
+    return { width, height };
+}
+
+WaylandCompositor::Surface::Surface()
+    : m_image(EGL_NO_IMAGE_KHR)
+{
+    glGenTextures(1, &m_texture);
+    glBindTexture(GL_TEXTURE_2D, m_texture);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+}
+
+WaylandCompositor::Surface::~Surface()
+{
+    // Destroy pending frame callbacks.
+    auto list = WTFMove(m_frameCallbackList);
+    for (auto* resource : list)
+        wl_resource_destroy(resource);
+
+    if (m_buffer)
+        m_buffer->unuse();
+
+    if (m_image != EGL_NO_IMAGE_KHR)
+        eglDestroyImage(PlatformDisplay::sharedDisplay().eglDisplay(), m_image);
+
+    glDeleteTextures(1, &m_texture);
+}
+
+void WaylandCompositor::Surface::makePendingBufferCurrent()
+{
+    if (m_pendingBuffer == m_buffer)
+        return;
+
+    if (m_buffer)
+        m_buffer->unuse();
+
+    if (m_pendingBuffer)
+        m_pendingBuffer->use();
+
+    m_buffer = m_pendingBuffer;
+}
+
+void WaylandCompositor::Surface::attachBuffer(struct wl_resource* buffer)
+{
+    if (m_pendingBuffer)
+        m_pendingBuffer = nullptr;
+
+    if (buffer) {
+        auto* compositorBuffer = WaylandCompositor::Buffer::getOrCreate(buffer);
+        m_pendingBuffer = compositorBuffer->createWeakPtr();
+    }
+}
+
+void WaylandCompositor::Surface::requestFrame(struct wl_resource* resource)
+{
+    wl_resource_set_implementation(resource, nullptr, this, [](struct wl_resource* resource) {
+        auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(resource));
+        if (size_t item = surface->m_frameCallbackList.find(resource) != notFound)
+            surface->m_frameCallbackList.remove(item);
+    });
+    m_frameCallbackList.append(resource);
+}
+
+bool WaylandCompositor::Surface::prepareTextureForPainting(unsigned& texture, IntSize& textureSize)
+{
+    if (m_image == EGL_NO_IMAGE_KHR)
+        return false;
+
+    glBindTexture(GL_TEXTURE_2D, m_texture);
+    eglImageTargetTexture2D(GL_TEXTURE_2D, m_image);
+
+    texture = m_texture;
+    textureSize = m_buffer->size();
+    return true;
+}
+
+bool WaylandCompositor::Surface::commit()
+{
+    EGLDisplay eglDisplay = PlatformDisplay::sharedDisplay().eglDisplay();
+    if (m_image != EGL_NO_IMAGE_KHR)
+        eglDestroyImage(eglDisplay, m_image);
+    m_image = m_pendingBuffer->createImage();
+    if (m_image == EGL_NO_IMAGE_KHR)
+        return false;
+
+    makePendingBufferCurrent();
+    if (m_webPage)
+        m_webPage->setViewNeedsDisplay(IntRect(IntPoint::zero(), m_webPage->viewSize()));
+
+    auto list = WTFMove(m_frameCallbackList);
+    for (auto* resource : list) {
+        wl_callback_send_done(resource, 0);
+        wl_resource_destroy(resource);
+    }
+
+    return true;
+}
+
+static const struct wl_surface_interface surfaceInterface = {
+    // destroyCallback
+    [](struct wl_client*, struct wl_resource* resource)
+    {
+        wl_resource_destroy(resource);
+    },
+    // attachCallback
+    [](struct wl_client* client, struct wl_resource* resource, struct wl_resource* buffer, int32_t sx, int32_t sy)
+    {
+        auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(resource));
+        if (!surface)
+            return;
+
+        EGLint format;
+        if (!eglQueryWaylandBuffer(PlatformDisplay::sharedDisplay().eglDisplay(), buffer, EGL_TEXTURE_FORMAT, &format)
+            || (format != EGL_TEXTURE_RGB && format != EGL_TEXTURE_RGBA))
+            return;
+
+        surface->attachBuffer(buffer);
+    },
+    // damageCallback
+    [](struct wl_client*, struct wl_resource*, int32_t, int32_t, int32_t, int32_t) { },
+    // frameCallback
+    [](struct wl_client* client, struct wl_resource* resource, uint32_t id)
+    {
+        auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(resource));
+        if (!surface)
+            return;
+
+        if (struct wl_resource* callbackResource = wl_resource_create(client, &wl_callback_interface, 1, id))
+            surface->requestFrame(callbackResource);
+        else
+            wl_client_post_no_memory(client);
+    },
+    // setOpaqueRegionCallback
+    [](struct wl_client*, struct wl_resource*, struct wl_resource*) { },
+    // setInputRegionCallback
+    [](struct wl_client*, struct wl_resource*, struct wl_resource*) { },
+    // commitCallback
+    [](struct wl_client* client, struct wl_resource* resource)
+    {
+        auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(resource));
+        if (!surface)
+            return;
+
+        if (surface->commit())
+            wl_display_flush_clients(wl_client_get_display(client));
+    },
+    // setBufferTransformCallback
+    [](struct wl_client*, struct wl_resource*, int32_t) { },
+    // setBufferScaleCallback
+    [](struct wl_client*, struct wl_resource*, int32_t) { }
+};
+
+static const struct wl_compositor_interface compositorInterface = {
+    // createSurfaceCallback
+    [](struct wl_client* client, struct wl_resource* resource, uint32_t id)
+    {
+        if (struct wl_resource* surfaceResource = wl_resource_create(client, &wl_surface_interface, 1, id)) {
+            wl_resource_set_implementation(surfaceResource, &surfaceInterface, new WaylandCompositor::Surface(),
+                [](struct wl_resource* resource) {
+                    auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(resource));
+                    delete surface;
+                });
+        } else
+            wl_client_post_no_memory(client);
+    },
+    // createRegionCallback
+    [](struct wl_client*, struct wl_resource*, uint32_t) { }
+};
+
+static const struct wl_webkitgtk_interface webkitgtkInterface = {
+    // bindSurfaceToPageCallback
+    [](struct wl_client*, struct wl_resource* resource, struct wl_resource* surfaceResource, uint32_t pageID)
+    {
+        auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(surfaceResource));
+        if (!surface)
+            return;
+
+        auto* compositor = static_cast<WaylandCompositor*>(wl_resource_get_user_data(resource));
+        compositor->bindSurfaceToWebPage(surface, pageID);
+    }
+};
+
+bool WaylandCompositor::initializeEGL()
+{
+    if (PlatformDisplay::sharedDisplay().eglCheckVersion(1, 5)) {
+        eglCreateImage = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImage"));
+        eglDestroyImage = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImage"));
+    } else {
+        const char* extensions = eglQueryString(PlatformDisplay::sharedDisplay().eglDisplay(), EGL_EXTENSIONS);
+        if (strstr(extensions, "EGL_KHR_image_base")) {
+            eglCreateImage = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC>(eglGetProcAddress("eglCreateImageKHR"));
+            eglDestroyImage = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC>(eglGetProcAddress("eglDestroyImageKHR"));
+        }
+    }
+    if (!eglCreateImage || !eglDestroyImage) {
+        WTFLogAlways("WaylandCompositor requires eglCreateImage and eglDestroyImage.");
+        return false;
+    }
+
+    eglImageTargetTexture2D = reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC>(eglGetProcAddress("glEGLImageTargetTexture2DOES"));
+    if (!eglImageTargetTexture2D) {
+        WTFLogAlways("WaylandCompositor requires glEGLImageTargetTexture.");
+        return false;
+    }
+
+    eglQueryWaylandBuffer = reinterpret_cast<PFNEGLQUERYWAYLANDBUFFERWL>(eglGetProcAddress("eglQueryWaylandBufferWL"));
+    if (!eglQueryWaylandBuffer) {
+        WTFLogAlways("WaylandCompositor requires eglQueryWaylandBuffer.");
+        return false;
+    }
+
+    eglBindWaylandDisplay = reinterpret_cast<PFNEGLBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglBindWaylandDisplayWL"));
+    eglUnbindWaylandDisplay = reinterpret_cast<PFNEGLUNBINDWAYLANDDISPLAYWL>(eglGetProcAddress("eglUnbindWaylandDisplayWL"));
+    if (!eglBindWaylandDisplay || !eglUnbindWaylandDisplay) {
+        WTFLogAlways("WaylandCompositor requires eglBindWaylandDisplayWL and eglUnbindWaylandDisplayWL.");
+        return false;
+    }
+
+    m_eglContext = GLContext::createOffscreenContext();
+    if (!m_eglContext)
+        return false;
+
+    if (!m_eglContext->makeContextCurrent())
+        return false;
+
+    return true;
+}
+
+typedef struct {
+    GSource source;
+    gpointer fdTag;
+    struct wl_display* display;
+} WaylandLoopSource;
+
+static const unsigned waylandLoopSourceCondition = G_IO_IN | G_IO_HUP | G_IO_ERR;
+
+static GSourceFuncs waylandLoopSourceFunctions = {
+    // prepare
+    [](GSource *source, int *timeout) -> gboolean
+    {
+        *timeout = -1;
+        auto* wlLoopSource = reinterpret_cast<WaylandLoopSource*>(source);
+        wl_display_flush_clients(wlLoopSource->display);
+        return FALSE;
+    },
+    nullptr, // check
+    // dispatch
+    [](GSource* source, GSourceFunc callback, gpointer userData) -> gboolean
+    {
+        auto* wlLoopSource = reinterpret_cast<WaylandLoopSource*>(source);
+        unsigned events = g_source_query_unix_fd(source, wlLoopSource->fdTag) & waylandLoopSourceCondition;
+        if (events & G_IO_HUP || events & G_IO_ERR) {
+            WTFLogAlways("Wayland Display Event Source: lost connection to nested Wayland compositor");
+            return G_SOURCE_REMOVE;
+        }
+
+        if (events & G_IO_IN)
+            wl_event_loop_dispatch(wl_display_get_event_loop(wlLoopSource->display), 0);
+        return G_SOURCE_CONTINUE;
+    },
+    nullptr, // finalize
+    nullptr, // closure_callback
+    nullptr, // closure_marshall
+};
+
+static GRefPtr<GSource> createWaylandLoopSource(struct wl_display* display)
+{
+    GRefPtr<GSource> source = adoptGRef(g_source_new(&waylandLoopSourceFunctions, sizeof(WaylandLoopSource)));
+    g_source_set_name(source.get(), "Nested Wayland compositor display event source");
+    g_source_set_priority(source.get(), G_PRIORITY_DEFAULT + 1);
+
+    auto* wlLoopSource = reinterpret_cast<WaylandLoopSource*>(source.get());
+    wlLoopSource->display = display;
+    wlLoopSource->fdTag = g_source_add_unix_fd(source.get(), wl_event_loop_get_fd(wl_display_get_event_loop(display)), static_cast<GIOCondition>(waylandLoopSourceCondition));
+    g_source_attach(source.get(), nullptr);
+
+    return source;
+}
+
+WaylandCompositor::WaylandCompositor()
+{
+    WlUniquePtr<struct wl_display> display(wl_display_create());
+    if (!display) {
+        WTFLogAlways("Nested Wayland compositor could not create display object");
+        return;
+    }
+
+    String displayName = "webkitgtk-wayland-compositor-" + createCanonicalUUIDString();
+    if (wl_display_add_socket(display.get(), displayName.utf8().data()) == -1) {
+        WTFLogAlways("Nested Wayland compositor could not create display socket");
+        return;
+    }
+
+    WlUniquePtr<struct wl_global> compositorGlobal(wl_global_create(display.get(), &wl_compositor_interface, wl_compositor_interface.version, this,
+        [](struct wl_client* client, void* data, uint32_t version, uint32_t id) {
+            if (struct wl_resource* resource = wl_resource_create(client, &wl_compositor_interface, std::min(static_cast<int>(version), 3), id))
+                wl_resource_set_implementation(resource, &compositorInterface, static_cast<WaylandCompositor*>(data), nullptr);
+            else
+                wl_client_post_no_memory(client);
+        }));
+    if (!compositorGlobal) {
+        WTFLogAlways("Nested Wayland compositor could not register compositor global");
+        return;
+    }
+
+    WlUniquePtr<struct wl_global> webkitgtkGlobal(wl_global_create(display.get(), &wl_webkitgtk_interface, 1, this,
+        [](struct wl_client* client, void* data, uint32_t version, uint32_t id) {
+            if (struct wl_resource* resource = wl_resource_create(client, &wl_webkitgtk_interface, 1, id))
+                wl_resource_set_implementation(resource, &webkitgtkInterface, static_cast<WaylandCompositor*>(data), nullptr);
+            else
+                wl_client_post_no_memory(client);
+        }));
+    if (!webkitgtkGlobal) {
+        WTFLogAlways("Nested Wayland compositor could not register webkitgtk global");
+        return;
+    }
+
+    if (!initializeEGL()) {
+        WTFLogAlways("Nested Wayland compositor could not initialize EGL");
+        return;
+    }
+
+    if (!eglBindWaylandDisplay(PlatformDisplay::sharedDisplay().eglDisplay(), display.get())) {
+        WTFLogAlways("Nested Wayland compositor could not bind nested display");
+        return;
+    }
+
+    m_displayName = WTFMove(displayName);
+    m_display = WTFMove(display);
+    m_compositorGlobal = WTFMove(compositorGlobal);
+    m_webkitgtkGlobal = WTFMove(webkitgtkGlobal);
+    m_eventSource = createWaylandLoopSource(m_display.get());
+}
+
+bool WaylandCompositor::getTexture(WebPageProxy& webPage, unsigned& texture, IntSize& textureSize)
+{
+    if (auto* surface = m_pageMap.get(&webPage))
+        return surface->prepareTextureForPainting(texture, textureSize);
+    return false;
+}
+
+void WaylandCompositor::bindSurfaceToWebPage(WaylandCompositor::Surface* surface, uint64_t pageID)
+{
+    WebPageProxy* webPage = nullptr;
+    for (auto* page : m_pageMap.keys()) {
+        if (page->pageID() == pageID) {
+            webPage = page;
+            break;
+        }
+    }
+    if (!webPage)
+        return;
+
+    surface->setWebPage(webPage);
+    m_pageMap.set(webPage, surface);
+}
+
+void WaylandCompositor::registerWebPage(WebPageProxy& webPage)
+{
+    m_pageMap.add(&webPage, nullptr);
+}
+
+void WaylandCompositor::unregisterWebPage(WebPageProxy& webPage)
+{
+    if (auto* surface = m_pageMap.take(&webPage))
+        surface->setWebPage(nullptr);
+}
+
+} // namespace WebKit
+
+#endif // PLATFORM(WAYLAND)
diff --git a/Source/WebKit2/UIProcess/gtk/WaylandCompositor.h b/Source/WebKit2/UIProcess/gtk/WaylandCompositor.h
new file mode 100644 (file)
index 0000000..0d28aa7
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2016 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 APPLE COMPUTER, INC. ``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 COMPUTER, INC. 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
+
+#if PLATFORM(WAYLAND)
+
+#include "WebPageProxy.h"
+#include <WebCore/RefPtrCairo.h>
+#include <WebCore/WlUniquePtr.h>
+#include <wtf/HashMap.h>
+#include <wtf/NeverDestroyed.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/WeakPtr.h>
+#include <wtf/glib/GRefPtr.h>
+#include <wtf/text/WTFString.h>
+
+typedef void *EGLImageKHR;
+
+namespace WebCore {
+class GLContext;
+}
+
+namespace WebKit {
+
+class WebPageProxy;
+
+class WaylandCompositor {
+    WTF_MAKE_NONCOPYABLE(WaylandCompositor);
+    friend class NeverDestroyed<WaylandCompositor>;
+public:
+    static WaylandCompositor& singleton();
+
+    class Buffer {
+        WTF_MAKE_NONCOPYABLE(Buffer); WTF_MAKE_FAST_ALLOCATED;
+    public:
+        static Buffer* getOrCreate(struct wl_resource*);
+        ~Buffer();
+
+        void use();
+        void unuse();
+
+        EGLImageKHR createImage() const;
+        WebCore::IntSize size() const;
+
+        WeakPtr<Buffer> createWeakPtr() { return m_weakPtrFactory.createWeakPtr(); }
+
+    private:
+        Buffer(struct wl_resource*);
+        static void destroyListenerCallback(struct wl_listener*, void*);
+
+        struct wl_resource* m_resource { nullptr };
+        struct wl_listener m_destroyListener;
+        uint32_t m_busyCount { 0 };
+        WeakPtrFactory<Buffer> m_weakPtrFactory;
+    };
+
+    class Surface {
+        WTF_MAKE_NONCOPYABLE(Surface); WTF_MAKE_FAST_ALLOCATED;
+    public:
+        Surface();
+        ~Surface();
+
+        void attachBuffer(struct wl_resource*);
+        void requestFrame(struct wl_resource*);
+        bool commit();
+
+        void setWebPage(WebPageProxy* webPage) { m_webPage = webPage; }
+        bool prepareTextureForPainting(unsigned&, WebCore::IntSize&);
+
+    private:
+        void makePendingBufferCurrent();
+
+        WeakPtr<Buffer> m_buffer;
+        WeakPtr<Buffer> m_pendingBuffer;
+        unsigned m_texture;
+        EGLImageKHR m_image;
+        Vector<wl_resource*> m_frameCallbackList;
+        WebPageProxy* m_webPage { nullptr };
+    };
+
+    bool isRunning() const { return !!m_display; }
+    String displayName() const { return m_displayName; }
+
+    void bindSurfaceToWebPage(Surface*, uint64_t pageID);
+    void registerWebPage(WebPageProxy&);
+    void unregisterWebPage(WebPageProxy&);
+
+    bool getTexture(WebPageProxy&, unsigned&, WebCore::IntSize&);
+
+private:
+    WaylandCompositor();
+
+    bool initializeEGL();
+
+    String m_displayName;
+    WebCore::WlUniquePtr<struct wl_display> m_display;
+    WebCore::WlUniquePtr<struct wl_global> m_compositorGlobal;
+    WebCore::WlUniquePtr<struct wl_global> m_webkitgtkGlobal;
+    GRefPtr<GSource> m_eventSource;
+    std::unique_ptr<WebCore::GLContext> m_eglContext;
+    HashMap<WebPageProxy*, Surface*> m_pageMap;
+};
+
+} // namespace WebKit
+
+#endif // PLATFORM(WAYLAND)
index ae14e9e..3f0585d 100644 (file)
 #include "config.h"
 #include "WebPreferences.h"
 
+#include "WaylandCompositor.h"
 #include <WebCore/NotImplemented.h>
 #include <WebCore/PlatformDisplay.h>
 
+#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
+#include <WebCore/PlatformDisplayX11.h>
+#endif
+
+using namespace WebCore;
+
 namespace WebKit {
 
 void WebPreferences::platformInitializeStore()
 {
-#if PLATFORM(WAYLAND)
-    if (WebCore::PlatformDisplay::sharedDisplay().type() == WebCore::PlatformDisplay::Type::Wayland) {
-        // FIXME: Accelerated compositing under Wayland is not yet supported.
-        // https://bugs.webkit.org/show_bug.cgi?id=115803
-        setAcceleratedCompositingEnabled(false);
-    }
-#endif
-#if USE(COORDINATED_GRAPHICS_THREADED)
-    setForceCompositingMode(true);
-#endif
 #if !ENABLE(OPENGL)
     setAcceleratedCompositingEnabled(false);
 #else
+#if USE(COORDINATED_GRAPHICS_THREADED)
+    setForceCompositingMode(true);
+#else
     if (getenv("WEBKIT_FORCE_COMPOSITING_MODE"))
         setForceCompositingMode(true);
-    if (getenv("WEBKIT_DISABLE_COMPOSITING_MODE"))
+#endif
+
+    if (getenv("WEBKIT_DISABLE_COMPOSITING_MODE")) {
         setAcceleratedCompositingEnabled(false);
+        return;
+    }
+
+#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
+    if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11) {
+        auto& display = downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay());
+        Optional<int> damageBase;
+        if (!display.supportsXComposite() || !display.supportsXDamage(damageBase))
+            setAcceleratedCompositingEnabled(false);
+    }
 #endif
+
+#if PLATFORM(WAYLAND)
+    if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland) {
+        if (!WaylandCompositor::singleton().isRunning())
+            setAcceleratedCompositingEnabled(false);
+    }
+#endif
+
+#endif // ENABLE(OPENGL)
 }
 
 void WebPreferences::platformUpdateStringValueForKey(const String&, const String&)
diff --git a/Source/WebKit2/UIProcess/gtk/XDamageNotifier.cpp b/Source/WebKit2/UIProcess/gtk/XDamageNotifier.cpp
deleted file mode 100644 (file)
index 7a33fcc..0000000
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2016 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 APPLE INC. ``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
- * 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 "XDamageNotifier.h"
-
-#if PLATFORM(X11)
-
-#include <WebCore/PlatformDisplayX11.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/Xdamage.h>
-#include <gdk/gdkx.h>
-
-using namespace WebCore;
-
-namespace WebKit {
-
-static Optional<int> s_damageEventBase;
-
-XDamageNotifier& XDamageNotifier::singleton()
-{
-    static NeverDestroyed<XDamageNotifier> notifier;
-    return notifier;
-}
-
-XDamageNotifier::XDamageNotifier()
-{
-    downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).supportsXDamage(s_damageEventBase);
-}
-
-void XDamageNotifier::add(Damage damage, std::function<void()>&& notifyFunction)
-{
-    if (!s_damageEventBase)
-        return;
-
-    if (m_notifyFunctions.isEmpty())
-        gdk_window_add_filter(nullptr, reinterpret_cast<GdkFilterFunc>(&filterXDamageEvent), this);
-    m_notifyFunctions.add(damage, WTFMove(notifyFunction));
-}
-
-void XDamageNotifier::remove(Damage damage)
-{
-    if (!s_damageEventBase)
-        return;
-
-    m_notifyFunctions.remove(damage);
-    if (m_notifyFunctions.isEmpty())
-        gdk_window_remove_filter(nullptr, reinterpret_cast<GdkFilterFunc>(&filterXDamageEvent), this);
-}
-
-GdkFilterReturn XDamageNotifier::filterXDamageEvent(GdkXEvent* event, GdkEvent*, XDamageNotifier* notifier)
-{
-    ASSERT(s_damageEventBase);
-    auto* xEvent = static_cast<XEvent*>(event);
-    if (xEvent->type != s_damageEventBase.value() + XDamageNotify)
-        return GDK_FILTER_CONTINUE;
-
-    auto* damageEvent = reinterpret_cast<XDamageNotifyEvent*>(xEvent);
-    if (notifier->notify(damageEvent->damage)) {
-        XDamageSubtract(xEvent->xany.display, damageEvent->damage, None, None);
-        return GDK_FILTER_REMOVE;
-    }
-
-    return GDK_FILTER_CONTINUE;
-}
-
-bool XDamageNotifier::notify(Damage damage) const
-{
-    if (const auto& notifyFunction = m_notifyFunctions.get(damage)) {
-        notifyFunction();
-        return true;
-    }
-    return false;
-}
-
-} // namespace WebCore
-
-#endif // PLATFORM(X11)
index 9383d87..8ce684e 100644 (file)
 #include "ThreadedCoordinatedLayerTreeHost.h"
 
 #if USE(COORDINATED_GRAPHICS_THREADED)
+
+#include "AcceleratedSurface.h"
 #include "WebPage.h"
 #include <WebCore/FrameView.h>
 #include <WebCore/MainFrame.h>
 
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-#include "RedirectedXCompositeWindow.h"
-#endif
-
 using namespace WebCore;
 
 namespace WebKit {
@@ -54,26 +52,23 @@ ThreadedCoordinatedLayerTreeHost::~ThreadedCoordinatedLayerTreeHost()
 ThreadedCoordinatedLayerTreeHost::ThreadedCoordinatedLayerTreeHost(WebPage& webPage)
     : CoordinatedLayerTreeHost(webPage)
     , m_compositorClient(*this)
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    , m_redirectedWindow(RedirectedXCompositeWindow::create(webPage))
-    , m_compositor(ThreadedCompositor::create(&m_compositorClient, m_redirectedWindow ? m_redirectedWindow->window() : 0))
-#else
-    , m_compositor(ThreadedCompositor::create(&m_compositorClient))
-#endif
+    , m_surface(AcceleratedSurface::create(webPage))
 {
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    if (m_redirectedWindow)
-        m_layerTreeContext.contextID = m_redirectedWindow->pixmap();
-#endif
+    if (m_surface) {
+        // Do not do frame sync when rendering offscreen in the web process to ensure that SwapBuffers never blocks.
+        // Rendering to the actual screen will happen later anyway since the UI process schedules a redraw for every update,
+        // the compositor will take care of syncing to vblank.
+        m_compositor = ThreadedCompositor::create(&m_compositorClient, m_surface->window(), ThreadedCompositor::ShouldDoFrameSync::No);
+        m_layerTreeContext.contextID = m_surface->surfaceID();
+    } else
+        m_compositor = ThreadedCompositor::create(&m_compositorClient);
 }
 
 void ThreadedCoordinatedLayerTreeHost::invalidate()
 {
     m_compositor->invalidate();
     CoordinatedLayerTreeHost::invalidate();
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    m_redirectedWindow = nullptr;
-#endif
+    m_surface = nullptr;
 }
 
 void ThreadedCoordinatedLayerTreeHost::forceRepaint()
@@ -95,12 +90,8 @@ void ThreadedCoordinatedLayerTreeHost::contentsSizeChanged(const WebCore::IntSiz
 
 void ThreadedCoordinatedLayerTreeHost::deviceOrPageScaleFactorChanged()
 {
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    if (m_redirectedWindow) {
-        m_redirectedWindow->resize(m_webPage.size());
-        m_layerTreeContext.contextID = m_redirectedWindow->pixmap();
-    }
-#endif
+    if (m_surface && m_surface->resize(m_webPage.size()))
+        m_layerTreeContext.contextID = m_surface->surfaceID();
 
     CoordinatedLayerTreeHost::deviceOrPageScaleFactorChanged();
     m_compositor->setDeviceScaleFactor(m_webPage.deviceScaleFactor());
@@ -114,12 +105,9 @@ void ThreadedCoordinatedLayerTreeHost::pageBackgroundTransparencyChanged()
 
 void ThreadedCoordinatedLayerTreeHost::sizeDidChange(const IntSize& size)
 {
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    if (m_redirectedWindow) {
-        m_redirectedWindow->resize(size);
-        m_layerTreeContext.contextID = m_redirectedWindow->pixmap();
-    }
-#endif
+    if (m_surface && m_surface->resize(size))
+        m_layerTreeContext.contextID = m_surface->surfaceID();
+
     CoordinatedLayerTreeHost::sizeDidChange(size);
     m_compositor->didChangeViewportSize(size);
 }
index a41a116..890e7be 100644 (file)
@@ -41,7 +41,7 @@ struct CoordinatedGraphicsState;
 
 namespace WebKit {
 
-class RedirectedXCompositeWindow;
+class AcceleratedSurface;
 class WebPage;
 
 class ThreadedCoordinatedLayerTreeHost final : public CoordinatedLayerTreeHost {
@@ -105,9 +105,7 @@ private:
     void commitSceneState(const WebCore::CoordinatedGraphicsState&) override;
 
     CompositorClient m_compositorClient;
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    std::unique_ptr<RedirectedXCompositeWindow> m_redirectedWindow;
-#endif
+    std::unique_ptr<AcceleratedSurface> m_surface;
     RefPtr<ThreadedCompositor> m_compositor;
     float m_lastScaleFactor { 1 };
     WebCore::IntPoint m_prevScrollPosition;
diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurface.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurface.cpp
new file mode 100644 (file)
index 0000000..8a984f5
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2016 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 APPLE INC. ``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
+ * 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 "AcceleratedSurface.h"
+
+#include <WebCore/PlatformDisplay.h>
+
+#if PLATFORM(WAYLAND)
+#include "AcceleratedSurfaceWayland.h"
+#endif
+
+#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
+#include "AcceleratedSurfaceX11.h"
+#endif
+
+using namespace WebCore;
+
+namespace WebKit {
+
+std::unique_ptr<AcceleratedSurface> AcceleratedSurface::create(WebPage& webPage)
+{
+#if PLATFORM(WAYLAND)
+    if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::Wayland)
+        return AcceleratedSurfaceWayland::create(webPage);
+#endif
+#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
+    if (PlatformDisplay::sharedDisplay().type() == PlatformDisplay::Type::X11)
+        return AcceleratedSurfaceX11::create(webPage);
+#endif
+    return nullptr;
+}
+
+AcceleratedSurface::AcceleratedSurface(WebPage& webPage)
+    : m_webPage(webPage)
+    , m_size(webPage.size())
+{
+    m_size.scale(m_webPage.deviceScaleFactor());
+}
+
+bool AcceleratedSurface::resize(const IntSize& size)
+{
+    IntSize scaledSize(size);
+    scaledSize.scale(m_webPage.deviceScaleFactor());
+    if (scaledSize == m_size)
+        return false;
+
+    m_size = scaledSize;
+    return true;
+}
+
+} // namespace WebKit
 
 #pragma once
 
-#if PLATFORM(X11)
-
-#include <gdk/gdkx.h>
-#include <wtf/FastMalloc.h>
-#include <wtf/HashMap.h>
-#include <wtf/NeverDestroyed.h>
+#include <WebCore/IntSize.h>
 #include <wtf/Noncopyable.h>
 
-typedef unsigned long Damage;
-
 namespace WebKit {
 
-class XDamageNotifier {
-    WTF_MAKE_NONCOPYABLE(XDamageNotifier); WTF_MAKE_FAST_ALLOCATED;
-    friend class NeverDestroyed<XDamageNotifier>;
-public:
-    static XDamageNotifier& singleton();
+class WebPage;
 
-    void add(Damage, std::function<void()>&&);
-    void remove(Damage);
+class AcceleratedSurface {
+    WTF_MAKE_NONCOPYABLE(AcceleratedSurface); WTF_MAKE_FAST_ALLOCATED;
+public:
+    static std::unique_ptr<AcceleratedSurface> create(WebPage&);
+    virtual ~AcceleratedSurface() = default;
 
-private:
-    XDamageNotifier();
+    virtual uint64_t window() const { ASSERT_NOT_REACHED(); return 0; }
+    virtual uint64_t surfaceID() const { ASSERT_NOT_REACHED(); return 0; };
+    virtual bool resize(const WebCore::IntSize&);
 
-    static GdkFilterReturn filterXDamageEvent(GdkXEvent*, GdkEvent*, XDamageNotifier*);
-    bool notify(Damage) const;
+protected:
+    AcceleratedSurface(WebPage&);
 
-    HashMap<Damage, std::function<void()>> m_notifyFunctions;
+    WebPage& m_webPage;
+    WebCore::IntSize m_size;
 };
 
 } // namespace WebKit
-
-#endif // PLATFORM(X11)
diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp
new file mode 100644 (file)
index 0000000..b6f0b87
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2016 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 APPLE INC. ``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
+ * 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 "AcceleratedSurfaceWayland.h"
+
+#if PLATFORM(WAYLAND)
+
+#include "WebKit2WaylandClientProtocol.h"
+#include "WebProcess.h"
+#include <WebCore/PlatformDisplayWayland.h>
+#include <cstring>
+#include <wayland-egl.h>
+#include <wtf/NeverDestroyed.h>
+
+using namespace WebCore;
+
+namespace WebKit {
+
+class WaylandCompositorDisplay final : public PlatformDisplayWayland {
+    WTF_MAKE_NONCOPYABLE(WaylandCompositorDisplay);
+public:
+    static std::unique_ptr<WaylandCompositorDisplay> create()
+    {
+        struct wl_display* display = wl_display_connect(WebProcess::singleton().waylandCompositorDisplayName().utf8().data());
+        if (!display) {
+            WTFLogAlways("PlatformDisplayWayland initialization: failed to connect to the Wayland display: %s", WebProcess::singleton().waylandCompositorDisplayName().utf8().data());
+            return nullptr;
+        }
+
+        return std::unique_ptr<WaylandCompositorDisplay>(new WaylandCompositorDisplay(display));
+    }
+
+    void bindSurfaceToPage(struct wl_surface* surface, WebPage& page)
+    {
+        if (!m_webkitgtk)
+            return;
+
+        wl_webkitgtk_bind_surface_to_page(reinterpret_cast<struct wl_webkitgtk*>(m_webkitgtk.get()), surface, page.pageID());
+        wl_display_roundtrip(m_display);
+    }
+
+private:
+    WaylandCompositorDisplay(struct wl_display* display)
+    {
+        initialize(display);
+        PlatformDisplay::setSharedDisplayForCompositing(*this);
+    }
+
+    void registryGlobal(const char* interface, uint32_t name) override
+    {
+        PlatformDisplayWayland::registryGlobal(interface, name);
+        if (!std::strcmp(interface, "wl_webkitgtk"))
+            m_webkitgtk.reset(static_cast<struct wl_proxy*>(wl_registry_bind(m_registry.get(), name, &wl_webkitgtk_interface, 1)));
+    }
+
+    WlUniquePtr<struct wl_proxy> m_webkitgtk;
+};
+
+static std::unique_ptr<WaylandCompositorDisplay>& waylandCompositorDisplay()
+{
+    static NeverDestroyed<std::unique_ptr<WaylandCompositorDisplay>> waylandDisplay(WaylandCompositorDisplay::create());
+    return waylandDisplay;
+}
+
+std::unique_ptr<AcceleratedSurfaceWayland> AcceleratedSurfaceWayland::create(WebPage& webPage)
+{
+    return waylandCompositorDisplay() ? std::unique_ptr<AcceleratedSurfaceWayland>(new AcceleratedSurfaceWayland(webPage)) : nullptr;
+}
+
+AcceleratedSurfaceWayland::AcceleratedSurfaceWayland(WebPage& webPage)
+    : AcceleratedSurface(webPage)
+    , m_surface(waylandCompositorDisplay()->createSurface())
+    , m_window(wl_egl_window_create(m_surface.get(), std::max(1, m_size.width()), std::max(1, m_size.height())))
+{
+    waylandCompositorDisplay()->bindSurfaceToPage(m_surface.get(), m_webPage);
+}
+
+AcceleratedSurfaceWayland::~AcceleratedSurfaceWayland()
+{
+    wl_egl_window_destroy(m_window);
+}
+
+bool AcceleratedSurfaceWayland::resize(const IntSize& size)
+{
+    if (!AcceleratedSurface::resize(size))
+        return false;
+
+    wl_egl_window_resize(m_window, m_size.width(), m_size.height(), 0, 0);
+    return true;
+}
+
+} // namespace WebKit
+
+#endif // PLATFORM(WAYLAND)
diff --git a/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h b/Source/WebKit2/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h
new file mode 100644 (file)
index 0000000..d250056
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2016 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 APPLE INC. ``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
+ * 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
+
+#if PLATFORM(WAYLAND)
+
+#include "AcceleratedSurface.h"
+#include "WebPage.h"
+#include <WebCore/WlUniquePtr.h>
+#include <wayland-egl.h>
+
+namespace WebKit {
+
+class AcceleratedSurfaceWayland final : public AcceleratedSurface {
+    WTF_MAKE_NONCOPYABLE(AcceleratedSurfaceWayland); WTF_MAKE_FAST_ALLOCATED;
+public:
+    static std::unique_ptr<AcceleratedSurfaceWayland> create(WebPage&);
+    ~AcceleratedSurfaceWayland();
+
+    uint64_t window() const override { return reinterpret_cast<uint64_t>(m_window); }
+    uint64_t surfaceID() const override { return m_webPage.pageID(); }
+    bool resize(const WebCore::IntSize&) override;
+
+private:
+    AcceleratedSurfaceWayland(WebPage&);
+
+    WebCore::WlUniquePtr<struct wl_surface> m_surface;
+    struct wl_egl_window* m_window { nullptr };
+};
+
+} // namespace WebKit
+
+#endif // PLATFORM(WAYLAND)
@@ -24,7 +24,7 @@
  */
 
 #include "config.h"
-#include "RedirectedXCompositeWindow.h"
+#include "AcceleratedSurfaceX11.h"
 
 #if USE(REDIRECTED_XCOMPOSITE_WINDOW)
 
@@ -39,20 +39,17 @@ using namespace WebCore;
 
 namespace WebKit {
 
-std::unique_ptr<RedirectedXCompositeWindow> RedirectedXCompositeWindow::create(WebPage& webPage)
+std::unique_ptr<AcceleratedSurfaceX11> AcceleratedSurfaceX11::create(WebPage& webPage)
 {
     if (!downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).supportsXComposite())
         return nullptr;
-    return std::unique_ptr<RedirectedXCompositeWindow>(new RedirectedXCompositeWindow(webPage));
+    return std::unique_ptr<AcceleratedSurfaceX11>(new AcceleratedSurfaceX11(webPage));
 }
 
-RedirectedXCompositeWindow::RedirectedXCompositeWindow(WebPage& webPage)
-    : m_webPage(webPage)
+AcceleratedSurfaceX11::AcceleratedSurfaceX11(WebPage& webPage)
+    : AcceleratedSurface(webPage)
     , m_display(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native())
-    , m_size(webPage.size())
 {
-    m_size.scale(m_webPage.deviceScaleFactor());
-
     Screen* screen = DefaultScreenOfDisplay(m_display);
 
     ASSERT(downcast<PlatformDisplayX11>(PlatformDisplay::sharedDisplay()).native() == m_display);
@@ -109,7 +106,7 @@ RedirectedXCompositeWindow::RedirectedXCompositeWindow(WebPage& webPage)
     m_pixmap = XCompositeNameWindowPixmap(m_display, m_window.get());
 }
 
-RedirectedXCompositeWindow::~RedirectedXCompositeWindow()
+AcceleratedSurfaceX11::~AcceleratedSurfaceX11()
 {
     ASSERT(m_display);
     ASSERT(m_window);
@@ -120,14 +117,10 @@ RedirectedXCompositeWindow::~RedirectedXCompositeWindow()
     m_parentWindow.reset();
 }
 
-void RedirectedXCompositeWindow::resize(const IntSize& size)
+bool AcceleratedSurfaceX11::resize(const IntSize& size)
 {
-    IntSize scaledSize(size);
-    scaledSize.scale(m_webPage.deviceScaleFactor());
-    if (scaledSize == m_size)
-        return;
-
-    m_size = scaledSize;
+    if (!AcceleratedSurface::resize(size))
+        return false;
 
     // Resize the window to at last 1x1 since X doesn't allow to create empty windows.
     XResizeWindow(m_display, m_window.get(), std::max(1, m_size.width()), std::max(1, m_size.height()));
@@ -136,6 +129,7 @@ void RedirectedXCompositeWindow::resize(const IntSize& size)
     // Release the previous pixmap later to give some time to the UI process to update.
     RunLoop::main().dispatchAfter(std::chrono::seconds(5), [pixmap = WTFMove(m_pixmap)] { });
     m_pixmap = XCompositeNameWindowPixmap(m_display, m_window.get());
+    return true;
 }
 
 } // namespace WebCore
@@ -27,9 +27,8 @@
 
 #if USE(REDIRECTED_XCOMPOSITE_WINDOW)
 
-#include <WebCore/IntSize.h>
+#include "AcceleratedSurface.h"
 #include <WebCore/XUniqueResource.h>
-#include <wtf/Noncopyable.h>
 
 typedef struct _XDisplay Display;
 typedef unsigned long Pixmap;
@@ -39,22 +38,20 @@ namespace WebKit {
 
 class WebPage;
 
-class RedirectedXCompositeWindow {
-    WTF_MAKE_NONCOPYABLE(RedirectedXCompositeWindow); WTF_MAKE_FAST_ALLOCATED;
+class AcceleratedSurfaceX11 final : public AcceleratedSurface {
+    WTF_MAKE_NONCOPYABLE(AcceleratedSurfaceX11); WTF_MAKE_FAST_ALLOCATED;
 public:
-    static std::unique_ptr<RedirectedXCompositeWindow> create(WebPage&);
-    ~RedirectedXCompositeWindow();
+    static std::unique_ptr<AcceleratedSurfaceX11> create(WebPage&);
+    ~AcceleratedSurfaceX11();
 
-    Window window() const { return m_window.get(); }
-    Pixmap pixmap() const { return m_pixmap.get(); }
-    void resize(const WebCore::IntSize&);
+    uint64_t window() const override { return m_window.get(); }
+    uint64_t surfaceID() const override { return m_pixmap.get(); }
+    bool resize(const WebCore::IntSize&) override;
 
 private:
-    RedirectedXCompositeWindow(WebPage&);
+    AcceleratedSurfaceX11(WebPage&);
 
-    WebPage& m_webPage;
     Display* m_display { nullptr };
-    WebCore::IntSize m_size;
     WebCore::XUniqueWindow m_window;
     WebCore::XUniqueWindow m_parentWindow;
     WebCore::XUniquePixmap m_pixmap;
index 9a092ed..5a170e9 100644 (file)
@@ -29,6 +29,7 @@
 
 #if USE(TEXTURE_MAPPER_GL)
 
+#include "AcceleratedSurface.h"
 #include "DrawingAreaImpl.h"
 #include "TextureMapperGL.h"
 #include "WebPage.h"
 #include <WebCore/MainFrame.h>
 #include <WebCore/Page.h>
 #include <WebCore/Settings.h>
-#include <wtf/CurrentTime.h>
-
 #include <gdk/gdk.h>
-#if defined(GDK_WINDOWING_X11)
-#define Region XRegion
-#define Font XFont
-#define Cursor XCursor
-#define Screen XScreen
-#include <gdk/gdkx.h>
-#endif
-
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-#include "RedirectedXCompositeWindow.h"
-#endif
+#include <wtf/CurrentTime.h>
 
 using namespace WebCore;
 
@@ -137,9 +126,7 @@ Ref<LayerTreeHostGtk> LayerTreeHostGtk::create(WebPage& webPage)
 
 LayerTreeHostGtk::LayerTreeHostGtk(WebPage& webPage)
     : LayerTreeHost(webPage)
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    , m_redirectedWindow(RedirectedXCompositeWindow::create(webPage))
-#endif
+    , m_surface(AcceleratedSurface::create(webPage))
     , m_renderFrameScheduler(std::bind(&LayerTreeHostGtk::renderFrame, this))
 {
     m_rootLayer = GraphicsLayer::create(graphicsLayerFactory(), *this);
@@ -167,34 +154,37 @@ LayerTreeHostGtk::LayerTreeHostGtk(WebPage& webPage)
     m_rootLayer->addChild(m_nonCompositedContentLayer.get());
     m_nonCompositedContentLayer->setNeedsDisplay();
 
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    if (m_redirectedWindow) {
+    if (m_surface) {
         createTextureMapper();
-        m_layerTreeContext.contextID = m_redirectedWindow->pixmap();
+        m_layerTreeContext.contextID = m_surface->surfaceID();
     }
-#endif
 }
 
 bool LayerTreeHostGtk::makeContextCurrent()
 {
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    uint64_t nativeHandle = m_redirectedWindow ? m_redirectedWindow->window() : m_layerTreeContext.contextID;
-#else
-    uint64_t nativeHandle = m_layerTreeContext.contextID;
-#endif
-
+    uint64_t nativeHandle = m_surface ? m_surface->window() : m_layerTreeContext.contextID;
     if (!nativeHandle) {
         m_context = nullptr;
         return false;
     }
 
-    if (!m_context) {
-        m_context = GLContext::createContextForWindow(reinterpret_cast<GLNativeWindowType>(nativeHandle), GLContext::sharingContext());
-        if (!m_context)
-            return false;
-    }
+    if (m_context)
+        return m_context->makeContextCurrent();
+
+    m_context = GLContext::createContextForWindow(reinterpret_cast<GLNativeWindowType>(nativeHandle), &PlatformDisplay::sharedDisplayForCompositing());
+    if (!m_context)
+        return false;
+
+    if (!m_context->makeContextCurrent())
+        return false;
+
+    // Do not do frame sync when rendering offscreen in the web process to ensure that SwapBuffers never blocks.
+    // Rendering to the actual screen will happen later anyway since the UI process schedules a redraw for every update,
+    // the compositor will take care of syncing to vblank.
+    if (m_surface)
+        m_context->swapInterval(0);
 
-    return m_context->makeContextCurrent();
+    return true;
 }
 
 LayerTreeHostGtk::~LayerTreeHostGtk()
@@ -229,9 +219,7 @@ void LayerTreeHostGtk::invalidate()
     m_context = nullptr;
     LayerTreeHost::invalidate();
 
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    m_redirectedWindow = nullptr;
-#endif
+    m_surface = nullptr;
 }
 
 void LayerTreeHostGtk::setNonCompositedContentsNeedDisplay()
@@ -271,24 +259,16 @@ void LayerTreeHostGtk::sizeDidChange(const IntSize& newSize)
         m_nonCompositedContentLayer->setNeedsDisplayInRect(FloatRect(0, oldSize.height(), newSize.width(), newSize.height() - oldSize.height()));
     m_nonCompositedContentLayer->setNeedsDisplay();
 
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    if (m_redirectedWindow) {
-        m_redirectedWindow->resize(newSize);
-        m_layerTreeContext.contextID = m_redirectedWindow->pixmap();
-    }
-#endif
+    if (m_surface && m_surface->resize(newSize))
+        m_layerTreeContext.contextID = m_surface->surfaceID();
 
     compositeLayersToContext(ForResize);
 }
 
 void LayerTreeHostGtk::deviceOrPageScaleFactorChanged()
 {
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    if (m_redirectedWindow) {
-        m_redirectedWindow->resize(m_webPage.size());
-        m_layerTreeContext.contextID = m_redirectedWindow->pixmap();
-    }
-#endif
+    if (m_surface && m_surface->resize(m_webPage.size()))
+        m_layerTreeContext.contextID = m_surface->surfaceID();
 
     // Other layers learn of the scale factor change via WebPage::setDeviceScaleFactor.
     m_nonCompositedContentLayer->deviceOrPageScaleFactorChanged();
index d69de97..4474505 100644 (file)
@@ -39,7 +39,7 @@
 
 namespace WebKit {
 
-class RedirectedXCompositeWindow;
+class AcceleratedSurface;
 
 class LayerTreeHostGtk final : public LayerTreeHost, WebCore::GraphicsLayerClient {
 public:
@@ -109,9 +109,7 @@ private:
     std::unique_ptr<WebCore::TextureMapper> m_textureMapper;
     std::unique_ptr<WebCore::GLContext> m_context;
     WebCore::TransformationMatrix m_scaleMatrix;
-#if USE(REDIRECTED_XCOMPOSITE_WINDOW)
-    std::unique_ptr<RedirectedXCompositeWindow> m_redirectedWindow;
-#endif
+    std::unique_ptr<AcceleratedSurface> m_surface;
     RenderFrameScheduler m_renderFrameScheduler;
 };
 
index 14b3a14..6c425f1 100644 (file)
@@ -300,6 +300,10 @@ void WebProcess::initializeWebProcess(WebProcessCreationParameters&& parameters)
     m_applicationCacheStorage->setDefaultOriginQuota(25ULL * 1024 * 1024);
 #endif
 
+#if PLATFORM(WAYLAND)
+    m_waylandCompositorDisplayName = parameters.waylandCompositorDisplayName;
+#endif
+
 #if ENABLE(VIDEO)
     if (!parameters.mediaCacheDirectory.isEmpty())
         WebCore::HTMLMediaElement::setMediaCacheDirectory(parameters.mediaCacheDirectory);
index b5bd8a2..60feec3 100644 (file)
@@ -198,6 +198,10 @@ public:
     void resetAllGeolocationPermissions();
 #endif
 
+#if PLATFORM(WAYLAND)
+    String waylandCompositorDisplayName() const { return m_waylandCompositorDisplayName; }
+#endif
+
     RefPtr<API::Object> transformHandlesToObjects(API::Object*);
     static RefPtr<API::Object> transformObjectsToHandles(API::Object*);
 
@@ -401,6 +405,10 @@ private:
     bool m_suppressMemoryPressureHandler { false };
 
     HashMap<WebCore::UserGestureToken *, uint64_t> m_userGestureTokens;
+
+#if PLATFORM(WAYLAND)
+    String m_waylandCompositorDisplayName;
+#endif
 };
 
 } // namespace WebKit
index 3114a39..f115176 100644 (file)
@@ -389,10 +389,14 @@ if (ENABLE_WAYLAND_TARGET)
         message(FATAL_ERROR "Recompile GTK+ with Wayland backend to use ENABLE_WAYLAND_TARGET")
     endif ()
 
-    if (ENABLE_WAYLAND_TARGET AND GTK3_VERSION VERSION_LESS 3.12)
+    if (GTK3_VERSION VERSION_LESS 3.12)
         message(FATAL_ERROR "GTK+ 3.12 is required to use ENABLE_WAYLAND_TARGET")
     endif ()
 
+    if (NOT EGL_FOUND)
+        message(FATAL_ERROR "EGL is required to use ENABLE_WAYLAND_TARGET")
+    endif ()
+
     find_package(Wayland REQUIRED)
 endif ()