diff options
Diffstat (limited to '')
-rw-r--r-- | widget/gtk/WindowSurfaceProvider.cpp | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/widget/gtk/WindowSurfaceProvider.cpp b/widget/gtk/WindowSurfaceProvider.cpp new file mode 100644 index 0000000000..282847a512 --- /dev/null +++ b/widget/gtk/WindowSurfaceProvider.cpp @@ -0,0 +1,131 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "WindowSurfaceProvider.h" + +#include "gfxPlatformGtk.h" +#include "mozilla/gfx/Logging.h" +#include "mozilla/layers/LayersTypes.h" +#include "nsWindow.h" +#include "WindowSurfaceX11Image.h" +#include "WindowSurfaceX11SHM.h" +#include "WindowSurfaceXRender.h" +#ifdef MOZ_WAYLAND +# include "WindowSurfaceWayland.h" +#endif + +namespace mozilla { +namespace widget { + +using namespace mozilla::layers; + +WindowSurfaceProvider::WindowSurfaceProvider() + : mIsX11Display(false), + mXDisplay(nullptr), + mXWindow(0), + mXVisual(nullptr), + mXDepth(0), + mWindowSurface(nullptr) +#ifdef MOZ_WAYLAND + , + mWidget(nullptr) +#endif + , + mIsShaped(false) { +} + +void WindowSurfaceProvider::Initialize(Display* aDisplay, Window aWindow, + Visual* aVisual, int aDepth, + bool aIsShaped) { + // We should not be initialized + MOZ_ASSERT(!mXDisplay); + + // This should also be a valid initialization + MOZ_ASSERT(aDisplay && aWindow != X11None && aVisual); + + mXDisplay = aDisplay; + mXWindow = aWindow; + mXVisual = aVisual; + mXDepth = aDepth; + mIsShaped = aIsShaped; + mIsX11Display = true; +} + +#ifdef MOZ_WAYLAND +void WindowSurfaceProvider::Initialize(nsWindow* aWidget) { + mWidget = aWidget; + mIsX11Display = false; +} +#endif + +void WindowSurfaceProvider::CleanupResources() { mWindowSurface = nullptr; } + +UniquePtr<WindowSurface> WindowSurfaceProvider::CreateWindowSurface() { +#ifdef MOZ_WAYLAND + if (!mIsX11Display) { + LOGDRAW(("Drawing to nsWindow %p will use wl_surface\n", mWidget)); + return MakeUnique<WindowSurfaceWayland>(mWidget); + } +#endif + + // We should be initialized + MOZ_ASSERT(mXDisplay); + + // Blit to the window with the following priority: + // 1. XRender (iff XRender is enabled && we are in-process) + // 2. MIT-SHM + // 3. XPutImage + if (!mIsShaped && gfx::gfxVars::UseXRender()) { + LOGDRAW(("Drawing to Window 0x%lx will use XRender\n", mXWindow)); + return MakeUnique<WindowSurfaceXRender>(mXDisplay, mXWindow, mXVisual, + mXDepth); + } + +#ifdef MOZ_HAVE_SHMIMAGE + if (!mIsShaped && nsShmImage::UseShm()) { + LOGDRAW(("Drawing to Window 0x%lx will use MIT-SHM\n", mXWindow)); + return MakeUnique<WindowSurfaceX11SHM>(mXDisplay, mXWindow, mXVisual, + mXDepth); + } +#endif // MOZ_HAVE_SHMIMAGE + + LOGDRAW(("Drawing to Window 0x%lx will use XPutImage\n", mXWindow)); + return MakeUnique<WindowSurfaceX11Image>(mXDisplay, mXWindow, mXVisual, + mXDepth, mIsShaped); +} + +already_AddRefed<gfx::DrawTarget> +WindowSurfaceProvider::StartRemoteDrawingInRegion( + LayoutDeviceIntRegion& aInvalidRegion, layers::BufferMode* aBufferMode) { + if (aInvalidRegion.IsEmpty()) return nullptr; + + if (!mWindowSurface) { + mWindowSurface = CreateWindowSurface(); + if (!mWindowSurface) return nullptr; + } + + *aBufferMode = BufferMode::BUFFER_NONE; + RefPtr<gfx::DrawTarget> dt = nullptr; + if (!(dt = mWindowSurface->Lock(aInvalidRegion)) && mIsX11Display && + !mWindowSurface->IsFallback()) { + // We can't use WindowSurfaceX11Image fallback on Wayland but + // Lock() call on WindowSurfaceWayland should never fail. + gfxWarningOnce() + << "Failed to lock WindowSurface, falling back to XPutImage backend."; + mWindowSurface = MakeUnique<WindowSurfaceX11Image>( + mXDisplay, mXWindow, mXVisual, mXDepth, mIsShaped); + dt = mWindowSurface->Lock(aInvalidRegion); + } + return dt.forget(); +} + +void WindowSurfaceProvider::EndRemoteDrawingInRegion( + gfx::DrawTarget* aDrawTarget, const LayoutDeviceIntRegion& aInvalidRegion) { + if (mWindowSurface) mWindowSurface->Commit(aInvalidRegion); +} + +} // namespace widget +} // namespace mozilla |