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