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 { |