Split SkPicturePlayback out of SkPictureData
This splits the playback functionality out of SkPictureData. The old SkPictureData::draw method is pulled out along
with its supporting functions as verbatim as possible. Some follow on CLs will be required to:
re-enable profiling in the debugger (and remove the vestiges of SkTimedPicture)
re-enable display of command offsets in the picture (this should probably wait until we've switched to SkRecord though)
Clean up CachedOperationList (maybe fuse with SkPicture::OperationList)
Split SkPicturePlayback into a base class and two derived classes
Implement parallel version of GatherGPUInfo for SkRecord
Landing this is blocked on removing Android's use of the abortPlayback entry point.
R=mtklein@google.com, reed@google.com
Author: robertphillips@google.com
Review URL: https://codereview.chromium.org/377623002
diff --git a/src/gpu/GrPictureUtils.cpp b/src/gpu/GrPictureUtils.cpp
index 4da9e3c..0bcd927 100644
--- a/src/gpu/GrPictureUtils.cpp
+++ b/src/gpu/GrPictureUtils.cpp
@@ -10,6 +10,7 @@
#include "SkDraw.h"
#include "SkPaintPriv.h"
#include "SkPictureData.h"
+#include "SkPicturePlayback.h"
SkPicture::AccelData::Key GPUAccelData::ComputeAccelDataKey() {
static const SkPicture::AccelData::Key gGPUID = SkPicture::AccelData::GenerateDomain();
@@ -29,14 +30,14 @@
public:
SK_DECLARE_INST_COUNT(GrGatherDevice)
- GrGatherDevice(int width, int height, const SkPicture* picture, GPUAccelData* accelData,
+ GrGatherDevice(int width, int height, SkPicturePlayback* playback, GPUAccelData* accelData,
int saveLayerDepth) {
- fPicture = picture;
+ fPlayback = playback;
fSaveLayerDepth = saveLayerDepth;
fInfo.fValid = true;
fInfo.fSize.set(width, height);
fInfo.fPaint = NULL;
- fInfo.fSaveLayerOpID = fPicture->EXPERIMENTAL_curOpID();
+ fInfo.fSaveLayerOpID = fPlayback->curOpID();
fInfo.fRestoreOpID = 0;
fInfo.fHasNestedLayers = false;
fInfo.fIsNested = (2 == fSaveLayerDepth);
@@ -123,7 +124,7 @@
return;
}
- device->fInfo.fRestoreOpID = fPicture->EXPERIMENTAL_curOpID();
+ device->fInfo.fRestoreOpID = fPlayback->curOpID();
device->fInfo.fCTM = *draw.fMatrix;
device->fInfo.fCTM.postTranslate(SkIntToScalar(-device->getOrigin().fX),
SkIntToScalar(-device->getOrigin().fY));
@@ -163,8 +164,8 @@
}
private:
- // The picture being processed
- const SkPicture *fPicture;
+ // The playback object driving this rendering
+ SkPicturePlayback *fPlayback;
SkBitmap fEmptyBitmap; // legacy -- need to remove
@@ -190,7 +191,7 @@
SkASSERT(kSaveLayer_Usage == usage);
fInfo.fHasNestedLayers = true;
- return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPicture,
+ return SkNEW_ARGS(GrGatherDevice, (info.width(), info.height(), fPlayback,
fAccelData, fSaveLayerDepth+1));
}
@@ -215,21 +216,7 @@
// which is all just to fill in 'accelData'
class SK_API GrGatherCanvas : public SkCanvas {
public:
- GrGatherCanvas(GrGatherDevice* device, const SkPicture* pict)
- : INHERITED(device)
- , fPicture(pict) {
- }
-
- void gather() {
- if (NULL == fPicture || 0 == fPicture->width() || 0 == fPicture->height()) {
- return;
- }
-
- this->clipRect(SkRect::MakeWH(SkIntToScalar(fPicture->width()),
- SkIntToScalar(fPicture->height())),
- SkRegion::kIntersect_Op, false);
- this->drawPicture(fPicture);
- }
+ GrGatherCanvas(GrGatherDevice* device) : INHERITED(device) {}
protected:
// disable aa for speed
@@ -248,32 +235,41 @@
}
virtual void onDrawPicture(const SkPicture* picture) SK_OVERRIDE {
- // 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.
if (NULL != picture->fData.get()) {
- picture->fData->setUseBBH(false);
- }
- picture->draw(this);
- if (NULL != picture->fData.get()) {
- picture->fData->setUseBBH(true);
+ // 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);
}
}
private:
- const SkPicture* fPicture;
-
typedef SkCanvas INHERITED;
};
// GatherGPUInfo is only intended to be called within the context of SkGpuDevice's
// EXPERIMENTAL_optimize method.
void GatherGPUInfo(const SkPicture* pict, GPUAccelData* accelData) {
- if (0 == pict->width() || 0 == pict->height()) {
+ if (NULL == pict || 0 == pict->width() || 0 == pict->height()) {
return ;
}
- GrGatherDevice device(pict->width(), pict->height(), pict, accelData, 0);
- GrGatherCanvas canvas(&device, pict);
+ // 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);
- canvas.gather();
+ GrGatherDevice device(pict->width(), pict->height(), &playback, accelData, 0);
+ GrGatherCanvas canvas(&device);
+
+ canvas.clipRect(SkRect::MakeWH(SkIntToScalar(pict->width()),
+ SkIntToScalar(pict->height())),
+ SkRegion::kIntersect_Op, false);
+ playback.draw(&canvas, NULL);
}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 9041bdf..cf152fa 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -30,6 +30,7 @@
#include "SkPathEffect.h"
#include "SkPicture.h"
#include "SkPictureData.h"
+#include "SkPicturePlayback.h"
#include "SkRRect.h"
#include "SkStroke.h"
#include "SkSurface.h"
@@ -1859,7 +1860,7 @@
SkIRect query;
clipBounds.roundOut(&query);
- const SkPicture::OperationList& ops = picture->EXPERIMENTAL_getActiveOps(query);
+ SkAutoTDelete<const SkPicture::OperationList> ops(picture->EXPERIMENTAL_getActiveOps(query));
// This code pre-renders the entire layer since it will be cached and potentially
// reused with different clips (e.g., in different tiles). Because of this the
@@ -1867,12 +1868,12 @@
// is used to limit which clips are pre-rendered.
static const int kSaveLayerMaxSize = 256;
- if (ops.valid()) {
+ if (NULL != ops.get()) {
// In this case the picture has been generated with a BBH so we use
// the BBH to limit the pre-rendering to just the layers needed to cover
// the region being drawn
- for (int i = 0; i < ops.numOps(); ++i) {
- uint32_t offset = ops.offset(i);
+ for (int i = 0; i < ops->numOps(); ++i) {
+ uint32_t offset = ops->offset(i);
// For now we're saving all the layers in the GPUAccelData so they
// can be nested. Additionally, the nested layers appear before
@@ -1928,7 +1929,7 @@
}
}
- SkPictureData::PlaybackReplacements replacements;
+ SkPicturePlayback::PlaybackReplacements replacements;
// Generate the layer and/or ensure it is locked
for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
@@ -1937,7 +1938,7 @@
const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
- SkPictureData::PlaybackReplacements::ReplacementInfo* layerInfo =
+ SkPicturePlayback::PlaybackReplacements::ReplacementInfo* layerInfo =
replacements.push();
layerInfo->fStart = info.fSaveLayerOpID;
layerInfo->fStop = info.fRestoreOpID;
@@ -2009,9 +2010,9 @@
SkIntToScalar(layer->rect().fTop));
}
- picture->fData->setDrawLimits(info.fSaveLayerOpID, info.fRestoreOpID);
- picture->fData->draw(*canvas, NULL);
- picture->fData->setDrawLimits(0, 0);
+ SkPicturePlayback playback(picture);
+ playback.setDrawLimits(info.fSaveLayerOpID, info.fRestoreOpID);
+ playback.draw(canvas, NULL);
canvas->flush();
}
@@ -2019,9 +2020,10 @@
}
// Playback using new layers
- picture->fData->setReplacements(&replacements);
- picture->fData->draw(*canvas, NULL);
- picture->fData->setReplacements(NULL);
+ SkPicturePlayback playback(picture);
+
+ playback.setReplacements(&replacements);
+ playback.draw(canvas, NULL);
// unlock the layers
for (int i = 0; i < gpuData->numSaveLayers(); ++i) {