Add the machinery to GrDrawTarget to enable topological sorting

This relies on https://codereview.chromium.org/1414503003/ (Add SkTTopoSort) landing first.

BUG=skia:4094

Review URL: https://codereview.chromium.org/1414773002
This commit is contained in:
robertphillips 2015-10-20 07:37:58 -07:00 committed by Commit bot
parent c84ccb0702
commit 6a18665a7e
3 changed files with 111 additions and 7 deletions

View File

@ -45,7 +45,7 @@
#include "SkTLazy.h"
#include "SkTLS.h"
#include "SkTraceEvent.h"
#include "SkTTopoSort.h"
#include "batches/GrBatch.h"
@ -95,9 +95,21 @@ void GrDrawingManager::reset() {
}
void GrDrawingManager::flush() {
SkDEBUGCODE(bool result =)
SkTTopoSort<GrDrawTarget, GrDrawTarget::TopoSortTraits>(&fDrawTargets);
SkASSERT(result);
for (int i = 0; i < fDrawTargets.count(); ++i) {
fDrawTargets[i]->flush();
}
#ifndef ENABLE_MDB
// When MDB is disabled we keep reusing the same drawTarget
if (fDrawTargets.count()) {
SkASSERT(fDrawTargets.count() == 1);
fDrawTargets[0]->resetFlag(GrDrawTarget::kWasOutput_Flag);
}
#endif
}
GrTextContext* GrDrawingManager::textContext(const SkSurfaceProps& props,
@ -131,8 +143,8 @@ GrTextContext* GrDrawingManager::textContext(const SkSurfaceProps& props,
GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) {
SkASSERT(fContext);
// When MDB is disabled we always just return the single drawTarget
#ifndef ENABLE_MDB
// When MDB is disabled we always just return the single drawTarget
if (fDrawTargets.count()) {
SkASSERT(fDrawTargets.count() == 1);
// DrawingManager gets the creation ref - this ref is for the caller

View File

@ -38,7 +38,7 @@ GrDrawTarget::GrDrawTarget(GrGpu* gpu, GrResourceProvider* resourceProvider)
, fFlushState(fGpu, fResourceProvider, 0)
, fFlushing(false)
, fFirstUnpreparedBatch(0)
, fClosed(false) {
, fFlags(0) {
// TODO: Stop extracting the context (currently needed by GrClipMaskManager)
fContext = fGpu->getContext();
fClipMaskManager.reset(new GrClipMaskManager(this));
@ -50,6 +50,35 @@ GrDrawTarget::~GrDrawTarget() {
////////////////////////////////////////////////////////////////////////////////
// Add a GrDrawTarget-based dependency
void GrDrawTarget::addDependency(GrDrawTarget* dependedOn) {
SkASSERT(!dependedOn->dependsOn(this)); // loops are bad
if (this->dependsOn(dependedOn)) {
return; // don't add duplicate dependencies
}
*fDependencies.push() = dependedOn;
}
// Convert from a GrSurface-based dependency to a GrDrawTarget one
void GrDrawTarget::addDependency(GrSurface* dependedOn) {
if (dependedOn->asRenderTarget() && dependedOn->asRenderTarget()->getLastDrawTarget()) {
// If it is still receiving dependencies, this DT shouldn't be closed
SkASSERT(!this->isClosed());
GrDrawTarget* dt = dependedOn->asRenderTarget()->getLastDrawTarget();
if (dt == this) {
// self-read - presumably for dst reads
} else {
this->addDependency(dt);
// Can't make it closed in the self-read case
dt->makeClosed();
}
}
}
bool GrDrawTarget::setupDstReadIfNecessary(const GrPipelineBuilder& pipelineBuilder,
const GrProcOptInfo& colorPOI,
const GrProcOptInfo& coveragePOI,
@ -414,7 +443,7 @@ template <class Left, class Right> static bool intersect(const Left& a, const Ri
void GrDrawTarget::recordBatch(GrBatch* batch) {
// A closed drawTarget should never receive new/more batches
SkASSERT(!fClosed);
SkASSERT(!this->isClosed());
// Check if there is a Batch Draw we can batch with by linearly searching back until we either
// 1) check every draw

View File

@ -53,10 +53,22 @@ public:
// We only close drawTargets When MDB is enabled. When MDB is disabled there is only
// ever one drawTarget and all calls will be funnelled into it.
#ifdef ENABLE_MDB
fClosed = true;
this->setFlag(kClosed_Flag);
#endif
}
bool isClosed() const { return fClosed; }
bool isClosed() const { return this->isSetFlag(kClosed_Flag); }
/*
* Notify this drawTarget that it relies on the contents of 'dependedOn'
*/
void addDependency(GrSurface* dependedOn);
/*
* Does this drawTarget depend on 'dependedOn'?
*/
bool dependsOn(GrDrawTarget* dependedOn) const {
return fDependencies.find(dependedOn) >= 0;
}
/**
* Empties the draw buffer of any queued up draws.
@ -204,7 +216,53 @@ public:
const CMMAccess cmmAccess() { return CMMAccess(this); }
private:
friend class GrDrawingManager; // for resetFlag & TopoSortTraits
enum Flags {
kClosed_Flag = 0x01, //!< This drawTarget can't accept any more batches
kWasOutput_Flag = 0x02, //!< Flag for topological sorting
kTempMark_Flag = 0x04, //!< Flag for topological sorting
};
void setFlag(uint32_t flag) {
fFlags |= flag;
}
void resetFlag(uint32_t flag) {
fFlags &= ~flag;
}
bool isSetFlag(uint32_t flag) const {
return SkToBool(fFlags & flag);
}
struct TopoSortTraits {
static void Output(GrDrawTarget* dt, int /* index */) {
dt->setFlag(GrDrawTarget::kWasOutput_Flag);
}
static bool WasOutput(const GrDrawTarget* dt) {
return dt->isSetFlag(GrDrawTarget::kWasOutput_Flag);
}
static void SetTempMark(GrDrawTarget* dt) {
dt->setFlag(GrDrawTarget::kTempMark_Flag);
}
static void ResetTempMark(GrDrawTarget* dt) {
dt->resetFlag(GrDrawTarget::kTempMark_Flag);
}
static bool IsTempMarked(const GrDrawTarget* dt) {
return dt->isSetFlag(GrDrawTarget::kTempMark_Flag);
}
static int NumDependencies(const GrDrawTarget* dt) {
return dt->fDependencies.count();
}
static GrDrawTarget* Dependency(GrDrawTarget* dt, int index) {
return dt->fDependencies[index];
}
};
void recordBatch(GrBatch*);
bool installPipelineInDrawBatch(const GrPipelineBuilder* pipelineBuilder,
const GrScissorState* scissor,
@ -231,6 +289,8 @@ private:
GrScissorState*,
const SkRect* devBounds);
void addDependency(GrDrawTarget* dependedOn);
// Used only by CMM.
void clearStencilClip(const SkIRect&, bool insideClip, GrRenderTarget*);
@ -244,7 +304,10 @@ private:
bool fFlushing;
int fFirstUnpreparedBatch;
bool fClosed;
uint32_t fFlags;
// 'this' drawTarget relies on the output of the drawTargets in 'fDependencies'
SkTDArray<GrDrawTarget*> fDependencies;
typedef SkRefCnt INHERITED;
};