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"
16 # include "mozilla/StaticPrefs_widget.h"
17 # include "WindowSurfaceWaylandMultiBuffer.h"
20 # include "mozilla/X11Util.h"
21 # include "WindowSurfaceX11Image.h"
22 # include "WindowSurfaceX11SHM.h"
27 # include "mozilla/Logging.h"
28 # include "nsTArray.h"
30 extern mozilla::LazyLogModule gWidgetLog
;
31 # define LOG(args) MOZ_LOG(gWidgetLog, mozilla::LogLevel::Debug, args)
34 #endif /* MOZ_LOGGING */
39 using namespace mozilla::layers
;
41 WindowSurfaceProvider::WindowSurfaceProvider()
42 : mWindowSurface(nullptr),
43 mMutex("WindowSurfaceProvider"),
44 mWindowSurfaceValid(false)
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());
67 void WindowSurfaceProvider::Initialize(Window aWindow
, Visual
* aVisual
,
68 int aDepth
, bool aIsShaped
) {
69 mWindowSurfaceValid
= false;
73 mIsShaped
= aIsShaped
;
77 void WindowSurfaceProvider::CleanupResources() {
78 MutexAutoLock
lock(mMutex
);
79 mWindowSurfaceValid
= false;
91 RefPtr
<WindowSurface
> WindowSurfaceProvider::CreateWindowSurface() {
93 if (GdkIsWaylandDisplay()) {
94 // We're called too early or we're unmapped.
98 return MakeRefPtr
<WindowSurfaceWaylandMB
>(mWidget
, mCompositorWidget
);
102 if (GdkIsX11Display()) {
103 // We're called too early or we're unmapped.
107 // Blit to the window with the following priority:
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
,
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
);
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()) {
134 MutexAutoLock
lock(mMutex
);
136 if (!mWindowSurfaceValid
) {
137 mWindowSurface
= nullptr;
138 mWindowSurfaceValid
= true;
141 if (!mWindowSurface
) {
142 mWindowSurface
= CreateWindowSurface();
143 if (!mWindowSurface
) {
148 *aBufferMode
= BufferMode::BUFFER_NONE
;
149 RefPtr
<gfx::DrawTarget
> dt
= mWindowSurface
->Lock(aInvalidRegion
);
151 if (!dt
&& GdkIsX11Display() && !mWindowSurface
->IsFallback()) {
152 // We can't use WindowSurfaceX11Image fallback on Wayland but
153 // Lock() call on WindowSurfaceWayland should never fail.
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
);
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
) {
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()) {
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()) {
188 MutexAutoLock
lock(mMutex
);
189 // Commit to mWindowSurface only when we have a valid one.
190 if (mWindowSurface
&& mWindowSurfaceValid
) {
191 mWindowSurface
->Commit(aInvalidRegion
);
198 mWindowSurface
->Commit(aInvalidRegion
);
201 } // namespace widget
202 } // namespace mozilla