Skip to content

Commit 114cfcb

Browse files
committed
Bug 1998657 [Wayland] Create EGLWindow over offscreen wl_surface and make it always available r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D271773
1 parent c2d08fd commit 114cfcb

File tree

4 files changed

+45
-148
lines changed

4 files changed

+45
-148
lines changed

widget/gtk/MozContainerWayland.cpp

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -262,25 +262,6 @@ static bool moz_container_wayland_ensure_surface(MozContainer* container,
262262
return true;
263263
}
264264

265-
struct wl_egl_window* moz_container_wayland_get_egl_window(
266-
MozContainer* container) {
267-
LOGCONTAINER("%s [%p] mapped %d eglwindow %d", __FUNCTION__,
268-
(void*)moz_container_get_nsWindow(container),
269-
MOZ_WL_SURFACE(container)->IsMapped(),
270-
MOZ_WL_SURFACE(container)->HasEGLWindow());
271-
272-
if (!MOZ_WL_SURFACE(container)->IsMapped()) {
273-
return nullptr;
274-
}
275-
276-
// TODO: Get size from bounds instead of GdkWindow?
277-
// We may be in rendering/compositor thread here.
278-
GdkWindow* window = gtk_widget_get_window(GTK_WIDGET(container));
279-
DesktopIntSize size(gdk_window_get_width(window),
280-
gdk_window_get_height(window));
281-
return MOZ_WL_SURFACE(container)->GetEGLWindow(size);
282-
}
283-
284265
double moz_container_wayland_get_scale(MozContainer* container) {
285266
nsWindow* window = moz_container_get_nsWindow(container);
286267
return window ? window->FractionalScaleFactor() : 1.0;

widget/gtk/MozContainerWayland.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,6 @@ void moz_container_wayland_map(GtkWidget*);
4949
gboolean moz_container_wayland_map_event(GtkWidget*, GdkEventAny*);
5050
void moz_container_wayland_size_allocate(GtkWidget*, GtkAllocation*);
5151
void moz_container_wayland_unmap(GtkWidget*);
52-
53-
struct wl_egl_window* moz_container_wayland_get_egl_window(
54-
MozContainer* container);
55-
5652
wl_surface* moz_gtk_widget_get_wl_surface(GtkWidget* aWidget);
5753
double moz_container_wayland_get_scale(MozContainer* container);
5854

widget/gtk/nsWindow.cpp

Lines changed: 43 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -411,8 +411,7 @@ static void GtkWindowSetTransientFor(GtkWindow* aWindow, GtkWindow* aParent) {
411411
}
412412

413413
nsWindow::nsWindow()
414-
: mWindowVisibilityMutex("nsWindow::mWindowVisibilityMutex"),
415-
mIsMapped(false),
414+
: mIsMapped(false),
416415
mIsDestroyed(false),
417416
mIsShown(false),
418417
mNeedsShow(false),
@@ -737,16 +736,21 @@ void nsWindow::Destroy() {
737736
gtk_accessible_set_widget(GTK_ACCESSIBLE(ac), nullptr);
738737
}
739738

739+
// Owned by WaylandSurface or it's X11 ID,
740+
// just drop the reference here.
741+
mEGLWindow = nullptr;
742+
743+
// mGdkWindow is owned by mContainer, will be deleted with mShell/mContainer.
744+
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", nullptr);
745+
mGdkWindow = nullptr;
746+
740747
gtk_widget_destroy(mShell);
741748
mShell = nullptr;
742749
mContainer = nullptr;
743750
#ifdef MOZ_WAYLAND
744751
mSurface = nullptr;
745752
#endif
746753

747-
MOZ_ASSERT(!mGdkWindow,
748-
"mGdkWindow should be NULL when mContainer is destroyed");
749-
750754
#ifdef ACCESSIBILITY
751755
if (mRootAccessible) {
752756
mRootAccessible = nullptr;
@@ -3758,41 +3762,8 @@ void* nsWindow::GetNativeData(uint32_t aDataType) {
37583762
}
37593763
case NS_NATIVE_OPENGL_CONTEXT:
37603764
return nullptr;
3761-
case NS_NATIVE_EGL_WINDOW: {
3762-
// On X11 we call it:
3763-
// 1) If window is mapped on OnMap() by nsWindow::ResumeCompositorImpl(),
3764-
// new EGLSurface/XWindow is created.
3765-
// 2) If window is hidden on OnUnmap(), we replace EGLSurface/XWindow
3766-
// by offline surface and release XWindow.
3767-
3768-
// On Wayland it:
3769-
// 1) If window is mapped on OnMap(), we request frame callback
3770-
// at MozContainer. If we get frame callback at MozContainer,
3771-
// nsWindow::ResumeCompositorImpl() is called from it
3772-
// and EGLSurface/wl_surface is created.
3773-
// 2) If window is hidden on OnUnmap(), we replace EGLSurface/wl_surface
3774-
// by offline surface and release XWindow.
3775-
3776-
// If nsWindow is already destroyed, don't try to get EGL window at all,
3777-
// we're going to be deleted anyway.
3778-
MutexAutoLock lock(mWindowVisibilityMutex);
3779-
void* eglWindow = nullptr;
3780-
if (mIsMapped && !mIsDestroyed) {
3781-
#ifdef MOZ_X11
3782-
if (GdkIsX11Display()) {
3783-
eglWindow = (void*)GDK_WINDOW_XID(mGdkWindow);
3784-
}
3785-
#endif
3786-
#ifdef MOZ_WAYLAND
3787-
if (GdkIsWaylandDisplay()) {
3788-
eglWindow = moz_container_wayland_get_egl_window(mContainer);
3789-
}
3790-
#endif
3791-
}
3792-
LOG("Get NS_NATIVE_EGL_WINDOW mGdkWindow %p returned eglWindow %p",
3793-
mGdkWindow, eglWindow);
3794-
return eglWindow;
3795-
}
3765+
case NS_NATIVE_EGL_WINDOW:
3766+
return mIsDestroyed ? nullptr : mEGLWindow;
37963767
default:
37973768
NS_WARNING("nsWindow::GetNativeData called with bad value");
37983769
return nullptr;
@@ -4121,8 +4092,8 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
41214092
}
41224093

41234094
// Windows that are not visible will be painted after they become visible.
4124-
if (!mGdkWindow || !mHasMappedToplevel) {
4125-
LOG("quit, !mGdkWindow || !mHasMappedToplevel");
4095+
if (!mHasMappedToplevel) {
4096+
LOG("quit, !mHasMappedToplevel");
41264097
return FALSE;
41274098
}
41284099

@@ -4156,8 +4127,8 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
41564127

41574128
// If the window has been destroyed during the will paint notification,
41584129
// there is nothing left to do.
4159-
if (!mGdkWindow || mIsDestroyed) {
4160-
LOG("quit, !mGdkWindow || mIsDestroyed");
4130+
if (mIsDestroyed) {
4131+
LOG("quit, mIsDestroyed");
41614132
return TRUE;
41624133
}
41634134

@@ -4310,7 +4281,7 @@ gboolean nsWindow::OnShellConfigureEvent(GdkEventConfigure* aEvent) {
43104281

43114282
// Don't fire configure event for scale changes, we handle that
43124283
// OnScaleEvent event. Skip that for toplevel windows only.
4313-
if (mGdkWindow && IsTopLevelWidget() &&
4284+
if (IsTopLevelWidget() &&
43144285
mCeiledScaleFactor != gdk_window_get_scale_factor(mGdkWindow)) {
43154286
LOG(" scale factor changed to %d, return early",
43164287
gdk_window_get_scale_factor(mGdkWindow));
@@ -4336,10 +4307,6 @@ void nsWindow::OnContainerSizeAllocate(GtkAllocation* aAllocation) {
43364307
mReceivedClientArea = DesktopIntRect(aAllocation->x, aAllocation->y,
43374308
aAllocation->width, aAllocation->height);
43384309

4339-
if (!mGdkWindow) {
4340-
return;
4341-
}
4342-
43434310
// Bounds will get updated on the main configure.
43444311
// Gecko permits running nested event loops during processing of events,
43454312
// GtkWindow callers of gtk_widget_size_allocate expect the signal handlers
@@ -4610,10 +4577,6 @@ void nsWindow::EmulateResizeDrag(GdkEventMotion* aEvent) {
46104577
void nsWindow::OnMotionNotifyEvent(GdkEventMotion* aEvent) {
46114578
mLastMouseCoordinates.Set(aEvent);
46124579

4613-
if (!mGdkWindow) {
4614-
return;
4615-
}
4616-
46174580
// Emulate gdk_window_begin_resize_drag() for windows
46184581
// with fixed aspect ratio on Wayland.
46194582
if (mAspectResizer && mAspectRatio != 0.0f) {
@@ -4630,10 +4593,8 @@ void nsWindow::OnMotionNotifyEvent(GdkEventMotion* aEvent) {
46304593
GdkWindow* dragWindow = nullptr;
46314594

46324595
// find the top-level window
4633-
if (mGdkWindow) {
4634-
dragWindow = gdk_window_get_toplevel(mGdkWindow);
4635-
MOZ_ASSERT(dragWindow, "gdk_window_get_toplevel should not return null");
4636-
}
4596+
dragWindow = gdk_window_get_toplevel(mGdkWindow);
4597+
MOZ_ASSERT(dragWindow, "gdk_window_get_toplevel should not return null");
46374598

46384599
#ifdef MOZ_X11
46394600
if (dragWindow && GdkIsX11Display()) {
@@ -5068,10 +5029,6 @@ void nsWindow::OnButtonReleaseEvent(GdkEventButton* aEvent) {
50685029
SetLastPointerDownEvent(nullptr);
50695030
mLastMouseCoordinates.Set(aEvent);
50705031

5071-
if (!mGdkWindow) {
5072-
return;
5073-
}
5074-
50755032
if (mAspectResizer) {
50765033
mAspectResizer = Nothing();
50775034
return;
@@ -5251,7 +5208,7 @@ WidgetEventTime nsWindow::GetWidgetEventTime(guint32 aEventTime) {
52515208
}
52525209

52535210
TimeStamp nsWindow::GetEventTimeStamp(guint32 aEventTime) {
5254-
if (MOZ_UNLIKELY(!mGdkWindow)) {
5211+
if (MOZ_UNLIKELY(mIsDestroyed)) {
52555212
// nsWindow has been Destroy()ed.
52565213
return TimeStamp::Now();
52575214
}
@@ -5287,7 +5244,6 @@ TimeStamp nsWindow::GetEventTimeStamp(guint32 aEventTime) {
52875244

52885245
#ifdef MOZ_X11
52895246
mozilla::CurrentX11TimeGetter* nsWindow::GetCurrentTimeGetter() {
5290-
MOZ_ASSERT(mGdkWindow, "Expected mGdkWindow to be set");
52915247
if (MOZ_UNLIKELY(!mCurrentTimeGetter)) {
52925248
mCurrentTimeGetter = MakeUnique<CurrentX11TimeGetter>(mGdkWindow);
52935249
}
@@ -5741,7 +5697,7 @@ void nsWindow::OnCompositedChanged() {
57415697
// Let's follow the working scenario for now to avoid complexity
57425698
// and maybe fix that later.
57435699
void nsWindow::OnScaleEvent() {
5744-
if (!mGdkWindow || !IsTopLevelWidget()) {
5700+
if (!IsTopLevelWidget()) {
57455701
return;
57465702
}
57475703

@@ -5759,7 +5715,6 @@ void nsWindow::RefreshScale(bool aRefreshScreen, bool aForceRefresh) {
57595715
LOG("nsWindow::RefreshScale() GdkWindow scale %d refresh %d",
57605716
gdk_window_get_scale_factor(mGdkWindow), aRefreshScreen);
57615717

5762-
MOZ_DIAGNOSTIC_ASSERT(mIsMapped && mGdkWindow);
57635718
int ceiledScale = gdk_window_get_scale_factor(mGdkWindow);
57645719
const bool scaleChanged =
57655720
aForceRefresh || GdkCeiledScaleFactor() != ceiledScale;
@@ -5804,7 +5759,7 @@ void nsWindow::SetDragPopupSurface(
58045759

58055760
mDragPopupSurface = aDragPopupSurface;
58065761
mDragPopupSurfaceRegion = aInvalidRegion;
5807-
if (mGdkWindow) {
5762+
if (!mIsDestroyed) {
58085763
gdk_window_invalidate_rect(mGdkWindow, nullptr, false);
58095764
}
58105765
}
@@ -6215,28 +6170,17 @@ nsCString nsWindow::GetPopupTypeName() {
62156170
Window nsWindow::GetX11Window() {
62166171
#ifdef MOZ_X11
62176172
if (GdkIsX11Display()) {
6218-
return mGdkWindow ? gdk_x11_window_get_xid(mGdkWindow) : X11None;
6173+
return gdk_x11_window_get_xid(mGdkWindow);
62196174
}
62206175
#endif
62216176
return (Window) nullptr;
62226177
}
62236178

6224-
void nsWindow::EnsureGdkWindow() {
6225-
MOZ_DIAGNOSTIC_ASSERT(mIsMapped);
6226-
if (!mGdkWindow) {
6227-
mGdkWindow = gtk_widget_get_window(GTK_WIDGET(mContainer));
6228-
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", this);
6229-
}
6230-
}
6231-
62326179
void nsWindow::ConfigureCompositor() {
6233-
MOZ_DIAGNOSTIC_ASSERT(mIsMapped);
6234-
62356180
LOG("nsWindow::ConfigureCompositor()");
62366181

6237-
if (mIsDestroyed || !mIsMapped) {
6238-
LOG(" quit, mIsDestroyed = %d mIsMapped = %d", !!mIsDestroyed,
6239-
!!mIsMapped);
6182+
if (mIsDestroyed) {
6183+
LOG(" quit, mIsDestroyed = %d", !!mIsDestroyed);
62406184
return;
62416185
}
62426186
// Compositor will be resumed at nsWindow::SetCompositorWidgetDelegate().
@@ -6499,6 +6443,24 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect,
64996443

65006444
gtk_widget_realize(container);
65016445

6446+
mGdkWindow = gtk_widget_get_window(GTK_WIDGET(mContainer));
6447+
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", this);
6448+
6449+
#ifdef MOZ_X11
6450+
if (GdkIsX11Display()) {
6451+
mEGLWindow = (void*)GDK_WINDOW_XID(mGdkWindow);
6452+
}
6453+
#endif
6454+
#ifdef MOZ_WAYLAND
6455+
if (GdkIsWaylandDisplay() && mIsAccelerated) {
6456+
mEGLWindow = MOZ_WL_SURFACE(container)->GetEGLWindow(mClientArea.Size());
6457+
}
6458+
#endif
6459+
if (mEGLWindow) {
6460+
LOG("Get NS_NATIVE_EGL_WINDOW mGdkWindow %p returned mEGLWindow %p",
6461+
mGdkWindow, mEGLWindow);
6462+
}
6463+
65026464
// make sure this is the focus widget in the container
65036465
gtk_widget_show(container);
65046466

@@ -9933,7 +9895,7 @@ bool nsWindow::SetEGLNativeWindowSize(
99339895
// SetEGLNativeWindowSize() is Wayland only call.
99349896
MOZ_ASSERT(GdkIsWaylandDisplay());
99359897

9936-
if (!mIsMapped) {
9898+
if (mIsDestroyed) {
99379899
return true;
99389900
}
99399901

@@ -9970,10 +9932,8 @@ void nsWindow::OnMap() {
99709932
MaybeCreatePipResources();
99719933

99729934
{
9973-
MutexAutoLock lock(mWindowVisibilityMutex);
99749935
mIsMapped = true;
99759936

9976-
EnsureGdkWindow();
99779937
RefreshScale(/* aRefreshScreen */ false);
99789938

99799939
if (mIsAlert) {
@@ -10025,7 +9985,6 @@ void nsWindow::OnUnmap() {
100259985
ClearPipResources();
100269986

100279987
{
10028-
MutexAutoLock lock(mWindowVisibilityMutex);
100299988
mIsMapped = false;
100309989
mHasReceivedSizeAllocate = false;
100319990

@@ -10039,23 +9998,8 @@ void nsWindow::OnUnmap() {
100399998
}
100409999
}
1004110000

10042-
if (mGdkWindow) {
10043-
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", nullptr);
10044-
mGdkWindow = nullptr;
10045-
}
10046-
1004710001
// Reset scale for hidden windows
1004810002
mCeiledScaleFactor = sNoScale;
10049-
10050-
// Clear resources (mainly XWindow) stored at GtkCompositorWidget.
10051-
// It makes sure we don't paint to it when nsWindow becomes hiden/deleted
10052-
// and XWindow is released.
10053-
if (mCompositorWidgetDelegate) {
10054-
mCompositorWidgetDelegate->CleanupResources();
10055-
}
10056-
10057-
// Clear nsWindow resources used for old (in-thread) rendering.
10058-
mSurfaceProvider.CleanupResources();
1005910003
}
1006010004

1006110005
// Until bug 1654938 is fixed we delete layer manager for hidden popups,
@@ -10066,28 +10010,6 @@ void nsWindow::OnUnmap() {
1006610010
// see bug 1958695.
1006710011
if (mWindowType == WindowType::Popup && !mPopupTemporaryHidden) {
1006810012
DestroyLayerManager();
10069-
} else {
10070-
// Widget is backed by OpenGL EGLSurface created over wl_surface/XWindow.
10071-
//
10072-
// RenderCompositorEGL::Resume() deletes recent EGLSurface,
10073-
// calls nsWindow::GetNativeData(NS_NATIVE_EGL_WINDOW) from compositor
10074-
// thread to get new native rendering surface.
10075-
//
10076-
// For hidden/unmapped windows we return nullptr NS_NATIVE_EGL_WINDOW at
10077-
// nsWindow::GetNativeData() so RenderCompositorEGL::Resume() creates
10078-
// offscreen fallback EGLSurface to avoid compositor pause.
10079-
//
10080-
// We don't want to pause compositor as it may lead to whole
10081-
// browser freeze (Bug 1777664).
10082-
//
10083-
// If RenderCompositorSWGL compositor is used (SW fallback)
10084-
// RenderCompositorSWGL::Resume() only requests full render for next paint
10085-
// as wl_surface/XWindow is managed by WindowSurfaceProvider owned
10086-
// directly by GtkCompositorWidget and that's covered by
10087-
// mCompositorWidgetDelegate->CleanupResources() call above.
10088-
if (CompositorBridgeChild* remoteRenderer = GetRemoteRenderer()) {
10089-
remoteRenderer->SendResume();
10090-
}
1009110013
}
1009210014
}
1009310015

0 commit comments

Comments
 (0)