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/. */ 6 7 #ifndef DMABufSurface_h__ 8 #define DMABufSurface_h__ 9 10 #include <stdint.h> 11 #include "mozilla/widget/nsWaylandDisplay.h" 12 #include "mozilla/widget/va_drmcommon.h" 13 #include "GLTypes.h" 14 15 typedef void* EGLImageKHR; 16 typedef void* EGLSyncKHR; 17 18 #define DMABUF_BUFFER_PLANES 4 19 20 namespace mozilla { 21 namespace layers { 22 class SurfaceDescriptor; 23 class SurfaceDescriptorDMABuf; 24 } // namespace layers 25 namespace gl { 26 class GLContext; 27 } 28 } // namespace mozilla 29 30 typedef enum { 31 // Use alpha pixel format 32 DMABUF_ALPHA = 1 << 0, 33 // Surface is used as texture and may be also shared 34 DMABUF_TEXTURE = 1 << 1, 35 // Use modifiers. Such dmabuf surface may have more planes 36 // and complex internal structure (tiling/compression/etc.) 37 // so we can't do direct rendering to it. 38 DMABUF_USE_MODIFIERS = 1 << 3, 39 } DMABufSurfaceFlags; 40 41 class DMABufSurfaceRGBA; 42 class DMABufSurfaceYUV; 43 44 class DMABufSurface { 45 public: 46 NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DMABufSurface) 47 48 enum SurfaceType { 49 SURFACE_RGBA, 50 SURFACE_NV12, 51 SURFACE_YUV420, 52 }; 53 54 // Import surface from SurfaceDescriptor. This is usually 55 // used to copy surface from another process over IPC. 56 // When a global reference counter was created for the surface 57 // (see bellow) it's automatically referenced. 58 static already_AddRefed<DMABufSurface> CreateDMABufSurface( 59 const mozilla::layers::SurfaceDescriptor& aDesc); 60 61 // Export surface to another process via. SurfaceDescriptor. 62 virtual bool Serialize( 63 mozilla::layers::SurfaceDescriptor& aOutDescriptor) = 0; 64 65 virtual int GetWidth(int aPlane = 0) = 0; 66 virtual int GetHeight(int aPlane = 0) = 0; 67 virtual mozilla::gfx::SurfaceFormat GetFormat() = 0; 68 virtual mozilla::gfx::SurfaceFormat GetFormatGL() = 0; 69 70 virtual bool CreateTexture(mozilla::gl::GLContext* aGLContext, 71 int aPlane = 0) = 0; 72 virtual void ReleaseTextures() = 0; 73 virtual GLuint GetTexture(int aPlane = 0) = 0; 74 virtual EGLImageKHR GetEGLImage(int aPlane = 0) = 0; 75 GetSurfaceType()76 SurfaceType GetSurfaceType() { return mSurfaceType; }; 77 virtual uint32_t GetTextureCount() = 0; 78 79 bool IsMapped(int aPlane = 0) { return (mMappedRegion[aPlane] != nullptr); }; 80 void Unmap(int aPlane = 0); 81 GetAsDMABufSurfaceRGBA()82 virtual DMABufSurfaceRGBA* GetAsDMABufSurfaceRGBA() { return nullptr; } GetAsDMABufSurfaceYUV()83 virtual DMABufSurfaceYUV* GetAsDMABufSurfaceYUV() { return nullptr; } 84 GetYUVColorSpace()85 virtual mozilla::gfx::YUVColorSpace GetYUVColorSpace() { 86 return mozilla::gfx::YUVColorSpace::Default; 87 }; IsFullRange()88 virtual bool IsFullRange() { return false; }; 89 90 void FenceSet(); 91 void FenceWait(); 92 void FenceDelete(); 93 94 // Set and get a global surface UID. The UID is shared across process 95 // and it's used to track surface lifetime in various parts of rendering 96 // engine. GetUID()97 uint32_t GetUID() const { return mUID; }; 98 99 // Creates a global reference counter objects attached to the surface. 100 // It's created as unreferenced, i.e. IsGlobalRefSet() returns false 101 // right after GlobalRefCountCreate() call. 102 // 103 // The counter is shared by all surface instances across processes 104 // so it tracks global surface usage. 105 // 106 // The counter is automatically referenced when a new surface instance is 107 // created with SurfaceDescriptor (usually copied to another process over IPC) 108 // and it's unreferenced when surface is deleted. 109 // 110 // So without any additional GlobalRefAdd()/GlobalRefRelease() calls 111 // the IsGlobalRefSet() returns true if any other process use the surface. 112 void GlobalRefCountCreate(); 113 114 // If global reference counter was created by GlobalRefCountCreate() 115 // returns true when there's an active surface reference. 116 bool IsGlobalRefSet() const; 117 118 // Add/Remove additional reference to the surface global reference counter. 119 void GlobalRefAdd(); 120 void GlobalRefRelease(); 121 122 // Release all underlying data. 123 virtual void ReleaseSurface() = 0; 124 125 #ifdef DEBUG DumpToFile(const char * pFile)126 virtual void DumpToFile(const char* pFile){}; 127 #endif 128 129 DMABufSurface(SurfaceType aSurfaceType); 130 131 protected: 132 virtual bool Create(const mozilla::layers::SurfaceDescriptor& aDesc) = 0; 133 bool FenceImportFromFd(); 134 135 void GlobalRefCountImport(int aFd); 136 void GlobalRefCountDelete(); 137 138 void ReleaseDMABuf(); 139 140 void* MapInternal(uint32_t aX, uint32_t aY, uint32_t aWidth, uint32_t aHeight, 141 uint32_t* aStride, int aGbmFlags, int aPlane = 0); 142 143 // We want to keep number of opened file descriptors low so open/close 144 // DMABuf file handles only when we need them, i.e. when DMABuf is exported 145 // to another process or to EGL. 146 virtual bool OpenFileDescriptorForPlane(int aPlane) = 0; 147 virtual void CloseFileDescriptorForPlane(int aPlane, 148 bool aForceClose = false) = 0; 149 bool OpenFileDescriptors(); 150 void CloseFileDescriptors(bool aForceClose = false); 151 152 virtual ~DMABufSurface(); 153 154 SurfaceType mSurfaceType; 155 uint64_t mBufferModifier; 156 157 int mBufferPlaneCount; 158 int mDmabufFds[DMABUF_BUFFER_PLANES]; 159 uint32_t mDrmFormats[DMABUF_BUFFER_PLANES]; 160 uint32_t mStrides[DMABUF_BUFFER_PLANES]; 161 uint32_t mOffsets[DMABUF_BUFFER_PLANES]; 162 163 struct gbm_bo* mGbmBufferObject[DMABUF_BUFFER_PLANES]; 164 void* mMappedRegion[DMABUF_BUFFER_PLANES]; 165 void* mMappedRegionData[DMABUF_BUFFER_PLANES]; 166 uint32_t mMappedRegionStride[DMABUF_BUFFER_PLANES]; 167 168 int mSyncFd; 169 EGLSyncKHR mSync; 170 RefPtr<mozilla::gl::GLContext> mGL; 171 172 int mGlobalRefCountFd; 173 uint32_t mUID; 174 mozilla::Mutex mSurfaceLock; 175 }; 176 177 class DMABufSurfaceRGBA : public DMABufSurface { 178 public: 179 static already_AddRefed<DMABufSurfaceRGBA> CreateDMABufSurface( 180 int aWidth, int aHeight, int aDMABufSurfaceFlags); 181 182 bool Serialize(mozilla::layers::SurfaceDescriptor& aOutDescriptor); 183 GetAsDMABufSurfaceRGBA()184 DMABufSurfaceRGBA* GetAsDMABufSurfaceRGBA() { return this; } 185 186 void Clear(); 187 188 void ReleaseSurface(); 189 190 bool CopyFrom(class DMABufSurface* aSourceSurface); 191 192 int GetWidth(int aPlane = 0) { return mWidth; }; 193 int GetHeight(int aPlane = 0) { return mHeight; }; 194 mozilla::gfx::SurfaceFormat GetFormat(); 195 mozilla::gfx::SurfaceFormat GetFormatGL(); 196 bool HasAlpha(); 197 198 void* MapReadOnly(uint32_t aX, uint32_t aY, uint32_t aWidth, uint32_t aHeight, 199 uint32_t* aStride = nullptr); 200 void* MapReadOnly(uint32_t* aStride = nullptr); 201 void* Map(uint32_t aX, uint32_t aY, uint32_t aWidth, uint32_t aHeight, 202 uint32_t* aStride = nullptr); 203 void* Map(uint32_t* aStride = nullptr); 204 void* GetMappedRegion(int aPlane = 0) { return mMappedRegion[aPlane]; }; 205 uint32_t GetMappedRegionStride(int aPlane = 0) { 206 return mMappedRegionStride[aPlane]; 207 }; 208 209 bool CreateTexture(mozilla::gl::GLContext* aGLContext, int aPlane = 0); 210 void ReleaseTextures(); 211 GLuint GetTexture(int aPlane = 0) { return mTexture; }; 212 EGLImageKHR GetEGLImage(int aPlane = 0) { return mEGLImage; }; 213 GetTextureCount()214 uint32_t GetTextureCount() { return 1; }; 215 216 #ifdef DEBUG 217 virtual void DumpToFile(const char* pFile); 218 #endif 219 220 DMABufSurfaceRGBA(); 221 222 private: 223 ~DMABufSurfaceRGBA(); 224 225 bool Create(int aWidth, int aHeight, int aDMABufSurfaceFlags); 226 bool Create(const mozilla::layers::SurfaceDescriptor& aDesc); 227 228 bool ImportSurfaceDescriptor(const mozilla::layers::SurfaceDescriptor& aDesc); 229 230 bool OpenFileDescriptorForPlane(int aPlane); 231 void CloseFileDescriptorForPlane(int aPlane, bool aForceClose); 232 233 private: 234 int mSurfaceFlags; 235 236 int mWidth; 237 int mHeight; 238 mozilla::widget::GbmFormat* mGmbFormat; 239 240 EGLImageKHR mEGLImage; 241 GLuint mTexture; 242 uint32_t mGbmBufferFlags; 243 }; 244 245 class DMABufSurfaceYUV : public DMABufSurface { 246 public: 247 static already_AddRefed<DMABufSurfaceYUV> CreateYUVSurface( 248 int aWidth, int aHeight, void** aPixelData = nullptr, 249 int* aLineSizes = nullptr); 250 251 static already_AddRefed<DMABufSurfaceYUV> CreateYUVSurface( 252 const VADRMPRIMESurfaceDescriptor& aDesc); 253 254 bool Serialize(mozilla::layers::SurfaceDescriptor& aOutDescriptor); 255 GetAsDMABufSurfaceYUV()256 DMABufSurfaceYUV* GetAsDMABufSurfaceYUV() { return this; }; 257 258 int GetWidth(int aPlane = 0) { return mWidth[aPlane]; } 259 int GetHeight(int aPlane = 0) { return mHeight[aPlane]; } 260 mozilla::gfx::SurfaceFormat GetFormat(); 261 mozilla::gfx::SurfaceFormat GetFormatGL(); 262 263 bool CreateTexture(mozilla::gl::GLContext* aGLContext, int aPlane = 0); 264 void ReleaseTextures(); 265 266 void ReleaseSurface(); 267 268 GLuint GetTexture(int aPlane = 0) { return mTexture[aPlane]; }; 269 EGLImageKHR GetEGLImage(int aPlane = 0) { return mEGLImage[aPlane]; }; 270 271 uint32_t GetTextureCount(); 272 SetYUVColorSpace(mozilla::gfx::YUVColorSpace aColorSpace)273 void SetYUVColorSpace(mozilla::gfx::YUVColorSpace aColorSpace) { 274 mColorSpace = aColorSpace; 275 } GetYUVColorSpace()276 mozilla::gfx::YUVColorSpace GetYUVColorSpace() { return mColorSpace; } 277 IsFullRange()278 bool IsFullRange() { return true; } 279 280 DMABufSurfaceYUV(); 281 282 bool UpdateYUVData(void** aPixelData, int* aLineSizes); 283 bool UpdateYUVData(const VADRMPRIMESurfaceDescriptor& aDesc); 284 285 private: 286 ~DMABufSurfaceYUV(); 287 288 bool Create(const mozilla::layers::SurfaceDescriptor& aDesc); 289 bool Create(int aWidth, int aHeight, void** aPixelData, int* aLineSizes); 290 bool CreateYUVPlane(int aPlane, int aWidth, int aHeight, int aDrmFormat); 291 void UpdateYUVPlane(int aPlane, void* aPixelData, int aLineSize); 292 293 bool ImportSurfaceDescriptor( 294 const mozilla::layers::SurfaceDescriptorDMABuf& aDesc); 295 296 bool OpenFileDescriptorForPlane(int aPlane); 297 void CloseFileDescriptorForPlane(int aPlane, bool aForceClose); 298 299 int mWidth[DMABUF_BUFFER_PLANES]; 300 int mHeight[DMABUF_BUFFER_PLANES]; 301 EGLImageKHR mEGLImage[DMABUF_BUFFER_PLANES]; 302 GLuint mTexture[DMABUF_BUFFER_PLANES]; 303 mozilla::gfx::YUVColorSpace mColorSpace = 304 mozilla::gfx::YUVColorSpace::Default; 305 }; 306 307 #endif 308