no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / widget / gtk / WindowSurfaceProvider.cpp
blobfaf147a80a4a1142b7f1aa4b5e230f100f412890
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "WindowSurfaceProvider.h"
9 #include "gfxPlatformGtk.h"
10 #include "GtkCompositorWidget.h"
11 #include "mozilla/gfx/Logging.h"
12 #include "mozilla/layers/LayersTypes.h"
13 #include "nsWindow.h"
15 #ifdef MOZ_WAYLAND
16 # include "mozilla/StaticPrefs_widget.h"
17 # include "WindowSurfaceWaylandMultiBuffer.h"
18 #endif
19 #ifdef MOZ_X11
20 # include "mozilla/X11Util.h"
21 # include "WindowSurfaceX11Image.h"
22 # include "WindowSurfaceX11SHM.h"
23 #endif
25 #undef LOG
26 #ifdef MOZ_LOGGING
27 # include "mozilla/Logging.h"
28 # include "nsTArray.h"
29 # include "Units.h"
30 extern mozilla::LazyLogModule gWidgetLog;
31 # define LOG(args) MOZ_LOG(gWidgetLog, mozilla::LogLevel::Debug, args)
32 #else
33 # define LOG(args)
34 #endif /* MOZ_LOGGING */
36 namespace mozilla {
37 namespace widget {
39 using namespace mozilla::layers;
41 WindowSurfaceProvider::WindowSurfaceProvider()
42 : mWindowSurface(nullptr),
43 mMutex("WindowSurfaceProvider"),
44 mWindowSurfaceValid(false)
45 #ifdef MOZ_X11
47 mIsShaped(false),
48 mXDepth(0),
49 mXWindow(0),
50 mXVisual(nullptr)
51 #endif
55 #ifdef MOZ_WAYLAND
56 void WindowSurfaceProvider::Initialize(RefPtr<nsWindow> aWidget) {
57 mWindowSurfaceValid = false;
58 mWidget = std::move(aWidget);
60 void WindowSurfaceProvider::Initialize(GtkCompositorWidget* aCompositorWidget) {
61 mWindowSurfaceValid = false;
62 mCompositorWidget = aCompositorWidget;
63 mWidget = static_cast<nsWindow*>(aCompositorWidget->RealWidget());
65 #endif
66 #ifdef MOZ_X11
67 void WindowSurfaceProvider::Initialize(Window aWindow, Visual* aVisual,
68 int aDepth, bool aIsShaped) {
69 mWindowSurfaceValid = false;
70 mXWindow = aWindow;
71 mXVisual = aVisual;
72 mXDepth = aDepth;
73 mIsShaped = aIsShaped;
75 #endif
77 void WindowSurfaceProvider::CleanupResources() {
78 MutexAutoLock lock(mMutex);
79 mWindowSurfaceValid = false;
80 #ifdef MOZ_WAYLAND
81 mWidget = nullptr;
82 #endif
83 #ifdef MOZ_X11
84 mXWindow = 0;
85 mXVisual = 0;
86 mXDepth = 0;
87 mIsShaped = false;
88 #endif
91 RefPtr<WindowSurface> WindowSurfaceProvider::CreateWindowSurface() {
92 #ifdef MOZ_WAYLAND
93 if (GdkIsWaylandDisplay()) {
94 // We're called too early or we're unmapped.
95 if (!mWidget) {
96 return nullptr;
98 return MakeRefPtr<WindowSurfaceWaylandMB>(mWidget, mCompositorWidget);
100 #endif
101 #ifdef MOZ_X11
102 if (GdkIsX11Display()) {
103 // We're called too early or we're unmapped.
104 if (!mXWindow) {
105 return nullptr;
107 // Blit to the window with the following priority:
108 // 1. MIT-SHM
109 // 2. XPutImage
110 # ifdef MOZ_HAVE_SHMIMAGE
111 if (!mIsShaped && nsShmImage::UseShm()) {
112 LOG(("Drawing to Window 0x%lx will use MIT-SHM\n", mXWindow));
113 return MakeRefPtr<WindowSurfaceX11SHM>(DefaultXDisplay(), mXWindow,
114 mXVisual, mXDepth);
116 # endif // MOZ_HAVE_SHMIMAGE
118 LOG(("Drawing to Window 0x%lx will use XPutImage\n", mXWindow));
119 return MakeRefPtr<WindowSurfaceX11Image>(DefaultXDisplay(), mXWindow,
120 mXVisual, mXDepth, mIsShaped);
122 #endif
123 MOZ_RELEASE_ASSERT(false);
126 already_AddRefed<gfx::DrawTarget>
127 WindowSurfaceProvider::StartRemoteDrawingInRegion(
128 const LayoutDeviceIntRegion& aInvalidRegion,
129 layers::BufferMode* aBufferMode) {
130 if (aInvalidRegion.IsEmpty()) {
131 return nullptr;
134 MutexAutoLock lock(mMutex);
136 if (!mWindowSurfaceValid) {
137 mWindowSurface = nullptr;
138 mWindowSurfaceValid = true;
141 if (!mWindowSurface) {
142 mWindowSurface = CreateWindowSurface();
143 if (!mWindowSurface) {
144 return nullptr;
148 *aBufferMode = BufferMode::BUFFER_NONE;
149 RefPtr<gfx::DrawTarget> dt = mWindowSurface->Lock(aInvalidRegion);
150 #ifdef MOZ_X11
151 if (!dt && GdkIsX11Display() && !mWindowSurface->IsFallback()) {
152 // We can't use WindowSurfaceX11Image fallback on Wayland but
153 // Lock() call on WindowSurfaceWayland should never fail.
154 gfxWarningOnce()
155 << "Failed to lock WindowSurface, falling back to XPutImage backend.";
156 mWindowSurface = MakeRefPtr<WindowSurfaceX11Image>(
157 DefaultXDisplay(), mXWindow, mXVisual, mXDepth, mIsShaped);
158 dt = mWindowSurface->Lock(aInvalidRegion);
160 #endif
161 return dt.forget();
164 void WindowSurfaceProvider::EndRemoteDrawingInRegion(
165 gfx::DrawTarget* aDrawTarget, const LayoutDeviceIntRegion& aInvalidRegion) {
166 MutexAutoLock lock(mMutex);
167 // Commit to mWindowSurface only if we have a valid one.
168 if (!mWindowSurface || !mWindowSurfaceValid) {
169 return;
171 #if defined(MOZ_WAYLAND)
172 if (GdkIsWaylandDisplay()) {
173 // We're called too early or we're unmapped.
174 // Don't draw anything.
175 if (!mWidget || !mWidget->IsMapped()) {
176 return;
178 if (moz_container_wayland_is_commiting_to_parent(
179 mWidget->GetMozContainer())) {
180 // If we're drawing directly to wl_surface owned by Gtk we need to use it
181 // in main thread to sync with Gtk access to it.
182 NS_DispatchToMainThread(NS_NewRunnableFunction(
183 "WindowSurfaceProvider::EndRemoteDrawingInRegion",
184 [widget = RefPtr{mWidget}, this, aInvalidRegion]() {
185 if (!widget->IsMapped()) {
186 return;
188 MutexAutoLock lock(mMutex);
189 // Commit to mWindowSurface only when we have a valid one.
190 if (mWindowSurface && mWindowSurfaceValid) {
191 mWindowSurface->Commit(aInvalidRegion);
193 }));
194 return;
197 #endif
198 mWindowSurface->Commit(aInvalidRegion);
201 } // namespace widget
202 } // namespace mozilla