diff --git a/include/core/SkBitmapDevice.h b/include/core/SkBitmapDevice.h index 8ca6a523be..caff6857da 100644 --- a/include/core/SkBitmapDevice.h +++ b/include/core/SkBitmapDevice.h @@ -98,11 +98,7 @@ protected: const SkColor colors[], SkXfermode* xmode, const uint16_t indices[], int indexCount, const SkPaint& paint) SK_OVERRIDE; - /** The SkBaseDevice passed will be an SkBaseDevice which was returned by a call to - onCreateCompatibleDevice on this device with kSaveLayer_Usage. - */ - virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, - const SkPaint&) SK_OVERRIDE; + virtual void drawDevice(const SkDraw&, SkBaseDevice*, int x, int y, const SkPaint&) SK_OVERRIDE; /////////////////////////////////////////////////////////////////////////// @@ -145,7 +141,7 @@ private: // any clip information. void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE; - SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE; + SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) SK_OVERRIDE; SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) SK_OVERRIDE; const void* peekPixels(SkImageInfo*, size_t* rowBytes) SK_OVERRIDE; diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index 74bf909c21..836f7b1115 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -1321,8 +1321,7 @@ private: void internalDrawBitmapNine(const SkBitmap& bitmap, const SkIRect& center, const SkRect& dst, const SkPaint* paint); void internalDrawPaint(const SkPaint& paint); - void internalSaveLayer(const SkRect* bounds, const SkPaint* paint, - SaveFlags, bool justForImageFilter, SaveLayerStrategy strategy); + void internalSaveLayer(const SkRect* bounds, const SkPaint*, SaveFlags, SaveLayerStrategy); void internalDrawDevice(SkBaseDevice*, int x, int y, const SkPaint*); // shared by save() and saveLayer() diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h index c7c5c30b3a..684a08404c 100644 --- a/include/core/SkDevice.h +++ b/include/core/SkDevice.h @@ -125,10 +125,9 @@ public: }; protected: - enum Usage { - kGeneral_Usage, - kSaveLayer_Usage, // onCreateCompatibleDevice(cinfo); + } +#else + /** + * Create a new device based on CreateInfo. If the paint is not null, then it represents a + * preview of how the new device will be composed with its creator device (this). + */ + virtual SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) { + return NULL; + } +#endif + virtual void initForRootLayer(SkPixelGeometry geo); private: diff --git a/include/device/xps/SkXPSDevice.h b/include/device/xps/SkXPSDevice.h index 514259dbaa..10dab81183 100644 --- a/include/device/xps/SkXPSDevice.h +++ b/include/device/xps/SkXPSDevice.h @@ -135,8 +135,6 @@ protected: int x, int y, const SkPaint& paint) SK_OVERRIDE; - bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE; - private: class TypefaceUse : ::SkNoncopyable { public: @@ -311,7 +309,7 @@ private: const SkVector& ppuScale, IXpsOMPath* shadedPath); - SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE; + SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) SK_OVERRIDE; // Disable the default copy and assign implementation. SkXPSDevice(const SkXPSDevice&); diff --git a/src/core/SkBitmapDevice.cpp b/src/core/SkBitmapDevice.cpp index 37cbff50e2..5fae2b5862 100644 --- a/src/core/SkBitmapDevice.cpp +++ b/src/core/SkBitmapDevice.cpp @@ -110,7 +110,7 @@ void SkBitmapDevice::replaceBitmapBackendForRasterSurface(const SkBitmap& bm) { fBitmap.lockPixels(); } -SkBaseDevice* SkBitmapDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) { +SkBaseDevice* SkBitmapDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) { SkDeviceProperties leaky(cinfo.fPixelGeometry); return SkBitmapDevice::Create(cinfo.fInfo, &leaky); } diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index a31ded0586..11dc739f4c 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -299,7 +299,7 @@ public: SkPaint tmp; tmp.setImageFilter(fOrigPaint.getImageFilter()); (void)canvas->internalSaveLayer(bounds, &tmp, SkCanvas::kARGB_ClipLayer_SaveFlag, - true, SkCanvas::kFullLayer_SaveLayerStrategy); + SkCanvas::kFullLayer_SaveLayerStrategy); // we'll clear the imageFilter for the actual draws in next(), so // it will only be applied during the restore(). fDoClearImageFilter = true; @@ -880,7 +880,7 @@ int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) { } SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag); fSaveCount += 1; - this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy); + this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, strategy); return this->getSaveCount() - 1; } @@ -890,12 +890,12 @@ int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags fl } SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags); fSaveCount += 1; - this->internalSaveLayer(bounds, paint, flags, false, strategy); + this->internalSaveLayer(bounds, paint, flags, strategy); return this->getSaveCount() - 1; } void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags, - bool justForImageFilter, SaveLayerStrategy strategy) { + SaveLayerStrategy strategy) { #ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG flags |= kClipToLayer_SaveFlag; #endif @@ -917,21 +917,13 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav return; } - // Kill the imagefilter if our device doesn't allow it - SkLazyPaint lazyP; - if (paint && paint->getImageFilter()) { - if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) { - if (justForImageFilter) { - // early exit if the layer was just for the imageFilter - return; - } - SkPaint* p = lazyP.set(*paint); - p->setImageFilter(NULL); - paint = p; + bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag); + if (isOpaque && paint) { + // TODO: perhaps add a query to filters so we might preserve opaqueness... + if (paint->getImageFilter() || paint->getColorFilter()) { + isOpaque = false; } } - - bool isOpaque = !SkToBool(flags & kHasAlphaLayer_SaveFlag); SkImageInfo info = SkImageInfo::MakeN32(ir.width(), ir.height(), isOpaque ? kOpaque_SkAlphaType : kPremul_SkAlphaType); @@ -941,12 +933,17 @@ void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Sav return; } - SkBaseDevice::Usage usage = SkBaseDevice::kSaveLayer_Usage; + SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage; +#if 1 + // this seems needed for current GMs, but makes us draw slower on the GPU + // Related to https://code.google.com/p/skia/issues/detail?id=3519 ? + // if (paint && paint->getImageFilter()) { - usage = SkBaseDevice::kImageFilter_Usage; + usage = SkBaseDevice::kPossible_TileUsage; } - device = device->onCreateCompatibleDevice(SkBaseDevice::CreateInfo(info, usage, - fProps.pixelGeometry())); +#endif + device = device->onCreateDevice(SkBaseDevice::CreateInfo(info, usage, fProps.pixelGeometry()), + paint); if (NULL == device) { SkErrorInternals::SetError( kInternalError_SkError, "Unable to create device for layer."); diff --git a/src/core/SkDevice.cpp b/src/core/SkDevice.cpp index a77e54c2ff..d76a180862 100644 --- a/src/core/SkDevice.cpp +++ b/src/core/SkDevice.cpp @@ -64,19 +64,16 @@ const SkBitmap& SkBaseDevice::accessBitmap(bool changePixels) { } SkPixelGeometry SkBaseDevice::CreateInfo::AdjustGeometry(const SkImageInfo& info, - Usage usage, + TileUsage tileUsage, SkPixelGeometry geo) { - switch (usage) { - case kGeneral_Usage: + switch (tileUsage) { + case kPossible_TileUsage: break; - case kSaveLayer_Usage: + case kNever_TileUsage: if (info.alphaType() != kOpaque_SkAlphaType) { geo = kUnknown_SkPixelGeometry; } break; - case kImageFilter_Usage: - geo = kUnknown_SkPixelGeometry; - break; } return geo; } @@ -86,7 +83,7 @@ void SkBaseDevice::initForRootLayer(SkPixelGeometry geo) { // anyway to document logically what is going on. // fLeakyProperties->setPixelGeometry(CreateInfo::AdjustGeometry(this->imageInfo(), - kGeneral_Usage, + kPossible_TileUsage, geo)); } diff --git a/src/core/SkDeviceImageFilterProxy.h b/src/core/SkDeviceImageFilterProxy.h index 0ae686d877..11a95ff31f 100644 --- a/src/core/SkDeviceImageFilterProxy.h +++ b/src/core/SkDeviceImageFilterProxy.h @@ -18,15 +18,15 @@ public: : fDevice(device) , fProps(props.flags(), SkBaseDevice::CreateInfo::AdjustGeometry(SkImageInfo(), - SkBaseDevice::kImageFilter_Usage, + SkBaseDevice::kPossible_TileUsage, props.pixelGeometry())) {} SkBaseDevice* createDevice(int w, int h) SK_OVERRIDE { SkBaseDevice::CreateInfo cinfo(SkImageInfo::MakeN32Premul(w, h), - SkBaseDevice::kImageFilter_Usage, + SkBaseDevice::kPossible_TileUsage, kUnknown_SkPixelGeometry); - return fDevice->onCreateCompatibleDevice(cinfo); + return fDevice->onCreateDevice(cinfo, NULL); } bool canHandleImageFilter(const SkImageFilter* filter) SK_OVERRIDE { return fDevice->canHandleImageFilter(filter); diff --git a/src/device/xps/SkXPSDevice.cpp b/src/device/xps/SkXPSDevice.cpp index 2ca799ac37..88d1182526 100644 --- a/src/device/xps/SkXPSDevice.cpp +++ b/src/device/xps/SkXPSDevice.cpp @@ -2251,7 +2251,7 @@ void SkXPSDevice::drawDevice(const SkDraw& d, SkBaseDevice* dev, "Could not add layer to current visuals."); } -SkBaseDevice* SkXPSDevice::onCreateCompatibleDevice(const CreateInfo& info) { +SkBaseDevice* SkXPSDevice::onCreateDevice(const CreateInfo& info, const SkPaint*) { //Conditional for bug compatibility with PDF device. #if 0 if (SkBaseDevice::kGeneral_Usage == info.fUsage) { @@ -2282,6 +2282,3 @@ SkXPSDevice::SkXPSDevice(IXpsOMObjectFactory* xpsFactory) "Could not create canvas for layer."); } -bool SkXPSDevice::allowImageFilter(const SkImageFilter*) { - return false; -} diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index fb5fa7cc7a..757dfbf521 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -1862,7 +1862,7 @@ void SkGpuDevice::flush() { /////////////////////////////////////////////////////////////////////////////// -SkBaseDevice* SkGpuDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) { +SkBaseDevice* SkGpuDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint*) { GrSurfaceDesc desc; desc.fConfig = fRenderTarget->config(); desc.fFlags = kRenderTarget_GrSurfaceFlag; @@ -1876,7 +1876,7 @@ SkBaseDevice* SkGpuDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) { // layers are never draw in repeat modes, so we can request an approx // match and ignore any padding. - const GrContext::ScratchTexMatch match = (kSaveLayer_Usage == cinfo.fUsage) ? + const GrContext::ScratchTexMatch match = (kNever_TileUsage == cinfo.fTileUsage) ? GrContext::kApprox_ScratchTexMatch : GrContext::kExact_ScratchTexMatch; texture.reset(fContext->refScratchTexture(desc, match)); diff --git a/src/gpu/SkGpuDevice.h b/src/gpu/SkGpuDevice.h index 6b520e7174..50aa58685f 100644 --- a/src/gpu/SkGpuDevice.h +++ b/src/gpu/SkGpuDevice.h @@ -51,9 +51,9 @@ public: virtual ~SkGpuDevice(); SkGpuDevice* cloneDevice(const SkSurfaceProps& props) { - SkBaseDevice* dev = this->onCreateCompatibleDevice(CreateInfo(this->imageInfo(), - kGeneral_Usage, - props.pixelGeometry())); + SkBaseDevice* dev = this->onCreateDevice(CreateInfo(this->imageInfo(), kPossible_TileUsage, + props.pixelGeometry()), + NULL); return static_cast(dev); } @@ -147,7 +147,7 @@ private: SkGpuDevice(GrRenderTarget*, const SkSurfaceProps*, unsigned flags); - SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE; + SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) SK_OVERRIDE; SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) SK_OVERRIDE; diff --git a/src/pdf/SkPDFDevice.cpp b/src/pdf/SkPDFDevice.cpp index 99f3ce1188..273b958a8c 100644 --- a/src/pdf/SkPDFDevice.cpp +++ b/src/pdf/SkPDFDevice.cpp @@ -566,13 +566,19 @@ void GraphicStackState::updateDrawingState(const GraphicStateEntry& state) { } } -SkBaseDevice* SkPDFDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) { +static bool not_supported_for_layers(const SkPaint& layerPaint) { // PDF does not support image filters, so render them on CPU. // Note that this rendering is done at "screen" resolution (100dpi), not // printer resolution. // FIXME: It may be possible to express some filters natively using PDF // to improve quality and file size (http://skbug.com/3043) - if (kImageFilter_Usage == cinfo.fUsage) { + + // TODO: should we return true if there is a colorfilter? + return layerPaint.getImageFilter() != NULL; +} + +SkBaseDevice* SkPDFDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint* layerPaint) { + if (layerPaint && not_supported_for_layers(*layerPaint)) { return SkBitmapDevice::Create(cinfo.fInfo); } SkISize size = SkISize::Make(cinfo.fInfo.width(), cinfo.fInfo.height()); diff --git a/src/pdf/SkPDFDevice.h b/src/pdf/SkPDFDevice.h index 8a88314009..a90ea115c1 100644 --- a/src/pdf/SkPDFDevice.h +++ b/src/pdf/SkPDFDevice.h @@ -235,8 +235,7 @@ private: ContentEntry* getLastContentEntry(); void setLastContentEntry(ContentEntry* contentEntry); - // override from SkBaseDevice - SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE; + SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) SK_OVERRIDE; void init(); void cleanUp(bool clearFontUsage); diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp index 8fe9f8a4b5..647105d757 100644 --- a/src/utils/SkDeferredCanvas.cpp +++ b/src/utils/SkDeferredCanvas.cpp @@ -162,7 +162,7 @@ public: GrRenderTarget* accessRenderTarget() SK_OVERRIDE; - SkBaseDevice* onCreateCompatibleDevice(const CreateInfo&) SK_OVERRIDE; + SkBaseDevice* onCreateDevice(const CreateInfo&, const SkPaint*) SK_OVERRIDE; SkSurface* newSurface(const SkImageInfo&, const SkSurfaceProps&) SK_OVERRIDE; @@ -231,9 +231,6 @@ protected: void lockPixels() SK_OVERRIDE {} void unlockPixels() SK_OVERRIDE {} - bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { - return false; - } bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; } @@ -461,16 +458,13 @@ const SkBitmap& SkDeferredDevice::onAccessBitmap() { return immediateDevice()->accessBitmap(false); } -SkBaseDevice* SkDeferredDevice::onCreateCompatibleDevice(const CreateInfo& cinfo) { - // Save layer usage not supported, and not required by SkDeferredCanvas. - SkASSERT(cinfo.fUsage != kSaveLayer_Usage); - +SkBaseDevice* SkDeferredDevice::onCreateDevice(const CreateInfo& cinfo, const SkPaint* layerPaint) { // Create a compatible non-deferred device. // We do not create a deferred device because we know the new device // will not be used with a deferred canvas (there is no API for that). // And connecting a SkDeferredDevice to non-deferred canvas can result // in unpredictable behavior. - return immediateDevice()->onCreateCompatibleDevice(cinfo); + return immediateDevice()->onCreateDevice(cinfo, layerPaint); } SkSurface* SkDeferredDevice::newSurface(const SkImageInfo& info, const SkSurfaceProps& props) {