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__
12 #include "mozilla/widget/va_drmcommon.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
27 #ifndef VA_FOURCC_YV12
28 # define VA_FOURCC_YV12 0x32315659
30 #ifndef VA_FOURCC_P010
31 # define VA_FOURCC_P010 0x30313050
36 class DataSourceSurface
;
40 class SurfaceDescriptor
;
41 class SurfaceDescriptorBuffer
;
42 class SurfaceDescriptorDMABuf
;
47 } // namespace mozilla
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,
60 class DMABufSurfaceRGBA
;
61 class DMABufSurfaceYUV
;
64 namespace mozilla::widget
{
70 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DMABufSurface
)
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
,
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() {
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
;
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
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.
158 void GlobalRefRelease();
160 // Release all underlying data.
161 virtual void ReleaseSurface() = 0;
164 virtual void DumpToFile(const char* pFile
){};
167 DMABufSurface(SurfaceType aSurfaceType
);
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
];
213 RefPtr
<mozilla::gl::GLContext
> mGL
;
215 int mGlobalRefCountFd
;
217 mozilla::Mutex mSurfaceLock MOZ_UNANNOTATED
;
219 mozilla::gfx::ColorRange mColorRange
= mozilla::gfx::ColorRange::LIMITED
;
222 class DMABufSurfaceRGBA final
: public DMABufSurface
{
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; }
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
;
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
; };
265 bool CreateWlBuffer();
266 void ReleaseWlBuffer();
267 wl_buffer
* GetWlBuffer() { return mWlBuffer
; };
270 int GetTextureCount() override
{ return 1; };
273 void DumpToFile(const char* pFile
) override
;
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
;
300 mozilla::widget::GbmFormat
* mGmbFormat
;
302 EGLImageKHR mEGLImage
;
304 uint32_t mGbmBufferFlags
;
306 wl_buffer
* mWlBuffer
= nullptr;
310 class DMABufSurfaceYUV final
: public DMABufSurface
{
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()
328 nsresult
BuildSurfaceDescriptorBuffer(
329 mozilla::layers::SurfaceDescriptorBuffer
& aSdBuffer
,
330 mozilla::layers::Image::BuildSdbFlags aFlags
,
331 const std::function
<mozilla::layers::MemoryOrShmem(uint32_t)>& aAllocate
)
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
{
361 bool UpdateYUVData(void** aPixelData
, int* aLineSizes
);
362 bool UpdateYUVData(const VADRMPRIMESurfaceDescriptor
& aDesc
, int aWidth
,
363 int aHeight
, bool aCopy
);
364 bool VerifyTextureCreation();
367 DMABufSurfaceYUV(const DMABufSurfaceYUV
&) = delete;
368 DMABufSurfaceYUV
& operator=(const DMABufSurfaceYUV
&) = delete;
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
,
376 void UpdateYUVPlane(int aPlane
, void* aPixelData
, int aLineSize
);
378 bool MoveYUVDataImpl(const VADRMPRIMESurfaceDescriptor
& aDesc
, int aWidth
,
380 bool CopyYUVDataImpl(const VADRMPRIMESurfaceDescriptor
& aDesc
, int aWidth
,
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
;