c355d1f
c355d1f
# HG changeset patch
c355d1f
# User Martin Stransky <stransky@redhat.com>
c355d1f
# Date 1525961060 -7200
c355d1f
# Node ID acaaa40ebdf142fda38d5661f7631f029a2406c6
c355d1f
# Parent  5543294befe9494593370f33c40ba50c8239e0c6
c355d1f
Bug 1460605 - Provide NS_NATIVE_EGL_WINDOW to get a native EGL window on Wayland, r=jhorak
c355d1f
c355d1f
Original patch author is Takuro Ashie <ashie@clear-code.com>
c355d1f
c355d1f
Provide ability to create native EGL window and provide it under NS_NATIVE_EGL_WINDOW
c355d1f
to GL code. The native EGL window is owned/managed by mozcontainer.
c355d1f
c355d1f
MozReview-Commit-ID: 4d0Kk6DRSaD
c355d1f
c355d1f
diff --git a/config/system-headers.mozbuild b/config/system-headers.mozbuild
c355d1f
--- a/config/system-headers.mozbuild
c355d1f
+++ b/config/system-headers.mozbuild
c355d1f
@@ -1334,8 +1334,14 @@ if CONFIG['MOZ_SYSTEM_ICU']:
c355d1f
         'unicode/unistr.h',
c355d1f
         'unicode/unorm.h',
c355d1f
         'unicode/unum.h',
c355d1f
         'unicode/upluralrules.h',
c355d1f
         'unicode/ureldatefmt.h',
c355d1f
         'unicode/ustring.h',
c355d1f
         'unicode/utypes.h',
c355d1f
     ]
c355d1f
+
c355d1f
+if CONFIG['MOZ_WAYLAND']:
c355d1f
+    system_headers += [
c355d1f
+        'wayland-client.h',
c355d1f
+        'wayland-egl.h',
c355d1f
+    ]
c355d1f
diff --git a/widget/gtk/mozcontainer.cpp b/widget/gtk/mozcontainer.cpp
c355d1f
--- a/widget/gtk/mozcontainer.cpp
c355d1f
+++ b/widget/gtk/mozcontainer.cpp
c355d1f
@@ -5,16 +5,17 @@
c355d1f
  * License, v. 2.0. If a copy of the MPL was not distributed with this
c355d1f
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
c355d1f
 
c355d1f
 #include "mozcontainer.h"
c355d1f
 #include <gtk/gtk.h>
c355d1f
 #ifdef MOZ_WAYLAND
c355d1f
 #include <gdk/gdkx.h>
c355d1f
 #include <gdk/gdkwayland.h>
c355d1f
+#include <wayland-egl.h>
c355d1f
 #endif
c355d1f
 #include <stdio.h>
c355d1f
 #include <dlfcn.h>
c355d1f
 
c355d1f
 #ifdef ACCESSIBILITY
c355d1f
 #include <atk/atk.h>
c355d1f
 #include "maiRedundantObjectFactory.h"
c355d1f
 #endif
c355d1f
@@ -202,16 +203,21 @@ void
c355d1f
 moz_container_init (MozContainer *container)
c355d1f
 {
c355d1f
     gtk_widget_set_can_focus(GTK_WIDGET(container), TRUE);
c355d1f
     gtk_container_set_resize_mode(GTK_CONTAINER(container), GTK_RESIZE_IMMEDIATE);
c355d1f
     gtk_widget_set_redraw_on_allocate(GTK_WIDGET(container), FALSE);
c355d1f
 
c355d1f
 #if defined(MOZ_WAYLAND)
c355d1f
     {
c355d1f
+      container->subcompositor = nullptr;
c355d1f
+      container->surface = nullptr;
c355d1f
+      container->subsurface = nullptr;
c355d1f
+      container->eglwindow = nullptr;
c355d1f
+
c355d1f
       GdkDisplay *gdk_display = gtk_widget_get_display(GTK_WIDGET(container));
c355d1f
       if (GDK_IS_WAYLAND_DISPLAY (gdk_display)) {
c355d1f
           // Available as of GTK 3.8+
c355d1f
           static auto sGdkWaylandDisplayGetWlDisplay =
c355d1f
               (wl_display *(*)(GdkDisplay *))
c355d1f
               dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
c355d1f
 
c355d1f
           wl_display* display = sGdkWaylandDisplayGetWlDisplay(gdk_display);
c355d1f
@@ -284,16 +290,17 @@ moz_container_map_surface(MozContainer *
c355d1f
         wl_region_destroy(region);
c355d1f
     }
c355d1f
     return true;
c355d1f
 }
c355d1f
 
c355d1f
 static void
c355d1f
 moz_container_unmap_surface(MozContainer *container)
c355d1f
 {
c355d1f
+    g_clear_pointer(&container->eglwindow, wl_egl_window_destroy);
c355d1f
     g_clear_pointer(&container->subsurface, wl_subsurface_destroy);
c355d1f
     g_clear_pointer(&container->surface, wl_surface_destroy);
c355d1f
 }
c355d1f
 
c355d1f
 #endif
c355d1f
 
c355d1f
 void
c355d1f
 moz_container_map (GtkWidget *widget)
c355d1f
@@ -429,16 +436,21 @@ moz_container_size_allocate (GtkWidget  
c355d1f
     // We need to position our subsurface according to GdkWindow
c355d1f
     // when offset changes (GdkWindow is maximized for instance).
c355d1f
     // see gtk-clutter-embed.c for reference.
c355d1f
     if (container->subsurface) {
c355d1f
         gint x, y;
c355d1f
         gdk_window_get_position(gtk_widget_get_window(widget), &x, &y);
c355d1f
         wl_subsurface_set_position(container->subsurface, x, y);
c355d1f
     }
c355d1f
+    if (container->eglwindow) {
c355d1f
+        wl_egl_window_resize(container->eglwindow,
c355d1f
+                             allocation->width, allocation->height,
c355d1f
+                             0, 0);
c355d1f
+    }
c355d1f
 #endif
c355d1f
 }
c355d1f
 
c355d1f
 void
c355d1f
 moz_container_remove (GtkContainer *container, GtkWidget *child_widget)
c355d1f
 {
c355d1f
     MozContainerChild *child;
c355d1f
     MozContainer *moz_container;
c355d1f
@@ -554,9 +566,32 @@ moz_container_get_wl_surface(MozContaine
c355d1f
         if (!gdk_window_is_visible(window))
c355d1f
             return nullptr;
c355d1f
 
c355d1f
         moz_container_map_surface(container);
c355d1f
     }
c355d1f
 
c355d1f
     return container->surface;
c355d1f
 }
c355d1f
+
c355d1f
+struct wl_egl_window *
c355d1f
+moz_container_get_wl_egl_window(MozContainer *container)
c355d1f
+{
c355d1f
+    if (!container->eglwindow) {
c355d1f
+        struct wl_surface *wlsurf = moz_container_get_wl_surface(container);
c355d1f
+        if (!wlsurf)
c355d1f
+            return nullptr;
c355d1f
+
c355d1f
+      GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container));
c355d1f
+      container->eglwindow
c355d1f
+            = wl_egl_window_create(wlsurf,
c355d1f
+                                   gdk_window_get_width(window),
c355d1f
+                                   gdk_window_get_height(window));
c355d1f
+    }
c355d1f
+    return container->eglwindow;
c355d1f
+}
c355d1f
+
c355d1f
+gboolean
c355d1f
+moz_container_has_wl_egl_window(MozContainer *container)
c355d1f
+{
c355d1f
+    return container->eglwindow ? true : false;
c355d1f
+}
c355d1f
 #endif
c355d1f
diff --git a/widget/gtk/mozcontainer.h b/widget/gtk/mozcontainer.h
c355d1f
--- a/widget/gtk/mozcontainer.h
c355d1f
+++ b/widget/gtk/mozcontainer.h
c355d1f
@@ -67,16 +67,17 @@ struct _MozContainer
c355d1f
 {
c355d1f
     GtkContainer   container;
c355d1f
     GList         *children;
c355d1f
 
c355d1f
 #ifdef MOZ_WAYLAND
c355d1f
     struct wl_subcompositor *subcompositor;
c355d1f
     struct wl_surface       *surface;
c355d1f
     struct wl_subsurface    *subsurface;
c355d1f
+    struct wl_egl_window    *eglwindow;
c355d1f
 #endif
c355d1f
 };
c355d1f
 
c355d1f
 struct _MozContainerClass
c355d1f
 {
c355d1f
     GtkContainerClass parent_class;
c355d1f
 };
c355d1f
 
c355d1f
@@ -90,11 +91,13 @@ void       moz_container_move          (
c355d1f
                                         GtkWidget    *child_widget,
c355d1f
                                         gint          x,
c355d1f
                                         gint          y,
c355d1f
                                         gint          width,
c355d1f
                                         gint          height);
c355d1f
 
c355d1f
 #ifdef MOZ_WAYLAND
c355d1f
 struct wl_surface* moz_container_get_wl_surface(MozContainer *container);
c355d1f
+struct wl_egl_window* moz_container_get_wl_egl_window(MozContainer *container);
c355d1f
+gboolean moz_container_has_wl_egl_window(MozContainer *container);
c355d1f
 #endif
c355d1f
 
c355d1f
 #endif /* __MOZ_CONTAINER_H__ */
c355d1f
diff --git a/widget/gtk/mozwayland/mozwayland.c b/widget/gtk/mozwayland/mozwayland.c
c355d1f
--- a/widget/gtk/mozwayland/mozwayland.c
c355d1f
+++ b/widget/gtk/mozwayland/mozwayland.c
c355d1f
@@ -266,8 +266,26 @@ wl_display_read_events(struct wl_display
c355d1f
    return -1;
c355d1f
 }
c355d1f
 
c355d1f
 MOZ_EXPORT void
c355d1f
 wl_log_set_handler_client(wl_log_func_t handler)
c355d1f
 {
c355d1f
 }
c355d1f
 
c355d1f
+MOZ_EXPORT struct wl_egl_window *
c355d1f
+wl_egl_window_create(struct wl_surface *surface,
c355d1f
+                     int width, int height)
c355d1f
+{
c355d1f
+    return NULL;
c355d1f
+}
c355d1f
+
c355d1f
+MOZ_EXPORT void
c355d1f
+wl_egl_window_destroy(struct wl_egl_window *egl_window)
c355d1f
+{
c355d1f
+}
c355d1f
+
c355d1f
+MOZ_EXPORT void
c355d1f
+wl_egl_window_resize(struct wl_egl_window *egl_window,
c355d1f
+                     int width, int height,
c355d1f
+                     int dx, int dy)
c355d1f
+{
c355d1f
+}
c355d1f
diff --git a/widget/gtk/nsWindow.cpp b/widget/gtk/nsWindow.cpp
c355d1f
--- a/widget/gtk/nsWindow.cpp
c355d1f
+++ b/widget/gtk/nsWindow.cpp
c355d1f
@@ -1734,16 +1734,25 @@ nsWindow::GetNativeData(uint32_t aDataTy
c355d1f
         return mIMContext.get();
c355d1f
     }
c355d1f
     case NS_NATIVE_OPENGL_CONTEXT:
c355d1f
       return nullptr;
c355d1f
 #ifdef MOZ_X11
c355d1f
     case NS_NATIVE_COMPOSITOR_DISPLAY:
c355d1f
         return gfxPlatformGtk::GetPlatform()->GetCompositorDisplay();
c355d1f
 #endif // MOZ_X11
c355d1f
+    case NS_NATIVE_EGL_WINDOW: {
c355d1f
+        if (mIsX11Display)
c355d1f
+            return mGdkWindow ? (void*)GDK_WINDOW_XID(mGdkWindow) : nullptr;
c355d1f
+#ifdef MOZ_WAYLAND
c355d1f
+        if (mContainer)
c355d1f
+            return moz_container_get_wl_egl_window(mContainer);
c355d1f
+#endif
c355d1f
+        return nullptr;
c355d1f
+    }
c355d1f
     default:
c355d1f
         NS_WARNING("nsWindow::GetNativeData called with bad value");
c355d1f
         return nullptr;
c355d1f
     }
c355d1f
 }
c355d1f
 
c355d1f
 nsresult
c355d1f
 nsWindow::SetTitle(const nsAString& aTitle)
c355d1f
@@ -4303,16 +4312,26 @@ nsWindow::NativeShow(bool aAction)
c355d1f
         else if (mContainer) {
c355d1f
             gtk_widget_show(GTK_WIDGET(mContainer));
c355d1f
         }
c355d1f
         else if (mGdkWindow) {
c355d1f
             gdk_window_show_unraised(mGdkWindow);
c355d1f
         }
c355d1f
     }
c355d1f
     else {
c355d1f
+#ifdef MOZ_WAYLAND
c355d1f
+        if (mContainer && moz_container_has_wl_egl_window(mContainer)) {
c355d1f
+            // Because wl_egl_window is destroyed on moz_container_unmap(),
c355d1f
+            // the current compositor cannot use it anymore. To avoid crash,
c355d1f
+            // destroy the compositor & recreate a new compositor on next
c355d1f
+            // expose event.
c355d1f
+            DestroyLayerManager();
c355d1f
+        }
c355d1f
+#endif
c355d1f
+
c355d1f
         if (mIsTopLevel) {
c355d1f
             // Workaround window freezes on GTK versions before 3.21.2 by
c355d1f
             // ensuring that configure events get dispatched to windows before
c355d1f
             // they are unmapped. See bug 1225044.
c355d1f
             if (gtk_check_version(3, 21, 2) != nullptr && mPendingConfigures > 0) {
c355d1f
                 GtkAllocation allocation;
c355d1f
                 gtk_widget_get_allocation(GTK_WIDGET(mShell), &allocation);
c355d1f
 
c355d1f
diff --git a/widget/nsIWidget.h b/widget/nsIWidget.h
c355d1f
--- a/widget/nsIWidget.h
c355d1f
+++ b/widget/nsIWidget.h
c355d1f
@@ -138,16 +138,17 @@ typedef void* nsNativeWidget;
c355d1f
 #define NS_NATIVE_CHILD_OF_SHAREABLE_WINDOW 105
c355d1f
 #endif
c355d1f
 #if defined(MOZ_WIDGET_GTK)
c355d1f
 // set/get nsPluginNativeWindowGtk, e10s specific
c355d1f
 #define NS_NATIVE_PLUGIN_OBJECT_PTR    104
c355d1f
 #ifdef MOZ_X11
c355d1f
 #define NS_NATIVE_COMPOSITOR_DISPLAY   105
c355d1f
 #endif // MOZ_X11
c355d1f
+#define NS_NATIVE_EGL_WINDOW           106
c355d1f
 #endif
c355d1f
 #ifdef MOZ_WIDGET_ANDROID
c355d1f
 #define NS_JAVA_SURFACE                100
c355d1f
 #define NS_PRESENTATION_WINDOW         101
c355d1f
 #define NS_PRESENTATION_SURFACE        102
c355d1f
 #endif
c355d1f
 
c355d1f
 // Must be kept in sync with xpcom/rust/xpcom/src/interfaces/nonidl.rs
c355d1f