From e963c8683d45c7702621537ebf76ced87f5219fd Mon Sep 17 00:00:00 2001 From: Ondrej Zoder Date: Tue, 17 Jul 2018 08:56:42 +0200 Subject: Added wayland patches --- mozilla-1441743.patch | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 mozilla-1441743.patch (limited to 'mozilla-1441743.patch') diff --git a/mozilla-1441743.patch b/mozilla-1441743.patch new file mode 100644 index 0000000..59018c7 --- /dev/null +++ b/mozilla-1441743.patch @@ -0,0 +1,336 @@ +diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h +--- a/widget/gtk/WindowSurfaceWayland.h ++++ b/widget/gtk/WindowSurfaceWayland.h +@@ -3,16 +3,17 @@ + * 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/. */ + + #ifndef _MOZILLA_WIDGET_GTK_WINDOW_SURFACE_WAYLAND_H + #define _MOZILLA_WIDGET_GTK_WINDOW_SURFACE_WAYLAND_H + + #include ++#include "mozilla/gfx/Types.h" + + namespace mozilla { + namespace widget { + + // Our general connection to Wayland display server, + // holds our display connection and runs event loop. + class nsWaylandDisplay : public nsISupports { + NS_DECL_THREADSAFE_ISUPPORTS +@@ -61,17 +62,17 @@ private: + }; + + // Holds actual graphics data for wl_surface + class WindowBackBuffer { + public: + WindowBackBuffer(nsWaylandDisplay* aDisplay, int aWidth, int aHeight); + ~WindowBackBuffer(); + +- already_AddRefed Lock(const LayoutDeviceIntRegion& aRegion); ++ already_AddRefed Lock(); + + void Attach(wl_surface* aSurface); + void Detach(); + bool IsAttached() { return mAttached; } + + bool Resize(int aWidth, int aHeight); + bool SetImageDataFromBackBuffer(class WindowBackBuffer* aSourceBuffer); + +@@ -107,27 +108,33 @@ public: + WindowSurfaceWayland(nsWindow *aWindow); + ~WindowSurfaceWayland(); + + already_AddRefed Lock(const LayoutDeviceIntRegion& aRegion) override; + void Commit(const LayoutDeviceIntRegion& aInvalidRegion) final; + void FrameCallbackHandler(); + + private: +- WindowBackBuffer* GetBufferToDraw(int aWidth, int aHeight); ++ WindowBackBuffer* GetFrontBufferToDraw(int aWidth, int aHeight); + void UpdateScaleFactor(); + ++ already_AddRefed LockFrontBuffer(int aWidth, int aHeight); ++ already_AddRefed LockImageSurface(const gfx::IntSize& aLockSize); ++ bool CommitImageSurface(const LayoutDeviceIntRegion& aRegion); ++ + // TODO: Do we need to hold a reference to nsWindow object? + nsWindow* mWindow; + nsWaylandDisplay* mWaylandDisplay; + WindowBackBuffer* mFrontBuffer; + WindowBackBuffer* mBackBuffer; ++ RefPtr mImageSurface; + wl_callback* mFrameCallback; + wl_surface* mFrameCallbackSurface; + MessageLoop* mDisplayThreadMessageLoop; ++ bool mDirectWlBufferDraw; + bool mDelayedCommit; + bool mFullScreenDamage; + bool mIsMainThread; + }; + + } // namespace widget + } // namespace mozilla + + +diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp +--- a/widget/gtk/WindowSurfaceWayland.cpp ++++ b/widget/gtk/WindowSurfaceWayland.cpp +@@ -299,16 +299,17 @@ nsWaylandDisplay::Matches(wl_display *aD + } + + NS_IMPL_ISUPPORTS(nsWaylandDisplay, nsISupports); + + nsWaylandDisplay::nsWaylandDisplay(wl_display *aDisplay) + : mThreadId(PR_GetCurrentThread()) + // gfx::SurfaceFormat::B8G8R8A8 is a basic Wayland format + // and is always present. ++ // TODO: Provide also format without alpha (Bug 1470126). + , mFormat(gfx::SurfaceFormat::B8G8R8A8) + , mShm(nullptr) + , mDisplay(aDisplay) + { + if (NS_IsMainThread()) { + // Use default event queue in main thread operated by Gtk+. + mEventQueue = nullptr; + } else { +@@ -530,21 +531,19 @@ WindowBackBuffer::SetImageDataFromBackBu + } + + mShmPool.SetImageDataFromPool(&aSourceBuffer->mShmPool, + aSourceBuffer->mWidth * aSourceBuffer->mHeight * BUFFER_BPP); + return true; + } + + already_AddRefed +-WindowBackBuffer::Lock(const LayoutDeviceIntRegion& aRegion) ++WindowBackBuffer::Lock() + { +- gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); +- gfx::IntSize lockSize(bounds.XMost(), bounds.YMost()); +- ++ gfx::IntSize lockSize(mWidth, mHeight); + return gfxPlatform::CreateDrawTargetForData(static_cast(mShmPool.GetImageData()), + lockSize, + BUFFER_BPP * mWidth, + mWaylandDisplay->GetSurfaceFormat()); + } + + static void + frame_callback_handler(void *data, struct wl_callback *callback, uint32_t time) +@@ -560,16 +559,17 @@ static const struct wl_callback_listener + WindowSurfaceWayland::WindowSurfaceWayland(nsWindow *aWindow) + : mWindow(aWindow) + , mWaylandDisplay(WaylandDisplayGet(aWindow->GetWaylandDisplay())) + , mFrontBuffer(nullptr) + , mBackBuffer(nullptr) + , mFrameCallback(nullptr) + , mFrameCallbackSurface(nullptr) + , mDisplayThreadMessageLoop(MessageLoop::current()) ++ , mDirectWlBufferDraw(true) + , mDelayedCommit(false) + , mFullScreenDamage(false) + , mIsMainThread(NS_IsMainThread()) + { + } + + WindowSurfaceWayland::~WindowSurfaceWayland() + { +@@ -598,17 +598,17 @@ WindowSurfaceWayland::UpdateScaleFactor( + { + wl_surface* waylandSurface = mWindow->GetWaylandSurface(); + if (waylandSurface) { + wl_surface_set_buffer_scale(waylandSurface, mWindow->GdkScaleFactor()); + } + } + + WindowBackBuffer* +-WindowSurfaceWayland::GetBufferToDraw(int aWidth, int aHeight) ++WindowSurfaceWayland::GetFrontBufferToDraw(int aWidth, int aHeight) + { + if (!mFrontBuffer) { + mFrontBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); + mBackBuffer = new WindowBackBuffer(mWaylandDisplay, aWidth, aHeight); + return mFrontBuffer; + } + + if (!mFrontBuffer->IsAttached()) { +@@ -647,46 +647,149 @@ WindowSurfaceWayland::GetBufferToDraw(in + // the new buffer and leave gecko to render new whole content. + mFrontBuffer->Resize(aWidth, aHeight); + } + + return mFrontBuffer; + } + + already_AddRefed ++WindowSurfaceWayland::LockFrontBuffer(int aWidth, int aHeight) ++{ ++ WindowBackBuffer* buffer = GetFrontBufferToDraw(aWidth, aHeight); ++ if (buffer) { ++ return buffer->Lock(); ++ } ++ ++ NS_WARNING("WindowSurfaceWayland::LockFrontBuffer(): No buffer available"); ++ return nullptr; ++} ++ ++already_AddRefed ++WindowSurfaceWayland::LockImageSurface(const gfx::IntSize& aLockSize) ++{ ++ if (!mImageSurface || mImageSurface->CairoStatus() || ++ !(aLockSize <= mImageSurface->GetSize())) { ++ mImageSurface = new gfxImageSurface(aLockSize, ++ SurfaceFormatToImageFormat(mWaylandDisplay->GetSurfaceFormat())); ++ if (mImageSurface->CairoStatus()) { ++ return nullptr; ++ } ++ } ++ ++ return gfxPlatform::CreateDrawTargetForData(mImageSurface->Data(), ++ mImageSurface->GetSize(), ++ mImageSurface->Stride(), ++ mWaylandDisplay->GetSurfaceFormat()); ++} ++ ++/* ++ There are some situations which can happen here: ++ ++ A) Lock() is called to whole surface. In that case we don't need ++ to clip/buffer the drawing and we can return wl_buffer directly ++ for drawing. ++ - mFrontBuffer is available - that's an ideal situation. ++ - mFrontBuffer is locked by compositor - flip buffers and draw. ++ - if we can't flip buffers - go B) ++ ++ B) Lock() is requested for part(s) of screen. We need to provide temporary ++ surface to draw into and copy result (clipped) to target wl_surface. ++ */ ++already_AddRefed + WindowSurfaceWayland::Lock(const LayoutDeviceIntRegion& aRegion) + { + MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); + +- // We allocate back buffer to widget size but return only +- // portion requested by aRegion. +- LayoutDeviceIntRect rect = mWindow->GetBounds(); +- WindowBackBuffer* buffer = GetBufferToDraw(rect.width, +- rect.height); +- if (!buffer) { +- NS_WARNING("No drawing buffer available"); +- return nullptr; ++ LayoutDeviceIntRect screenRect = mWindow->GetBounds(); ++ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); ++ gfx::IntSize lockSize(bounds.XMost(), bounds.YMost()); ++ ++ // Are we asked for entire nsWindow to draw? ++ mDirectWlBufferDraw = (aRegion.GetNumRects() == 1 && ++ bounds.x == 0 && bounds.y == 0 && ++ lockSize.width == screenRect.width && ++ lockSize.height == screenRect.height); ++ ++ if (mDirectWlBufferDraw) { ++ RefPtr dt = LockFrontBuffer(screenRect.width, ++ screenRect.height); ++ if (dt) { ++ return dt.forget(); ++ } ++ ++ // We don't have any front buffer available. Try indirect drawing ++ // to mImageSurface which is mirrored to front buffer at commit. ++ mDirectWlBufferDraw = false; + } + +- return buffer->Lock(aRegion); ++ return LockImageSurface(lockSize); ++} ++ ++bool ++WindowSurfaceWayland::CommitImageSurface(const LayoutDeviceIntRegion& aRegion) ++{ ++ MOZ_ASSERT(!mDirectWlBufferDraw); ++ ++ LayoutDeviceIntRect screenRect = mWindow->GetBounds(); ++ gfx::IntRect bounds = aRegion.GetBounds().ToUnknownRect(); ++ ++ gfx::Rect rect(bounds); ++ if (rect.IsEmpty()) { ++ return false; ++ } ++ ++ RefPtr dt = LockFrontBuffer(screenRect.width, ++ screenRect.height); ++ RefPtr surf = ++ gfx::Factory::CreateSourceSurfaceForCairoSurface(mImageSurface->CairoSurface(), ++ mImageSurface->GetSize(), ++ mImageSurface->Format()); ++ if (!dt || !surf) { ++ return false; ++ } ++ ++ uint32_t numRects = aRegion.GetNumRects(); ++ if (numRects != 1) { ++ AutoTArray rects; ++ rects.SetCapacity(numRects); ++ for (auto iter = aRegion.RectIter(); !iter.Done(); iter.Next()) { ++ rects.AppendElement(iter.Get().ToUnknownRect()); ++ } ++ dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length()); ++ } ++ ++ dt->DrawSurface(surf, rect, rect); ++ ++ if (numRects != 1) { ++ dt->PopClip(); ++ } ++ ++ return true; + } + + void + WindowSurfaceWayland::Commit(const LayoutDeviceIntRegion& aInvalidRegion) + { + MOZ_ASSERT(mIsMainThread == NS_IsMainThread()); + + wl_surface* waylandSurface = mWindow->GetWaylandSurface(); + if (!waylandSurface) { + // Target window is already destroyed - don't bother to render there. ++ NS_WARNING("WindowSurfaceWayland::Commit(): parent wl_surface is already hidden/deleted."); + return; + } + wl_proxy_set_queue((struct wl_proxy *)waylandSurface, + mWaylandDisplay->GetEventQueue()); + ++ if (!mDirectWlBufferDraw) { ++ // We have new content at mImageSurface - copy data to mFrontBuffer first. ++ CommitImageSurface(aInvalidRegion); ++ } ++ + if (mFullScreenDamage) { + LayoutDeviceIntRect rect = mWindow->GetBounds(); + wl_surface_damage(waylandSurface, 0, 0, rect.width, rect.height); + mFullScreenDamage = false; + } else { + for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) { + const mozilla::LayoutDeviceIntRect &r = iter.Get(); + wl_surface_damage(waylandSurface, r.x, r.y, r.width, r.height); +@@ -730,17 +833,17 @@ WindowSurfaceWayland::FrameCallbackHandl + mFrameCallback = nullptr; + mFrameCallbackSurface = nullptr; + } + + if (mDelayedCommit) { + wl_surface* waylandSurface = mWindow->GetWaylandSurface(); + if (!waylandSurface) { + // Target window is already destroyed - don't bother to render there. +- NS_WARNING("No drawing buffer available"); ++ NS_WARNING("WindowSurfaceWayland::FrameCallbackHandler(): parent wl_surface is already hidden/deleted."); + return; + } + wl_proxy_set_queue((struct wl_proxy *)waylandSurface, + mWaylandDisplay->GetEventQueue()); + + // Send pending surface to compositor and register frame callback + // for possible subsequent drawing. + mFrameCallback = wl_surface_frame(waylandSurface); -- cgit