Bug 1668805: Enable opaque region if new GDK API is availabe, r=stransky

From GTK 3.24.25 on we have a new API that allows us to savely apply
opaque regions to our own surfaces without risking to freeze GDK.

Differential Revision: https://phabricator.services.mozilla.com/D102835
This commit is contained in:
Robert Mader 2021-02-16 09:04:47 +00:00
Родитель da690f85ed
Коммит daafa866da
6 изменённых файлов: 85 добавлений и 18 удалений

Просмотреть файл

@ -10561,6 +10561,12 @@
type: RelaxedAtomicBool
value: true
mirror: always
# Use opaque region for MozContainer wl_surface
- name: widget.wayland.opaque-region.enabled
type: RelaxedAtomicBool
value: true
mirror: always
#endif
# Enable the RemoteLookAndFeel in content processes, which will cause all

Просмотреть файл

@ -3785,7 +3785,6 @@ pref("network.psl.onUpdate_notify", false);
#endif
#ifdef MOZ_WAYLAND
pref("widget.wayland_vsync.enabled", true);
pref("widget.wayland.use-opaque-region", false);
pref("widget.use-xdg-desktop-portal", false);
#endif

Просмотреть файл

@ -50,14 +50,14 @@
#include "MozContainer.h"
#include <glib.h>
#include <gtk/gtk.h>
#include <gdk/gdkx.h>
#include "nsWaylandDisplay.h"
#include "gfxPlatformGtk.h"
#include <wayland-egl.h>
#include <stdio.h>
#include <dlfcn.h>
#include <glib.h>
#include <stdio.h>
#include <wayland-egl.h>
#include "gfxPlatformGtk.h"
#include "nsGtkUtils.h"
#include "nsWaylandDisplay.h"
#undef LOG
#ifdef MOZ_LOGGING
@ -167,8 +167,9 @@ void moz_container_wayland_init(MozContainerWayland* container) {
container->eglwindow = nullptr;
container->frame_callback_handler = nullptr;
container->ready_to_draw = false;
container->opaque_region_updates = false;
container->opaque_region_needs_updates = false;
container->opaque_region_subtract_corners = false;
container->opaque_region_used = false;
container->surface_needs_clear = true;
container->subsurface_dx = 0;
container->subsurface_dy = 0;
@ -213,10 +214,65 @@ static void moz_container_wayland_frame_callback_handler(
static const struct wl_callback_listener moz_container_frame_listener = {
moz_container_wayland_frame_callback_handler};
static void after_frame_clock_after_paint(GdkFrameClock* clock,
MozContainer* container) {
struct wl_surface* surface = moz_container_wayland_surface_lock(container);
if (surface) {
wl_surface_commit(surface);
moz_container_wayland_surface_unlock(container, &surface);
}
}
static bool moz_gdk_wayland_window_add_frame_callback_surface_locked(
MozContainer* container) {
static auto sGdkWaylandWindowAddCallbackSurface =
(void (*)(GdkWindow*, struct wl_surface*))dlsym(
RTLD_DEFAULT, "gdk_wayland_window_add_frame_callback_surface");
if (!StaticPrefs::widget_wayland_opaque_region_enabled() ||
!sGdkWaylandWindowAddCallbackSurface) {
return false;
}
GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
MozContainerWayland* wl_container = &container->wl_container;
sGdkWaylandWindowAddCallbackSurface(window, wl_container->surface);
GdkFrameClock* frame_clock = gdk_window_get_frame_clock(window);
g_signal_connect_after(frame_clock, "after-paint",
G_CALLBACK(after_frame_clock_after_paint), container);
return true;
}
static void moz_gdk_wayland_window_remove_frame_callback_surface_locked(
MozContainer* container) {
static auto sGdkWaylandWindowRemoveCallbackSurface =
(void (*)(GdkWindow*, struct wl_surface*))dlsym(
RTLD_DEFAULT, "gdk_wayland_window_remove_frame_callback_surface");
if (!sGdkWaylandWindowRemoveCallbackSurface) {
return;
}
GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
MozContainerWayland* wl_container = &container->wl_container;
sGdkWaylandWindowRemoveCallbackSurface(window, wl_container->surface);
GdkFrameClock* frame_clock = gdk_window_get_frame_clock(window);
g_signal_handlers_disconnect_by_func(
frame_clock, FuncToGpointer(after_frame_clock_after_paint), container);
}
static void moz_container_wayland_unmap_internal(MozContainer* container) {
MozContainerWayland* wl_container = &container->wl_container;
MutexAutoLock lock(*wl_container->container_lock);
if (wl_container->opaque_region_used) {
moz_gdk_wayland_window_remove_frame_callback_surface_locked(container);
}
g_clear_pointer(&wl_container->eglwindow, wl_egl_window_destroy);
g_clear_pointer(&wl_container->subsurface, wl_subsurface_destroy);
g_clear_pointer(&wl_container->surface, wl_surface_destroy);
@ -336,7 +392,12 @@ static void moz_container_wayland_set_opaque_region_locked(
MozContainer* container) {
MozContainerWayland* wl_container = &container->wl_container;
if (!wl_container->opaque_region_updates) {
if (!wl_container->opaque_region_needs_updates) {
return;
}
if (!wl_container->opaque_region_used) {
wl_container->opaque_region_needs_updates = false;
return;
}
@ -348,6 +409,7 @@ static void moz_container_wayland_set_opaque_region_locked(
wl_container->opaque_region_subtract_corners);
wl_surface_set_opaque_region(wl_container->surface, region);
wl_region_destroy(region);
wl_container->opaque_region_needs_updates = false;
}
static void moz_container_wayland_set_opaque_region(MozContainer* container) {
@ -437,6 +499,9 @@ static bool moz_container_wayland_surface_create_locked(
wl_surface_commit(wl_container->surface);
wl_display_flush(WaylandDisplayGet()->GetDisplay());
wl_container->opaque_region_used =
moz_gdk_wayland_window_add_frame_callback_surface_locked(container);
LOGWAYLAND((" created surface %p ID %d\n", (void*)wl_container->surface,
wl_proxy_get_id((struct wl_proxy*)wl_container->surface)));
return true;
@ -504,7 +569,7 @@ gboolean moz_container_wayland_surface_needs_clear(MozContainer* container) {
void moz_container_wayland_update_opaque_region(MozContainer* container,
bool aSubtractCorners) {
MozContainerWayland* wl_container = &container->wl_container;
wl_container->opaque_region_updates = true;
wl_container->opaque_region_needs_updates = true;
wl_container->opaque_region_subtract_corners = aSubtractCorners;
// When GL compositor / WebRender is used,

Просмотреть файл

@ -37,9 +37,9 @@ struct MozContainerWayland {
int subsurface_dx, subsurface_dy;
struct wl_egl_window* eglwindow;
struct wl_callback* frame_callback_handler;
gboolean opaque_region_updates;
gboolean opaque_region_needs_updates;
gboolean opaque_region_subtract_corners;
gboolean opaque_region_fullscreen;
gboolean opaque_region_used;
gboolean surface_needs_clear;
gboolean ready_to_draw;
gboolean before_first_size_alloc;

Просмотреть файл

@ -550,6 +550,7 @@ STUB(gdk_display_manager_open_display)
STUB(gdk_error_trap_pop_ignored)
STUB(gdk_event_get_source_device)
STUB(gdk_screen_get_monitor_workarea)
STUB(gdk_window_get_frame_clock)
STUB(gdk_window_get_type)
STUB(gdk_window_set_opaque_region)
STUB(gdk_x11_window_get_xid)

Просмотреть файл

@ -379,7 +379,6 @@ static bool gBlockActivateEvent = false;
static bool gGlobalsInitialized = false;
static bool gRaiseWindows = true;
static bool gUseWaylandVsync = true;
static bool gUseWaylandUseOpaqueRegion = true;
static bool gUseAspectRatio = true;
static GList* gVisibleWaylandPopupWindows = nullptr;
static uint32_t gLastTouchID = 0;
@ -5662,8 +5661,7 @@ void nsWindow::UpdateTopLevelOpaqueRegion(void) {
cairo_region_destroy(region);
#ifdef MOZ_WAYLAND
// We don't set opaque region to mozContainer by default due to Bug 1615098.
if (!mIsX11Display && gUseWaylandUseOpaqueRegion) {
if (!mIsX11Display) {
moz_container_wayland_update_opaque_region(mContainer, subtractCorners);
}
#endif
@ -7345,8 +7343,6 @@ static nsresult initialize_prefs(void) {
Preferences::GetBool("mozilla.widget.raise-on-setfocus", true);
gUseWaylandVsync =
Preferences::GetBool("widget.wayland_vsync.enabled", false);
gUseWaylandUseOpaqueRegion =
Preferences::GetBool("widget.wayland.use-opaque-region", false);
if (Preferences::HasUserValue("widget.use-aspect-ratio")) {
gUseAspectRatio = Preferences::GetBool("widget.use-aspect-ratio", true);