352 lines
11 KiB
Diff
352 lines
11 KiB
Diff
|
changeset: 556172:143b4ca96ec9
|
||
|
tag: tip
|
||
|
parent: 556169:61c35792ca70
|
||
|
user: stransky <stransky@redhat.com>
|
||
|
date: Mon Oct 26 12:15:49 2020 +0100
|
||
|
files: widget/gtk/WindowSurfaceWayland.cpp widget/gtk/WindowSurfaceWayland.h
|
||
|
description:
|
||
|
Bug 1673313 [Wayland] Don't fail when Shm allocation fails, r?jhorak
|
||
|
|
||
|
- Make WaylandAllocateShmMemory() fallible.
|
||
|
- Implement WaylandReAllocateShmMemory() to re-allocate Shm pool.
|
||
|
- Remove WaylandShmPool::Resize() and use WaylandShmPool::Create() only.
|
||
|
- Implement and use WaylandShmPool::Release().
|
||
|
- Make WindowSurfaceWayland::CreateWaylandBuffer() as fallible.
|
||
|
|
||
|
Differential Revision: https://phabricator.services.mozilla.com/D94735
|
||
|
|
||
|
|
||
|
diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp
|
||
|
--- a/widget/gtk/WindowSurfaceWayland.cpp
|
||
|
+++ b/widget/gtk/WindowSurfaceWayland.cpp
|
||
|
@@ -209,14 +209,23 @@ RefPtr<nsWaylandDisplay> WindowBackBuffe
|
||
|
}
|
||
|
|
||
|
static int WaylandAllocateShmMemory(int aSize) {
|
||
|
- static int counter = 0;
|
||
|
- nsPrintfCString shmName("/wayland.mozilla.ipc.%d", counter++);
|
||
|
- int fd = shm_open(shmName.get(), O_CREAT | O_RDWR | O_EXCL, 0600);
|
||
|
- if (fd >= 0) {
|
||
|
- shm_unlink(shmName.get());
|
||
|
- } else {
|
||
|
- printf_stderr("Unable to SHM memory segment\n");
|
||
|
- MOZ_CRASH();
|
||
|
+ int fd = -1;
|
||
|
+ do {
|
||
|
+ static int counter = 0;
|
||
|
+ nsPrintfCString shmName("/wayland.mozilla.ipc.%d", counter++);
|
||
|
+ fd = shm_open(shmName.get(), O_CREAT | O_RDWR | O_EXCL, 0600);
|
||
|
+ if (fd >= 0) {
|
||
|
+ // We don't want to use leaked file
|
||
|
+ if (shm_unlink(shmName.get()) != 0) {
|
||
|
+ NS_WARNING("shm_unlink failed");
|
||
|
+ return -1;
|
||
|
+ }
|
||
|
+ }
|
||
|
+ } while (fd < 0 && errno == EEXIST);
|
||
|
+
|
||
|
+ if (fd < 0) {
|
||
|
+ NS_WARNING(nsPrintfCString("shm_open failed: %s", strerror(errno)).get());
|
||
|
+ return -1;
|
||
|
}
|
||
|
|
||
|
int ret = 0;
|
||
|
@@ -225,59 +234,103 @@ static int WaylandAllocateShmMemory(int
|
||
|
ret = posix_fallocate(fd, 0, aSize);
|
||
|
} while (ret == EINTR);
|
||
|
if (ret != 0) {
|
||
|
+ NS_WARNING(
|
||
|
+ nsPrintfCString("posix_fallocate() fails to allocate shm memory: %s",
|
||
|
+ strerror(ret))
|
||
|
+ .get());
|
||
|
close(fd);
|
||
|
- MOZ_CRASH("posix_fallocate() fails to allocate shm memory");
|
||
|
+ return -1;
|
||
|
}
|
||
|
#else
|
||
|
do {
|
||
|
ret = ftruncate(fd, aSize);
|
||
|
} while (ret < 0 && errno == EINTR);
|
||
|
if (ret < 0) {
|
||
|
+ NS_WARNING(nsPrintfCString("ftruncate() fails to allocate shm memory: %s",
|
||
|
+ strerror(ret))
|
||
|
+ .get());
|
||
|
close(fd);
|
||
|
- MOZ_CRASH("ftruncate() fails to allocate shm memory");
|
||
|
+ fd = -1;
|
||
|
}
|
||
|
#endif
|
||
|
|
||
|
return fd;
|
||
|
}
|
||
|
|
||
|
-WaylandShmPool::WaylandShmPool(RefPtr<nsWaylandDisplay> aWaylandDisplay,
|
||
|
- int aSize)
|
||
|
- : mAllocatedSize(aSize) {
|
||
|
- mShmPoolFd = WaylandAllocateShmMemory(mAllocatedSize);
|
||
|
- mImageData = mmap(nullptr, mAllocatedSize, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||
|
- mShmPoolFd, 0);
|
||
|
- MOZ_RELEASE_ASSERT(mImageData != MAP_FAILED,
|
||
|
- "Unable to map drawing surface!");
|
||
|
+static bool WaylandReAllocateShmMemory(int aFd, int aSize) {
|
||
|
+ if (ftruncate(aFd, aSize) < 0) {
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+#ifdef HAVE_POSIX_FALLOCATE
|
||
|
+ do {
|
||
|
+ errno = posix_fallocate(aFd, 0, aSize);
|
||
|
+ } while (errno == EINTR);
|
||
|
+ if (errno != 0) {
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+#endif
|
||
|
+ return true;
|
||
|
+}
|
||
|
|
||
|
- mShmPool =
|
||
|
- wl_shm_create_pool(aWaylandDisplay->GetShm(), mShmPoolFd, mAllocatedSize);
|
||
|
+WaylandShmPool::WaylandShmPool()
|
||
|
+ : mShmPool(nullptr),
|
||
|
+ mShmPoolFd(-1),
|
||
|
+ mAllocatedSize(0),
|
||
|
+ mImageData(MAP_FAILED){};
|
||
|
|
||
|
- // We set our queue to get mShmPool events at compositor thread.
|
||
|
- wl_proxy_set_queue((struct wl_proxy*)mShmPool,
|
||
|
- aWaylandDisplay->GetEventQueue());
|
||
|
+void WaylandShmPool::Release() {
|
||
|
+ if (mImageData != MAP_FAILED) {
|
||
|
+ munmap(mImageData, mAllocatedSize);
|
||
|
+ mImageData = MAP_FAILED;
|
||
|
+ }
|
||
|
+ if (mShmPool) {
|
||
|
+ wl_shm_pool_destroy(mShmPool);
|
||
|
+ mShmPool = 0;
|
||
|
+ }
|
||
|
+ if (mShmPoolFd >= 0) {
|
||
|
+ close(mShmPoolFd);
|
||
|
+ mShmPoolFd = -1;
|
||
|
+ }
|
||
|
}
|
||
|
|
||
|
-bool WaylandShmPool::Resize(int aSize) {
|
||
|
+bool WaylandShmPool::Create(RefPtr<nsWaylandDisplay> aWaylandDisplay,
|
||
|
+ int aSize) {
|
||
|
// We do size increase only
|
||
|
- if (aSize <= mAllocatedSize) return true;
|
||
|
-
|
||
|
- if (ftruncate(mShmPoolFd, aSize) < 0) return false;
|
||
|
+ if (aSize <= mAllocatedSize) {
|
||
|
+ return true;
|
||
|
+ }
|
||
|
|
||
|
-#ifdef HAVE_POSIX_FALLOCATE
|
||
|
- do {
|
||
|
- errno = posix_fallocate(mShmPoolFd, 0, aSize);
|
||
|
- } while (errno == EINTR);
|
||
|
- if (errno != 0) return false;
|
||
|
-#endif
|
||
|
+ if (mShmPoolFd < 0) {
|
||
|
+ mShmPoolFd = WaylandAllocateShmMemory(aSize);
|
||
|
+ if (mShmPoolFd < 0) {
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ if (!WaylandReAllocateShmMemory(mShmPoolFd, aSize)) {
|
||
|
+ Release();
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+ }
|
||
|
|
||
|
- wl_shm_pool_resize(mShmPool, aSize);
|
||
|
-
|
||
|
- munmap(mImageData, mAllocatedSize);
|
||
|
-
|
||
|
+ if (mImageData != MAP_FAILED) {
|
||
|
+ munmap(mImageData, mAllocatedSize);
|
||
|
+ }
|
||
|
mImageData =
|
||
|
mmap(nullptr, aSize, PROT_READ | PROT_WRITE, MAP_SHARED, mShmPoolFd, 0);
|
||
|
- if (mImageData == MAP_FAILED) return false;
|
||
|
+ if (mImageData == MAP_FAILED) {
|
||
|
+ NS_WARNING("Unable to map drawing surface!");
|
||
|
+ Release();
|
||
|
+ return false;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (mShmPool) {
|
||
|
+ wl_shm_pool_resize(mShmPool, aSize);
|
||
|
+ } else {
|
||
|
+ mShmPool = wl_shm_create_pool(aWaylandDisplay->GetShm(), mShmPoolFd, aSize);
|
||
|
+ // We set our queue to get mShmPool events at compositor thread.
|
||
|
+ wl_proxy_set_queue((struct wl_proxy*)mShmPool,
|
||
|
+ aWaylandDisplay->GetEventQueue());
|
||
|
+ }
|
||
|
|
||
|
mAllocatedSize = aSize;
|
||
|
return true;
|
||
|
@@ -289,11 +342,7 @@ void WaylandShmPool::SetImageDataFromPoo
|
||
|
memcpy(mImageData, aSourcePool->GetImageData(), aImageDataSize);
|
||
|
}
|
||
|
|
||
|
-WaylandShmPool::~WaylandShmPool() {
|
||
|
- munmap(mImageData, mAllocatedSize);
|
||
|
- wl_shm_pool_destroy(mShmPool);
|
||
|
- close(mShmPoolFd);
|
||
|
-}
|
||
|
+WaylandShmPool::~WaylandShmPool() { Release(); }
|
||
|
|
||
|
static void buffer_release(void* data, wl_buffer* buffer) {
|
||
|
auto surface = reinterpret_cast<WindowBackBuffer*>(data);
|
||
|
@@ -302,14 +351,14 @@ static void buffer_release(void* data, w
|
||
|
|
||
|
static const struct wl_buffer_listener buffer_listener = {buffer_release};
|
||
|
|
||
|
-void WindowBackBufferShm::Create(int aWidth, int aHeight) {
|
||
|
+bool WindowBackBufferShm::Create(int aWidth, int aHeight) {
|
||
|
MOZ_ASSERT(!IsAttached(), "We can't create attached buffers.");
|
||
|
- MOZ_ASSERT(!mWLBuffer, "there is wl_buffer already!");
|
||
|
|
||
|
- int newBufferSize = aWidth * aHeight * BUFFER_BPP;
|
||
|
- if (!mShmPool.Resize(newBufferSize)) {
|
||
|
- mWLBuffer = nullptr;
|
||
|
- return;
|
||
|
+ ReleaseShmSurface();
|
||
|
+
|
||
|
+ int size = aWidth * aHeight * BUFFER_BPP;
|
||
|
+ if (!mShmPool.Create(GetWaylandDisplay(), size)) {
|
||
|
+ return false;
|
||
|
}
|
||
|
|
||
|
mWLBuffer =
|
||
|
@@ -325,14 +374,16 @@ void WindowBackBufferShm::Create(int aWi
|
||
|
LOGWAYLAND(("WindowBackBufferShm::Create [%p] wl_buffer %p ID %d\n",
|
||
|
(void*)this, (void*)mWLBuffer,
|
||
|
mWLBuffer ? wl_proxy_get_id((struct wl_proxy*)mWLBuffer) : -1));
|
||
|
+ return true;
|
||
|
}
|
||
|
|
||
|
void WindowBackBufferShm::ReleaseShmSurface() {
|
||
|
LOGWAYLAND(("WindowBackBufferShm::Release [%p]\n", (void*)this));
|
||
|
-
|
||
|
- wl_buffer_destroy(mWLBuffer);
|
||
|
+ if (mWLBuffer) {
|
||
|
+ wl_buffer_destroy(mWLBuffer);
|
||
|
+ mWLBuffer = nullptr;
|
||
|
+ }
|
||
|
mWidth = mHeight = 0;
|
||
|
- mWLBuffer = nullptr;
|
||
|
}
|
||
|
|
||
|
void WindowBackBufferShm::Clear() {
|
||
|
@@ -340,16 +391,13 @@ void WindowBackBufferShm::Clear() {
|
||
|
}
|
||
|
|
||
|
WindowBackBufferShm::WindowBackBufferShm(
|
||
|
- WindowSurfaceWayland* aWindowSurfaceWayland, int aWidth, int aHeight)
|
||
|
+ WindowSurfaceWayland* aWindowSurfaceWayland)
|
||
|
: WindowBackBuffer(aWindowSurfaceWayland),
|
||
|
- mShmPool(aWindowSurfaceWayland->GetWaylandDisplay(),
|
||
|
- aWidth * aHeight * BUFFER_BPP),
|
||
|
+ mShmPool(),
|
||
|
mWLBuffer(nullptr),
|
||
|
- mWidth(aWidth),
|
||
|
- mHeight(aHeight),
|
||
|
- mAttached(false) {
|
||
|
- Create(aWidth, aHeight);
|
||
|
-}
|
||
|
+ mWidth(0),
|
||
|
+ mHeight(0),
|
||
|
+ mAttached(false) {}
|
||
|
|
||
|
WindowBackBufferShm::~WindowBackBufferShm() { ReleaseShmSurface(); }
|
||
|
|
||
|
@@ -357,13 +405,9 @@ bool WindowBackBufferShm::Resize(int aWi
|
||
|
if (aWidth == mWidth && aHeight == mHeight) {
|
||
|
return true;
|
||
|
}
|
||
|
-
|
||
|
LOGWAYLAND(("WindowBackBufferShm::Resize [%p] %d %d\n", (void*)this, aWidth,
|
||
|
aHeight));
|
||
|
-
|
||
|
- ReleaseShmSurface();
|
||
|
Create(aWidth, aHeight);
|
||
|
-
|
||
|
return (mWLBuffer != nullptr);
|
||
|
}
|
||
|
|
||
|
@@ -488,11 +532,13 @@ WindowBackBuffer* WindowSurfaceWayland::
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
- WindowBackBuffer* buffer = new WindowBackBufferShm(this, aWidth, aHeight);
|
||
|
- if (buffer) {
|
||
|
- mShmBackupBuffer[availableBuffer] = buffer;
|
||
|
+ WindowBackBuffer* buffer = new WindowBackBufferShm(this);
|
||
|
+ if (!buffer->Create(aWidth, aHeight)) {
|
||
|
+ delete buffer;
|
||
|
+ return nullptr;
|
||
|
}
|
||
|
|
||
|
+ mShmBackupBuffer[availableBuffer] = buffer;
|
||
|
return buffer;
|
||
|
}
|
||
|
|
||
|
diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h
|
||
|
--- a/widget/gtk/WindowSurfaceWayland.h
|
||
|
+++ b/widget/gtk/WindowSurfaceWayland.h
|
||
|
@@ -25,14 +25,14 @@ class WindowSurfaceWayland;
|
||
|
// Allocates and owns shared memory for Wayland drawing surface
|
||
|
class WaylandShmPool {
|
||
|
public:
|
||
|
- WaylandShmPool(RefPtr<nsWaylandDisplay> aDisplay, int aSize);
|
||
|
- ~WaylandShmPool();
|
||
|
-
|
||
|
- bool Resize(int aSize);
|
||
|
+ bool Create(RefPtr<nsWaylandDisplay> aWaylandDisplay, int aSize);
|
||
|
+ void Release();
|
||
|
wl_shm_pool* GetShmPool() { return mShmPool; };
|
||
|
void* GetImageData() { return mImageData; };
|
||
|
void SetImageDataFromPool(class WaylandShmPool* aSourcePool,
|
||
|
int aImageDataSize);
|
||
|
+ WaylandShmPool();
|
||
|
+ ~WaylandShmPool();
|
||
|
|
||
|
private:
|
||
|
wl_shm_pool* mShmPool;
|
||
|
@@ -53,6 +53,7 @@ class WindowBackBuffer {
|
||
|
virtual bool IsAttached() = 0;
|
||
|
|
||
|
virtual void Clear() = 0;
|
||
|
+ virtual bool Create(int aWidth, int aHeight) = 0;
|
||
|
virtual bool Resize(int aWidth, int aHeight) = 0;
|
||
|
|
||
|
virtual int GetWidth() = 0;
|
||
|
@@ -87,8 +88,7 @@ class WindowBackBuffer {
|
||
|
|
||
|
class WindowBackBufferShm : public WindowBackBuffer {
|
||
|
public:
|
||
|
- WindowBackBufferShm(WindowSurfaceWayland* aWindowSurfaceWayland, int aWidth,
|
||
|
- int aHeight);
|
||
|
+ WindowBackBufferShm(WindowSurfaceWayland* aWindowSurfaceWayland);
|
||
|
~WindowBackBufferShm();
|
||
|
|
||
|
already_AddRefed<gfx::DrawTarget> Lock();
|
||
|
@@ -100,6 +100,7 @@ class WindowBackBufferShm : public Windo
|
||
|
void SetAttached() { mAttached = true; };
|
||
|
|
||
|
void Clear();
|
||
|
+ bool Create(int aWidth, int aHeight);
|
||
|
bool Resize(int aWidth, int aHeight);
|
||
|
bool SetImageDataFromBuffer(class WindowBackBuffer* aSourceBuffer);
|
||
|
|
||
|
@@ -109,7 +110,6 @@ class WindowBackBufferShm : public Windo
|
||
|
wl_buffer* GetWlBuffer() { return mWLBuffer; };
|
||
|
|
||
|
private:
|
||
|
- void Create(int aWidth, int aHeight);
|
||
|
void ReleaseShmSurface();
|
||
|
|
||
|
// WaylandShmPool provides actual shared memory we draw into
|
||
|
|