| Index: src/gpu/GrPictureUtils.cpp
|
| diff --git a/src/gpu/GrPictureUtils.cpp b/src/gpu/GrPictureUtils.cpp
|
| index 7295089e821cefff413d55c425c69c082794c37b..521160ac8afd172d34b4d79ab8914fbbb2e20102 100644
|
| --- a/src/gpu/GrPictureUtils.cpp
|
| +++ b/src/gpu/GrPictureUtils.cpp
|
| @@ -6,12 +6,10 @@
|
| */
|
|
|
| #include "GrPictureUtils.h"
|
| -#include "SkCanvasPriv.h"
|
| -#include "SkDevice.h"
|
| -#include "SkDraw.h"
|
| +
|
| #include "SkPaintPriv.h"
|
| -#include "SkPictureData.h"
|
| -#include "SkPicturePlayback.h"
|
| +#include "SkRecord.h"
|
| +#include "SkRecords.h"
|
|
|
| SkPicture::AccelData::Key GrAccelData::ComputeAccelDataKey() {
|
| static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain();
|
| @@ -19,261 +17,261 @@ SkPicture::AccelData::Key GrAccelData::ComputeAccelDataKey() {
|
| return gGPUID;
|
| }
|
|
|
| -// The GrGather device performs GPU-backend-specific preprocessing on
|
| -// a picture. The results are stored in a GrAccelData.
|
| -//
|
| -// Currently the only interesting work is done in drawDevice (i.e., when a
|
| -// saveLayer is collapsed back into its parent) and, maybe, in onCreateDevice.
|
| -// All the current work could be done much more efficiently by just traversing the
|
| -// raw op codes in the SkPicture (although we would still need to replay all the
|
| -// clip calls).
|
| -class GrGatherDevice : public SkBaseDevice {
|
| +// SkRecord visitor to gather saveLayer/restore information.
|
| +class CollectLayers {
|
| public:
|
| - SK_DECLARE_INST_COUNT(GrGatherDevice)
|
| -
|
| - GrGatherDevice(int width, int height, SkPicturePlayback* playback, GrAccelData* accelData,
|
| - int saveLayerDepth) {
|
| - fPlayback = playback;
|
| - fSaveLayerDepth = saveLayerDepth;
|
| - fInfo.fValid = true;
|
| - fInfo.fSize.set(width, height);
|
| - fInfo.fPaint = NULL;
|
| - fInfo.fSaveLayerOpID = fPlayback->curOpID();
|
| - fInfo.fRestoreOpID = 0;
|
| - fInfo.fHasNestedLayers = false;
|
| - fInfo.fIsNested = (2 == fSaveLayerDepth);
|
| -
|
| - fEmptyBitmap.setInfo(SkImageInfo::MakeUnknown(fInfo.fSize.fWidth, fInfo.fSize.fHeight));
|
| - fAccelData = accelData;
|
| - fAlreadyDrawn = false;
|
| - }
|
| -
|
| - virtual ~GrGatherDevice() { }
|
| + CollectLayers(const SkPicture* pict, GrAccelData* accelData)
|
| + : fPictureID(pict->uniqueID())
|
| + , fCTM(&SkMatrix::I())
|
| + , fCurrentClipBounds(SkIRect::MakeXYWH(0, 0, pict->width(), pict->height()))
|
| + , fSaveLayersInStack(0)
|
| + , fAccelData(accelData) {
|
| +
|
| + if (NULL == pict->fRecord.get()) {
|
| + return;
|
| + }
|
|
|
| - virtual SkImageInfo imageInfo() const SK_OVERRIDE {
|
| - return fEmptyBitmap.info();
|
| - }
|
| + for (fCurrentOp = 0; fCurrentOp < pict->fRecord->count(); ++fCurrentOp) {
|
| + pict->fRecord->visit<void>(fCurrentOp, *this);
|
| + }
|
|
|
| -#ifdef SK_SUPPORT_LEGACY_WRITEPIXELSCONFIG
|
| - virtual void writePixels(const SkBitmap& bitmap, int x, int y,
|
| - SkCanvas::Config8888 config8888) SK_OVERRIDE {
|
| - NotSupported();
|
| + while (!fSaveStack.isEmpty()) {
|
| + this->popSaveBlock();
|
| + }
|
| }
|
| -#endif
|
| - virtual GrRenderTarget* accessRenderTarget() SK_OVERRIDE { return NULL; }
|
|
|
| -protected:
|
| - virtual bool filterTextFlags(const SkPaint& paint, TextFlags*) SK_OVERRIDE {
|
| - return false;
|
| - }
|
| - virtual void clear(SkColor color) SK_OVERRIDE {
|
| - NothingToDo();
|
| - }
|
| - virtual void drawPaint(const SkDraw& draw, const SkPaint& paint) SK_OVERRIDE {
|
| - }
|
| - virtual void drawPoints(const SkDraw& draw, SkCanvas::PointMode mode, size_t count,
|
| - const SkPoint points[], const SkPaint& paint) SK_OVERRIDE {
|
| - }
|
| - virtual void drawRect(const SkDraw& draw, const SkRect& rect,
|
| - const SkPaint& paint) SK_OVERRIDE {
|
| - }
|
| - virtual void drawOval(const SkDraw& draw, const SkRect& rect,
|
| - const SkPaint& paint) SK_OVERRIDE {
|
| - }
|
| - virtual void drawRRect(const SkDraw& draw, const SkRRect& rrect,
|
| - const SkPaint& paint) SK_OVERRIDE {
|
| - }
|
| - virtual void drawPath(const SkDraw& draw, const SkPath& path,
|
| - const SkPaint& paint, const SkMatrix* prePathMatrix,
|
| - bool pathIsMutable) SK_OVERRIDE {
|
| + template <typename T> void operator()(const T& op) {
|
| + this->updateCTM(op);
|
| + this->updateClipBounds(op);
|
| + this->trackSaveLayers(op);
|
| }
|
| - virtual void drawBitmap(const SkDraw& draw, const SkBitmap& bitmap,
|
| - const SkMatrix& matrix, const SkPaint& paint) SK_OVERRIDE {
|
| - }
|
| - virtual void drawSprite(const SkDraw&, const SkBitmap& bitmap,
|
| - int x, int y, const SkPaint& paint) SK_OVERRIDE {
|
| - }
|
| - virtual void drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
|
| - const SkRect* srcOrNull, const SkRect& dst,
|
| - const SkPaint& paint,
|
| - SkCanvas::DrawBitmapRectFlags flags) SK_OVERRIDE {
|
| - }
|
| - virtual void drawText(const SkDraw& draw, const void* text, size_t len,
|
| - SkScalar x, SkScalar y,
|
| - const SkPaint& paint) SK_OVERRIDE {
|
| - }
|
| - virtual void drawPosText(const SkDraw& draw, const void* text, size_t len,
|
| - const SkScalar pos[], SkScalar constY,
|
| - int scalarsPerPos, const SkPaint& paint) SK_OVERRIDE {
|
| - }
|
| - virtual void drawTextOnPath(const SkDraw& draw, const void* text, size_t len,
|
| - const SkPath& path, const SkMatrix* matrix,
|
| - const SkPaint& paint) SK_OVERRIDE {
|
| - }
|
| - virtual void drawVertices(const SkDraw& draw, SkCanvas::VertexMode, int vertexCount,
|
| - const SkPoint verts[], const SkPoint texs[],
|
| - const SkColor colors[], SkXfermode* xmode,
|
| - const uint16_t indices[], int indexCount,
|
| - const SkPaint& paint) SK_OVERRIDE {
|
| - }
|
| - virtual void drawDevice(const SkDraw& draw, SkBaseDevice* deviceIn, int x, int y,
|
| - const SkPaint& paint) SK_OVERRIDE {
|
| - // deviceIn is the one that is being "restored" back to its parent
|
| - GrGatherDevice* device = static_cast<GrGatherDevice*>(deviceIn);
|
|
|
| - if (device->fAlreadyDrawn) {
|
| - return;
|
| - }
|
| +private:
|
|
|
| - device->fInfo.fRestoreOpID = fPlayback->curOpID();
|
| - device->fInfo.fCTM = *draw.fMatrix;
|
| - device->fInfo.fCTM.postTranslate(SkIntToScalar(-device->getOrigin().fX),
|
| - SkIntToScalar(-device->getOrigin().fY));
|
| + class SaveInfo {
|
| + public:
|
| + SaveInfo() { }
|
| + SaveInfo(int opIndex, bool isSaveLayer, const SkPaint* paint, const SkIRect& bounds)
|
| + : fStartIndex(opIndex)
|
| + , fIsSaveLayer(isSaveLayer)
|
| + , fHasNestedSaveLayer(false)
|
| + , fPaint(paint)
|
| + , fBounds(bounds) {
|
|
|
| - device->fInfo.fOffset = device->getOrigin();
|
| + }
|
|
|
| - if (NeedsDeepCopy(paint)) {
|
| - // This NULL acts as a signal that the paint was uncopyable (for now)
|
| - device->fInfo.fPaint = NULL;
|
| - device->fInfo.fValid = false;
|
| - } else {
|
| - device->fInfo.fPaint = SkNEW_ARGS(SkPaint, (paint));
|
| + int fStartIndex;
|
| + bool fIsSaveLayer;
|
| + bool fHasNestedSaveLayer;
|
| + const SkPaint* fPaint;
|
| + SkIRect fBounds;
|
| + };
|
| +
|
| + uint32_t fPictureID;
|
| + unsigned int fCurrentOp;
|
| + const SkMatrix* fCTM;
|
| + SkIRect fCurrentClipBounds;
|
| + int fSaveLayersInStack;
|
| + SkTDArray<SaveInfo> fSaveStack;
|
| + GrAccelData* fAccelData;
|
| +
|
| + template <typename T> void updateCTM(const T&) { /* most ops don't change the CTM */ }
|
| + void updateCTM(const SkRecords::Restore& op) { fCTM = &op.matrix; }
|
| + void updateCTM(const SkRecords::SetMatrix& op) { fCTM = &op.matrix; }
|
| +
|
| + template <typename T> void updateClipBounds(const T&) { /* most ops don't change the clip */ }
|
| + // Each of these devBounds fields is the state of the device bounds after the op.
|
| + // So Restore's devBounds are those bounds saved by its paired Save or SaveLayer.
|
| + void updateClipBounds(const SkRecords::Restore& op) { fCurrentClipBounds = op.devBounds; }
|
| + void updateClipBounds(const SkRecords::ClipPath& op) { fCurrentClipBounds = op.devBounds; }
|
| + void updateClipBounds(const SkRecords::ClipRRect& op) { fCurrentClipBounds = op.devBounds; }
|
| + void updateClipBounds(const SkRecords::ClipRect& op) { fCurrentClipBounds = op.devBounds; }
|
| + void updateClipBounds(const SkRecords::ClipRegion& op) { fCurrentClipBounds = op.devBounds; }
|
| + void updateClipBounds(const SkRecords::SaveLayer& op) {
|
| + if (NULL != op.bounds) {
|
| + fCurrentClipBounds.intersect(this->adjustAndMap(*op.bounds, op.paint));
|
| }
|
| + }
|
|
|
| - fAccelData->addSaveLayerInfo(device->fInfo);
|
| - device->fAlreadyDrawn = true;
|
| + template <typename T> void trackSaveLayers(const T& op) {
|
| + /* most ops aren't involved in saveLayers */
|
| }
|
| - // TODO: allow this call to return failure, or move to SkBitmapDevice only.
|
| - virtual const SkBitmap& onAccessBitmap() SK_OVERRIDE {
|
| - return fEmptyBitmap;
|
| + void trackSaveLayers(const SkRecords::Save& s) { this->pushSaveBlock(); }
|
| + void trackSaveLayers(const SkRecords::SaveLayer& sl) { this->pushSaveLayerBlock(sl.paint); }
|
| + void trackSaveLayers(const SkRecords::Restore& r) { this->popSaveBlock(); }
|
| + void trackSaveLayers(const SkRecords::DrawPicture& dp) {
|
| + // For sub-pictures, we wrap their layer information within the parent
|
| + // picture's rendering hierarchy
|
| + const GrAccelData* childData = GPUOptimize(dp.picture);
|
| +
|
| + for (int i = 0; i < childData->numSaveLayers(); ++i) {
|
| + const GrAccelData::SaveLayerInfo& src = childData->saveLayerInfo(i);
|
| +
|
| + this->updateStackForSaveLayer();
|
| +
|
| + GrAccelData::SaveLayerInfo dst;
|
| +
|
| + // TODO: need to store an SkRect in GrAccelData::SaveLayerInfo?
|
| + SkRect srcRect = SkRect::MakeXYWH(SkIntToScalar(src.fOffset.fX),
|
| + SkIntToScalar(src.fOffset.fY),
|
| + SkIntToScalar(src.fSize.width()),
|
| + SkIntToScalar(src.fSize.height()));
|
| + SkIRect newClip(fCurrentClipBounds);
|
| + newClip.intersect(this->adjustAndMap(srcRect, dp.paint));
|
| +
|
| + dst.fValid = true;
|
| + dst.fPictureID = dp.picture->uniqueID();
|
| + dst.fSize = SkISize::Make(newClip.width(), newClip.height());
|
| + dst.fOffset = SkIPoint::Make(newClip.fLeft, newClip.fTop);
|
| + dst.fOriginXform = *fCTM;
|
| + dst.fOriginXform.postConcat(src.fOriginXform);
|
| + dst.fOriginXform.postTranslate(SkIntToScalar(-newClip.fLeft),
|
| + SkIntToScalar(-newClip.fTop));
|
| +
|
| + if (NULL == src.fPaint) {
|
| + dst.fPaint = NULL;
|
| + } else {
|
| + dst.fPaint = SkNEW_ARGS(SkPaint, (*src.fPaint));
|
| + }
|
| +
|
| + dst.fSaveLayerOpID = src.fSaveLayerOpID;
|
| + dst.fRestoreOpID = src.fRestoreOpID;
|
| + dst.fHasNestedLayers = src.fHasNestedLayers;
|
| + dst.fIsNested = fSaveLayersInStack > 0 || src.fIsNested;
|
| +
|
| + fAccelData->addSaveLayerInfo(dst);
|
| + }
|
| }
|
| -#ifdef SK_SUPPORT_LEGACY_READPIXELSCONFIG
|
| - virtual bool onReadPixels(const SkBitmap& bitmap,
|
| - int x, int y,
|
| - SkCanvas::Config8888 config8888) SK_OVERRIDE {
|
| - NotSupported();
|
| - return false;
|
| +
|
| + void pushSaveBlock() {
|
| + fSaveStack.push(SaveInfo(fCurrentOp, false, NULL, SkIRect::MakeEmpty()));
|
| }
|
| -#endif
|
| - virtual void lockPixels() SK_OVERRIDE { NothingToDo(); }
|
| - virtual void unlockPixels() SK_OVERRIDE { NothingToDo(); }
|
| - virtual bool allowImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
|
| - virtual bool canHandleImageFilter(const SkImageFilter*) SK_OVERRIDE { return false; }
|
| - virtual bool filterImage(const SkImageFilter*, const SkBitmap&, const SkImageFilter::Context&,
|
| - SkBitmap* result, SkIPoint* offset) SK_OVERRIDE {
|
| - return false;
|
| +
|
| + // Inform all the saveLayers already on the stack that they now have a
|
| + // nested saveLayer inside them
|
| + void updateStackForSaveLayer() {
|
| + for (int index = fSaveStack.count() - 1; index >= 0; --index) {
|
| + if (fSaveStack[index].fHasNestedSaveLayer) {
|
| + break;
|
| + }
|
| + fSaveStack[index].fHasNestedSaveLayer = true;
|
| + if (fSaveStack[index].fIsSaveLayer) {
|
| + break;
|
| + }
|
| + }
|
| }
|
|
|
| -private:
|
| - // The playback object driving this rendering
|
| - SkPicturePlayback *fPlayback;
|
| + void pushSaveLayerBlock(const SkPaint* paint) {
|
| + this->updateStackForSaveLayer();
|
|
|
| - SkBitmap fEmptyBitmap; // legacy -- need to remove
|
| + fSaveStack.push(SaveInfo(fCurrentOp, true, paint, fCurrentClipBounds));
|
| + ++fSaveLayersInStack;
|
| + }
|
|
|
| - // All information gathered during the gather process is stored here
|
| - GrAccelData* fAccelData;
|
| + void popSaveBlock() {
|
| + if (fSaveStack.count() <= 0) {
|
| + SkASSERT(false);
|
| + return;
|
| + }
|
|
|
| - // true if this device has already been drawn back to its parent(s) at least
|
| - // once.
|
| - bool fAlreadyDrawn;
|
| + SaveInfo si;
|
| + fSaveStack.pop(&si);
|
|
|
| - // The information regarding the saveLayer call this device represents.
|
| - GrAccelData::SaveLayerInfo fInfo;
|
| + if (!si.fIsSaveLayer) {
|
| + return;
|
| + }
|
|
|
| - // The depth of this device in the saveLayer stack
|
| - int fSaveLayerDepth;
|
| + --fSaveLayersInStack;
|
|
|
| - virtual void replaceBitmapBackendForRasterSurface(const SkBitmap&) SK_OVERRIDE {
|
| - NotSupported();
|
| - }
|
| + GrAccelData::SaveLayerInfo slInfo;
|
|
|
| - virtual SkBaseDevice* onCreateDevice(const SkImageInfo& info, Usage usage) SK_OVERRIDE {
|
| - // we expect to only get called via savelayer, in which case it is fine.
|
| - SkASSERT(kSaveLayer_Usage == usage);
|
| + slInfo.fValid = true;
|
| + slInfo.fPictureID = fPictureID;
|
| + slInfo.fSize = SkISize::Make(si.fBounds.width(), si.fBounds.height());
|
| + slInfo.fOffset = SkIPoint::Make(si.fBounds.fLeft, si.fBounds.fTop);
|
| + slInfo.fOriginXform = *fCTM;
|
| + slInfo.fOriginXform.postTranslate(SkIntToScalar(-si.fBounds.fLeft),
|
| + SkIntToScalar(-si.fBounds.fTop));
|
|
|
| - fInfo.fHasNestedLayers = true;
|
| - return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPlayback,
|
| - fAccelData, fSaveLayerDepth+1));
|
| - }
|
| + if (NULL == si.fPaint) {
|
| + slInfo.fPaint = NULL;
|
| + } else {
|
| + slInfo.fPaint = SkNEW_ARGS(SkPaint, (*si.fPaint));
|
| + }
|
|
|
| - virtual void flush() SK_OVERRIDE {}
|
| + slInfo.fSaveLayerOpID = si.fStartIndex;
|
| + slInfo.fRestoreOpID = fCurrentOp;
|
| + slInfo.fHasNestedLayers = si.fHasNestedSaveLayer;
|
| + slInfo.fIsNested = fSaveLayersInStack > 0;
|
|
|
| - static void NotSupported() {
|
| - SkDEBUGFAIL("this method should never be called");
|
| + fAccelData->addSaveLayerInfo(slInfo);
|
| }
|
|
|
| - static void NothingToDo() {}
|
| + // Returns true if rect was meaningfully adjusted for the effects of paint,
|
| + // false if the paint could affect the rect in unknown ways.
|
| + static bool AdjustForPaint(const SkPaint* paint, SkRect* rect) {
|
| + if (paint) {
|
| + if (paint->canComputeFastBounds()) {
|
| + *rect = paint->computeFastBounds(*rect, rect);
|
| + return true;
|
| + }
|
| + return false;
|
| + }
|
| + return true;
|
| + }
|
|
|
| - typedef SkBaseDevice INHERITED;
|
| -};
|
| + // Adjust rect for all paints that may affect its geometry, then map it to device space.
|
| + SkIRect adjustAndMap(SkRect rect, const SkPaint* paint) const {
|
| + // Inverted rectangles really confuse our BBHs.
|
| + rect.sort();
|
|
|
| -// The GrGatherCanvas allows saveLayers but simplifies clipping. It is really
|
| -// only intended to be used as:
|
| -//
|
| -// GrGatherDevice dev(w, h, picture, accelData);
|
| -// GrGatherCanvas canvas(..., picture);
|
| -// canvas.gather();
|
| -//
|
| -// which is all just to fill in 'accelData'
|
| -class SK_API GrGatherCanvas : public SkCanvas {
|
| -public:
|
| - GrGatherCanvas(GrGatherDevice* device) : INHERITED(device) {}
|
| + // Adjust the rect for its own paint.
|
| + if (!AdjustForPaint(paint, &rect)) {
|
| + // The paint could do anything to our bounds. The only safe answer is the current clip.
|
| + return fCurrentClipBounds;
|
| + }
|
|
|
| -protected:
|
| - // disable aa for speed
|
| - virtual void onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
|
| - this->INHERITED::onClipRect(rect, op, kHard_ClipEdgeStyle);
|
| - }
|
| + // Adjust rect for all the paints from the SaveLayers we're inside.
|
| + for (int i = fSaveStack.count() - 1; i >= 0; i--) {
|
| + if (!AdjustForPaint(fSaveStack[i].fPaint, &rect)) {
|
| + // Same deal as above.
|
| + return fCurrentClipBounds;
|
| + }
|
| + }
|
|
|
| - // for speed, just respect the bounds, and disable AA. May give us a few
|
| - // false positives and negatives.
|
| - virtual void onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
|
| - this->updateClipConservativelyUsingBounds(path.getBounds(), op,
|
| - path.isInverseFillType());
|
| - }
|
| - virtual void onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle) SK_OVERRIDE {
|
| - this->updateClipConservativelyUsingBounds(rrect.getBounds(), op, false);
|
| - }
|
| + // Map the rect back to device space.
|
| + fCTM->mapRect(&rect);
|
| + SkIRect devRect;
|
| + rect.roundOut(&devRect);
|
|
|
| - virtual void onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
|
| - const SkPaint* paint) SK_OVERRIDE {
|
| - SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->width(), picture->height());
|
| -
|
| - if (NULL != picture->fData.get()) {
|
| - // Disable the BBH for the old path so all the draw calls
|
| - // will be seen. The stock SkPicture::draw method can't be
|
| - // invoked since it just uses a vanilla SkPicturePlayback.
|
| - SkPicturePlayback playback(picture);
|
| - playback.setUseBBH(false);
|
| - playback.draw(this, NULL);
|
| - } else {
|
| - // Since we know this is the SkRecord path we can just call
|
| - // SkPicture::draw.
|
| - picture->draw(this);
|
| - }
|
| + // Nothing can draw outside the current clip.
|
| + // (Only bounded ops call into this method, so oddballs like Clear don't matter here.)
|
| + devRect.intersect(fCurrentClipBounds);
|
| + return devRect;
|
| }
|
| -
|
| -private:
|
| - typedef SkCanvas INHERITED;
|
| };
|
|
|
| -// GatherGPUInfo is only intended to be called within the context of SkGpuDevice's
|
| +
|
| +// GPUOptimize is only intended to be called within the context of SkGpuDevice's
|
| // EXPERIMENTAL_optimize method.
|
| -void GatherGPUInfo(const SkPicture* pict, GrAccelData* accelData) {
|
| +const GrAccelData* GPUOptimize(const SkPicture* pict) {
|
| if (NULL == pict || 0 == pict->width() || 0 == pict->height()) {
|
| - return ;
|
| + return NULL;
|
| }
|
|
|
| - // BBH-based rendering doesn't re-issue many of the operations the gather
|
| - // process cares about (e.g., saves and restores) so it must be disabled.
|
| - SkPicturePlayback playback(pict);
|
| - playback.setUseBBH(false);
|
| + SkPicture::AccelData::Key key = GrAccelData::ComputeAccelDataKey();
|
| +
|
| + const GrAccelData* existing =
|
| + static_cast<const GrAccelData*>(pict->EXPERIMENTAL_getAccelData(key));
|
| + if (NULL != existing) {
|
| + return existing;
|
| + }
|
| +
|
| + SkAutoTUnref<GrAccelData> data(SkNEW_ARGS(GrAccelData, (key)));
|
| +
|
| + pict->EXPERIMENTAL_addAccelData(data);
|
|
|
| - GrGatherDevice device(pict->width(), pict->height(), &playback, accelData, 0);
|
| - GrGatherCanvas canvas(&device);
|
| + CollectLayers collector(pict, data);
|
|
|
| - canvas.clipRect(SkRect::MakeWH(SkIntToScalar(pict->width()),
|
| - SkIntToScalar(pict->height())),
|
| - SkRegion::kIntersect_Op, false);
|
| - playback.draw(&canvas, NULL);
|
| + return data;
|
| }
|
|
|