no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / widget / gtk / WaylandBuffer.cpp
blobf3fc4093623f2091ac4992bdaa3c1748dcacb6e9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 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/. */
7 #include "WaylandBuffer.h"
9 #include <sys/mman.h>
10 #include <fcntl.h>
11 #include <errno.h>
13 #include "gfx2DGlue.h"
14 #include "gfxPlatform.h"
15 #include "mozilla/WidgetUtilsGtk.h"
16 #include "mozilla/gfx/Tools.h"
17 #include "nsGtkUtils.h"
18 #include "nsPrintfCString.h"
19 #include "prenv.h" // For PR_GetEnv
21 #ifdef MOZ_LOGGING
22 # include "mozilla/Logging.h"
23 # include "mozilla/ScopeExit.h"
24 # include "Units.h"
25 extern mozilla::LazyLogModule gWidgetWaylandLog;
26 # define LOGWAYLAND(...) \
27 MOZ_LOG(gWidgetWaylandLog, mozilla::LogLevel::Debug, (__VA_ARGS__))
28 #else
29 # define LOGWAYLAND(...)
30 #endif /* MOZ_LOGGING */
32 using namespace mozilla::gl;
34 namespace mozilla::widget {
36 #define BUFFER_BPP 4
37 gfx::SurfaceFormat WaylandBuffer::mFormat = gfx::SurfaceFormat::B8G8R8A8;
39 #ifdef MOZ_LOGGING
40 int WaylandBufferSHM::mDumpSerial =
41 PR_GetEnv("MOZ_WAYLAND_DUMP_WL_BUFFERS") ? 1 : 0;
42 char* WaylandBufferSHM::mDumpDir = PR_GetEnv("MOZ_WAYLAND_DUMP_DIR");
43 #endif
45 /* static */
46 RefPtr<WaylandShmPool> WaylandShmPool::Create(nsWaylandDisplay* aWaylandDisplay,
47 int aSize) {
48 if (!aWaylandDisplay->GetShm()) {
49 NS_WARNING("WaylandShmPool: Missing Wayland shm interface!");
50 return nullptr;
53 RefPtr<WaylandShmPool> shmPool = new WaylandShmPool();
55 shmPool->mShm = MakeUnique<base::SharedMemory>();
56 if (!shmPool->mShm->Create(aSize)) {
57 NS_WARNING("WaylandShmPool: Unable to allocate shared memory!");
58 return nullptr;
61 shmPool->mSize = aSize;
62 shmPool->mShmPool = wl_shm_create_pool(
63 aWaylandDisplay->GetShm(), shmPool->mShm->CloneHandle().get(), aSize);
64 if (!shmPool->mShmPool) {
65 NS_WARNING("WaylandShmPool: Unable to allocate shared memory pool!");
66 return nullptr;
69 return shmPool;
72 void* WaylandShmPool::GetImageData() {
73 if (mImageData) {
74 return mImageData;
76 if (!mShm->Map(mSize)) {
77 NS_WARNING("WaylandShmPool: Failed to map Shm!");
78 return nullptr;
80 mImageData = mShm->memory();
81 return mImageData;
84 WaylandShmPool::~WaylandShmPool() {
85 MozClearPointer(mShmPool, wl_shm_pool_destroy);
88 static const struct wl_buffer_listener sBufferListenerWaylandBuffer = {
89 WaylandBuffer::BufferReleaseCallbackHandler};
91 WaylandBuffer::WaylandBuffer(const LayoutDeviceIntSize& aSize) : mSize(aSize) {}
93 void WaylandBuffer::AttachAndCommit(wl_surface* aSurface) {
94 LOGWAYLAND(
95 "WaylandBuffer::AttachAndCommit [%p] wl_surface %p ID %d wl_buffer "
96 "%p ID %d\n",
97 (void*)this, (void*)aSurface,
98 aSurface ? wl_proxy_get_id((struct wl_proxy*)aSurface) : -1,
99 (void*)GetWlBuffer(),
100 GetWlBuffer() ? wl_proxy_get_id((struct wl_proxy*)GetWlBuffer()) : -1);
102 wl_buffer* buffer = GetWlBuffer();
103 if (buffer) {
104 mAttached = true;
105 wl_surface_attach(aSurface, buffer, 0, 0);
106 wl_surface_commit(aSurface);
110 void WaylandBuffer::BufferReleaseCallbackHandler(wl_buffer* aBuffer) {
111 mAttached = false;
113 if (mBufferReleaseFunc) {
114 mBufferReleaseFunc(mBufferReleaseData, aBuffer);
118 void WaylandBuffer::BufferReleaseCallbackHandler(void* aData,
119 wl_buffer* aBuffer) {
120 auto* buffer = reinterpret_cast<WaylandBuffer*>(aData);
121 buffer->BufferReleaseCallbackHandler(aBuffer);
124 /* static */
125 RefPtr<WaylandBufferSHM> WaylandBufferSHM::Create(
126 const LayoutDeviceIntSize& aSize) {
127 RefPtr<WaylandBufferSHM> buffer = new WaylandBufferSHM(aSize);
128 nsWaylandDisplay* waylandDisplay = WaylandDisplayGet();
130 int size = aSize.width * aSize.height * BUFFER_BPP;
131 buffer->mShmPool = WaylandShmPool::Create(waylandDisplay, size);
132 if (!buffer->mShmPool) {
133 return nullptr;
136 buffer->mWLBuffer = wl_shm_pool_create_buffer(
137 buffer->mShmPool->GetShmPool(), 0, aSize.width, aSize.height,
138 aSize.width * BUFFER_BPP, WL_SHM_FORMAT_ARGB8888);
139 if (!buffer->mWLBuffer) {
140 return nullptr;
143 wl_buffer_add_listener(buffer->GetWlBuffer(), &sBufferListenerWaylandBuffer,
144 buffer.get());
146 LOGWAYLAND("WaylandBufferSHM Created [%p] WaylandDisplay [%p]\n",
147 buffer.get(), waylandDisplay);
149 return buffer;
152 WaylandBufferSHM::WaylandBufferSHM(const LayoutDeviceIntSize& aSize)
153 : WaylandBuffer(aSize) {}
155 WaylandBufferSHM::~WaylandBufferSHM() {
156 MozClearPointer(mWLBuffer, wl_buffer_destroy);
159 already_AddRefed<gfx::DrawTarget> WaylandBufferSHM::Lock() {
160 return gfxPlatform::CreateDrawTargetForData(
161 static_cast<unsigned char*>(mShmPool->GetImageData()),
162 mSize.ToUnknownSize(), BUFFER_BPP * mSize.width, GetSurfaceFormat());
165 void WaylandBufferSHM::Clear() {
166 memset(mShmPool->GetImageData(), 0, mSize.height * mSize.width * BUFFER_BPP);
169 #ifdef MOZ_LOGGING
170 void WaylandBufferSHM::DumpToFile(const char* aHint) {
171 if (!mDumpSerial) {
172 return;
175 cairo_surface_t* surface = nullptr;
176 auto unmap = MakeScopeExit([&] {
177 if (surface) {
178 cairo_surface_destroy(surface);
181 surface = cairo_image_surface_create_for_data(
182 (unsigned char*)mShmPool->GetImageData(), CAIRO_FORMAT_ARGB32,
183 mSize.width, mSize.height, BUFFER_BPP * mSize.width);
184 if (cairo_surface_status(surface) == CAIRO_STATUS_SUCCESS) {
185 nsCString filename;
186 if (mDumpDir) {
187 filename.Append(mDumpDir);
188 filename.Append('/');
190 filename.Append(
191 nsPrintfCString("firefox-wl-buffer-%.5d-%s.png", mDumpSerial++, aHint));
192 cairo_surface_write_to_png(surface, filename.get());
193 LOGWAYLAND("Dumped wl_buffer to %s\n", filename.get());
196 #endif
198 /* static */
199 RefPtr<WaylandBufferDMABUF> WaylandBufferDMABUF::Create(
200 const LayoutDeviceIntSize& aSize, GLContext* aGL) {
201 RefPtr<WaylandBufferDMABUF> buffer = new WaylandBufferDMABUF(aSize);
203 const auto flags =
204 static_cast<DMABufSurfaceFlags>(DMABUF_TEXTURE | DMABUF_ALPHA);
205 buffer->mDMABufSurface =
206 DMABufSurfaceRGBA::CreateDMABufSurface(aSize.width, aSize.height, flags);
207 if (!buffer->mDMABufSurface || !buffer->mDMABufSurface->CreateTexture(aGL)) {
208 return nullptr;
211 if (!buffer->mDMABufSurface->CreateWlBuffer()) {
212 return nullptr;
215 wl_buffer_add_listener(buffer->GetWlBuffer(), &sBufferListenerWaylandBuffer,
216 buffer.get());
218 return buffer;
221 WaylandBufferDMABUF::WaylandBufferDMABUF(const LayoutDeviceIntSize& aSize)
222 : WaylandBuffer(aSize) {}
224 } // namespace mozilla::widget