зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1489902 - [Wayland/OpenGL] Don't draw to wl_surface owned by GtkWidget (mozcontainer) until it's commited, r=jhorak
Use frame callback to determine if we can draw to wl_surface owned by GtkWidget and use it as a base for EGL Window. Differential Revision: https://phabricator.services.mozilla.com/D13722 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
3c70e0c917
Коммит
45555dc042
|
@ -147,55 +147,48 @@ void moz_container_init(MozContainer *container) {
|
|||
container->surface = nullptr;
|
||||
container->subsurface = nullptr;
|
||||
container->eglwindow = nullptr;
|
||||
container->frame_callback_handler = nullptr;
|
||||
container->ready_to_draw = false;
|
||||
container->surface_needs_clear = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(MOZ_WAYLAND)
|
||||
static void moz_on_frame_clock_after_paint(GdkFrameClock *clock,
|
||||
MozContainer *container) {
|
||||
container->ready_to_draw = true;
|
||||
g_signal_handler_disconnect(clock,
|
||||
container->frame_clock_after_paint_handler);
|
||||
container->frame_clock_after_paint_handler = 0;
|
||||
}
|
||||
|
||||
static void moz_container_map_wayland(MozContainer *container) {
|
||||
MOZ_ASSERT(!container->ready_to_draw, "MozContainer is already mapped.");
|
||||
MOZ_ASSERT(!container->frame_clock_after_paint_handler,
|
||||
"Repeated gdk_window_get_frame_clock() request?");
|
||||
|
||||
GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container));
|
||||
if (GDK_IS_X11_DISPLAY(display)) return;
|
||||
|
||||
container->surface_needs_clear = true;
|
||||
|
||||
static auto sGdkWindowGetFrameClock = (GdkFrameClock * (*)(GdkWindow *))
|
||||
dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock");
|
||||
static wl_surface *moz_container_get_gtk_container_surface(
|
||||
MozContainer *container) {
|
||||
static auto sGdkWaylandWindowGetWlSurface = (wl_surface * (*)(GdkWindow *))
|
||||
dlsym(RTLD_DEFAULT, "gdk_wayland_window_get_wl_surface");
|
||||
|
||||
GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container));
|
||||
GdkFrameClock *clock = sGdkWindowGetFrameClock(window);
|
||||
container->frame_clock_after_paint_handler = g_signal_connect_after(
|
||||
clock, "after-paint", G_CALLBACK(moz_on_frame_clock_after_paint),
|
||||
container);
|
||||
return sGdkWaylandWindowGetWlSurface(window);
|
||||
}
|
||||
|
||||
static void frame_callback_handler(void *data, struct wl_callback *callback,
|
||||
uint32_t time) {
|
||||
MozContainer *container = MOZ_CONTAINER(data);
|
||||
g_clear_pointer(&container->frame_callback_handler, wl_callback_destroy);
|
||||
container->ready_to_draw = true;
|
||||
}
|
||||
|
||||
static const struct wl_callback_listener frame_listener = {
|
||||
frame_callback_handler};
|
||||
|
||||
static void moz_container_map_wayland(MozContainer *container) {
|
||||
container->surface_needs_clear = true;
|
||||
container->ready_to_draw = false;
|
||||
|
||||
static wl_surface *gtk_container_surface =
|
||||
moz_container_get_gtk_container_surface(container);
|
||||
container->frame_callback_handler = wl_surface_frame(gtk_container_surface);
|
||||
wl_callback_add_listener(container->frame_callback_handler, &frame_listener,
|
||||
container);
|
||||
}
|
||||
|
||||
static void moz_container_unmap_wayland(MozContainer *container) {
|
||||
g_clear_pointer(&container->eglwindow, wl_egl_window_destroy);
|
||||
g_clear_pointer(&container->subsurface, wl_subsurface_destroy);
|
||||
g_clear_pointer(&container->surface, wl_surface_destroy);
|
||||
|
||||
if (container->frame_clock_after_paint_handler) {
|
||||
static auto sGdkWindowGetFrameClock = (GdkFrameClock * (*)(GdkWindow *))
|
||||
dlsym(RTLD_DEFAULT, "gdk_window_get_frame_clock");
|
||||
GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container));
|
||||
GdkFrameClock *clock = sGdkWindowGetFrameClock(window);
|
||||
|
||||
g_signal_handler_disconnect(clock,
|
||||
container->frame_clock_after_paint_handler);
|
||||
container->frame_clock_after_paint_handler = 0;
|
||||
}
|
||||
g_clear_pointer(&container->frame_callback_handler, wl_callback_destroy);
|
||||
container->ready_to_draw = false;
|
||||
}
|
||||
#endif
|
||||
|
@ -223,7 +216,9 @@ void moz_container_map(GtkWidget *widget) {
|
|||
if (gtk_widget_get_has_window(widget)) {
|
||||
gdk_window_show(gtk_widget_get_window(widget));
|
||||
#if defined(MOZ_WAYLAND)
|
||||
moz_container_map_wayland(MOZ_CONTAINER(widget));
|
||||
if (!GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
|
||||
moz_container_map_wayland(MOZ_CONTAINER(widget));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -236,7 +231,9 @@ void moz_container_unmap(GtkWidget *widget) {
|
|||
if (gtk_widget_get_has_window(widget)) {
|
||||
gdk_window_hide(gtk_widget_get_window(widget));
|
||||
#if defined(MOZ_WAYLAND)
|
||||
moz_container_unmap_wayland(MOZ_CONTAINER(widget));
|
||||
if (!GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
|
||||
moz_container_unmap_wayland(MOZ_CONTAINER(widget));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -429,34 +426,27 @@ static void moz_container_add(GtkContainer *container, GtkWidget *widget) {
|
|||
|
||||
#ifdef MOZ_WAYLAND
|
||||
struct wl_surface *moz_container_get_wl_surface(MozContainer *container) {
|
||||
// We're not mapped yet.
|
||||
if (!container->ready_to_draw) return nullptr;
|
||||
|
||||
if (!container->surface) {
|
||||
if (!container->ready_to_draw) {
|
||||
return nullptr;
|
||||
}
|
||||
GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container));
|
||||
|
||||
// Available as of GTK 3.8+
|
||||
static auto sGdkWaylandDisplayGetWlCompositor =
|
||||
(wl_compositor * (*)(GdkDisplay *))
|
||||
dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_compositor");
|
||||
static auto sGdkWaylandWindowGetWlSurface = (wl_surface * (*)(GdkWindow *))
|
||||
dlsym(RTLD_DEFAULT, "gdk_wayland_window_get_wl_surface");
|
||||
static auto sGdkWindowGetScaleFactorPtr = (gint(*)(GdkWindow *))dlsym(
|
||||
RTLD_DEFAULT, "gdk_window_get_scale_factor");
|
||||
|
||||
GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container));
|
||||
GdkDisplay *display = gtk_widget_get_display(GTK_WIDGET(container));
|
||||
|
||||
struct wl_compositor *compositor =
|
||||
sGdkWaylandDisplayGetWlCompositor(display);
|
||||
container->surface = wl_compositor_create_surface(compositor);
|
||||
|
||||
wl_surface *parent_surface = sGdkWaylandWindowGetWlSurface(window);
|
||||
|
||||
nsWaylandDisplay *waylandDisplay = WaylandDisplayGet(display);
|
||||
wl_subcompositor *subcompositor = waylandDisplay->GetSubcompositor();
|
||||
container->subsurface = wl_subcompositor_get_subsurface(
|
||||
subcompositor, container->surface, parent_surface);
|
||||
waylandDisplay->GetSubcompositor(), container->surface,
|
||||
moz_container_get_gtk_container_surface(container));
|
||||
WaylandDisplayRelease(waylandDisplay);
|
||||
|
||||
GdkWindow *window = gtk_widget_get_window(GTK_WIDGET(container));
|
||||
gint x, y;
|
||||
gdk_window_get_position(window, &x, &y);
|
||||
wl_subsurface_set_position(container->subsurface, x, y);
|
||||
|
@ -468,8 +458,8 @@ struct wl_surface *moz_container_get_wl_surface(MozContainer *container) {
|
|||
wl_surface_set_input_region(container->surface, region);
|
||||
wl_region_destroy(region);
|
||||
|
||||
container->surface_needs_clear = true;
|
||||
|
||||
static auto sGdkWindowGetScaleFactorPtr = (gint(*)(GdkWindow *))dlsym(
|
||||
RTLD_DEFAULT, "gdk_window_get_scale_factor");
|
||||
if (sGdkWindowGetScaleFactorPtr) {
|
||||
gint scaleFactor = (*sGdkWindowGetScaleFactorPtr)(window);
|
||||
wl_surface_set_buffer_scale(container->surface, scaleFactor);
|
||||
|
|
|
@ -75,9 +75,9 @@ struct _MozContainer {
|
|||
struct wl_surface *surface;
|
||||
struct wl_subsurface *subsurface;
|
||||
struct wl_egl_window *eglwindow;
|
||||
struct wl_callback *frame_callback_handler;
|
||||
gboolean surface_needs_clear;
|
||||
gboolean ready_to_draw;
|
||||
gulong frame_clock_after_paint_handler;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
@ -93,6 +93,7 @@ void moz_container_put(MozContainer *container, GtkWidget *child_widget, gint x,
|
|||
#ifdef MOZ_WAYLAND
|
||||
struct wl_surface *moz_container_get_wl_surface(MozContainer *container);
|
||||
struct wl_egl_window *moz_container_get_wl_egl_window(MozContainer *container);
|
||||
|
||||
gboolean moz_container_has_wl_egl_window(MozContainer *container);
|
||||
gboolean moz_container_surface_needs_clear(MozContainer *container);
|
||||
#endif
|
||||
|
|
|
@ -1870,13 +1870,6 @@ gboolean nsWindow::OnExposeEvent(cairo_t *cr) {
|
|||
// Windows that are not visible will be painted after they become visible.
|
||||
if (!mGdkWindow || mIsFullyObscured || !mHasMappedToplevel) return FALSE;
|
||||
|
||||
#ifdef MOZ_WAYLAND
|
||||
// Window does not have visible MozContainer/wl_surface yet.
|
||||
if (!mIsX11Display && (!mContainer || !mContainer->ready_to_draw)) {
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
nsIWidgetListener *listener = GetListener();
|
||||
if (!listener) return FALSE;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче