SkCanvas: switch from SkDeque to std::deque
Bug: skia:10987 Change-Id: If252f644dc3b8827356f9c7044c8e01fd0fc5afe Reviewed-on: https://skia-review.googlesource.com/c/skia/+/434676 Reviewed-by: Michael Ludwig <michaelludwig@google.com> Reviewed-by: Mike Reed <reed@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
94df5d607c
commit
cc9d20f308
@ -26,10 +26,10 @@
|
|||||||
#include "include/core/SkString.h"
|
#include "include/core/SkString.h"
|
||||||
#include "include/core/SkSurfaceProps.h"
|
#include "include/core/SkSurfaceProps.h"
|
||||||
#include "include/core/SkTypes.h"
|
#include "include/core/SkTypes.h"
|
||||||
#include "include/private/SkDeque.h"
|
|
||||||
#include "include/private/SkMacros.h"
|
#include "include/private/SkMacros.h"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -57,6 +57,7 @@ class SkPixmap;
|
|||||||
class SkRegion;
|
class SkRegion;
|
||||||
class SkRRect;
|
class SkRRect;
|
||||||
struct SkRSXform;
|
struct SkRSXform;
|
||||||
|
class SkSpecialImage;
|
||||||
class SkSurface;
|
class SkSurface;
|
||||||
class SkSurface_Base;
|
class SkSurface_Base;
|
||||||
class SkTextBlob;
|
class SkTextBlob;
|
||||||
@ -2288,20 +2289,55 @@ private:
|
|||||||
// operations should route to this device.
|
// operations should route to this device.
|
||||||
SkBaseDevice* topDevice() const;
|
SkBaseDevice* topDevice() const;
|
||||||
|
|
||||||
class MCRec;
|
// Canvases maintain a sparse stack of layers, where the top-most layer receives the drawing,
|
||||||
|
// clip, and matrix commands. There is a layer per call to saveLayer() using the
|
||||||
|
// kFullLayer_SaveLayerStrategy.
|
||||||
|
struct Layer {
|
||||||
|
sk_sp<SkBaseDevice> fDevice;
|
||||||
|
sk_sp<SkImageFilter> fImageFilter; // applied to layer *before* being drawn by paint
|
||||||
|
SkPaint fPaint;
|
||||||
|
|
||||||
SkDeque fMCStack;
|
Layer(sk_sp<SkBaseDevice> device, sk_sp<SkImageFilter> imageFilter, const SkPaint& paint);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Encapsulate state needed to restore from saveBehind()
|
||||||
|
struct BackImage {
|
||||||
|
sk_sp<SkSpecialImage> fImage;
|
||||||
|
SkIPoint fLoc;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MCRec {
|
||||||
|
public:
|
||||||
|
// If not null, this MCRec corresponds with the saveLayer() record that made the layer.
|
||||||
|
// The base "layer" is not stored here, since it is stored inline in SkCanvas and has no
|
||||||
|
// restoration behavior.
|
||||||
|
std::unique_ptr<Layer> fLayer;
|
||||||
|
|
||||||
|
// This points to the device of the top-most layer (which may be lower in the stack), or
|
||||||
|
// to the canvas's fBaseDevice. The MCRec does not own the device.
|
||||||
|
SkBaseDevice* fDevice;
|
||||||
|
|
||||||
|
std::unique_ptr<BackImage> fBackImage;
|
||||||
|
SkM44 fMatrix;
|
||||||
|
int fDeferredSaveCount = 0;
|
||||||
|
|
||||||
|
MCRec(SkBaseDevice* device);
|
||||||
|
MCRec(const MCRec* prev);
|
||||||
|
~MCRec();
|
||||||
|
|
||||||
|
void newLayer(sk_sp<SkBaseDevice> layerDevice,
|
||||||
|
sk_sp<SkImageFilter> filter,
|
||||||
|
const SkPaint& restorePaint);
|
||||||
|
|
||||||
|
void reset(SkBaseDevice* device);
|
||||||
|
};
|
||||||
|
|
||||||
|
std::deque<MCRec> fMCStack;
|
||||||
// points to top of stack
|
// points to top of stack
|
||||||
MCRec* fMCRec;
|
MCRec* fMCRec;
|
||||||
|
|
||||||
sk_sp<SkMarkerStack> fMarkerStack;
|
sk_sp<SkMarkerStack> fMarkerStack;
|
||||||
|
|
||||||
// the first N recs that can fit here mean we won't call malloc
|
|
||||||
static constexpr int kMCRecSize = 96; // most recent measurement
|
|
||||||
static constexpr int kMCRecCount = 32; // common depth for save/restores
|
|
||||||
|
|
||||||
intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)];
|
|
||||||
|
|
||||||
// Installed via init()
|
// Installed via init()
|
||||||
sk_sp<SkBaseDevice> fBaseDevice;
|
sk_sp<SkBaseDevice> fBaseDevice;
|
||||||
const SkSurfaceProps fProps;
|
const SkSurfaceProps fProps;
|
||||||
|
@ -186,31 +186,6 @@ void SkCanvas::predrawNotify(const SkRect* rect, const SkPaint* paint,
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Canvases maintain a sparse stack of layers, where the top-most layer receives the drawing,
|
|
||||||
// clip, and matrix commands. There is a layer per call to saveLayer() using the
|
|
||||||
// kFullLayer_SaveLayerStrategy.
|
|
||||||
struct Layer {
|
|
||||||
sk_sp<SkBaseDevice> fDevice;
|
|
||||||
sk_sp<SkImageFilter> fImageFilter; // applied to layer *before* being drawn by paint
|
|
||||||
SkPaint fPaint;
|
|
||||||
|
|
||||||
Layer(sk_sp<SkBaseDevice> device, sk_sp<SkImageFilter> imageFilter, const SkPaint& paint)
|
|
||||||
: fDevice(std::move(device))
|
|
||||||
, fImageFilter(std::move(imageFilter))
|
|
||||||
, fPaint(paint) {
|
|
||||||
SkASSERT(fDevice);
|
|
||||||
// Any image filter should have been pulled out and stored in 'imageFilter' so that 'paint'
|
|
||||||
// can be used as-is to draw the result of the filter to the dst device.
|
|
||||||
SkASSERT(!fPaint.getImageFilter());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Encapsulate state needed to restore from saveBehind()
|
|
||||||
struct BackImage {
|
|
||||||
sk_sp<SkSpecialImage> fImage;
|
|
||||||
SkIPoint fLoc;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class CheckForOverwrite : bool {
|
enum class CheckForOverwrite : bool {
|
||||||
kNo = false,
|
kNo = false,
|
||||||
kYes = true
|
kYes = true
|
||||||
@ -218,65 +193,43 @@ enum class CheckForOverwrite : bool {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
/* This is the record we keep for each save/restore level in the stack.
|
SkCanvas::Layer::Layer(sk_sp<SkBaseDevice> device,
|
||||||
Since a level optionally copies the matrix and/or stack, we have pointers
|
sk_sp<SkImageFilter> imageFilter,
|
||||||
for these fields. If the value is copied for this level, the copy is
|
const SkPaint& paint)
|
||||||
stored in the ...Storage field, and the pointer points to that. If the
|
: fDevice(std::move(device)), fImageFilter(std::move(imageFilter)), fPaint(paint) {
|
||||||
value is not copied for this level, we ignore ...Storage, and just point
|
SkASSERT(fDevice);
|
||||||
at the corresponding value in the previous level in the stack.
|
// Any image filter should have been pulled out and stored in 'imageFilter' so that 'paint'
|
||||||
*/
|
// can be used as-is to draw the result of the filter to the dst device.
|
||||||
class SkCanvas::MCRec {
|
SkASSERT(!fPaint.getImageFilter());
|
||||||
public:
|
}
|
||||||
// If not null, this MCRec corresponds with the saveLayer() record that made the layer.
|
|
||||||
// The base "layer" is not stored here, since it is stored inline in SkCanvas and has no
|
|
||||||
// restoration behavior.
|
|
||||||
std::unique_ptr<Layer> fLayer;
|
|
||||||
|
|
||||||
// This points to the device of the top-most layer (which may be lower in the stack), or
|
SkCanvas::MCRec::MCRec(SkBaseDevice* device) : fDevice(device) {
|
||||||
// to the canvas's fBaseDevice. The MCRec does not own the device.
|
SkASSERT(fDevice);
|
||||||
SkBaseDevice* fDevice;
|
inc_rec();
|
||||||
|
}
|
||||||
|
|
||||||
std::unique_ptr<BackImage> fBackImage;
|
SkCanvas::MCRec::MCRec(const MCRec* prev) : fDevice(prev->fDevice), fMatrix(prev->fMatrix) {
|
||||||
SkM44 fMatrix;
|
SkASSERT(fDevice);
|
||||||
int fDeferredSaveCount;
|
inc_rec();
|
||||||
|
}
|
||||||
|
|
||||||
MCRec(SkBaseDevice* device)
|
SkCanvas::MCRec::~MCRec() { dec_rec(); }
|
||||||
: fLayer(nullptr)
|
|
||||||
, fDevice(device)
|
|
||||||
, fBackImage(nullptr)
|
|
||||||
, fDeferredSaveCount(0) {
|
|
||||||
SkASSERT(fDevice);
|
|
||||||
fMatrix.setIdentity();
|
|
||||||
inc_rec();
|
|
||||||
}
|
|
||||||
|
|
||||||
MCRec(const MCRec& prev)
|
void SkCanvas::MCRec::newLayer(sk_sp<SkBaseDevice> layerDevice,
|
||||||
: fLayer(nullptr)
|
sk_sp<SkImageFilter> filter,
|
||||||
, fDevice(prev.fDevice)
|
const SkPaint& restorePaint) {
|
||||||
, fMatrix(prev.fMatrix)
|
SkASSERT(!fBackImage);
|
||||||
, fDeferredSaveCount(0) {
|
fLayer = std::make_unique<Layer>(std::move(layerDevice), std::move(filter), restorePaint);
|
||||||
SkASSERT(fDevice);
|
fDevice = fLayer->fDevice.get();
|
||||||
inc_rec();
|
}
|
||||||
}
|
|
||||||
~MCRec() {
|
|
||||||
dec_rec();
|
|
||||||
}
|
|
||||||
|
|
||||||
void newLayer(sk_sp<SkBaseDevice> layerDevice, sk_sp<SkImageFilter> filter,
|
void SkCanvas::MCRec::reset(SkBaseDevice* device) {
|
||||||
const SkPaint& restorePaint) {
|
SkASSERT(!fLayer);
|
||||||
SkASSERT(!fBackImage);
|
SkASSERT(device);
|
||||||
fLayer = std::make_unique<Layer>(std::move(layerDevice), std::move(filter), restorePaint);
|
SkASSERT(fDeferredSaveCount == 0);
|
||||||
fDevice = fLayer->fDevice.get();
|
fDevice = device;
|
||||||
}
|
fMatrix.setIdentity();
|
||||||
|
}
|
||||||
void reset(SkBaseDevice* device) {
|
|
||||||
SkASSERT(!fLayer);
|
|
||||||
SkASSERT(device);
|
|
||||||
SkASSERT(fDeferredSaveCount == 0);
|
|
||||||
fDevice = device;
|
|
||||||
fMatrix.setIdentity();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class SkCanvas::AutoUpdateQRBounds {
|
class SkCanvas::AutoUpdateQRBounds {
|
||||||
public:
|
public:
|
||||||
@ -421,11 +374,6 @@ void SkCanvas::resetForNextPicture(const SkIRect& bounds) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkCanvas::init(sk_sp<SkBaseDevice> device) {
|
void SkCanvas::init(sk_sp<SkBaseDevice> device) {
|
||||||
// SkCanvas.h declares internal storage for the hidden struct MCRec, and this
|
|
||||||
// assert ensure it's sufficient. <= is used because the struct has pointer fields, so the
|
|
||||||
// declared size is an upper bound across architectures. When the size is smaller, more stack
|
|
||||||
static_assert(sizeof(MCRec) <= kMCRecSize);
|
|
||||||
|
|
||||||
if (!device) {
|
if (!device) {
|
||||||
device = sk_make_sp<SkNoPixelsDevice>(SkIRect::MakeEmpty(), fProps);
|
device = sk_make_sp<SkNoPixelsDevice>(SkIRect::MakeEmpty(), fProps);
|
||||||
}
|
}
|
||||||
@ -434,7 +382,7 @@ void SkCanvas::init(sk_sp<SkBaseDevice> device) {
|
|||||||
SkASSERT(device);
|
SkASSERT(device);
|
||||||
|
|
||||||
fSaveCount = 1;
|
fSaveCount = 1;
|
||||||
fMCRec = new (fMCStack.push_back()) MCRec(device.get());
|
fMCRec = &fMCStack.emplace_back(device.get());
|
||||||
fMarkerStack = sk_make_sp<SkMarkerStack>();
|
fMarkerStack = sk_make_sp<SkMarkerStack>();
|
||||||
|
|
||||||
// The root device and the canvas should always have the same pixel geometry
|
// The root device and the canvas should always have the same pixel geometry
|
||||||
@ -448,58 +396,42 @@ void SkCanvas::init(sk_sp<SkBaseDevice> device) {
|
|||||||
fQuickRejectBounds = this->computeDeviceClipBounds();
|
fQuickRejectBounds = this->computeDeviceClipBounds();
|
||||||
}
|
}
|
||||||
|
|
||||||
SkCanvas::SkCanvas()
|
SkCanvas::SkCanvas() {
|
||||||
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
|
|
||||||
, fProps()
|
|
||||||
{
|
|
||||||
inc_canvas();
|
inc_canvas();
|
||||||
this->init(nullptr);
|
this->init(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
|
SkCanvas::SkCanvas(int width, int height, const SkSurfaceProps* props)
|
||||||
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
|
: fProps(SkSurfacePropsCopyOrDefault(props)) {
|
||||||
, fProps(SkSurfacePropsCopyOrDefault(props))
|
|
||||||
{
|
|
||||||
inc_canvas();
|
inc_canvas();
|
||||||
this->init(sk_make_sp<SkNoPixelsDevice>(
|
this->init(sk_make_sp<SkNoPixelsDevice>(
|
||||||
SkIRect::MakeWH(std::max(width, 0), std::max(height, 0)), fProps));
|
SkIRect::MakeWH(std::max(width, 0), std::max(height, 0)), fProps));
|
||||||
}
|
}
|
||||||
|
|
||||||
SkCanvas::SkCanvas(const SkIRect& bounds)
|
SkCanvas::SkCanvas(const SkIRect& bounds) {
|
||||||
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
|
|
||||||
, fProps()
|
|
||||||
{
|
|
||||||
inc_canvas();
|
inc_canvas();
|
||||||
|
|
||||||
SkIRect r = bounds.isEmpty() ? SkIRect::MakeEmpty() : bounds;
|
SkIRect r = bounds.isEmpty() ? SkIRect::MakeEmpty() : bounds;
|
||||||
this->init(sk_make_sp<SkNoPixelsDevice>(r, fProps));
|
this->init(sk_make_sp<SkNoPixelsDevice>(r, fProps));
|
||||||
}
|
}
|
||||||
|
|
||||||
SkCanvas::SkCanvas(sk_sp<SkBaseDevice> device)
|
SkCanvas::SkCanvas(sk_sp<SkBaseDevice> device) : fProps(device->surfaceProps()) {
|
||||||
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
|
|
||||||
, fProps(device->surfaceProps())
|
|
||||||
{
|
|
||||||
inc_canvas();
|
inc_canvas();
|
||||||
|
|
||||||
this->init(device);
|
this->init(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props)
|
SkCanvas::SkCanvas(const SkBitmap& bitmap, const SkSurfaceProps& props) : fProps(props) {
|
||||||
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
|
|
||||||
, fProps(props)
|
|
||||||
{
|
|
||||||
inc_canvas();
|
inc_canvas();
|
||||||
|
|
||||||
sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps, nullptr, nullptr));
|
sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps, nullptr, nullptr));
|
||||||
this->init(device);
|
this->init(device);
|
||||||
}
|
}
|
||||||
|
|
||||||
SkCanvas::SkCanvas(const SkBitmap& bitmap, std::unique_ptr<SkRasterHandleAllocator> alloc,
|
SkCanvas::SkCanvas(const SkBitmap& bitmap,
|
||||||
|
std::unique_ptr<SkRasterHandleAllocator> alloc,
|
||||||
SkRasterHandleAllocator::Handle hndl)
|
SkRasterHandleAllocator::Handle hndl)
|
||||||
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage))
|
: fAllocator(std::move(alloc)) {
|
||||||
, fProps()
|
|
||||||
, fAllocator(std::move(alloc))
|
|
||||||
{
|
|
||||||
inc_canvas();
|
inc_canvas();
|
||||||
|
|
||||||
sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps, hndl, nullptr));
|
sk_sp<SkBaseDevice> device(new SkBitmapDevice(bitmap, fProps, hndl, nullptr));
|
||||||
@ -509,9 +441,7 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap, std::unique_ptr<SkRasterHandleAllocat
|
|||||||
SkCanvas::SkCanvas(const SkBitmap& bitmap) : SkCanvas(bitmap, nullptr, nullptr) {}
|
SkCanvas::SkCanvas(const SkBitmap& bitmap) : SkCanvas(bitmap, nullptr, nullptr) {}
|
||||||
|
|
||||||
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
#ifdef SK_BUILD_FOR_ANDROID_FRAMEWORK
|
||||||
SkCanvas::SkCanvas(const SkBitmap& bitmap, ColorBehavior)
|
SkCanvas::SkCanvas(const SkBitmap& bitmap, ColorBehavior) {
|
||||||
: fMCStack(sizeof(MCRec), fMCRecStorage, sizeof(fMCRecStorage)), fProps(), fAllocator(nullptr)
|
|
||||||
{
|
|
||||||
inc_canvas();
|
inc_canvas();
|
||||||
|
|
||||||
SkBitmap tmp(bitmap);
|
SkBitmap tmp(bitmap);
|
||||||
@ -522,9 +452,7 @@ SkCanvas::SkCanvas(const SkBitmap& bitmap, ColorBehavior)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
SkCanvas::~SkCanvas() {
|
SkCanvas::~SkCanvas() {
|
||||||
// free up the contents of our deque
|
|
||||||
this->restoreToCount(1); // restore everything but the last
|
this->restoreToCount(1); // restore everything but the last
|
||||||
|
|
||||||
this->internalRestore(); // restore the last, since we're going away
|
this->internalRestore(); // restore the last, since we're going away
|
||||||
|
|
||||||
dec_canvas();
|
dec_canvas();
|
||||||
@ -614,13 +542,8 @@ void SkCanvas::checkForDeferredSave() {
|
|||||||
int SkCanvas::getSaveCount() const {
|
int SkCanvas::getSaveCount() const {
|
||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
int count = 0;
|
int count = 0;
|
||||||
SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
|
for (const auto &rec : fMCStack) {
|
||||||
for (;;) {
|
count += 1 + rec.fDeferredSaveCount;
|
||||||
const MCRec* rec = (const MCRec*)iter.next();
|
|
||||||
if (!rec) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
count += 1 + rec->fDeferredSaveCount;
|
|
||||||
}
|
}
|
||||||
SkASSERT(count == fSaveCount);
|
SkASSERT(count == fSaveCount);
|
||||||
#endif
|
#endif
|
||||||
@ -648,7 +571,7 @@ void SkCanvas::restore() {
|
|||||||
fMCRec->fDeferredSaveCount -= 1;
|
fMCRec->fDeferredSaveCount -= 1;
|
||||||
} else {
|
} else {
|
||||||
// check for underflow
|
// check for underflow
|
||||||
if (fMCStack.count() > 1) {
|
if (fMCStack.size() > 1) {
|
||||||
this->willRestore();
|
this->willRestore();
|
||||||
SkASSERT(fSaveCount > 1);
|
SkASSERT(fSaveCount > 1);
|
||||||
fSaveCount -= 1;
|
fSaveCount -= 1;
|
||||||
@ -671,7 +594,7 @@ void SkCanvas::restoreToCount(int count) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkCanvas::internalSave() {
|
void SkCanvas::internalSave() {
|
||||||
fMCRec = new (fMCStack.push_back()) MCRec(*fMCRec);
|
fMCRec = &fMCStack.emplace_back(fMCRec);
|
||||||
|
|
||||||
this->topDevice()->save();
|
this->topDevice()->save();
|
||||||
}
|
}
|
||||||
@ -1182,7 +1105,7 @@ void SkCanvas::internalSaveBehind(const SkRect* localBounds) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SkCanvas::internalRestore() {
|
void SkCanvas::internalRestore() {
|
||||||
SkASSERT(fMCStack.count() != 0);
|
SkASSERT(!fMCStack.empty());
|
||||||
|
|
||||||
// now detach these from fMCRec so we can pop(). Gets freed after its drawn
|
// now detach these from fMCRec so we can pop(). Gets freed after its drawn
|
||||||
std::unique_ptr<Layer> layer = std::move(fMCRec->fLayer);
|
std::unique_ptr<Layer> layer = std::move(fMCRec->fLayer);
|
||||||
@ -1191,15 +1114,16 @@ void SkCanvas::internalRestore() {
|
|||||||
fMarkerStack->restore(fMCRec);
|
fMarkerStack->restore(fMCRec);
|
||||||
|
|
||||||
// now do the normal restore()
|
// now do the normal restore()
|
||||||
fMCRec->~MCRec(); // balanced in save()
|
|
||||||
fMCStack.pop_back();
|
fMCStack.pop_back();
|
||||||
fMCRec = (MCRec*) fMCStack.back();
|
|
||||||
|
|
||||||
if (!fMCRec) {
|
if (fMCStack.empty()) {
|
||||||
// This was the last record, restored during the destruction of the SkCanvas
|
// This was the last record, restored during the destruction of the SkCanvas
|
||||||
|
fMCRec = nullptr;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fMCRec = &fMCStack.back();
|
||||||
|
|
||||||
this->topDevice()->restore(fMCRec->fMatrix);
|
this->topDevice()->restore(fMCRec->fMatrix);
|
||||||
|
|
||||||
if (backImage) {
|
if (backImage) {
|
||||||
@ -1967,23 +1891,19 @@ void SkCanvas::onDrawBehind(const SkPaint& paint) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SkIRect bounds;
|
auto rec = std::find_if(fMCStack.rbegin(), fMCStack.rend(), [](const MCRec& r) {
|
||||||
SkDeque::Iter iter(fMCStack, SkDeque::Iter::kBack_IterStart);
|
return r.fBackImage != nullptr;
|
||||||
for (;;) {
|
});
|
||||||
const MCRec* rec = (const MCRec*)iter.prev();
|
if (rec == fMCStack.rend()) {
|
||||||
if (!rec) {
|
return; // no backimages, so nothing to draw
|
||||||
return; // no backimages, so nothing to draw
|
}
|
||||||
}
|
|
||||||
if (rec->fBackImage) {
|
// drawBehind should only have been called when the saveBehind record is active;
|
||||||
// drawBehind should only have been called when the saveBehind record is active;
|
// if this fails, it means a real saveLayer was made w/o being restored first.
|
||||||
// if this fails, it means a real saveLayer was made w/o being restored first.
|
SkASSERT(dev == rec->fDevice);
|
||||||
SkASSERT(dev == rec->fDevice);
|
SkIRect bounds = SkIRect::MakeXYWH(rec->fBackImage->fLoc.fX, rec->fBackImage->fLoc.fY,
|
||||||
bounds = SkIRect::MakeXYWH(rec->fBackImage->fLoc.fX, rec->fBackImage->fLoc.fY,
|
|
||||||
rec->fBackImage->fImage->width(),
|
rec->fBackImage->fImage->width(),
|
||||||
rec->fBackImage->fImage->height());
|
rec->fBackImage->fImage->height());
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The backimage location (and thus bounds) were defined in the device's space, so mark it
|
// The backimage location (and thus bounds) were defined in the device's space, so mark it
|
||||||
// as a clip. We use a clip instead of just drawing a rect in case the paint has an image
|
// as a clip. We use a clip instead of just drawing a rect in case the paint has an image
|
||||||
|
@ -75,7 +75,7 @@ struct MSKPPlayer::DrawLayerCmd : Cmd {
|
|||||||
void MSKPPlayer::DrawLayerCmd::draw(SkCanvas* canvas,
|
void MSKPPlayer::DrawLayerCmd::draw(SkCanvas* canvas,
|
||||||
const LayerMap& layerMap,
|
const LayerMap& layerMap,
|
||||||
LayerStateMap* layerStateMap) const {
|
LayerStateMap* layerStateMap) const {
|
||||||
const Layer& layer = layerMap.at(fLayerId);
|
const LayerCmds& layer = layerMap.at(fLayerId);
|
||||||
LayerState* layerState = &(*layerStateMap)[fLayerId];
|
LayerState* layerState = &(*layerStateMap)[fLayerId];
|
||||||
if (!layerState->fSurface) {
|
if (!layerState->fSurface) {
|
||||||
layerState->fCurrCmd = 0;
|
layerState->fCurrCmd = 0;
|
||||||
@ -119,7 +119,7 @@ void MSKPPlayer::DrawLayerCmd::draw(SkCanvas* canvas,
|
|||||||
|
|
||||||
class MSKPPlayer::CmdRecordCanvas : public SkCanvasVirtualEnforcer<SkCanvas> {
|
class MSKPPlayer::CmdRecordCanvas : public SkCanvasVirtualEnforcer<SkCanvas> {
|
||||||
public:
|
public:
|
||||||
CmdRecordCanvas(Layer* dst, LayerMap* offscreenLayers, const SkIRect* clipRect = nullptr)
|
CmdRecordCanvas(LayerCmds* dst, LayerMap* offscreenLayers, const SkIRect* clipRect = nullptr)
|
||||||
: fDst(dst), fOffscreenLayers(offscreenLayers) {
|
: fDst(dst), fOffscreenLayers(offscreenLayers) {
|
||||||
if (clipRect) {
|
if (clipRect) {
|
||||||
fClipRect = *clipRect;
|
fClipRect = *clipRect;
|
||||||
@ -332,7 +332,7 @@ protected:
|
|||||||
if (fNextDrawPictureToLayerID != -1) {
|
if (fNextDrawPictureToLayerID != -1) {
|
||||||
SkASSERT(!matrix);
|
SkASSERT(!matrix);
|
||||||
SkASSERT(!paint);
|
SkASSERT(!paint);
|
||||||
Layer* layer = &fOffscreenLayers->at(fNextDrawPictureToLayerID);
|
LayerCmds* layer = &fOffscreenLayers->at(fNextDrawPictureToLayerID);
|
||||||
CmdRecordCanvas sc(layer, fOffscreenLayers, &fNextDrawPictureToLayerClipRect);
|
CmdRecordCanvas sc(layer, fOffscreenLayers, &fNextDrawPictureToLayerClipRect);
|
||||||
picture->playback(&sc);
|
picture->playback(&sc);
|
||||||
fNextDrawPictureToLayerID = -1;
|
fNextDrawPictureToLayerID = -1;
|
||||||
@ -371,7 +371,7 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
SkPictureRecorder fRecorder; // accumulates draws until we draw an offscreen into this layer.
|
SkPictureRecorder fRecorder; // accumulates draws until we draw an offscreen into this layer.
|
||||||
Layer* fDst = nullptr;
|
LayerCmds* fDst = nullptr;
|
||||||
SkIRect fClipRect = SkIRect::MakeEmpty();
|
SkIRect fClipRect = SkIRect::MakeEmpty();
|
||||||
int fNextDrawPictureToLayerID = -1;
|
int fNextDrawPictureToLayerID = -1;
|
||||||
SkIRect fNextDrawPictureToLayerClipRect = SkIRect::MakeEmpty();
|
SkIRect fNextDrawPictureToLayerClipRect = SkIRect::MakeEmpty();
|
||||||
@ -438,14 +438,14 @@ bool MSKPPlayer::playFrame(SkCanvas* canvas, int i) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Replay all the commands for this frame to the caller's canvas.
|
// Replay all the commands for this frame to the caller's canvas.
|
||||||
const Layer& layer = fRootLayers[i];
|
const LayerCmds& layer = fRootLayers[i];
|
||||||
for (const auto& cmd : layer.fCmds) {
|
for (const auto& cmd : layer.fCmds) {
|
||||||
cmd->draw(canvas, fOffscreenLayers, &fOffscreenLayerStates);
|
cmd->draw(canvas, fOffscreenLayers, &fOffscreenLayerStates);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_sp<SkSurface> MSKPPlayer::MakeSurfaceForLayer(const Layer& layer, SkCanvas* rootCanvas) {
|
sk_sp<SkSurface> MSKPPlayer::MakeSurfaceForLayer(const LayerCmds& layer, SkCanvas* rootCanvas) {
|
||||||
// Assume layer has same surface props and info as this (mskp doesn't currently record this
|
// Assume layer has same surface props and info as this (mskp doesn't currently record this
|
||||||
// data).
|
// data).
|
||||||
SkSurfaceProps props;
|
SkSurfaceProps props;
|
||||||
@ -497,7 +497,7 @@ sk_sp<SkImage> MSKPPlayer::layerSnapshot(int layerID) const {
|
|||||||
return iter->second.fSurface->makeImageSnapshot();
|
return iter->second.fSurface->makeImageSnapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MSKPPlayer::collectReferencedLayers(const Layer& layer, std::vector<int>* out) const {
|
void MSKPPlayer::collectReferencedLayers(const LayerCmds& layer, std::vector<int>* out) const {
|
||||||
for (const auto& cmd : layer.fCmds) {
|
for (const auto& cmd : layer.fCmds) {
|
||||||
if (int id = cmd->layerID(); id >= 0) {
|
if (int id = cmd->layerID(); id >= 0) {
|
||||||
// Linear, but we'd need to have a lot of layers to actually care.
|
// Linear, but we'd need to have a lot of layers to actually care.
|
||||||
|
@ -95,9 +95,9 @@ private:
|
|||||||
struct DrawLayerCmd;
|
struct DrawLayerCmd;
|
||||||
|
|
||||||
// The commands for a root/offscreen layer and dimensions of the layer.
|
// The commands for a root/offscreen layer and dimensions of the layer.
|
||||||
struct Layer {
|
struct LayerCmds {
|
||||||
Layer() = default;
|
LayerCmds() = default;
|
||||||
Layer(Layer&&) = default;
|
LayerCmds(LayerCmds&&) = default;
|
||||||
SkISize fDimensions;
|
SkISize fDimensions;
|
||||||
std::vector<std::unique_ptr<Cmd>> fCmds;
|
std::vector<std::unique_ptr<Cmd>> fCmds;
|
||||||
};
|
};
|
||||||
@ -108,19 +108,19 @@ private:
|
|||||||
sk_sp<SkSurface> fSurface;
|
sk_sp<SkSurface> fSurface;
|
||||||
};
|
};
|
||||||
|
|
||||||
static sk_sp<SkSurface> MakeSurfaceForLayer(const Layer&, SkCanvas* rootCanvas);
|
static sk_sp<SkSurface> MakeSurfaceForLayer(const LayerCmds&, SkCanvas* rootCanvas);
|
||||||
|
|
||||||
void collectReferencedLayers(const Layer& layer, std::vector<int>*) const;
|
void collectReferencedLayers(const LayerCmds& layer, std::vector<int>*) const;
|
||||||
|
|
||||||
// MSKP layer ID -> Layer
|
// MSKP layer ID -> LayerCmds
|
||||||
using LayerMap = std::unordered_map<int, Layer>;
|
using LayerMap = std::unordered_map<int, LayerCmds>;
|
||||||
// MSKP layer ID -> LayerState
|
// MSKP layer ID -> LayerState
|
||||||
using LayerStateMap = std::unordered_map<int, LayerState>;
|
using LayerStateMap = std::unordered_map<int, LayerState>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A SkCanvas that consumes the SkPicture and records Cmds into a Layer. It will spawn
|
* A SkCanvas that consumes the SkPicture and records Cmds into a Layer. It will spawn
|
||||||
* additional Layers and record nested SkPictures into those using additional CmdRecordCanvas
|
* additional Layers and record nested SkPictures into those using additional CmdRecordCanvas
|
||||||
* CmdRecordCanvas instances. It needs access to fOffscreenLayers to create and update Layer
|
* CmdRecordCanvas instances. It needs access to fOffscreenLayers to create and update LayerCmds
|
||||||
* structs for offscreen layers.
|
* structs for offscreen layers.
|
||||||
*/
|
*/
|
||||||
class CmdRecordCanvas;
|
class CmdRecordCanvas;
|
||||||
@ -129,7 +129,7 @@ private:
|
|||||||
LayerMap fOffscreenLayers; // All the offscreen layers for all frames.
|
LayerMap fOffscreenLayers; // All the offscreen layers for all frames.
|
||||||
LayerStateMap fOffscreenLayerStates; // Current surfaces and command idx for offscreen
|
LayerStateMap fOffscreenLayerStates; // Current surfaces and command idx for offscreen
|
||||||
// layers
|
// layers
|
||||||
std::vector<Layer> fRootLayers; // One root layer for each frame.
|
std::vector<LayerCmds> fRootLayers; // One root layer for each frame.
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user