diff options
author | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-06-17 13:10:25 +0000 |
---|---|---|
committer | bsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2011-06-17 13:10:25 +0000 |
commit | e97f0856a8044866b12527819d14cdfbcdfd96f2 (patch) | |
tree | d0273fcd80930ebfbb0e2640dd6d0adf3bbbf632 | |
parent | a54e2f61f8d181b95dd1757d405eacf9f6a9d792 (diff) |
Add createNewCompatibleDevice. Allow devices to have a NULL factory and saveLayer will fall back on createNewCompatibleDevice.
Review URL: http://codereview.appspot.com/4633044/
git-svn-id: http://skia.googlecode.com/svn/trunk@1625 2bbb7eff-a529-9590-31e7-b0007b416f81
-rw-r--r-- | include/core/SkCanvas.h | 29 | ||||
-rw-r--r-- | include/core/SkDevice.h | 39 | ||||
-rw-r--r-- | include/gpu/SkGpuDevice.h | 21 | ||||
-rw-r--r-- | include/pdf/SkPDFDevice.h | 6 | ||||
-rwxr-xr-x | samplecode/SampleTextureDomain.cpp | 2 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 44 | ||||
-rw-r--r-- | src/core/SkDevice.cpp | 23 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 28 | ||||
-rw-r--r-- | src/pdf/SkPDFDevice.cpp | 11 | ||||
-rw-r--r-- | src/utils/SkProxyCanvas.cpp | 5 |
10 files changed, 166 insertions, 42 deletions
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index d5032a76c4..9b96790f3e 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -53,15 +53,19 @@ class SkShape; */ class SK_API SkCanvas : public SkRefCnt { public: - /** Construct a canvas with the given device factory. + /** + DEPRECATED: Will be replaced by SkDevice::createCompatibleDevice + + Construct a canvas with the given device factory. @param factory Specify the factory for generating additional devices. The factory may be null, in which case SkRasterDeviceFactory will be used. */ explicit SkCanvas(SkDeviceFactory* factory = NULL); - /** Construct a canvas with the specified device to draw into. The device + /** Construct a canvas with the specified device to draw into. The device
factory will be retrieved from the passed device. + @param device Specifies a device for the canvas to draw into. */ explicit SkCanvas(SkDevice* device); @@ -96,13 +100,6 @@ public: */ SkDevice* getTopDevice() const; - /** May be overridden by subclasses. This returns a compatible device - for this canvas, with the specified config/width/height. If the device - is raster, the pixels will be allocated automatically. - */ - virtual SkDevice* createDevice(SkBitmap::Config, int width, int height, - bool isOpaque); - /** * Create a new raster device and make it current. This also returns * the new device. @@ -110,18 +107,29 @@ public: SkDevice* setBitmapDevice(const SkBitmap& bitmap); /** + * DEPRECATED: Will be replaced by SkDevice::createCompatibleDevice + * * Return the current device factory, or NULL. The reference count of * the returned factory is not changed. */ SkDeviceFactory* getDeviceFactory() const { return fDeviceFactory; } /** + * DEPRECATED: Will be replaced by SkDevice::createCompatibleDevice + * * 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*); + /** + * Shortcut for getDevice()->createCompatibleDevice(...) + */ + SkDevice* createCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque); + /////////////////////////////////////////////////////////////////////////// /** @@ -834,6 +842,9 @@ private: friend class SkDrawIter; // needs setupDrawForLayerDevice() + SkDevice* createLayerDevice(SkBitmap::Config, int width, int height, + bool isOpaque); + SkDevice* init(SkDevice*); void internalDrawBitmap(const SkBitmap&, const SkIRect*, const SkMatrix& m, const SkPaint* paint); diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h index ff9c4d1361..59e95e7fdf 100644 --- a/include/core/SkDevice.h +++ b/include/core/SkDevice.h @@ -32,6 +32,8 @@ class SkRegion; /** \class SkDeviceFactory + DEPRECATED: Will be replaced by SkDevice::createCompatibleDevice + Devices that extend SkDevice should also provide a SkDeviceFactory class to pass into SkCanvas. Doing so will eliminate the need to extend SkCanvas as well. @@ -79,12 +81,27 @@ public: virtual ~SkDevice(); /** + * DEPRECATED: Will be replaced by SkDevice::createCompatibleDevice + * * 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(); + /** + * Creates a device that is of the same type as this device (e.g. SW-raster, + * GPU, or PDF). + * + * @param width width of the device to create + * @param height height of the device to create + * @param isOpaque + * @param usage clients should always use the default, kGeneral_Usage. + */ + SkDevice* createCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque); + enum Capabilities { kGL_Capability = 0x1, //!< mask indicating GL support kVector_Capability = 0x2, //!< mask indicating a vector representation @@ -264,9 +281,13 @@ public: protected: /** - * subclasses must override this to return a new (or ref'd) instance of + * DEPRECATED: Will be replaced by SkDevice::createCompatibleDevice + * + * subclasses can 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. + * + * If not overriden then createCompatibleDevice will be used by canvas. */ virtual SkDeviceFactory* onNewDeviceFactory(); @@ -276,6 +297,18 @@ protected: */ virtual void onAccessBitmap(SkBitmap*); + enum Usage { + kGeneral_Usage, + kSaveLayer_Usage, // <! internal use only + }; + /** + * subclasses should override this to implement createCompatibleDevice. + */ + virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque, + Usage usage); + SkPixelRef* getPixelRef() const { return fBitmap.pixelRef(); } // just for subclasses, to assign a custom pixelref SkPixelRef* setPixelRef(SkPixelRef* pr, size_t offset) { @@ -287,6 +320,10 @@ private: friend class SkCanvas; // just called by SkCanvas when built as a layer void setOrigin(int x, int y) { fOrigin.set(x, y); } + // just called by SkCanvas for saveLayer + SkDevice* createCompatibleDeviceForSaveLayer(SkBitmap::Config config, + int width, int height, + bool isOpaque); SkBitmap fBitmap; SkIPoint fOrigin; diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h index 4d0efeb511..3a675be24a 100644 --- a/include/gpu/SkGpuDevice.h +++ b/include/gpu/SkGpuDevice.h @@ -37,11 +37,12 @@ public: * New device that will create an offscreen renderTarget based on the * config, width, height. * - * isForSaveLayer is a special flag that should only be set by SkCanvas + * usage is a special flag that should only be set by SkCanvas * internally. */ - SkGpuDevice(GrContext*, SkBitmap::Config, int width, int height, - bool isForSaveLayer = false); + SkGpuDevice(GrContext*, SkBitmap::Config, + int width, int height, + SkDevice::Usage usage = SkDevice::kGeneral_Usage); /** * New device that will render to the specified renderTarget. @@ -132,11 +133,15 @@ protected: virtual SkDeviceFactory* onNewDeviceFactory(); class TexCache; + enum TexType { + kBitmap_TexType, + kDeviceRenderTarget_TexType, + kSaveLayerDeviceRenderTarget_TexType + }; TexCache* lockCachedTexture(const SkBitmap& bitmap, const GrSamplerState& sampler, GrTexture** texture, - bool forDeviceRenderTarget = false, - bool isSaveLayer = false); + TexType type = kBitmap_TexType); void unlockCachedTexture(TexCache*); class SkAutoCachedTexture { @@ -192,6 +197,12 @@ private: GrPaint* grPaint, bool constantColor); + // override from SkDevice + virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque, + Usage usage); + SkDrawProcs* initDrawForText(GrTextContext*); bool bindDeviceAsTexture(GrPaint* paint); diff --git a/include/pdf/SkPDFDevice.h b/include/pdf/SkPDFDevice.h index 6e4d8db725..2205f6cf58 100644 --- a/include/pdf/SkPDFDevice.h +++ b/include/pdf/SkPDFDevice.h @@ -173,6 +173,12 @@ private: SkPDFDevice(const SkISize& layerSize, const SkClipStack& existingClipStack, const SkRegion& existingClipRegion); + // override from SkDevice + virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque, + Usage usage); + void init(); void cleanUp(); void createFormXObjectFromDevice(SkRefPtr<SkPDFFormXObject>* xobject); diff --git a/samplecode/SampleTextureDomain.cpp b/samplecode/SampleTextureDomain.cpp index 37f584e136..1810723c06 100755 --- a/samplecode/SampleTextureDomain.cpp +++ b/samplecode/SampleTextureDomain.cpp @@ -54,7 +54,7 @@ protected: // Note: GPU-backed bitmaps follow a different rendering path // when copying from one GPU device to another. SkRefPtr<SkDevice> primaryDevice(canvas->getDevice()); - SkRefPtr<SkDevice> secondDevice(canvas->createDevice( + SkRefPtr<SkDevice> secondDevice(canvas->createCompatibleDevice( SkBitmap::kARGB_8888_Config, 5, 5, true)); secondDevice->unref(); SkCanvas secondCanvas(secondDevice.get()); diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 5b2e96459e..0b6f086313 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -434,10 +434,9 @@ SkCanvas::SkCanvas(SkDevice* device) : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)) { inc_canvas(); - fDeviceFactory = device->getDeviceFactory(); - SkASSERT(fDeviceFactory); - fDeviceFactory->ref(); - + fDeviceFactory = device->getDeviceFactory();
+ SkSafeRef(fDeviceFactory); + this->init(device); } @@ -446,9 +445,8 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap) inc_canvas(); SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap)); - fDeviceFactory = device->getDeviceFactory(); - SkASSERT(fDeviceFactory); - fDeviceFactory->ref(); + fDeviceFactory = device->getDeviceFactory();
+ SkSafeRef(fDeviceFactory); this->init(device)->unref(); } @@ -736,8 +734,9 @@ int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, bool isOpaque; SkBitmap::Config config = resolve_config(this, ir, flags, &isOpaque); - SkDevice* device = this->createDevice(config, ir.width(), ir.height(), - isOpaque); + SkDevice* device = this->createLayerDevice(config, ir.width(), ir.height(), + isOpaque); + device->setOrigin(ir.fLeft, ir.fTop); DeviceCM* layer = SkNEW_ARGS(DeviceCM, (device, ir.fLeft, ir.fTop, paint)); device->unref(); @@ -1176,11 +1175,32 @@ void SkCanvas::setExternalMatrix(const SkMatrix* matrix) { } } -SkDevice* SkCanvas::createDevice(SkBitmap::Config config, int width, int height, - bool isOpaque) { - return fDeviceFactory->newDevice(this, config, width, height, isOpaque, true); +SkDevice* SkCanvas::createLayerDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque) { + if (fDeviceFactory) { + return fDeviceFactory->newDevice(this, config, width, height, + isOpaque, true); + } else { + return this->getDevice()->createCompatibleDeviceForSaveLayer( + config, width, height, + isOpaque); + } } +SkDevice* SkCanvas::createCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque) { + SkDevice* device = this->getDevice(); + if (device) { + return device->createCompatibleDevice(config, width, height, + isOpaque); + } else { + return NULL; + } +} + + ////////////////////////////////////////////////////////////////////////////// // These are the virtual drawing methods ////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index 0c0133558b..ae283b04ef 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -57,7 +57,7 @@ SkDevice::~SkDevice() { } SkDeviceFactory* SkDevice::onNewDeviceFactory() { - return SkNEW(SkRasterDeviceFactory); + return NULL; } SkDeviceFactory* SkDevice::getDeviceFactory() { @@ -67,6 +67,27 @@ SkDeviceFactory* SkDevice::getDeviceFactory() { return fCachedDeviceFactory; } +SkDevice* SkDevice::createCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque) { + return this->onCreateCompatibleDevice(config, width, height, + isOpaque, kGeneral_Usage); +} + +SkDevice* SkDevice::createCompatibleDeviceForSaveLayer(SkBitmap::Config config, + int width, int height, + bool isOpaque) { + return this->onCreateCompatibleDevice(config, width, height, + isOpaque, kSaveLayer_Usage); +} + +SkDevice* SkDevice::onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque, + Usage usage) { + return SkNEW_ARGS(SkDevice,(config, width, height, isOpaque)); +} + SkMetaData& SkDevice::getMetaData() { // metadata users are rare, so we lazily allocate it. If that changes we // can decide to just make it a field in the device (rather than a ptr) diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 189b692dde..cda10d24ff 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -76,7 +76,7 @@ GrTexture* SkGpuDevice::SkAutoCachedTexture::set(SkGpuDevice* device, fTex = NULL; } else { // look it up in our cache - fTex = device->lockCachedTexture(bitmap, sampler, &texture, false); + fTex = device->lockCachedTexture(bitmap, sampler, &texture); } return texture; } @@ -166,7 +166,7 @@ SkGpuDevice::SkGpuDevice(GrContext* context, GrRenderTarget* renderTarget) } SkGpuDevice::SkGpuDevice(GrContext* context, SkBitmap::Config config, int width, - int height, bool isForSaveLayer) + int height, Usage usage) : SkDevice(config, width, height, false /*isOpaque*/) { fNeedPrepareRenderTarget = false; fDrawProcs = NULL; @@ -186,9 +186,11 @@ SkGpuDevice::SkGpuDevice(GrContext* context, SkBitmap::Config config, int width, bm.setConfig(config, width, height); #if CACHE_LAYER_TEXTURES - + TexType type = (kSaveLayer_Usage == usage) ? + kSaveLayerDeviceRenderTarget_TexType : + kDeviceRenderTarget_TexType; fCache = this->lockCachedTexture(bm, GrSamplerState::ClampNoFilter(), - &fTexture, true, isForSaveLayer); + &fTexture, type); if (fCache) { SkASSERT(NULL != fTexture); SkASSERT(NULL != fTexture->asRenderTarget()); @@ -1394,13 +1396,12 @@ bool SkGpuDevice::filterTextFlags(const SkPaint& paint, TextFlags* flags) { SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap, const GrSamplerState& sampler, GrTexture** texture, - bool forDeviceRenderTarget, - bool isSaveLayer) { + TexType type) { GrTexture* newTexture = NULL; GrTextureEntry* entry = NULL; GrContext* ctx = this->context(); - if (forDeviceRenderTarget) { + if (kBitmap_TexType != type) { const GrTextureDesc desc = { kRenderTarget_GrTextureFlagBit, kNone_GrAALevel, @@ -1408,12 +1409,13 @@ SkGpuDevice::TexCache* SkGpuDevice::lockCachedTexture(const SkBitmap& bitmap, bitmap.height(), SkGr::Bitmap2PixelConfig(bitmap) }; - if (isSaveLayer) { + if (kSaveLayerDeviceRenderTarget_TexType == type) { // we know layers will only be drawn through drawDevice. // drawDevice has been made to work with content embedded in a // larger texture so its okay to use the approximate version. entry = ctx->findApproximateKeylessTexture(desc); } else { + SkASSERT(kDeviceRenderTarget_TexType == type); entry = ctx->lockKeylessTexture(desc); } } else { @@ -1446,6 +1448,15 @@ void SkGpuDevice::unlockCachedTexture(TexCache* cache) { this->context()->unlockTexture((GrTextureEntry*)cache); } +SkDevice* SkGpuDevice::onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque, + Usage usage) { + return SkNEW_ARGS(SkGpuDevice,(this->context(), config, + width, height, usage)); +} + + /////////////////////////////////////////////////////////////////////////////// SkGpuDeviceFactory::SkGpuDeviceFactory(GrContext* context, @@ -1499,3 +1510,4 @@ SkDevice* SkGpuDeviceFactory::newDevice(SkCanvas*, SkBitmap::Config config, return SkNEW_ARGS(SkGpuDevice, (fContext, fRootRenderTarget)); } } + diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index d17f8640c4..67bc64acce 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -423,6 +423,17 @@ void GraphicStackState::updateDrawingState(const GraphicStateEntry& state) { } } +SkDevice* SkPDFDevice::onCreateCompatibleDevice(SkBitmap::Config config, + int width, int height, + bool isOpaque, + Usage usage) { + SkMatrix initialTransform; + initialTransform.reset(); + SkISize size = SkISize::Make(width, height); + return SkNEW_ARGS(SkPDFDevice, (size, size, initialTransform)); +} + + struct ContentEntry { GraphicStateEntry fState; SkDynamicMemoryWStream fContent; diff --git a/src/utils/SkProxyCanvas.cpp b/src/utils/SkProxyCanvas.cpp index a7b7f971b9..33f77e485e 100644 --- a/src/utils/SkProxyCanvas.cpp +++ b/src/utils/SkProxyCanvas.cpp @@ -151,8 +151,3 @@ SkDrawFilter* SkProxyCanvas::setDrawFilter(SkDrawFilter* filter) { return fProxy->setDrawFilter(filter); } -SkDevice* SkProxyCanvas::createDevice(SkBitmap::Config config, int width, int height, - bool isOpaque) { - return fProxy->createDevice(config, width, height, isOpaque); -} - |