Skip to content

Commit de6ac36

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 b39b0ef commit de6ac36

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),
@@ -735,16 +734,21 @@ void nsWindow::Destroy() {
735734
gtk_accessible_set_widget(GTK_ACCESSIBLE(ac), nullptr);
736735
}
737736

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

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

41214092
// Windows that are not visible will be painted after they become visible.
4122-
if (!mGdkWindow || !mHasMappedToplevel) {
4123-
LOG("quit, !mGdkWindow || !mHasMappedToplevel");
4093+
if (!mHasMappedToplevel) {
4094+
LOG("quit, !mHasMappedToplevel");
41244095
return FALSE;
41254096
}
41264097

@@ -4154,8 +4125,8 @@ gboolean nsWindow::OnExposeEvent(cairo_t* cr) {
41544125

41554126
// If the window has been destroyed during the will paint notification,
41564127
// there is nothing left to do.
4157-
if (!mGdkWindow || mIsDestroyed) {
4158-
LOG("quit, !mGdkWindow || mIsDestroyed");
4128+
if (mIsDestroyed) {
4129+
LOG("quit, mIsDestroyed");
41594130
return TRUE;
41604131
}
41614132

@@ -4308,7 +4279,7 @@ gboolean nsWindow::OnShellConfigureEvent(GdkEventConfigure* aEvent) {
43084279

43094280
// Don't fire configure event for scale changes, we handle that
43104281
// OnScaleEvent event. Skip that for toplevel windows only.
4311-
if (mGdkWindow && IsTopLevelWidget() &&
4282+
if (IsTopLevelWidget() &&
43124283
mCeiledScaleFactor != gdk_window_get_scale_factor(mGdkWindow)) {
43134284
LOG(" scale factor changed to %d, return early",
43144285
gdk_window_get_scale_factor(mGdkWindow));
@@ -4334,10 +4305,6 @@ void nsWindow::OnContainerSizeAllocate(GtkAllocation* aAllocation) {
43344305
mReceivedClientArea = DesktopIntRect(aAllocation->x, aAllocation->y,
43354306
aAllocation->width, aAllocation->height);
43364307

4337-
if (!mGdkWindow) {
4338-
return;
4339-
}
4340-
43414308
// Bounds will get updated on the main configure.
43424309
// Gecko permits running nested event loops during processing of events,
43434310
// GtkWindow callers of gtk_widget_size_allocate expect the signal handlers
@@ -4608,10 +4575,6 @@ void nsWindow::EmulateResizeDrag(GdkEventMotion* aEvent) {
46084575
void nsWindow::OnMotionNotifyEvent(GdkEventMotion* aEvent) {
46094576
mLastMouseCoordinates.Set(aEvent);
46104577

4611-
if (!mGdkWindow) {
4612-
return;
4613-
}
4614-
46154578
// Emulate gdk_window_begin_resize_drag() for windows
46164579
// with fixed aspect ratio on Wayland.
46174580
if (mAspectResizer && mAspectRatio != 0.0f) {
@@ -4628,10 +4591,8 @@ void nsWindow::OnMotionNotifyEvent(GdkEventMotion* aEvent) {
46284591
GdkWindow* dragWindow = nullptr;
46294592

46304593
// find the top-level window
4631-
if (mGdkWindow) {
4632-
dragWindow = gdk_window_get_toplevel(mGdkWindow);
4633-
MOZ_ASSERT(dragWindow, "gdk_window_get_toplevel should not return null");
4634-
}
4594+
dragWindow = gdk_window_get_toplevel(mGdkWindow);
4595+
MOZ_ASSERT(dragWindow, "gdk_window_get_toplevel should not return null");
46354596

46364597
#ifdef MOZ_X11
46374598
if (dragWindow && GdkIsX11Display()) {
@@ -5066,10 +5027,6 @@ void nsWindow::OnButtonReleaseEvent(GdkEventButton* aEvent) {
50665027
SetLastPointerDownEvent(nullptr);
50675028
mLastMouseCoordinates.Set(aEvent);
50685029

5069-
if (!mGdkWindow) {
5070-
return;
5071-
}
5072-
50735030
if (mAspectResizer) {
50745031
mAspectResizer = Nothing();
50755032
return;
@@ -5249,7 +5206,7 @@ WidgetEventTime nsWindow::GetWidgetEventTime(guint32 aEventTime) {
52495206
}
52505207

52515208
TimeStamp nsWindow::GetEventTimeStamp(guint32 aEventTime) {
5252-
if (MOZ_UNLIKELY(!mGdkWindow)) {
5209+
if (MOZ_UNLIKELY(mIsDestroyed)) {
52535210
// nsWindow has been Destroy()ed.
52545211
return TimeStamp::Now();
52555212
}
@@ -5285,7 +5242,6 @@ TimeStamp nsWindow::GetEventTimeStamp(guint32 aEventTime) {
52855242

52865243
#ifdef MOZ_X11
52875244
mozilla::CurrentX11TimeGetter* nsWindow::GetCurrentTimeGetter() {
5288-
MOZ_ASSERT(mGdkWindow, "Expected mGdkWindow to be set");
52895245
if (MOZ_UNLIKELY(!mCurrentTimeGetter)) {
52905246
mCurrentTimeGetter = MakeUnique<CurrentX11TimeGetter>(mGdkWindow);
52915247
}
@@ -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;
@@ -5806,7 +5761,7 @@ void nsWindow::SetDragPopupSurface(
58065761

58075762
mDragPopupSurface = aDragPopupSurface;
58085763
mDragPopupSurfaceRegion = aInvalidRegion;
5809-
if (mGdkWindow) {
5764+
if (!mIsDestroyed) {
58105765
gdk_window_invalidate_rect(mGdkWindow, nullptr, false);
58115766
}
58125767
}
@@ -6217,28 +6172,17 @@ nsCString nsWindow::GetPopupTypeName() {
62176172
Window nsWindow::GetX11Window() {
62186173
#ifdef MOZ_X11
62196174
if (GdkIsX11Display()) {
6220-
return mGdkWindow ? gdk_x11_window_get_xid(mGdkWindow) : X11None;
6175+
return gdk_x11_window_get_xid(mGdkWindow);
62216176
}
62226177
#endif
62236178
return (Window) nullptr;
62246179
}
62256180

6226-
void nsWindow::EnsureGdkWindow() {
6227-
MOZ_DIAGNOSTIC_ASSERT(mIsMapped);
6228-
if (!mGdkWindow) {
6229-
mGdkWindow = gtk_widget_get_window(GTK_WIDGET(mContainer));
6230-
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", this);
6231-
}
6232-
}
6233-
62346181
void nsWindow::ConfigureCompositor() {
6235-
MOZ_DIAGNOSTIC_ASSERT(mIsMapped);
6236-
62376182
LOG("nsWindow::ConfigureCompositor()");
62386183

6239-
if (mIsDestroyed || !mIsMapped) {
6240-
LOG(" quit, mIsDestroyed = %d mIsMapped = %d", !!mIsDestroyed,
6241-
!!mIsMapped);
6184+
if (mIsDestroyed) {
6185+
LOG(" quit, mIsDestroyed = %d", !!mIsDestroyed);
62426186
return;
62436187
}
62446188
// Compositor will be resumed at nsWindow::SetCompositorWidgetDelegate().
@@ -6501,6 +6445,24 @@ nsresult nsWindow::Create(nsIWidget* aParent, const LayoutDeviceIntRect& aRect,
65016445

65026446
gtk_widget_realize(container);
65036447

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

@@ -9940,7 +9902,7 @@ bool nsWindow::SetEGLNativeWindowSize(
99409902
// SetEGLNativeWindowSize() is Wayland only call.
99419903
MOZ_ASSERT(GdkIsWaylandDisplay());
99429904

9943-
if (!mIsMapped) {
9905+
if (mIsDestroyed) {
99449906
return true;
99459907
}
99469908

@@ -9977,10 +9939,8 @@ void nsWindow::OnMap() {
99779939
MaybeCreatePipResources();
99789940

99799941
{
9980-
MutexAutoLock lock(mWindowVisibilityMutex);
99819942
mIsMapped = true;
99829943

9983-
EnsureGdkWindow();
99849944
RefreshScale(/* aRefreshScreen */ false);
99859945

99869946
if (mIsAlert) {
@@ -10032,7 +9992,6 @@ void nsWindow::OnUnmap() {
100329992
ClearPipResources();
100339993

100349994
{
10035-
MutexAutoLock lock(mWindowVisibilityMutex);
100369995
mIsMapped = false;
100379996
mHasReceivedSizeAllocate = false;
100389997

@@ -10046,23 +10005,8 @@ void nsWindow::OnUnmap() {
1004610005
}
1004710006
}
1004810007

10049-
if (mGdkWindow) {
10050-
g_object_set_data(G_OBJECT(mGdkWindow), "nsWindow", nullptr);
10051-
mGdkWindow = nullptr;
10052-
}
10053-
1005410008
// Reset scale for hidden windows
1005510009
mCeiledScaleFactor = sNoScale;
10056-
10057-
// Clear resources (mainly XWindow) stored at GtkCompositorWidget.
10058-
// It makes sure we don't paint to it when nsWindow becomes hiden/deleted
10059-
// and XWindow is released.
10060-
if (mCompositorWidgetDelegate) {
10061-
mCompositorWidgetDelegate->CleanupResources();
10062-
}
10063-
10064-
// Clear nsWindow resources used for old (in-thread) rendering.
10065-
mSurfaceProvider.CleanupResources();
1006610010
}
1006710011

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

0 commit comments

Comments
 (0)