diff --git a/Source/WebKit/ChangeLog b/Source/WebKit/ChangeLog index cb992c38d366..0adc92573dce 100644 --- a/Source/WebKit/ChangeLog +++ b/Source/WebKit/ChangeLog @@ -1,3 +1,35 @@ +2017-09-02 Carlos Garcia Campos + + [GTK][Wayland] Opening FedoraProject's pastebin chews CPU + https://bugs.webkit.org/show_bug.cgi?id=175942 + + Reviewed by Žan Doberšek. + + This regressed when we introduced the display refresh monitor. The monitor schedules updates immediately, + because we removed the option to not do frame sync in X11 to let swapBuffers do the throttling, but that's + not happening in Wayland because the nested compositor is dispatching frame callbacks on surface commit. + We need to ensure that frame callbacks are dispatched on every monitor refresh, because swapBuffers waits for + frame callbacks to be queued on display. + + * UIProcess/gtk/WaylandCompositor.cpp: + (WebKit::WaylandCompositor::Surface::~Surface): Destroy pending frame callbacks too. + (WebKit::WaylandCompositor::Surface::setWebPage): Add a tick callback to the web view widget to flush all + committed frame callbacks on every frame update. + (WebKit::WaylandCompositor::Surface::requestFrame): Add the callbacks to m_pendingFrameCallbackList. + (WebKit::WaylandCompositor::Surface::flushFrameCallbacks): Dispatch all committed frame callabcks. + (WebKit::WaylandCompositor::Surface::flushPendingFrameCallbacks): Dispatch all pending frame callbacks. + (WebKit::WaylandCompositor::Surface::commit): Do not dispatch frame callbacks here, move them to the list of + committed frame callbacks that will be dispatched on the next frame clock update. + * UIProcess/gtk/WaylandCompositor.h: + (WebKit::WaylandCompositor::Surface::setWebPage): Moved to the cpp. + * WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp: + (WebKit::AcceleratedSurfaceWayland::AcceleratedSurfaceWayland): Move surface initialization and destruction to + the compositing thread. + (WebKit::AcceleratedSurfaceWayland::initialize): + (WebKit::AcceleratedSurfaceWayland::finalize): + (WebKit::AcceleratedSurfaceWayland::~AcceleratedSurfaceWayland): Deleted. + * WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h: + 2017-08-31 Carlos Garcia Campos [GTK] Several InputMethodFilter tests are failing and crashing diff --git a/Source/WebKit/UIProcess/gtk/WaylandCompositor.cpp b/Source/WebKit/UIProcess/gtk/WaylandCompositor.cpp index 64692da8fe8d..759444488d9a 100644 --- a/Source/WebKit/UIProcess/gtk/WaylandCompositor.cpp +++ b/Source/WebKit/UIProcess/gtk/WaylandCompositor.cpp @@ -156,7 +156,12 @@ WaylandCompositor::Surface::Surface() WaylandCompositor::Surface::~Surface() { + setWebPage(nullptr); + // Destroy pending frame callbacks. + auto pendingList = WTFMove(m_pendingFrameCallbackList); + for (auto* resource : pendingList) + wl_resource_destroy(resource); auto list = WTFMove(m_frameCallbackList); for (auto* resource : list) wl_resource_destroy(resource); @@ -170,6 +175,26 @@ WaylandCompositor::Surface::~Surface() glDeleteTextures(1, &m_texture); } +void WaylandCompositor::Surface::setWebPage(WebPageProxy* webPage) +{ + if (m_webPage) { + flushPendingFrameCallbacks(); + flushFrameCallbacks(); + gtk_widget_remove_tick_callback(m_webPage->viewWidget(), m_tickCallbackID); + m_tickCallbackID = 0; + } + + m_webPage = webPage; + if (!m_webPage) + return; + + m_tickCallbackID = gtk_widget_add_tick_callback(m_webPage->viewWidget(), [](GtkWidget*, GdkFrameClock*, gpointer userData) -> gboolean { + auto* surface = static_cast(userData); + surface->flushFrameCallbacks(); + return G_SOURCE_CONTINUE; + }, this, nullptr); +} + void WaylandCompositor::Surface::makePendingBufferCurrent() { if (m_pendingBuffer == m_buffer) @@ -199,10 +224,10 @@ void WaylandCompositor::Surface::requestFrame(struct wl_resource* resource) { wl_resource_set_implementation(resource, nullptr, this, [](struct wl_resource* resource) { auto* surface = static_cast(wl_resource_get_user_data(resource)); - if (size_t item = surface->m_frameCallbackList.find(resource) != notFound) - surface->m_frameCallbackList.remove(item); + if (size_t item = surface->m_pendingFrameCallbackList.find(resource) != notFound) + surface->m_pendingFrameCallbackList.remove(item); }); - m_frameCallbackList.append(resource); + m_pendingFrameCallbackList.append(resource); } bool WaylandCompositor::Surface::prepareTextureForPainting(unsigned& texture, IntSize& textureSize) @@ -218,8 +243,32 @@ bool WaylandCompositor::Surface::prepareTextureForPainting(unsigned& texture, In return true; } +void WaylandCompositor::Surface::flushFrameCallbacks() +{ + auto list = WTFMove(m_frameCallbackList); + for (auto* resource : list) { + wl_callback_send_done(resource, 0); + wl_resource_destroy(resource); + } +} + +void WaylandCompositor::Surface::flushPendingFrameCallbacks() +{ + auto list = WTFMove(m_pendingFrameCallbackList); + for (auto* resource : list) { + wl_callback_send_done(resource, 0); + wl_resource_destroy(resource); + } +} + void WaylandCompositor::Surface::commit() { + if (!m_webPage) { + makePendingBufferCurrent(); + flushPendingFrameCallbacks(); + return; + } + EGLDisplay eglDisplay = PlatformDisplay::sharedDisplay().eglDisplay(); if (m_image != EGL_NO_IMAGE_KHR) eglDestroyImage(eglDisplay, m_image); @@ -230,18 +279,11 @@ void WaylandCompositor::Surface::commit() m_imageSize = m_pendingBuffer->size(); makePendingBufferCurrent(); - if (m_webPage) - m_webPage->setViewNeedsDisplay(IntRect(IntPoint::zero(), m_webPage->viewSize())); - // From a Wayland point-of-view frame callbacks should be fired where the - // compositor knows it has *used* the committed contents, so firing them here - // can be surprising but we don't need them as a throttling mechanism because - // rendering synchronization is handled elsewhere by WebKit. - auto list = WTFMove(m_frameCallbackList); - for (auto* resource : list) { - wl_callback_send_done(resource, 0); - wl_resource_destroy(resource); - } + m_webPage->setViewNeedsDisplay(IntRect(IntPoint::zero(), m_webPage->viewSize())); + + auto list = WTFMove(m_pendingFrameCallbackList); + m_frameCallbackList.appendVector(list); } static const struct wl_surface_interface surfaceInterface = { diff --git a/Source/WebKit/UIProcess/gtk/WaylandCompositor.h b/Source/WebKit/UIProcess/gtk/WaylandCompositor.h index 14b9a836d95c..9bbeb7a7cdbb 100644 --- a/Source/WebKit/UIProcess/gtk/WaylandCompositor.h +++ b/Source/WebKit/UIProcess/gtk/WaylandCompositor.h @@ -87,10 +87,12 @@ class WaylandCompositor { void requestFrame(struct wl_resource*); void commit(); - void setWebPage(WebPageProxy* webPage) { m_webPage = webPage; } + void setWebPage(WebPageProxy*); bool prepareTextureForPainting(unsigned&, WebCore::IntSize&); private: + void flushFrameCallbacks(); + void flushPendingFrameCallbacks(); void makePendingBufferCurrent(); WeakPtr m_buffer; @@ -98,8 +100,10 @@ class WaylandCompositor { unsigned m_texture; EGLImageKHR m_image; WebCore::IntSize m_imageSize; + Vector m_pendingFrameCallbackList; Vector m_frameCallbackList; WebPageProxy* m_webPage { nullptr }; + unsigned m_tickCallbackID { 0 }; }; bool isRunning() const { return !!m_display; } diff --git a/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp b/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp index c7332b642414..4787c9904252 100644 --- a/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp +++ b/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp @@ -43,13 +43,17 @@ std::unique_ptr AcceleratedSurfaceWayland::create(Web AcceleratedSurfaceWayland::AcceleratedSurfaceWayland(WebPage& webPage, Client& client) : AcceleratedSurface(webPage, client) - , m_surface(WebProcess::singleton().waylandCompositorDisplay()->createSurface()) - , m_window(wl_egl_window_create(m_surface.get(), std::max(1, m_size.width()), std::max(1, m_size.height()))) { +} + +void AcceleratedSurfaceWayland::initialize() +{ + m_surface = WebProcess::singleton().waylandCompositorDisplay()->createSurface(); + m_window = wl_egl_window_create(m_surface.get(), std::max(1, m_size.width()), std::max(1, m_size.height())); WebProcess::singleton().waylandCompositorDisplay()->bindSurfaceToPage(m_surface.get(), m_webPage); } -AcceleratedSurfaceWayland::~AcceleratedSurfaceWayland() +void AcceleratedSurfaceWayland::finalize() { wl_egl_window_destroy(m_window); } diff --git a/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h b/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h index c3c886e59e93..4320215bdf77 100644 --- a/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h +++ b/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h @@ -38,13 +38,15 @@ class AcceleratedSurfaceWayland final : public AcceleratedSurface { WTF_MAKE_NONCOPYABLE(AcceleratedSurfaceWayland); WTF_MAKE_FAST_ALLOCATED; public: static std::unique_ptr create(WebPage&, Client&); - ~AcceleratedSurfaceWayland(); + ~AcceleratedSurfaceWayland() = default; uint64_t window() const override { return reinterpret_cast(m_window); } uint64_t surfaceID() const override { return m_webPage.pageID(); } bool resize(const WebCore::IntSize&) override; bool shouldPaintMirrored() const override { return true; } + void initialize() override; + void finalize() override; void didRenderFrame() override; private: