Bug 1873042 - Part 3: Optimise substring(0, 1) pattern. r=jandem
[gecko.git] / widget / gtk / DMABufSurface.h
blob9bb8928cca92764bb8c7b58fd6f680ea85d80f4e
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 #ifndef DMABufSurface_h__
8 #define DMABufSurface_h__
10 #include <functional>
11 #include <stdint.h>
12 #include "mozilla/widget/va_drmcommon.h"
13 #include "GLTypes.h"
14 #include "ImageContainer.h"
15 #include "nsISupportsImpl.h"
16 #include "mozilla/gfx/Types.h"
17 #include "mozilla/Mutex.h"
19 typedef void* EGLImageKHR;
20 typedef void* EGLSyncKHR;
22 #define DMABUF_BUFFER_PLANES 4
24 #ifndef VA_FOURCC_NV12
25 # define VA_FOURCC_NV12 0x3231564E
26 #endif
27 #ifndef VA_FOURCC_YV12
28 # define VA_FOURCC_YV12 0x32315659
29 #endif
30 #ifndef VA_FOURCC_P010
31 # define VA_FOURCC_P010 0x30313050
32 #endif
34 namespace mozilla {
35 namespace gfx {
36 class DataSourceSurface;
38 namespace layers {
39 class MemoryOrShmem;
40 class SurfaceDescriptor;
41 class SurfaceDescriptorBuffer;
42 class SurfaceDescriptorDMABuf;
43 } // namespace layers
44 namespace gl {
45 class GLContext;
47 } // namespace mozilla
49 typedef enum {
50 // Use alpha pixel format
51 DMABUF_ALPHA = 1 << 0,
52 // Surface is used as texture and may be also shared
53 DMABUF_TEXTURE = 1 << 1,
54 // Use modifiers. Such dmabuf surface may have more planes
55 // and complex internal structure (tiling/compression/etc.)
56 // so we can't do direct rendering to it.
57 DMABUF_USE_MODIFIERS = 1 << 3,
58 } DMABufSurfaceFlags;
60 class DMABufSurfaceRGBA;
61 class DMABufSurfaceYUV;
62 struct wl_buffer;
64 namespace mozilla::widget {
65 struct GbmFormat;
68 class DMABufSurface {
69 public:
70 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DMABufSurface)
72 enum SurfaceType {
73 SURFACE_RGBA,
74 SURFACE_NV12,
75 SURFACE_YUV420,
78 // Import surface from SurfaceDescriptor. This is usually
79 // used to copy surface from another process over IPC.
80 // When a global reference counter was created for the surface
81 // (see bellow) it's automatically referenced.
82 static already_AddRefed<DMABufSurface> CreateDMABufSurface(
83 const mozilla::layers::SurfaceDescriptor& aDesc);
85 // Export surface to another process via. SurfaceDescriptor.
86 virtual bool Serialize(
87 mozilla::layers::SurfaceDescriptor& aOutDescriptor) = 0;
89 virtual int GetWidth(int aPlane = 0) = 0;
90 virtual int GetHeight(int aPlane = 0) = 0;
91 virtual mozilla::gfx::SurfaceFormat GetFormat() = 0;
92 virtual mozilla::gfx::SurfaceFormat GetFormatGL() = 0;
94 virtual bool CreateTexture(mozilla::gl::GLContext* aGLContext,
95 int aPlane = 0) = 0;
96 virtual void ReleaseTextures() = 0;
97 virtual GLuint GetTexture(int aPlane = 0) = 0;
98 virtual EGLImageKHR GetEGLImage(int aPlane = 0) = 0;
100 SurfaceType GetSurfaceType() { return mSurfaceType; };
101 virtual int GetTextureCount() = 0;
103 bool IsMapped(int aPlane = 0) { return (mMappedRegion[aPlane] != nullptr); };
104 void Unmap(int aPlane = 0);
106 virtual DMABufSurfaceRGBA* GetAsDMABufSurfaceRGBA() { return nullptr; }
107 virtual DMABufSurfaceYUV* GetAsDMABufSurfaceYUV() { return nullptr; }
108 virtual already_AddRefed<mozilla::gfx::DataSourceSurface>
109 GetAsSourceSurface() {
110 return nullptr;
113 virtual nsresult BuildSurfaceDescriptorBuffer(
114 mozilla::layers::SurfaceDescriptorBuffer& aSdBuffer,
115 mozilla::layers::Image::BuildSdbFlags aFlags,
116 const std::function<mozilla::layers::MemoryOrShmem(uint32_t)>& aAllocate);
118 virtual mozilla::gfx::YUVColorSpace GetYUVColorSpace() {
119 return mozilla::gfx::YUVColorSpace::Default;
122 bool IsFullRange() { return mColorRange == mozilla::gfx::ColorRange::FULL; };
123 void SetColorRange(mozilla::gfx::ColorRange aColorRange) {
124 mColorRange = aColorRange;
127 void FenceSet();
128 void FenceWait();
129 void FenceDelete();
131 // Set and get a global surface UID. The UID is shared across process
132 // and it's used to track surface lifetime in various parts of rendering
133 // engine.
134 uint32_t GetUID() const { return mUID; };
136 // Creates a global reference counter objects attached to the surface.
137 // It's created as unreferenced, i.e. IsGlobalRefSet() returns false
138 // right after GlobalRefCountCreate() call.
140 // The counter is shared by all surface instances across processes
141 // so it tracks global surface usage.
143 // The counter is automatically referenced when a new surface instance is
144 // created with SurfaceDescriptor (usually copied to another process over IPC)
145 // and it's unreferenced when surface is deleted.
147 // So without any additional GlobalRefAdd()/GlobalRefRelease() calls
148 // the IsGlobalRefSet() returns true if any other process use the surface.
149 void GlobalRefCountCreate();
150 void GlobalRefCountDelete();
152 // If global reference counter was created by GlobalRefCountCreate()
153 // returns true when there's an active surface reference.
154 bool IsGlobalRefSet() const;
156 // Add/Remove additional reference to the surface global reference counter.
157 void GlobalRefAdd();
158 void GlobalRefRelease();
160 // Release all underlying data.
161 virtual void ReleaseSurface() = 0;
163 #ifdef DEBUG
164 virtual void DumpToFile(const char* pFile){};
165 #endif
167 DMABufSurface(SurfaceType aSurfaceType);
169 protected:
170 virtual bool Create(const mozilla::layers::SurfaceDescriptor& aDesc) = 0;
172 // Import global ref count object from IPC by file descriptor.
173 // This adds global ref count reference to the surface.
174 void GlobalRefCountImport(int aFd);
175 // Export global ref count object by file descriptor.
176 int GlobalRefCountExport();
178 void ReleaseDMABuf();
180 void* MapInternal(uint32_t aX, uint32_t aY, uint32_t aWidth, uint32_t aHeight,
181 uint32_t* aStride, int aGbmFlags, int aPlane = 0);
183 // We want to keep number of opened file descriptors low so open/close
184 // DMABuf file handles only when we need them, i.e. when DMABuf is exported
185 // to another process or to EGL.
186 virtual bool OpenFileDescriptorForPlane(
187 const mozilla::MutexAutoLock& aProofOfLock, int aPlane) = 0;
188 virtual void CloseFileDescriptorForPlane(
189 const mozilla::MutexAutoLock& aProofOfLock, int aPlane,
190 bool aForceClose = false) = 0;
191 bool OpenFileDescriptors(const mozilla::MutexAutoLock& aProofOfLock);
192 void CloseFileDescriptors(const mozilla::MutexAutoLock& aProofOfLock,
193 bool aForceClose = false);
195 virtual ~DMABufSurface();
197 SurfaceType mSurfaceType;
198 uint64_t mBufferModifiers[DMABUF_BUFFER_PLANES];
200 int mBufferPlaneCount;
201 int mDmabufFds[DMABUF_BUFFER_PLANES];
202 int32_t mDrmFormats[DMABUF_BUFFER_PLANES];
203 int32_t mStrides[DMABUF_BUFFER_PLANES];
204 int32_t mOffsets[DMABUF_BUFFER_PLANES];
206 struct gbm_bo* mGbmBufferObject[DMABUF_BUFFER_PLANES];
207 void* mMappedRegion[DMABUF_BUFFER_PLANES];
208 void* mMappedRegionData[DMABUF_BUFFER_PLANES];
209 uint32_t mMappedRegionStride[DMABUF_BUFFER_PLANES];
211 int mSyncFd;
212 EGLSyncKHR mSync;
213 RefPtr<mozilla::gl::GLContext> mGL;
215 int mGlobalRefCountFd;
216 uint32_t mUID;
217 mozilla::Mutex mSurfaceLock MOZ_UNANNOTATED;
219 mozilla::gfx::ColorRange mColorRange = mozilla::gfx::ColorRange::LIMITED;
222 class DMABufSurfaceRGBA final : public DMABufSurface {
223 public:
224 static already_AddRefed<DMABufSurfaceRGBA> CreateDMABufSurface(
225 int aWidth, int aHeight, int aDMABufSurfaceFlags);
227 static already_AddRefed<DMABufSurface> CreateDMABufSurface(
228 mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage,
229 int aWidth, int aHeight);
231 bool Serialize(mozilla::layers::SurfaceDescriptor& aOutDescriptor) override;
233 DMABufSurfaceRGBA* GetAsDMABufSurfaceRGBA() override { return this; }
235 void Clear();
237 void ReleaseSurface() override;
239 bool CopyFrom(class DMABufSurface* aSourceSurface);
241 int GetWidth(int aPlane = 0) override { return mWidth; };
242 int GetHeight(int aPlane = 0) override { return mHeight; };
243 mozilla::gfx::SurfaceFormat GetFormat() override;
244 mozilla::gfx::SurfaceFormat GetFormatGL() override;
245 bool HasAlpha();
247 void* MapReadOnly(uint32_t aX, uint32_t aY, uint32_t aWidth, uint32_t aHeight,
248 uint32_t* aStride = nullptr);
249 void* MapReadOnly(uint32_t* aStride = nullptr);
250 void* Map(uint32_t aX, uint32_t aY, uint32_t aWidth, uint32_t aHeight,
251 uint32_t* aStride = nullptr);
252 void* Map(uint32_t* aStride = nullptr);
253 void* GetMappedRegion(int aPlane = 0) { return mMappedRegion[aPlane]; };
254 uint32_t GetMappedRegionStride(int aPlane = 0) {
255 return mMappedRegionStride[aPlane];
258 bool CreateTexture(mozilla::gl::GLContext* aGLContext,
259 int aPlane = 0) override;
260 void ReleaseTextures() override;
261 GLuint GetTexture(int aPlane = 0) override { return mTexture; };
262 EGLImageKHR GetEGLImage(int aPlane = 0) override { return mEGLImage; };
264 #ifdef MOZ_WAYLAND
265 bool CreateWlBuffer();
266 void ReleaseWlBuffer();
267 wl_buffer* GetWlBuffer() { return mWlBuffer; };
268 #endif
270 int GetTextureCount() override { return 1; };
272 #ifdef DEBUG
273 void DumpToFile(const char* pFile) override;
274 #endif
276 DMABufSurfaceRGBA();
278 private:
279 DMABufSurfaceRGBA(const DMABufSurfaceRGBA&) = delete;
280 DMABufSurfaceRGBA& operator=(const DMABufSurfaceRGBA&) = delete;
281 ~DMABufSurfaceRGBA();
283 bool Create(int aWidth, int aHeight, int aDMABufSurfaceFlags);
284 bool Create(const mozilla::layers::SurfaceDescriptor& aDesc) override;
285 bool Create(mozilla::gl::GLContext* aGLContext, const EGLImageKHR aEGLImage,
286 int aWidth, int aHeight);
288 bool ImportSurfaceDescriptor(const mozilla::layers::SurfaceDescriptor& aDesc);
290 bool OpenFileDescriptorForPlane(const mozilla::MutexAutoLock& aProofOfLock,
291 int aPlane) override;
292 void CloseFileDescriptorForPlane(const mozilla::MutexAutoLock& aProofOfLock,
293 int aPlane, bool aForceClose) override;
295 private:
296 int mSurfaceFlags;
298 int mWidth;
299 int mHeight;
300 mozilla::widget::GbmFormat* mGmbFormat;
302 EGLImageKHR mEGLImage;
303 GLuint mTexture;
304 uint32_t mGbmBufferFlags;
305 #ifdef MOZ_WAYLAND
306 wl_buffer* mWlBuffer = nullptr;
307 #endif
310 class DMABufSurfaceYUV final : public DMABufSurface {
311 public:
312 static already_AddRefed<DMABufSurfaceYUV> CreateYUVSurface(
313 int aWidth, int aHeight, void** aPixelData = nullptr,
314 int* aLineSizes = nullptr);
315 static already_AddRefed<DMABufSurfaceYUV> CreateYUVSurface(
316 const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth, int aHeight);
317 static already_AddRefed<DMABufSurfaceYUV> CopyYUVSurface(
318 const VADRMPRIMESurfaceDescriptor& aVaDesc, int aWidth, int aHeight);
319 static void ReleaseVADRMPRIMESurfaceDescriptor(
320 VADRMPRIMESurfaceDescriptor& aDesc);
322 bool Serialize(mozilla::layers::SurfaceDescriptor& aOutDescriptor) override;
324 DMABufSurfaceYUV* GetAsDMABufSurfaceYUV() override { return this; };
325 already_AddRefed<mozilla::gfx::DataSourceSurface> GetAsSourceSurface()
326 override;
328 nsresult BuildSurfaceDescriptorBuffer(
329 mozilla::layers::SurfaceDescriptorBuffer& aSdBuffer,
330 mozilla::layers::Image::BuildSdbFlags aFlags,
331 const std::function<mozilla::layers::MemoryOrShmem(uint32_t)>& aAllocate)
332 override;
334 int GetWidth(int aPlane = 0) override { return mWidth[aPlane]; }
335 int GetHeight(int aPlane = 0) override { return mHeight[aPlane]; }
336 mozilla::gfx::SurfaceFormat GetFormat() override;
337 mozilla::gfx::SurfaceFormat GetFormatGL() override;
339 bool CreateTexture(mozilla::gl::GLContext* aGLContext,
340 int aPlane = 0) override;
341 void ReleaseTextures() override;
343 void ReleaseSurface() override;
345 GLuint GetTexture(int aPlane = 0) override { return mTexture[aPlane]; };
346 EGLImageKHR GetEGLImage(int aPlane = 0) override {
347 return mEGLImage[aPlane];
350 int GetTextureCount() override;
352 void SetYUVColorSpace(mozilla::gfx::YUVColorSpace aColorSpace) {
353 mColorSpace = aColorSpace;
355 mozilla::gfx::YUVColorSpace GetYUVColorSpace() override {
356 return mColorSpace;
359 DMABufSurfaceYUV();
361 bool UpdateYUVData(void** aPixelData, int* aLineSizes);
362 bool UpdateYUVData(const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth,
363 int aHeight, bool aCopy);
364 bool VerifyTextureCreation();
366 private:
367 DMABufSurfaceYUV(const DMABufSurfaceYUV&) = delete;
368 DMABufSurfaceYUV& operator=(const DMABufSurfaceYUV&) = delete;
369 ~DMABufSurfaceYUV();
371 bool Create(const mozilla::layers::SurfaceDescriptor& aDesc) override;
372 bool Create(int aWidth, int aHeight, void** aPixelData, int* aLineSizes);
373 bool CreateYUVPlane(int aPlane);
374 bool CreateLinearYUVPlane(int aPlane, int aWidth, int aHeight,
375 int aDrmFormat);
376 void UpdateYUVPlane(int aPlane, void* aPixelData, int aLineSize);
378 bool MoveYUVDataImpl(const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth,
379 int aHeight);
380 bool CopyYUVDataImpl(const VADRMPRIMESurfaceDescriptor& aDesc, int aWidth,
381 int aHeight);
383 bool ImportPRIMESurfaceDescriptor(const VADRMPRIMESurfaceDescriptor& aDesc,
384 int aWidth, int aHeight);
385 bool ImportSurfaceDescriptor(
386 const mozilla::layers::SurfaceDescriptorDMABuf& aDesc);
388 bool OpenFileDescriptorForPlane(const mozilla::MutexAutoLock& aProofOfLock,
389 int aPlane) override;
390 void CloseFileDescriptorForPlane(const mozilla::MutexAutoLock& aProofOfLock,
391 int aPlane, bool aForceClose) override;
393 bool CreateEGLImage(mozilla::gl::GLContext* aGLContext, int aPlane);
394 void ReleaseEGLImages(mozilla::gl::GLContext* aGLContext);
396 nsresult ReadIntoBuffer(uint8_t* aData, int32_t aStride,
397 const mozilla::gfx::IntSize& aSize,
398 mozilla::gfx::SurfaceFormat aFormat);
400 int mWidth[DMABUF_BUFFER_PLANES];
401 int mHeight[DMABUF_BUFFER_PLANES];
402 // Aligned size of the surface imported from VADRMPRIMESurfaceDescriptor.
403 // It's used only internally to create EGLImage as some GL drivers
404 // needs that (Bug 1724385).
405 int mWidthAligned[DMABUF_BUFFER_PLANES];
406 int mHeightAligned[DMABUF_BUFFER_PLANES];
407 EGLImageKHR mEGLImage[DMABUF_BUFFER_PLANES];
408 GLuint mTexture[DMABUF_BUFFER_PLANES];
409 mozilla::gfx::YUVColorSpace mColorSpace =
410 mozilla::gfx::YUVColorSpace::Default;
413 #endif