Changeset 221514 in webkit


Ignore:
Timestamp:
Sep 2, 2017 12:05:46 AM (7 years ago)
Author:
Carlos Garcia Campos
Message:

[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:
Location:
trunk/Source/WebKit
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebKit/ChangeLog

    r221506 r221514  
     12017-09-02  Carlos Garcia Campos  <cgarcia@igalia.com>
     2
     3        [GTK][Wayland] Opening FedoraProject's pastebin chews CPU
     4        https://bugs.webkit.org/show_bug.cgi?id=175942
     5
     6        Reviewed by Žan Doberšek.
     7
     8        This regressed when we introduced the display refresh monitor. The monitor schedules updates immediately,
     9        because we removed the option to not do frame sync in X11 to let swapBuffers do the throttling, but that's
     10        not happening in Wayland because the nested compositor is dispatching frame callbacks on surface commit.
     11        We need to ensure that frame callbacks are dispatched on every monitor refresh, because swapBuffers waits for
     12        frame callbacks to be queued on display.
     13
     14        * UIProcess/gtk/WaylandCompositor.cpp:
     15        (WebKit::WaylandCompositor::Surface::~Surface): Destroy pending frame callbacks too.
     16        (WebKit::WaylandCompositor::Surface::setWebPage): Add a tick callback to the web view widget to flush all
     17        committed frame callbacks on every frame update.
     18        (WebKit::WaylandCompositor::Surface::requestFrame): Add the callbacks to m_pendingFrameCallbackList.
     19        (WebKit::WaylandCompositor::Surface::flushFrameCallbacks): Dispatch all committed frame callabcks.
     20        (WebKit::WaylandCompositor::Surface::flushPendingFrameCallbacks): Dispatch all pending frame callbacks.
     21        (WebKit::WaylandCompositor::Surface::commit): Do not dispatch frame callbacks here, move them to the list of
     22        committed frame callbacks that will be dispatched on the next frame clock update.
     23        * UIProcess/gtk/WaylandCompositor.h:
     24        (WebKit::WaylandCompositor::Surface::setWebPage): Moved to the cpp.
     25        * WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp:
     26        (WebKit::AcceleratedSurfaceWayland::AcceleratedSurfaceWayland): Move surface initialization and destruction to
     27        the compositing thread.
     28        (WebKit::AcceleratedSurfaceWayland::initialize):
     29        (WebKit::AcceleratedSurfaceWayland::finalize):
     30        (WebKit::AcceleratedSurfaceWayland::~AcceleratedSurfaceWayland): Deleted.
     31        * WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h:
     32
    1332017-09-01  Youenn Fablet  <youenn@apple.com>
    234
  • trunk/Source/WebKit/UIProcess/gtk/WaylandCompositor.cpp

    r215922 r221514  
    157157WaylandCompositor::Surface::~Surface()
    158158{
     159    setWebPage(nullptr);
     160
    159161    // Destroy pending frame callbacks.
     162    auto pendingList = WTFMove(m_pendingFrameCallbackList);
     163    for (auto* resource : pendingList)
     164        wl_resource_destroy(resource);
    160165    auto list = WTFMove(m_frameCallbackList);
    161166    for (auto* resource : list)
     
    171176}
    172177
     178void WaylandCompositor::Surface::setWebPage(WebPageProxy* webPage)
     179{
     180    if (m_webPage) {
     181        flushPendingFrameCallbacks();
     182        flushFrameCallbacks();
     183        gtk_widget_remove_tick_callback(m_webPage->viewWidget(), m_tickCallbackID);
     184        m_tickCallbackID = 0;
     185    }
     186
     187    m_webPage = webPage;
     188    if (!m_webPage)
     189        return;
     190
     191    m_tickCallbackID = gtk_widget_add_tick_callback(m_webPage->viewWidget(), [](GtkWidget*, GdkFrameClock*, gpointer userData) -> gboolean {
     192        auto* surface = static_cast<Surface*>(userData);
     193        surface->flushFrameCallbacks();
     194        return G_SOURCE_CONTINUE;
     195    }, this, nullptr);
     196}
     197
    173198void WaylandCompositor::Surface::makePendingBufferCurrent()
    174199{
     
    200225    wl_resource_set_implementation(resource, nullptr, this, [](struct wl_resource* resource) {
    201226        auto* surface = static_cast<WaylandCompositor::Surface*>(wl_resource_get_user_data(resource));
    202         if (size_t item = surface->m_frameCallbackList.find(resource) != notFound)
    203             surface->m_frameCallbackList.remove(item);
     227        if (size_t item = surface->m_pendingFrameCallbackList.find(resource) != notFound)
     228            surface->m_pendingFrameCallbackList.remove(item);
    204229    });
    205     m_frameCallbackList.append(resource);
     230    m_pendingFrameCallbackList.append(resource);
    206231}
    207232
     
    219244}
    220245
     246void WaylandCompositor::Surface::flushFrameCallbacks()
     247{
     248    auto list = WTFMove(m_frameCallbackList);
     249    for (auto* resource : list) {
     250        wl_callback_send_done(resource, 0);
     251        wl_resource_destroy(resource);
     252    }
     253}
     254
     255void WaylandCompositor::Surface::flushPendingFrameCallbacks()
     256{
     257    auto list = WTFMove(m_pendingFrameCallbackList);
     258    for (auto* resource : list) {
     259        wl_callback_send_done(resource, 0);
     260        wl_resource_destroy(resource);
     261    }
     262}
     263
    221264void WaylandCompositor::Surface::commit()
    222265{
     266    if (!m_webPage) {
     267        makePendingBufferCurrent();
     268        flushPendingFrameCallbacks();
     269        return;
     270    }
     271
    223272    EGLDisplay eglDisplay = PlatformDisplay::sharedDisplay().eglDisplay();
    224273    if (m_image != EGL_NO_IMAGE_KHR)
     
    231280
    232281    makePendingBufferCurrent();
    233     if (m_webPage)
    234         m_webPage->setViewNeedsDisplay(IntRect(IntPoint::zero(), m_webPage->viewSize()));
    235 
    236     // From a Wayland point-of-view frame callbacks should be fired where the
    237     // compositor knows it has *used* the committed contents, so firing them here
    238     // can be surprising but we don't need them as a throttling mechanism because
    239     // rendering synchronization is handled elsewhere by WebKit.
    240     auto list = WTFMove(m_frameCallbackList);
    241     for (auto* resource : list) {
    242         wl_callback_send_done(resource, 0);
    243         wl_resource_destroy(resource);
    244     }
     282
     283    m_webPage->setViewNeedsDisplay(IntRect(IntPoint::zero(), m_webPage->viewSize()));
     284
     285    auto list = WTFMove(m_pendingFrameCallbackList);
     286    m_frameCallbackList.appendVector(list);
    245287}
    246288
  • trunk/Source/WebKit/UIProcess/gtk/WaylandCompositor.h

    r209177 r221514  
    8888        void commit();
    8989
    90         void setWebPage(WebPageProxy* webPage) { m_webPage = webPage; }
     90        void setWebPage(WebPageProxy*);
    9191        bool prepareTextureForPainting(unsigned&, WebCore::IntSize&);
    9292
    9393    private:
     94        void flushFrameCallbacks();
     95        void flushPendingFrameCallbacks();
    9496        void makePendingBufferCurrent();
    9597
     
    99101        EGLImageKHR m_image;
    100102        WebCore::IntSize m_imageSize;
     103        Vector<wl_resource*> m_pendingFrameCallbackList;
    101104        Vector<wl_resource*> m_frameCallbackList;
    102105        WebPageProxy* m_webPage { nullptr };
     106        unsigned m_tickCallbackID { 0 };
    103107    };
    104108
  • trunk/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.cpp

    r218629 r221514  
    4444AcceleratedSurfaceWayland::AcceleratedSurfaceWayland(WebPage& webPage, Client& client)
    4545    : AcceleratedSurface(webPage, client)
    46     , m_surface(WebProcess::singleton().waylandCompositorDisplay()->createSurface())
    47     , m_window(wl_egl_window_create(m_surface.get(), std::max(1, m_size.width()), std::max(1, m_size.height())))
    4846{
     47}
     48
     49void AcceleratedSurfaceWayland::initialize()
     50{
     51    m_surface = WebProcess::singleton().waylandCompositorDisplay()->createSurface();
     52    m_window = wl_egl_window_create(m_surface.get(), std::max(1, m_size.width()), std::max(1, m_size.height()));
    4953    WebProcess::singleton().waylandCompositorDisplay()->bindSurfaceToPage(m_surface.get(), m_webPage);
    5054}
    5155
    52 AcceleratedSurfaceWayland::~AcceleratedSurfaceWayland()
     56void AcceleratedSurfaceWayland::finalize()
    5357{
    5458    wl_egl_window_destroy(m_window);
  • trunk/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceWayland.h

    r217123 r221514  
    3939public:
    4040    static std::unique_ptr<AcceleratedSurfaceWayland> create(WebPage&, Client&);
    41     ~AcceleratedSurfaceWayland();
     41    ~AcceleratedSurfaceWayland() = default;
    4242
    4343    uint64_t window() const override { return reinterpret_cast<uint64_t>(m_window); }
     
    4646    bool shouldPaintMirrored() const override { return true; }
    4747
     48    void initialize() override;
     49    void finalize() override;
    4850    void didRenderFrame() override;
    4951
Note: See TracChangeset for help on using the changeset viewer.