Bug 1573668 - Add MacIOSurface::GetAsDrawTargetLocked. r=mattwoodrow
authorMarkus Stange <mstange@themasta.com>
Thu, 15 Aug 2019 04:54:57 +0000
changeset 488376 ed710f979ba18daa62f49d25dd8d9ff19fab10d8
parent 488375 840b81a4581e45f2b2e99e759377d35651159720
child 488377 cf470b2c90c8d9b6a46559302cb2ee60ea0e02a6
push id113906
push userncsoregi@mozilla.com
push dateFri, 16 Aug 2019 04:07:24 +0000
treeherdermozilla-inbound@d887276421d3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1573668
milestone70.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1573668 - Add MacIOSurface::GetAsDrawTargetLocked. r=mattwoodrow Differential Revision: https://phabricator.services.mozilla.com/D41844
gfx/2d/MacIOSurface.cpp
gfx/2d/MacIOSurface.h
--- a/gfx/2d/MacIOSurface.cpp
+++ b/gfx/2d/MacIOSurface.cpp
@@ -20,17 +20,20 @@ MacIOSurface::MacIOSurface(CFTypeRefPtr<
                            gfx::YUVColorSpace aColorSpace)
     : mIOSurfaceRef(std::move(aIOSurfaceRef)),
       mContentsScaleFactor(aContentsScaleFactor),
       mHasAlpha(aHasAlpha),
       mColorSpace(aColorSpace) {
   IncrementUseCount();
 }
 
-MacIOSurface::~MacIOSurface() { DecrementUseCount(); }
+MacIOSurface::~MacIOSurface() {
+  MOZ_RELEASE_ASSERT(!IsLocked(), "Destroying locked surface");
+  DecrementUseCount();
+}
 
 /* static */
 already_AddRefed<MacIOSurface> MacIOSurface::CreateIOSurface(
     int aWidth, int aHeight, double aContentsScaleFactor, bool aHasAlpha) {
   if (aContentsScaleFactor <= 0) return nullptr;
 
   CFMutableDictionaryRef props = ::CFDictionaryCreateMutable(
       kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks,
@@ -144,23 +147,27 @@ void MacIOSurface::IncrementUseCount() {
   ::IOSurfaceIncrementUseCount(mIOSurfaceRef.get());
 }
 
 void MacIOSurface::DecrementUseCount() {
   ::IOSurfaceDecrementUseCount(mIOSurfaceRef.get());
 }
 
 void MacIOSurface::Lock(bool aReadOnly) {
+  MOZ_RELEASE_ASSERT(!mIsLocked, "double MacIOSurface lock");
   ::IOSurfaceLock(mIOSurfaceRef.get(), aReadOnly ? kIOSurfaceLockReadOnly : 0,
                   nullptr);
+  mIsLocked = true;
 }
 
 void MacIOSurface::Unlock(bool aReadOnly) {
+  MOZ_RELEASE_ASSERT(mIsLocked, "MacIOSurface unlock without being locked");
   ::IOSurfaceUnlock(mIOSurfaceRef.get(), aReadOnly ? kIOSurfaceLockReadOnly : 0,
                     nullptr);
+  mIsLocked = false;
 }
 
 using mozilla::gfx::IntSize;
 using mozilla::gfx::SourceSurface;
 using mozilla::gfx::SurfaceFormat;
 
 static void MacIOSurfaceBufferDeallocator(void* aClosure) {
   MOZ_ASSERT(aClosure);
@@ -189,16 +196,31 @@ already_AddRefed<SourceSurface> MacIOSur
   RefPtr<mozilla::gfx::DataSourceSurface> surf =
       mozilla::gfx::Factory::CreateWrappingDataSourceSurface(
           dataCpy, bytesPerRow, IntSize(ioWidth, ioHeight), format,
           &MacIOSurfaceBufferDeallocator, static_cast<void*>(dataCpy));
 
   return surf.forget();
 }
 
+already_AddRefed<mozilla::gfx::DrawTarget> MacIOSurface::GetAsDrawTargetLocked(
+    mozilla::gfx::BackendType aBackendType) {
+  MOZ_RELEASE_ASSERT(
+      IsLocked(),
+      "Only call GetAsDrawTargetLocked while the surface is locked.");
+
+  size_t bytesPerRow = GetBytesPerRow();
+  size_t ioWidth = GetDevicePixelWidth();
+  size_t ioHeight = GetDevicePixelHeight();
+  unsigned char* ioData = (unsigned char*)GetBaseAddress();
+  SurfaceFormat format = GetFormat();
+  return mozilla::gfx::Factory::CreateDrawTargetForData(
+      aBackendType, ioData, IntSize(ioWidth, ioHeight), bytesPerRow, format);
+}
+
 SurfaceFormat MacIOSurface::GetFormat() const {
   switch (GetPixelFormat()) {
     case kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange:
     case kCVPixelFormatType_420YpCbCr8BiPlanarFullRange:
       return SurfaceFormat::NV12;
     case kCVPixelFormatType_422YpCbCr8:
       return SurfaceFormat::YUV422;
     case kCVPixelFormatType_32BGRA:
--- a/gfx/2d/MacIOSurface.h
+++ b/gfx/2d/MacIOSurface.h
@@ -41,16 +41,18 @@ typedef int CGLError;
 #  include "mozilla/RefCounted.h"
 #  include "mozilla/RefPtr.h"
 
 class MacIOSurface final
     : public mozilla::external::AtomicRefCounted<MacIOSurface> {
  public:
   MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(MacIOSurface)
   typedef mozilla::gfx::SourceSurface SourceSurface;
+  typedef mozilla::gfx::DrawTarget DrawTarget;
+  typedef mozilla::gfx::BackendType BackendType;
 
   // The usage count of the IOSurface is increased by 1 during the lifetime
   // of the MacIOSurface instance.
   // MacIOSurface holds a reference to the corresponding IOSurface.
 
   static already_AddRefed<MacIOSurface> CreateIOSurface(
       int aWidth, int aHeight, double aContentsScaleFactor = 1.0,
       bool aHasAlpha = true);
@@ -79,16 +81,17 @@ class MacIOSurface final
   size_t GetWidth(size_t plane = 0) const;
   size_t GetHeight(size_t plane = 0) const;
   double GetContentsScaleFactor() const { return mContentsScaleFactor; }
   size_t GetDevicePixelWidth(size_t plane = 0) const;
   size_t GetDevicePixelHeight(size_t plane = 0) const;
   size_t GetBytesPerRow(size_t plane = 0) const;
   void Lock(bool aReadOnly = true);
   void Unlock(bool aReadOnly = true);
+  bool IsLocked() const { return mIsLocked; }
   void IncrementUseCount();
   void DecrementUseCount();
   bool HasAlpha() const { return mHasAlpha; }
   mozilla::gfx::SurfaceFormat GetFormat() const;
   mozilla::gfx::SurfaceFormat GetReadFormat() const;
   // This would be better suited on MacIOSurfaceImage type, however due to the
   // current data structure, this is not possible as only the IOSurfaceRef is
   // being used across.
@@ -106,22 +109,32 @@ class MacIOSurface final
       mozilla::gl::GLContext* aGL, CGLContextObj ctxt, size_t plane,
       mozilla::gfx::SurfaceFormat* aOutReadFormat = nullptr);
   CGLError CGLTexImageIOSurface2D(CGLContextObj ctxt, GLenum target,
                                   GLenum internalFormat, GLsizei width,
                                   GLsizei height, GLenum format, GLenum type,
                                   GLuint plane) const;
   already_AddRefed<SourceSurface> GetAsSurface();
 
+  // Creates a DrawTarget that wraps the data in the IOSurface. Rendering to
+  // this DrawTarget directly manipulates the contents of the IOSurface.
+  // Only call when the surface is already locked for writing!
+  // The returned DrawTarget must only be used while the surface is still
+  // locked.
+  // Also, only call this if you're reasonably sure that the DrawTarget of the
+  // selected backend supports the IOSurface's SurfaceFormat.
+  already_AddRefed<DrawTarget> GetAsDrawTargetLocked(BackendType aBackendType);
+
   static size_t GetMaxWidth();
   static size_t GetMaxHeight();
   CFTypeRefPtr<IOSurfaceRef> GetIOSurfaceRef() { return mIOSurfaceRef; }
 
  private:
   CFTypeRefPtr<IOSurfaceRef> mIOSurfaceRef;
   double mContentsScaleFactor;
   bool mHasAlpha;
+  bool mIsLocked = false;
   mozilla::gfx::YUVColorSpace mColorSpace =
       mozilla::gfx::YUVColorSpace::UNKNOWN;
 };
 
 #endif
 #endif