1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
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/. */
6
7 #include "WindowSurfaceProvider.h"
8
9 #include "gfxPlatformGtk.h"
10 #include "mozilla/gfx/Logging.h"
11 #include "mozilla/layers/LayersTypes.h"
12 #include "nsWindow.h"
13
14 #ifdef MOZ_WAYLAND
15 # include "mozilla/StaticPrefs_widget.h"
16 # include "WindowSurfaceWayland.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 # include "WindowSurfaceXRender.h"
24 #endif
25
26 #undef LOG
27 #ifdef MOZ_LOGGING
28 # include "mozilla/Logging.h"
29 # include "nsTArray.h"
30 # include "Units.h"
31 extern mozilla::LazyLogModule gWidgetLog;
32 # define LOG(args) MOZ_LOG(gWidgetLog, mozilla::LogLevel::Debug, args)
33 #else
34 # define LOG(args)
35 #endif /* MOZ_LOGGING */
36
37 namespace mozilla {
38 namespace widget {
39
40 using namespace mozilla::layers;
41
WindowSurfaceProvider()42 WindowSurfaceProvider::WindowSurfaceProvider()
43 : mWindowSurface(nullptr)
44 #ifdef MOZ_WAYLAND
45 ,
46 mWidget(nullptr)
47 #endif
48 #ifdef MOZ_X11
49 ,
50 mIsShaped(false),
51 mXDepth(0),
52 mXWindow(0),
53 mXVisual(nullptr)
54 #endif
55 {
56 }
57
58 #ifdef MOZ_WAYLAND
Initialize(nsWindow * aWidget)59 void WindowSurfaceProvider::Initialize(nsWindow* aWidget) { mWidget = aWidget; }
60 #endif
61 #ifdef MOZ_X11
Initialize(Window aWindow,Visual * aVisual,int aDepth,bool aIsShaped)62 void WindowSurfaceProvider::Initialize(Window aWindow, Visual* aVisual,
63 int aDepth, bool aIsShaped) {
64 mXWindow = aWindow;
65 mXVisual = aVisual;
66 mXDepth = aDepth;
67 mIsShaped = aIsShaped;
68 }
69 #endif
70
CleanupResources()71 void WindowSurfaceProvider::CleanupResources() { mWindowSurface = nullptr; }
72
CreateWindowSurface()73 RefPtr<WindowSurface> WindowSurfaceProvider::CreateWindowSurface() {
74 #ifdef MOZ_WAYLAND
75 if (GdkIsWaylandDisplay()) {
76 if (StaticPrefs::
77 widget_wayland_multi_buffer_software_backend_enabled_AtStartup()) {
78 LOG(
79 ("Drawing to nsWindow %p will use wl_surface. Using multi-buffered "
80 "backend.\n",
81 mWidget));
82 return MakeRefPtr<WindowSurfaceWaylandMB>(mWidget);
83 }
84 LOG(
85 ("Drawing to nsWindow %p will use wl_surface. Using single-buffered "
86 "backend.\n",
87 mWidget));
88 return MakeRefPtr<WindowSurfaceWayland>(mWidget);
89 }
90 #endif
91 #ifdef MOZ_X11
92 if (GdkIsX11Display()) {
93 // Blit to the window with the following priority:
94 // 1. XRender (iff XRender is enabled && we are in-process)
95 // 2. MIT-SHM
96 // 3. XPutImage
97 if (!mIsShaped && gfx::gfxVars::UseXRender()) {
98 LOG(("Drawing to Window 0x%lx will use XRender\n", mXWindow));
99 return MakeRefPtr<WindowSurfaceXRender>(DefaultXDisplay(), mXWindow,
100 mXVisual, mXDepth);
101 }
102
103 # ifdef MOZ_HAVE_SHMIMAGE
104 if (!mIsShaped && nsShmImage::UseShm()) {
105 LOG(("Drawing to Window 0x%lx will use MIT-SHM\n", mXWindow));
106 return MakeRefPtr<WindowSurfaceX11SHM>(DefaultXDisplay(), mXWindow,
107 mXVisual, mXDepth);
108 }
109 # endif // MOZ_HAVE_SHMIMAGE
110
111 LOG(("Drawing to Window 0x%lx will use XPutImage\n", mXWindow));
112 return MakeRefPtr<WindowSurfaceX11Image>(DefaultXDisplay(), mXWindow,
113 mXVisual, mXDepth, mIsShaped);
114 }
115 #endif
116 MOZ_RELEASE_ASSERT(false);
117 }
118
119 already_AddRefed<gfx::DrawTarget>
StartRemoteDrawingInRegion(const LayoutDeviceIntRegion & aInvalidRegion,layers::BufferMode * aBufferMode)120 WindowSurfaceProvider::StartRemoteDrawingInRegion(
121 const LayoutDeviceIntRegion& aInvalidRegion,
122 layers::BufferMode* aBufferMode) {
123 if (aInvalidRegion.IsEmpty()) return nullptr;
124
125 if (!mWindowSurface) {
126 mWindowSurface = CreateWindowSurface();
127 if (!mWindowSurface) return nullptr;
128 }
129
130 *aBufferMode = BufferMode::BUFFER_NONE;
131 RefPtr<gfx::DrawTarget> dt = mWindowSurface->Lock(aInvalidRegion);
132 #ifdef MOZ_X11
133 if (!dt && GdkIsX11Display() && !mWindowSurface->IsFallback()) {
134 // We can't use WindowSurfaceX11Image fallback on Wayland but
135 // Lock() call on WindowSurfaceWayland should never fail.
136 gfxWarningOnce()
137 << "Failed to lock WindowSurface, falling back to XPutImage backend.";
138 mWindowSurface = MakeRefPtr<WindowSurfaceX11Image>(
139 DefaultXDisplay(), mXWindow, mXVisual, mXDepth, mIsShaped);
140 dt = mWindowSurface->Lock(aInvalidRegion);
141 }
142 #endif
143 return dt.forget();
144 }
145
EndRemoteDrawingInRegion(gfx::DrawTarget * aDrawTarget,const LayoutDeviceIntRegion & aInvalidRegion)146 void WindowSurfaceProvider::EndRemoteDrawingInRegion(
147 gfx::DrawTarget* aDrawTarget, const LayoutDeviceIntRegion& aInvalidRegion) {
148 if (mWindowSurface) mWindowSurface->Commit(aInvalidRegion);
149 }
150
151 } // namespace widget
152 } // namespace mozilla
153