make SkDeviceFactory reference counted
authormike@reedtribe.org <mike@reedtribe.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 26 Apr 2011 11:48:33 +0000 (11:48 +0000)
committermike@reedtribe.org <mike@reedtribe.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 26 Apr 2011 11:48:33 +0000 (11:48 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@1180 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkCanvas.h
include/core/SkDevice.h
include/gpu/SkGpuDevice.h
include/pdf/SkPDFDevice.h
src/core/SkCanvas.cpp
src/core/SkDevice.cpp
src/gpu/SkGpuCanvas.cpp
src/gpu/SkGpuDevice.cpp
src/pdf/SkPDFDevice.cpp

index 6b2ee10e75e57a0ee5ed0d5e3cbde2b0903d4289..b1222eb874b77f38251d966f574f2dbf7116811c 100644 (file)
@@ -126,12 +126,15 @@ public:
     SkDevice* setBitmapDevice(const SkBitmap& bitmap, bool forLayer = false);
 
     /**
-     *  Return the current device factory, or NULL.
+     *  Return the current device factory, or NULL. The reference count of
+     *  the returned factory is not changed.
      */
     SkDeviceFactory* getDeviceFactory() const { return fDeviceFactory; }
 
     /**
-     *  Replace any existing factory with the specified factory.
+     *  Replace any existing factory with the specified factory, unrefing the
+     *  previous (if any), and refing the new one (if any). For convenience,
+     *  the factory parameter is also returned.
      */
     SkDeviceFactory* setDeviceFactory(SkDeviceFactory*);
 
index 5755e955e056e7bbbaf5e4e6e6ad1bce9c7aec32..d9a4fde4c28d657dbeb7e334c4f0d234bb6bd2ff 100644 (file)
@@ -36,8 +36,9 @@ class SkRegion;
     to pass into SkCanvas.  Doing so will eliminate the need to extend
     SkCanvas as well.
 */
-class SK_API SkDeviceFactory {
+class SK_API SkDeviceFactory : public SkRefCnt {
 public:
+    SkDeviceFactory();
     virtual ~SkDeviceFactory();
     virtual SkDevice* newDevice(SkCanvas*, SkBitmap::Config, int width,
                                 int height, bool isOpaque, bool isLayer) = 0;
@@ -65,9 +66,12 @@ public:
     SkDevice(SkCanvas*, const SkBitmap& bitmap, bool forOffscreen);
     virtual ~SkDevice();
 
-    virtual SkDeviceFactory* getDeviceFactory() {
-        return SkNEW(SkRasterDeviceFactory);
-    }
+    /**
+     *  Return the factory that will create this subclass of SkDevice.
+     *  The returned factory is cached by the device, and so its reference count
+     *  is not changed by this call.
+     */
+    SkDeviceFactory* getDeviceFactory();
 
     enum Capabilities {
         kGL_Capability     = 0x1,  //!< mask indicating GL support
@@ -247,6 +251,13 @@ public:
     virtual bool filterTextFlags(const SkPaint& paint, TextFlags*);
 
 protected:
+    /**
+     *  subclasses must override this to return a new (or ref'd) instance of
+     *  a device factory that will create this subclass of device. This value
+     *  is cached, so it should get called at most once for a given instance.
+     */
+    virtual SkDeviceFactory* onNewDeviceFactory();
+
     /** Update as needed the pixel value in the bitmap, so that the caller can access
         the pixels directly. Note: only the pixels field should be altered. The config/width/height/rowbytes
         must remain unchanged.
@@ -269,6 +280,8 @@ private:
     SkBitmap    fBitmap;
     SkIPoint    fOrigin;
     SkMetaData* fMetaData;
+
+    SkDeviceFactory* fCachedDeviceFactory;
 };
 
 #endif
index ff1bb0d3621d4e2fd9d2080155ceb0b82c1aea0b..15def87942f37efbba49e3dd5dce950f5e5b5022 100644 (file)
@@ -121,6 +121,9 @@ public:
     virtual void makeRenderTargetCurrent();
 
 protected:
+    // override
+    virtual SkDeviceFactory* onNewDeviceFactory();
+
     class TexCache;
     TexCache* lockCachedTexture(const SkBitmap& bitmap,
                                 const GrSamplerState& sampler,
index ac9ef20fc42bc2c1b0e4b055e4fbdc1e3028f08b..0d06fe67157dbcf0e3ddd001ab7526e5f720cbd3 100644 (file)
@@ -61,10 +61,6 @@ public:
     SkPDFDevice(int width, int height, const SkMatrix& initialTransform);
     virtual ~SkPDFDevice();
 
-    virtual SkDeviceFactory* getDeviceFactory() {
-        return SkNEW(SkPDFDeviceFactory);
-    }
-
     virtual uint32_t getDeviceCapabilities() { return kVector_Capability; }
 
     virtual int width() const { return fWidth; };
@@ -138,6 +134,10 @@ public:
      */
     SkStream* content() const;
 
+protected:
+    // override
+    virtual SkDeviceFactory* onNewDeviceFactory();
+
 private:
     int fWidth;
     int fHeight;
index 07c2748a7a4e4cacef60de054e0a409c49fb3b11..dbd4852006f7fed3682f60c21e616a5b8f3ec8dc 100644 (file)
@@ -417,21 +417,27 @@ SkDevice* SkCanvas::init(SkDevice* device) {
 }
 
 SkCanvas::SkCanvas(SkDeviceFactory* factory)
-        : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)),
-          fDeviceFactory(factory) {
+        : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
     inc_canvas();
 
-    if (!factory)
-        fDeviceFactory = SkNEW(SkRasterDeviceFactory);
+    if (factory) {
+        factory->ref();
+    } else {
+        factory = SkNEW(SkRasterDeviceFactory);
+    }
+    fDeviceFactory = factory;
 
     this->init(NULL);
 }
 
 SkCanvas::SkCanvas(SkDevice* device)
-        : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)),
-          fDeviceFactory(device->getDeviceFactory()) {
+        : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) {
     inc_canvas();
 
+    fDeviceFactory = device->getDeviceFactory();
+    SkASSERT(fDeviceFactory);
+    fDeviceFactory->ref();
+              
     this->init(device);
 }
 
@@ -441,6 +447,9 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap)
 
     SkDevice* device = SkNEW_ARGS(SkDevice, (this, bitmap, false));
     fDeviceFactory = device->getDeviceFactory();
+    SkASSERT(fDeviceFactory);
+    fDeviceFactory->ref();
+
     this->init(device)->unref();
 }
 
@@ -450,7 +459,7 @@ SkCanvas::~SkCanvas() {
     this->internalRestore();    // restore the last, since we're going away
 
     SkSafeUnref(fBounder);
-    SkDELETE(fDeviceFactory);
+    SkSafeUnref(fDeviceFactory);
 
     dec_canvas();
 }
@@ -560,8 +569,7 @@ bool SkCanvas::readPixels(const SkIRect& srcRect, SkBitmap* bitmap) {
 }
 
 SkDeviceFactory* SkCanvas::setDeviceFactory(SkDeviceFactory* factory) {
-    SkDELETE(fDeviceFactory);
-    fDeviceFactory = factory;
+    SkRefCnt_SafeAssign(fDeviceFactory, factory);
     return factory;
 }
 
index 6305e190fe938bc8b967cd5601b1842e25dd6407..850a53fd167ebf896bb75e5c8ddaa90f5b6fcbbb 100644 (file)
@@ -3,10 +3,31 @@
 #include "SkMetaData.h"
 #include "SkRect.h"
 
-SkDeviceFactory::~SkDeviceFactory() {}
+//#define TRACE_FACTORY_LIFETIME
+
+#ifdef TRACE_FACTORY_LIFETIME
+    static int gFactoryCounter;
+#endif
+
+SkDeviceFactory::SkDeviceFactory() {
+#ifdef TRACE_FACTORY_LIFETIME
+    SkDebugf("+++ factory index %d\n", gFactoryCounter);
+    ++gFactoryCounter;
+#endif
+}
+
+SkDeviceFactory::~SkDeviceFactory() {
+#ifdef TRACE_FACTORY_LIFETIME
+    --gFactoryCounter;
+    SkDebugf("--- factory index %d\n", gFactoryCounter);
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
 
 SkDevice::SkDevice(SkCanvas* canvas) : fCanvas(canvas), fMetaData(NULL) {
     fOrigin.setZero();
+    fCachedDeviceFactory = NULL;
 }
 
 SkDevice::SkDevice(SkCanvas* canvas, const SkBitmap& bitmap, bool isForLayer)
@@ -21,10 +42,23 @@ SkDevice::SkDevice(SkCanvas* canvas, const SkBitmap& bitmap, bool isForLayer)
             }
         }
     }
+    fCachedDeviceFactory = NULL;
 }
 
 SkDevice::~SkDevice() {
     delete fMetaData;
+    SkSafeUnref(fCachedDeviceFactory);
+}
+
+SkDeviceFactory* SkDevice::onNewDeviceFactory() {
+    return SkNEW(SkRasterDeviceFactory);
+}
+
+SkDeviceFactory* SkDevice::getDeviceFactory() {
+    if (NULL == fCachedDeviceFactory) {
+        fCachedDeviceFactory = this->onNewDeviceFactory();
+    }
+    return fCachedDeviceFactory;
 }
 
 SkMetaData& SkDevice::getMetaData() {
index 9513bbd91fe5e61ab7237647716556f64d1dd9a2..08cbb32a05972d9ee27465da6c3b89a6cdae4dc9 100644 (file)
 
 ///////////////////////////////////////////////////////////////////////////////
 
-static SkDeviceFactory* make_df(GrContext* context, 
-                                GrRenderTarget* renderTarget) {
-    return SkNEW_ARGS(SkGpuDeviceFactory, (context, renderTarget));
-}
+SkGpuCanvas::SkGpuCanvas(GrContext* context, GrRenderTarget* renderTarget) {
+    SkDeviceFactory* factory = SkNEW_ARGS(SkGpuDeviceFactory,
+                                          (context, renderTarget));
+    this->setDeviceFactory(factory)->unref();
 
-SkGpuCanvas::SkGpuCanvas(GrContext* context,
-                         GrRenderTarget* renderTarget) 
-      : SkCanvas(make_df(context, renderTarget)) {
     SkASSERT(context);
     fContext = context;
     fContext->ref();
index 036d9b5ae924d7b8c08c15b1376a35d510106d2f..1c70513245367d334f3c816e20ce35d6172117ac 100644 (file)
@@ -210,6 +210,11 @@ intptr_t SkGpuDevice::getLayerTextureHandle() const {
         return 0;
     }
 }
+
+SkDeviceFactory* SkGpuDevice::onNewDeviceFactory() {
+    return SkNEW_ARGS(SkGpuDeviceFactory, (fContext, fRenderTarget));
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 void SkGpuDevice::makeRenderTargetCurrent() {
index efe725770478473b8cf4a50a0e770b0a38fed0b6..13ffd5b0d4b324a5e0a35b4e5fc0697c6b0e0afc 100644 (file)
@@ -168,6 +168,10 @@ void SkPDFDevice::init() {
     }
 }
 
+SkDeviceFactory* SkPDFDevice::onNewDeviceFactory() {
+    return SkNEW(SkPDFDeviceFactory);
+}
+
 void SkPDFDevice::cleanUp() {
     fGraphicStateResources.unrefAll();
     fXObjectResources.unrefAll();