Bug 1057216 - Make DrawTargetCG hold a reference to DataSourceSurface when we're wrapping their data. r=jrmuizel
authorMatt Woodrow <mwoodrow@mozilla.com>
Wed, 27 Aug 2014 10:20:18 +1200
changeset 224655 c9e48790f6fa33dd04dfa1ce0009a5658dc2a636
parent 224654 247755b96ab8513391ca537fbe82e24f68ac7167
child 224656 5ee7a98d1e2fe5fd290f23bad457a1b098331fa5
push idunknown
push userunknown
push dateunknown
reviewersjrmuizel
bugs1057216
milestone34.0a1
Bug 1057216 - Make DrawTargetCG hold a reference to DataSourceSurface when we're wrapping their data. r=jrmuizel
gfx/2d/DrawTargetCG.cpp
gfx/2d/SourceSurfaceCG.cpp
gfx/2d/SourceSurfaceCG.h
--- a/gfx/2d/DrawTargetCG.cpp
+++ b/gfx/2d/DrawTargetCG.cpp
@@ -210,16 +210,21 @@ DrawTargetCG::CreateSourceSurfaceFromDat
 
   if (!newSurf->InitFromData(aData, aSize, aStride, aFormat)) {
     return nullptr;
   }
 
   return newSurf.forget();
 }
 
+static void releaseDataSurface(void* info, const void *data, size_t size)
+{
+  static_cast<DataSourceSurface*>(info)->Release();
+}
+
 // This function returns a retained CGImage that needs to be released after
 // use. The reason for this is that we want to either reuse an existing CGImage
 // or create a new one.
 static CGImageRef
 GetRetainedImageFromSourceSurface(SourceSurface *aSurface)
 {
   switch(aSurface->GetType()) {
     case SurfaceType::COREGRAPHICS_IMAGE:
@@ -229,17 +234,19 @@ GetRetainedImageFromSourceSurface(Source
       return CGImageRetain(static_cast<SourceSurfaceCGContext*>(aSurface)->GetImage());
 
     default:
     {
       RefPtr<DataSourceSurface> data = aSurface->GetDataSurface();
       if (!data) {
         MOZ_CRASH("unsupported source surface");
       }
-      return CreateCGImage(nullptr, data->GetData(), data->GetSize(),
+      data->AddRef();
+      return CreateCGImage(releaseDataSurface, data.get(),
+                           data->GetData(), data->GetSize(),
                            data->Stride(), data->GetFormat());
     }
   }
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetCG::OptimizeSourceSurface(SourceSurface *aSurface) const
 {
--- a/gfx/2d/SourceSurfaceCG.cpp
+++ b/gfx/2d/SourceSurfaceCG.cpp
@@ -54,16 +54,32 @@ static void releaseCallback(void *info, 
 
 CGImageRef
 CreateCGImage(void *aInfo,
               const void *aData,
               const IntSize &aSize,
               int32_t aStride,
               SurfaceFormat aFormat)
 {
+  return CreateCGImage(releaseCallback,
+                       aInfo,
+                       aData,
+                       aSize,
+                       aStride,
+                       aFormat);
+}
+
+CGImageRef
+CreateCGImage(CGDataProviderReleaseDataCallback aCallback,
+              void *aInfo,
+              const void *aData,
+              const IntSize &aSize,
+              int32_t aStride,
+              SurfaceFormat aFormat)
+{
   //XXX: we should avoid creating this colorspace everytime
   CGColorSpaceRef colorSpace = nullptr;
   CGBitmapInfo bitinfo = 0;
   int bitsPerComponent = 0;
   int bitsPerPixel = 0;
 
   switch (aFormat) {
     case SurfaceFormat::B8G8R8A8:
@@ -92,17 +108,17 @@ CreateCGImage(void *aInfo,
 
   size_t bufLen = BufferSizeFromStrideAndHeight(aStride, aSize.height);
   if (bufLen == 0) {
     return nullptr;
   }
   CGDataProviderRef dataProvider = CGDataProviderCreateWithData(aInfo,
                                                                 aData,
                                                                 bufLen,
-                                                                releaseCallback);
+                                                                aCallback);
 
   CGImageRef image;
   if (aFormat == SurfaceFormat::A8) {
     CGFloat decode[] = {1.0, 0.0};
     image = CGImageMaskCreate (aSize.width, aSize.height,
                                bitsPerComponent,
                                bitsPerPixel,
                                aStride,
--- a/gfx/2d/SourceSurfaceCG.h
+++ b/gfx/2d/SourceSurfaceCG.h
@@ -11,16 +11,24 @@
 #include "2D.h"
 
 class MacIOSurface;
 
 namespace mozilla {
 namespace gfx {
 
 CGImageRef
+CreateCGImage(CGDataProviderReleaseDataCallback aCallback,
+              void *aInfo,
+              const void *aData,
+              const IntSize &aSize,
+              int32_t aStride,
+              SurfaceFormat aFormat);
+
+CGImageRef
 CreateCGImage(void *aInfo,
               const void *aData,
               const IntSize &aSize,
               int32_t aStride,
               SurfaceFormat aFormat);
 
 class DrawTargetCG;