Title: [197064] releases/WebKitGTK/webkit-2.10/Source
Revision
197064
Author
carlo...@webkit.org
Date
2016-02-24 23:45:13 -0800 (Wed, 24 Feb 2016)

Log Message

Merge r197062 - [GTK] Tearing when entering AC mode
https://bugs.webkit.org/show_bug.cgi?id=150955

Reviewed by Michael Catanzaro.

Source/WebCore:

* platform/gtk/GtkUtilities.cpp:
(WebCore::widgetIsOnscreenToplevelWindow): Allow passing nullptr.

Source/WebKit2:

When entering accelerated compositing mode, we keep rendering the
non accelerated contents until we have the first frame of
accelerated compositing contents. When the view is created hidden,
for example when the browser opens a link in a new tab, the view
is not realized until it is mapped. The native surface handle for
compositing, needed by the web process to render accelerated
compositing contents, is not available until the view is realized,
because it depends on the properties of the parent. When a web
view is mapped for the first time, and then realized, we send the
native surface handle for compositing to the web process, and keep
rendering the non composited contents until we get the first
frame, but in this case we never had non composited contents and
we end up rendering an untinitalized surface. This sometimes just
produces flickering and sometimes rendering artifacts.
We can prevent this from happening by realizing the web view as
soon as possible. A GtkWidget can't be realized until it has been
added to a toplevel, so we can realize our view right after it is
added to a toplevel window, and wait until the view is actually
mapped to notify the web process that it has been added to a
window. This way can we enter accelerated compositing mode before
the web view is mapped, so that when mapped we don't try to paint
the previous contents and don't need to wait for the first frame.

* UIProcess/API/gtk/WebKitWebViewBase.cpp:
(toplevelWindowFocusInEvent): Handle the case of the window being
hidden when receiving focus in. According to
gtk_window_focus_in_event, this can happen.
(webkitWebViewBaseSetToplevelOnScreenWindow): When the web view is
removed from its toplevel parent, update the IsInWindow and
WindowIsActive flags accordingly. When the view is added to a
toplevel, realize it and don't update the window flags, they will be
updated when the view is mapped the first time.
(webkitWebViewBaseMap): Also update IsInWindow and WindowIsActive
flags if needed. This way, if for example you open a youtube video
in a new tab, the video won't start playing until you visit the
tab, like we did when the view was realized on map.
(webkitWebViewBaseHierarchyChanged): Use hierarchy-changed signal
instead of parent-set to be notified when the view is added to or
removed from a toplevel.
(webkit_web_view_base_class_init): Implement hierarchy-changed
instead of parent-set.
(webkitWebViewBaseRealize): Do not call
webkitWebViewBaseSetToplevelOnScreenWindow on realize, it's now
webkitWebViewBaseSetToplevelOnScreenWindow the one realizing the view.
* UIProcess/cairo/BackingStoreCairo.cpp:
(WebKit::BackingStore::createBackend): Do not realize the view
here, it should be realized already at this point. If it's not
realized at this point is because it hasn't been added to a
toplevel and gtk_widget_realize will not work anyway.
(WebKit::BackingStore::paint): This is changing the cairo source
operator, so save/restore the cairo context to ensure it doesn't
affect other drawing done after this.

Modified Paths

Diff

Modified: releases/WebKitGTK/webkit-2.10/Source/WebCore/ChangeLog (197063 => 197064)


--- releases/WebKitGTK/webkit-2.10/Source/WebCore/ChangeLog	2016-02-25 07:43:49 UTC (rev 197063)
+++ releases/WebKitGTK/webkit-2.10/Source/WebCore/ChangeLog	2016-02-25 07:45:13 UTC (rev 197064)
@@ -1,3 +1,13 @@
+2016-02-24  Carlos Garcia Campos  <cgar...@igalia.com>
+
+        [GTK] Tearing when entering AC mode
+        https://bugs.webkit.org/show_bug.cgi?id=150955
+
+        Reviewed by Michael Catanzaro.
+
+        * platform/gtk/GtkUtilities.cpp:
+        (WebCore::widgetIsOnscreenToplevelWindow): Allow passing nullptr.
+
 2016-02-19  Philippe Normand  <pnorm...@igalia.com>
 
         [GStreamer] clean-up various leaks

Modified: releases/WebKitGTK/webkit-2.10/Source/WebCore/platform/gtk/GtkUtilities.cpp (197063 => 197064)


--- releases/WebKitGTK/webkit-2.10/Source/WebCore/platform/gtk/GtkUtilities.cpp	2016-02-25 07:43:49 UTC (rev 197063)
+++ releases/WebKitGTK/webkit-2.10/Source/WebCore/platform/gtk/GtkUtilities.cpp	2016-02-25 07:45:13 UTC (rev 197064)
@@ -51,7 +51,7 @@
 
 bool widgetIsOnscreenToplevelWindow(GtkWidget* widget)
 {
-    return gtk_widget_is_toplevel(widget) && GTK_IS_WINDOW(widget) && !GTK_IS_OFFSCREEN_WINDOW(widget);
+    return widget && gtk_widget_is_toplevel(widget) && GTK_IS_WINDOW(widget) && !GTK_IS_OFFSCREEN_WINDOW(widget);
 }
 
 #if ENABLE(DEVELOPER_MODE)

Modified: releases/WebKitGTK/webkit-2.10/Source/WebKit2/ChangeLog (197063 => 197064)


--- releases/WebKitGTK/webkit-2.10/Source/WebKit2/ChangeLog	2016-02-25 07:43:49 UTC (rev 197063)
+++ releases/WebKitGTK/webkit-2.10/Source/WebKit2/ChangeLog	2016-02-25 07:45:13 UTC (rev 197064)
@@ -1,3 +1,63 @@
+2016-02-24  Carlos Garcia Campos  <cgar...@igalia.com>
+
+        [GTK] Tearing when entering AC mode
+        https://bugs.webkit.org/show_bug.cgi?id=150955
+
+        Reviewed by Michael Catanzaro.
+
+        When entering accelerated compositing mode, we keep rendering the
+        non accelerated contents until we have the first frame of
+        accelerated compositing contents. When the view is created hidden,
+        for example when the browser opens a link in a new tab, the view
+        is not realized until it is mapped. The native surface handle for
+        compositing, needed by the web process to render accelerated
+        compositing contents, is not available until the view is realized,
+        because it depends on the properties of the parent. When a web
+        view is mapped for the first time, and then realized, we send the
+        native surface handle for compositing to the web process, and keep
+        rendering the non composited contents until we get the first
+        frame, but in this case we never had non composited contents and
+        we end up rendering an untinitalized surface. This sometimes just
+        produces flickering and sometimes rendering artifacts.
+        We can prevent this from happening by realizing the web view as
+        soon as possible. A GtkWidget can't be realized until it has been
+        added to a toplevel, so we can realize our view right after it is
+        added to a toplevel window, and wait until the view is actually
+        mapped to notify the web process that it has been added to a
+        window. This way can we enter accelerated compositing mode before
+        the web view is mapped, so that when mapped we don't try to paint
+        the previous contents and don't need to wait for the first frame.
+
+        * UIProcess/API/gtk/WebKitWebViewBase.cpp:
+        (toplevelWindowFocusInEvent): Handle the case of the window being
+        hidden when receiving focus in. According to
+        gtk_window_focus_in_event, this can happen.
+        (webkitWebViewBaseSetToplevelOnScreenWindow): When the web view is
+        removed from its toplevel parent, update the IsInWindow and
+        WindowIsActive flags accordingly. When the view is added to a
+        toplevel, realize it and don't update the window flags, they will be
+        updated when the view is mapped the first time.
+        (webkitWebViewBaseMap): Also update IsInWindow and WindowIsActive
+        flags if needed. This way, if for example you open a youtube video
+        in a new tab, the video won't start playing until you visit the
+        tab, like we did when the view was realized on map.
+        (webkitWebViewBaseHierarchyChanged): Use hierarchy-changed signal
+        instead of parent-set to be notified when the view is added to or
+        removed from a toplevel.
+        (webkit_web_view_base_class_init): Implement hierarchy-changed
+        instead of parent-set.
+        (webkitWebViewBaseRealize): Do not call
+        webkitWebViewBaseSetToplevelOnScreenWindow on realize, it's now
+        webkitWebViewBaseSetToplevelOnScreenWindow the one realizing the view.
+        * UIProcess/cairo/BackingStoreCairo.cpp:
+        (WebKit::BackingStore::createBackend): Do not realize the view
+        here, it should be realized already at this point. If it's not
+        realized at this point is because it hasn't been added to a
+        toplevel and gtk_widget_realize will not work anyway.
+        (WebKit::BackingStore::paint): This is changing the cairo source
+        operator, so save/restore the cairo context to ensure it doesn't
+        affect other drawing done after this.
+
 2016-02-03  Carlos Garcia Campos  <cgar...@igalia.com>
 
         [GTK] Reduce IPC traffic due to view state changes

Modified: releases/WebKitGTK/webkit-2.10/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp (197063 => 197064)


--- releases/WebKitGTK/webkit-2.10/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp	2016-02-25 07:43:49 UTC (rev 197063)
+++ releases/WebKitGTK/webkit-2.10/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewBase.cpp	2016-02-25 07:45:13 UTC (rev 197064)
@@ -226,8 +226,12 @@
     priv->updateViewStateTimer.startOneShot(0);
 }
 
-static gboolean toplevelWindowFocusInEvent(GtkWidget*, GdkEventFocus*, WebKitWebViewBase* webViewBase)
+static gboolean toplevelWindowFocusInEvent(GtkWidget* widget, GdkEventFocus*, WebKitWebViewBase* webViewBase)
 {
+    // Spurious focus in events can occur when the window is hidden.
+    if (!gtk_widget_get_visible(widget))
+        return FALSE;
+
     WebKitWebViewBasePrivate* priv = webViewBase->priv;
     if (priv->viewState & ViewState::WindowIsActive)
         return FALSE;
@@ -289,12 +293,22 @@
     }
 
     priv->toplevelOnScreenWindow = window;
-    if (!(priv->viewState & ViewState::IsInWindow)) {
-        priv->viewState |= ViewState::IsInWindow;
-        webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::IsInWindow);
+
+    if (!priv->toplevelOnScreenWindow) {
+        ViewState::Flags flagsToUpdate = 0;
+        if (priv->viewState & ViewState::IsInWindow) {
+            priv->viewState &= ~ViewState::IsInWindow;
+            flagsToUpdate |= ViewState::IsInWindow;
+        }
+        if (priv->viewState & ViewState::WindowIsActive) {
+            priv->viewState &= ~ViewState::WindowIsActive;
+            flagsToUpdate |= ViewState::IsInWindow;
+        }
+        if (flagsToUpdate)
+            webkitWebViewBaseScheduleUpdateViewState(webViewBase, flagsToUpdate);
+
+        return;
     }
-    if (!priv->toplevelOnScreenWindow)
-        return;
 
     priv->toplevelFocusInEventID =
         g_signal_connect(priv->toplevelOnScreenWindow, "focus-in-event",
@@ -304,6 +318,7 @@
                          G_CALLBACK(toplevelWindowFocusOutEvent), webViewBase);
     priv->toplevelWindowStateEventID =
         g_signal_connect(priv->toplevelOnScreenWindow, "window-state-event", G_CALLBACK(toplevelWindowStateEvent), webViewBase);
+    gtk_widget_realize(GTK_WIDGET(webViewBase));
 }
 
 static void webkitWebViewBaseRealize(GtkWidget* widget)
@@ -372,10 +387,6 @@
     gtk_style_context_set_background(gtk_widget_get_style_context(widget), window);
 
     gtk_im_context_set_client_window(priv->inputMethodFilter.context(), window);
-
-    GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
-    if (widgetIsOnscreenToplevelWindow(toplevel))
-        webkitWebViewBaseSetToplevelOnScreenWindow(webView, GTK_WINDOW(toplevel));
 }
 
 static void webkitWebViewBaseUnrealize(GtkWidget* widget)
@@ -659,11 +670,20 @@
 
     WebKitWebViewBase* webViewBase = WEBKIT_WEB_VIEW_BASE(widget);
     WebKitWebViewBasePrivate* priv = webViewBase->priv;
-    if (priv->viewState & ViewState::IsVisible)
+    ViewState::Flags flagsToUpdate = 0;
+    if (!(priv->viewState & ViewState::IsVisible))
+        flagsToUpdate |= ViewState::IsVisible;
+    if (priv->toplevelOnScreenWindow) {
+        if (!(priv->viewState & ViewState::IsInWindow))
+            flagsToUpdate |= ViewState::IsInWindow;
+        if (gtk_window_is_active(GTK_WINDOW(priv->toplevelOnScreenWindow)) && !(priv->viewState & ViewState::WindowIsActive))
+            flagsToUpdate |= ViewState::WindowIsActive;
+    }
+    if (!flagsToUpdate)
         return;
 
-    priv->viewState |= ViewState::IsVisible;
-    webkitWebViewBaseScheduleUpdateViewState(webViewBase, ViewState::IsVisible);
+    priv->viewState |= flagsToUpdate;
+    webkitWebViewBaseScheduleUpdateViewState(webViewBase, flagsToUpdate);
 }
 
 static void webkitWebViewBaseUnmap(GtkWidget* widget)
@@ -1061,10 +1081,19 @@
 }
 #endif // ENABLE(DRAG_SUPPORT)
 
-static void webkitWebViewBaseParentSet(GtkWidget* widget, GtkWidget* /* oldParent */)
+static void webkitWebViewBaseHierarchyChanged(GtkWidget* widget, GtkWidget* oldToplevel)
 {
-    if (!gtk_widget_get_parent(widget))
-        webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), 0);
+    WebKitWebViewBasePrivate* priv = WEBKIT_WEB_VIEW_BASE(widget)->priv;
+    if (widgetIsOnscreenToplevelWindow(oldToplevel) && GTK_WINDOW(oldToplevel) == priv->toplevelOnScreenWindow) {
+        webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), nullptr);
+        return;
+    }
+
+    if (!oldToplevel) {
+        GtkWidget* toplevel = gtk_widget_get_toplevel(widget);
+        if (widgetIsOnscreenToplevelWindow(toplevel))
+            webkitWebViewBaseSetToplevelOnScreenWindow(WEBKIT_WEB_VIEW_BASE(widget), GTK_WINDOW(toplevel));
+    }
 }
 
 static gboolean webkitWebViewBaseFocus(GtkWidget* widget, GtkDirectionType direction)
@@ -1123,7 +1152,7 @@
     widgetClass->drag_data_received = webkitWebViewBaseDragDataReceived;
 #endif // ENABLE(DRAG_SUPPORT)
     widgetClass->get_accessible = webkitWebViewBaseGetAccessible;
-    widgetClass->parent_set = webkitWebViewBaseParentSet;
+    widgetClass->hierarchy_changed = webkitWebViewBaseHierarchyChanged;
     widgetClass->destroy = webkitWebViewBaseDestroy;
 
     GObjectClass* gobjectClass = G_OBJECT_CLASS(webkitWebViewBaseClass);

Modified: releases/WebKitGTK/webkit-2.10/Source/WebKit2/UIProcess/cairo/BackingStoreCairo.cpp (197063 => 197064)


--- releases/WebKitGTK/webkit-2.10/Source/WebKit2/UIProcess/cairo/BackingStoreCairo.cpp	2016-02-25 07:43:49 UTC (rev 197063)
+++ releases/WebKitGTK/webkit-2.10/Source/WebKit2/UIProcess/cairo/BackingStoreCairo.cpp	2016-02-25 07:45:13 UTC (rev 197064)
@@ -67,9 +67,7 @@
     scaledSize.scale(m_deviceScaleFactor);
 
 #if PLATFORM(GTK)
-    GtkWidget* viewWidget = m_webPageProxy.viewWidget();
-    gtk_widget_realize(viewWidget);
-    RefPtr<cairo_surface_t> surface = adoptRef(gdk_window_create_similar_surface(gtk_widget_get_window(viewWidget),
+    RefPtr<cairo_surface_t> surface = adoptRef(gdk_window_create_similar_surface(gtk_widget_get_window(m_webPageProxy.viewWidget()),
         CAIRO_CONTENT_COLOR_ALPHA, scaledSize.width(), scaledSize.height()));
 #else
     RefPtr<cairo_surface_t> surface = adoptRef(cairo_image_surface_create(CAIRO_FORMAT_ARGB32, scaledSize.width(), scaledSize.height()));
@@ -83,10 +81,12 @@
 {
     ASSERT(m_backend);
 
+    cairo_save(context);
     cairo_set_operator(context, CAIRO_OPERATOR_SOURCE);
     cairo_set_source_surface(context, m_backend->surface(), 0, 0);
     cairo_rectangle(context, rect.x(), rect.y(), rect.width(), rect.height());
     cairo_fill(context);
+    cairo_restore(context);
 }
 
 void BackingStore::incorporateUpdate(ShareableBitmap* bitmap, const UpdateInfo& updateInfo)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to