| Index: src/core/SkCanvas.cpp
|
| diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
|
| index 4150a9a55b663584879600346610b2d042259824..90b1562ac56afe6382a4e4ff0c1a8934293bd722 100644
|
| --- a/src/core/SkCanvas.cpp
|
| +++ b/src/core/SkCanvas.cpp
|
| @@ -25,6 +25,7 @@
|
| #include "SkPaintPriv.h"
|
| #include "SkPatchUtils.h"
|
| #include "SkPicture.h"
|
| +#include "SkRasterCanvasLayerAllocator.h"
|
| #include "SkRasterClip.h"
|
| #include "SkReadPixelsRec.h"
|
| #include "SkRRect.h"
|
| @@ -196,6 +197,8 @@ struct DeviceCM {
|
| SkRasterClip fClip;
|
| SkPaint* fPaint; // may be null (in the future)
|
| const SkMatrix* fMatrix;
|
| + SkRasterCanvasLayerAllocator* fAllocator;
|
| + void* fNativeContext;
|
| SkMatrix fMatrixStorage;
|
| SkMatrix fStashedMatrix; // original CTM; used by imagefilter in saveLayer
|
| const bool fDeviceIsBitmapDevice;
|
| @@ -204,6 +207,8 @@ struct DeviceCM {
|
| bool conservativeRasterClip, bool deviceIsBitmapDevice, const SkMatrix& stashed)
|
| : fNext(nullptr)
|
| , fClip(conservativeRasterClip)
|
| + , fAllocator(nullptr)
|
| + , fNativeContext(nullptr)
|
| , fStashedMatrix(stashed)
|
| , fDeviceIsBitmapDevice(deviceIsBitmapDevice)
|
| {
|
| @@ -217,6 +222,10 @@ struct DeviceCM {
|
|
|
| ~DeviceCM() {
|
| if (fDevice) {
|
| + if (fAllocator) {
|
| + fAllocator->free(fDevice->accessBitmap(false).getPixels(),
|
| + fNativeContext);
|
| + }
|
| fDevice->onDetachFromCanvas();
|
| fDevice->unref();
|
| }
|
| @@ -643,7 +652,8 @@ void SkCanvas::resetForNextPicture(const SkIRect& bounds) {
|
| static_cast<SkBitmapDevice*>(fMCRec->fLayer->fDevice)->setNewSize(bounds.size());
|
| }
|
|
|
| -SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
|
| +SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags,
|
| + sk_sp<SkRasterCanvasLayerAllocator> allocator) {
|
| if (device && device->forceConservativeRasterClip()) {
|
| flags = InitFlags(flags | kConservativeRasterClip_InitFlag);
|
| }
|
| @@ -672,6 +682,8 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
|
| fMCRec->fTopLayer = fMCRec->fLayer;
|
|
|
| fSurfaceBase = nullptr;
|
| + fAllocator = allocator;
|
| + fMCRec->fLayer->fAllocator = allocator.get();
|
|
|
| if (device) {
|
| // The root device and the canvas should always have the same pixel geometry
|
| @@ -690,7 +702,7 @@ SkCanvas::SkCanvas()
|
| {
|
| inc_canvas();
|
|
|
| - this->init(nullptr, kDefault_InitFlags);
|
| + this->init(nullptr, kDefault_InitFlags, nullptr);
|
| }
|
|
|
| static SkBitmap make_nopixels(int width, int height) {
|
| @@ -720,7 +732,7 @@ SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
|
| inc_canvas();
|
|
|
| this->init(new SkNoPixelsBitmapDevice(SkIRect::MakeWH(width, height), fProps),
|
| - kDefault_InitFlags)->unref();
|
| + kDefault_InitFlags, nullptr)->unref();
|
| }
|
|
|
| SkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
|
| @@ -730,7 +742,8 @@ SkCanvas::SkCanvas(const SkIRect& bounds, InitFlags flags)
|
| {
|
| inc_canvas();
|
|
|
| - this->init(new SkNoPixelsBitmapDevice(bounds, fProps), flags)->unref();
|
| + this->init(new SkNoPixelsBitmapDevice(bounds, fProps), flags,
|
| + nullptr)->unref();
|
| }
|
|
|
| SkCanvas::SkCanvas(SkBaseDevice* device)
|
| @@ -740,7 +753,7 @@ SkCanvas::SkCanvas(SkBaseDevice* device)
|
| {
|
| inc_canvas();
|
|
|
| - this->init(device, kDefault_InitFlags);
|
| + this->init(device, kDefault_InitFlags, nullptr);
|
| }
|
|
|
| SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
|
| @@ -750,7 +763,7 @@ SkCanvas::SkCanvas(SkBaseDevice* device, InitFlags flags)
|
| {
|
| inc_canvas();
|
|
|
| - this->init(device, flags);
|
| + this->init(device, flags, nullptr);
|
| }
|
|
|
| SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
|
| @@ -761,7 +774,7 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
|
| inc_canvas();
|
|
|
| SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
|
| - this->init(device, kDefault_InitFlags);
|
| + this->init(device, kDefault_InitFlags, nullptr);
|
| }
|
|
|
| SkCanvas::SkCanvas(const SkBitmap& bitmap)
|
| @@ -772,7 +785,22 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap)
|
| inc_canvas();
|
|
|
| SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
|
| - this->init(device, kDefault_InitFlags);
|
| + this->init(device, kDefault_InitFlags, nullptr);
|
| +}
|
| +
|
| +SkCanvas::SkCanvas(const SkBitmap& bitmap,
|
| + sk_sp<SkRasterCanvasLayerAllocator> allocator)
|
| + : fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
|
| + , fProps(SkSurfaceProps::kLegacyFontHost_InitType)
|
| + , fConservativeRasterClip(false)
|
| +{
|
| + inc_canvas();
|
| +
|
| + SkAutoTUnref<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps));
|
| + this->init(device, kDefault_InitFlags, allocator);
|
| + // TODO(tomhudson): this is circuitous, wasteful, and ugly to boot
|
| + this->fMCRec->fLayer->fNativeContext =
|
| + allocator->getNativeContext(this->accessTopLayerPixels(nullptr, nullptr));
|
| }
|
|
|
| SkCanvas::~SkCanvas() {
|
| @@ -1275,7 +1303,7 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
|
| const SkBaseDevice::TileUsage usage = SkBaseDevice::kNever_TileUsage;
|
| const SkBaseDevice::CreateInfo createInfo = SkBaseDevice::CreateInfo(info, usage, geo,
|
| preserveLCDText, false);
|
| - SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint);
|
| + SkBaseDevice* newDev = device->onCreateDevice(createInfo, paint, fAllocator.get());
|
| if (nullptr == newDev) {
|
| // If onCreateDevice didn't succeed, try raster (e.g. PDF couldn't handle the paint)
|
| const SkSurfaceProps surfaceProps(fProps.flags(), createInfo.fPixelGeometry);
|
| @@ -1300,6 +1328,10 @@ void SkCanvas::internalSaveLayer(const SaveLayerRec& rec, SaveLayerStrategy stra
|
| device->unref();
|
|
|
| layer->fNext = fMCRec->fTopLayer;
|
| + layer->fAllocator = fAllocator.get();
|
| + layer->fNativeContext = fAllocator
|
| + ? fAllocator->getNativeContext(device->accessBitmap(false).getPixels())
|
| + : nullptr;
|
| fMCRec->fLayer = layer;
|
| fMCRec->fTopLayer = layer; // this field is NOT an owner of layer
|
| }
|
| @@ -1324,6 +1356,7 @@ void SkCanvas::internalRestore() {
|
|
|
| // reserve our layer (if any)
|
| DeviceCM* layer = fMCRec->fLayer; // may be null
|
| +
|
| // now detach it from fMCRec so we can pop(). Gets freed after its drawn
|
| fMCRec->fLayer = nullptr;
|
|
|
| @@ -1337,6 +1370,7 @@ void SkCanvas::internalRestore() {
|
| recorder will have already recorded the restore).
|
| */
|
| if (layer) {
|
| + SkASSERT(layer->fAllocator == fAllocator.get());
|
| if (layer->fNext) {
|
| const SkIPoint& origin = layer->fDevice->getOrigin();
|
| this->internalDrawDevice(layer->fDevice, origin.x(), origin.y(),
|
| @@ -1767,6 +1801,11 @@ void SkCanvas::replayClips(ClipVisitor* visitor) const {
|
| }
|
| }
|
|
|
| +void* SkCanvas::getTopLayerNative() const {
|
| + return fMCRec->fLayer->fNativeContext;
|
| +}
|
| +
|
| +
|
| ///////////////////////////////////////////////////////////////////////////////
|
|
|
| bool SkCanvas::isClipEmpty() const {
|
|
|