Loosen requirement that there be only one GrDrawTarget

BUG=skia:4094

Review URL: https://codereview.chromium.org/1406173003
This commit is contained in:
robertphillips 2015-10-16 09:07:06 -07:00 committed by Commit bot
parent 26ad22ab61
commit a106c62753
9 changed files with 166 additions and 58 deletions

View File

@ -188,6 +188,12 @@ public:
return fDrawingMgr.textContext(surfaceProps, rt);
}
// The caller automatically gets a ref on the returned drawTarget. It must
// be balanced by an unref call.
GrDrawTarget* newDrawTarget(GrRenderTarget* rt) {
return fDrawingMgr.newDrawTarget(rt);
}
///////////////////////////////////////////////////////////////////////////
// Misc.
@ -426,7 +432,10 @@ private:
// each GrRenderTarget/GrDrawTarget and manage the DAG.
class DrawingMgr {
public:
DrawingMgr() : fDrawTarget(nullptr), fNVPRTextContext(nullptr) {
DrawingMgr()
: fContext(nullptr)
, fAbandoned(false)
, fNVPRTextContext(nullptr) {
sk_bzero(fTextContexts, sizeof(fTextContexts));
}
@ -435,7 +444,7 @@ private:
void init(GrContext* context);
void abandon();
bool abandoned() const { return NULL == fDrawTarget; }
bool abandoned() const { return fAbandoned; }
void reset();
void flush();
@ -445,6 +454,8 @@ private:
GrDrawContext* drawContext(GrRenderTarget* rt, const SkSurfaceProps* surfaceProps);
GrTextContext* textContext(const SkSurfaceProps& props, GrRenderTarget* rt);
GrDrawTarget* newDrawTarget(GrRenderTarget* rt);
private:
void cleanup();
@ -455,7 +466,9 @@ private:
static const int kNumDFTOptions = 2; // DFT or no DFT
GrContext* fContext;
GrDrawTarget* fDrawTarget;
bool fAbandoned;
SkTDArray<GrDrawTarget*> fDrawTargets;
GrTextContext* fNVPRTextContext;
GrTextContext* fTextContexts[kNumPixelGeometries][kNumDFTOptions];

View File

@ -256,7 +256,7 @@ private:
SkDEBUGCODE(void validate() const;)
GrDrawContext(GrContext*, GrRenderTarget*, GrDrawTarget*, const SkSurfaceProps* surfaceProps);
GrDrawContext(GrContext*, GrRenderTarget*, const SkSurfaceProps* surfaceProps);
void internalDrawPath(GrDrawTarget*,
GrPipelineBuilder*,
@ -270,8 +270,13 @@ private:
// the drawTarget.
void drawBatch(GrPipelineBuilder* pipelineBuilder, GrDrawBatch* batch);
GrDrawTarget* getDrawTarget();
GrContext* fContext; // owning context -> no ref
GrRenderTarget* fRenderTarget;
// In MDB-mode the drawTarget can be closed by some other drawContext that has picked
// it up. For this reason, the drawTarget should only ever be accessed via 'getDrawTarget'.
GrDrawTarget* fDrawTarget;
GrTextContext* fTextContext; // lazily gotten from GrContext::DrawingMgr

View File

@ -11,6 +11,7 @@
#include "GrSurface.h"
#include "SkRect.h"
class GrDrawTarget;
class GrStencilAttachment;
class GrRenderTargetPriv;
@ -151,12 +152,16 @@ public:
GrRenderTargetPriv renderTargetPriv();
const GrRenderTargetPriv renderTargetPriv() const;
void setLastDrawTarget(GrDrawTarget* dt);
GrDrawTarget* getLastDrawTarget() { return fLastDrawTarget; }
protected:
GrRenderTarget(GrGpu* gpu, LifeCycle lifeCycle, const GrSurfaceDesc& desc,
SampleConfig sampleConfig, GrStencilAttachment* stencil = nullptr)
: INHERITED(gpu, lifeCycle, desc)
, fStencilAttachment(stencil)
, fSampleConfig(sampleConfig) {
, fSampleConfig(sampleConfig)
, fLastDrawTarget(nullptr) {
fResolveRect.setLargestInverted();
}
@ -178,6 +183,14 @@ private:
SkIRect fResolveRect;
// The last drawTarget that wrote to or is currently going to write to this renderTarget
// The drawTarget can be closed (e.g., no draw context is currently bound
// to this renderTarget).
// This back-pointer is required so that we can add a dependancy between
// the drawTarget used to create the current contents of this renderTarget
// and the drawTarget of a destination renderTarget to which this one is being drawn.
GrDrawTarget* fLastDrawTarget;
typedef GrSurface INHERITED;
};

View File

@ -62,13 +62,18 @@
void GrContext::DrawingMgr::init(GrContext* context) {
fContext = context;
fDrawTarget = new GrDrawTarget(context->getGpu(), context->resourceProvider());
}
void GrContext::DrawingMgr::cleanup() {
SkSafeSetNull(fDrawTarget);
for (int i = 0; i < fDrawTargets.count(); ++i) {
fDrawTargets[i]->unref();
}
fDrawTargets.reset();
delete fNVPRTextContext;
fNVPRTextContext = nullptr;
for (int i = 0; i < kNumPixelGeometries; ++i) {
delete fTextContexts[i][0];
fTextContexts[i][0] = nullptr;
@ -82,18 +87,19 @@ GrContext::DrawingMgr::~DrawingMgr() {
}
void GrContext::DrawingMgr::abandon() {
fAbandoned = true;
this->cleanup();
}
void GrContext::DrawingMgr::reset() {
if (fDrawTarget) {
fDrawTarget->reset();
for (int i = 0; i < fDrawTargets.count(); ++i) {
fDrawTargets[i]->reset();
}
}
void GrContext::DrawingMgr::flush() {
if (fDrawTarget) {
fDrawTarget->flush();
for (int i = 0; i < fDrawTargets.count(); ++i) {
fDrawTargets[i]->flush();
}
}
@ -125,13 +131,33 @@ GrTextContext* GrContext::DrawingMgr::textContext(const SkSurfaceProps& props,
return fTextContexts[props.pixelGeometry()][useDIF];
}
GrDrawTarget* GrContext::DrawingMgr::newDrawTarget(GrRenderTarget* rt) {
SkASSERT(fContext);
// When MDB is disabled we always just return the single drawTarget
#ifndef ENABLE_MDB
if (fDrawTargets.count()) {
SkASSERT(fDrawTargets.count() == 1);
// DrawingMgr gets the creation ref - this ref is for the caller
return SkRef(fDrawTargets[0]);
}
#endif
GrDrawTarget* dt = new GrDrawTarget(fContext->getGpu(), fContext->resourceProvider());
*fDrawTargets.append() = dt;
// DrawingMgr gets the creation ref - this ref is for the caller
return SkRef(dt);
}
GrDrawContext* GrContext::DrawingMgr::drawContext(GrRenderTarget* rt,
const SkSurfaceProps* surfaceProps) {
if (this->abandoned()) {
return nullptr;
}
return new GrDrawContext(fContext, rt, fDrawTarget, surfaceProps);
return new GrDrawContext(fContext, rt, surfaceProps);
}
////////////////////////////////////////////////////////////////////////////////

View File

@ -37,34 +37,52 @@ private:
GrContext* fContext;
};
// In MDB mode the reffing of the 'getLastDrawTarget' call's result allows in-progress
// drawTargets to be picked up and added to by drawContexts lower in the call
// stack. When this occurs with a closed drawTarget, a new one will be allocated
// when the drawContext attempts to use it (via getDrawTarget).
GrDrawContext::GrDrawContext(GrContext* context,
GrRenderTarget* rt,
GrDrawTarget* drawTarget,
const SkSurfaceProps* surfaceProps)
: fContext(context)
, fRenderTarget(rt)
, fDrawTarget(SkRef(drawTarget))
, fDrawTarget(SkSafeRef(rt->getLastDrawTarget()))
, fTextContext(nullptr)
, fSurfaceProps(SkSurfacePropsCopyOrDefault(surfaceProps)) {
SkDEBUGCODE(this->validate();)
}
GrDrawContext::~GrDrawContext() {
SkSafeUnref(fDrawTarget);
}
#ifdef SK_DEBUG
void GrDrawContext::validate() const {
SkASSERT(fRenderTarget);
ASSERT_OWNED_RESOURCE(fRenderTarget);
if (fDrawTarget && !fDrawTarget->isClosed()) {
SkASSERT(fRenderTarget->getLastDrawTarget() == fDrawTarget);
}
}
#endif
GrDrawContext::~GrDrawContext() {
SkSafeUnref(fDrawTarget);
}
GrDrawTarget* GrDrawContext::getDrawTarget() {
SkDEBUGCODE(this->validate();)
if (!fDrawTarget || fDrawTarget->isClosed()) {
fDrawTarget = fContext->newDrawTarget(fRenderTarget);
fRenderTarget->setLastDrawTarget(fDrawTarget);
}
return fDrawTarget;
}
void GrDrawContext::copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
RETURN_IF_ABANDONED
SkDEBUGCODE(this->validate();)
fDrawTarget->copySurface(fRenderTarget, src, srcRect, dstPoint);
this->getDrawTarget()->copySurface(fRenderTarget, src, srcRect, dstPoint);
}
@ -126,8 +144,8 @@ void GrDrawContext::drawPathsFromRange(const GrPipelineBuilder* pipelineBuilder,
RETURN_IF_ABANDONED
SkDEBUGCODE(this->validate();)
fDrawTarget->drawPathsFromRange(*pipelineBuilder, viewMatrix, localMatrix, color, range, draw,
(GrPathRendering::FillType) fill);
this->getDrawTarget()->drawPathsFromRange(*pipelineBuilder, viewMatrix, localMatrix, color,
range, draw, (GrPathRendering::FillType) fill);
}
void GrDrawContext::discard() {
@ -135,7 +153,7 @@ void GrDrawContext::discard() {
SkDEBUGCODE(this->validate();)
AutoCheckFlush acf(fContext);
fDrawTarget->discard(fRenderTarget);
this->getDrawTarget()->discard(fRenderTarget);
}
void GrDrawContext::clear(const SkIRect* rect,
@ -145,7 +163,7 @@ void GrDrawContext::clear(const SkIRect* rect,
SkDEBUGCODE(this->validate();)
AutoCheckFlush acf(fContext);
fDrawTarget->clear(rect, color, canIgnoreRect, fRenderTarget);
this->getDrawTarget()->clear(rect, color, canIgnoreRect, fRenderTarget);
}
@ -191,11 +209,11 @@ void GrDrawContext::drawPaint(const GrClip& clip,
AutoCheckFlush acf(fContext);
GrPipelineBuilder pipelineBuilder(*paint, fRenderTarget, clip);
fDrawTarget->drawNonAARect(pipelineBuilder,
paint->getColor(),
SkMatrix::I(),
r,
localMatrix);
this->getDrawTarget()->drawNonAARect(pipelineBuilder,
paint->getColor(),
SkMatrix::I(),
r,
localMatrix);
}
}
@ -253,7 +271,7 @@ void GrDrawContext::drawRect(const GrClip& clip,
// Will it blend?
GrColor clearColor;
if (paint.isConstantBlendedColor(&clearColor)) {
fDrawTarget->clear(nullptr, clearColor, true, fRenderTarget);
this->getDrawTarget()->clear(nullptr, clearColor, true, fRenderTarget);
return;
}
}
@ -279,7 +297,7 @@ void GrDrawContext::drawRect(const GrClip& clip,
viewMatrix.mapRect(&devBoundRect, rect);
batch.reset(GrRectBatchFactory::CreateAAFill(color, viewMatrix, rect, devBoundRect));
}
fDrawTarget->drawBatch(pipelineBuilder, batch);
this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
return;
}
@ -294,10 +312,10 @@ void GrDrawContext::drawRect(const GrClip& clip,
// is enabled because it can cause ugly artifacts.
pipelineBuilder.setState(GrPipelineBuilder::kSnapVerticesToPixelCenters_Flag,
snapToPixelCenters);
fDrawTarget->drawBatch(pipelineBuilder, batch);
this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
} else {
// filled BW rect
fDrawTarget->drawNonAARect(pipelineBuilder, color, viewMatrix, rect);
this->getDrawTarget()->drawNonAARect(pipelineBuilder, color, viewMatrix, rect);
}
}
@ -312,11 +330,11 @@ void GrDrawContext::drawNonAARectToRect(const GrClip& clip,
AutoCheckFlush acf(fContext);
GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
fDrawTarget->drawNonAARect(pipelineBuilder,
paint.getColor(),
viewMatrix,
rectToDraw,
localRect);
this->getDrawTarget()->drawNonAARect(pipelineBuilder,
paint.getColor(),
viewMatrix,
rectToDraw,
localRect);
}
void GrDrawContext::drawNonAARectWithLocalMatrix(const GrClip& clip,
@ -330,11 +348,11 @@ void GrDrawContext::drawNonAARectWithLocalMatrix(const GrClip& clip,
AutoCheckFlush acf(fContext);
GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
fDrawTarget->drawNonAARect(pipelineBuilder,
paint.getColor(),
viewMatrix,
rectToDraw,
localMatrix);
this->getDrawTarget()->drawNonAARect(pipelineBuilder,
paint.getColor(),
viewMatrix,
rectToDraw,
localMatrix);
}
void GrDrawContext::drawVertices(const GrClip& clip,
@ -376,7 +394,7 @@ void GrDrawContext::drawVertices(const GrClip& clip,
indexCount, colors, texCoords,
bounds));
fDrawTarget->drawBatch(pipelineBuilder, batch);
this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
}
///////////////////////////////////////////////////////////////////////////////
@ -400,7 +418,7 @@ void GrDrawContext::drawAtlas(const GrClip& clip,
SkAutoTUnref<GrDrawBatch> batch(GrDrawAtlasBatch::Create(geometry, viewMatrix, spriteCount,
xform, texRect, colors));
fDrawTarget->drawBatch(pipelineBuilder, batch);
this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
}
///////////////////////////////////////////////////////////////////////////////
@ -430,7 +448,7 @@ void GrDrawContext::drawRRect(const GrClip& clip,
GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
GrColor color = paint.getColor();
if (!GrOvalRenderer::DrawRRect(fDrawTarget,
if (!GrOvalRenderer::DrawRRect(this->getDrawTarget(),
pipelineBuilder,
color,
viewMatrix,
@ -440,7 +458,7 @@ void GrDrawContext::drawRRect(const GrClip& clip,
SkPath path;
path.setIsVolatile(true);
path.addRRect(rrect);
this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color,
this->internalDrawPath(this->getDrawTarget(), &pipelineBuilder, viewMatrix, color,
paint.isAntiAlias(), path, strokeInfo);
}
}
@ -463,7 +481,7 @@ void GrDrawContext::drawDRRect(const GrClip& clip,
GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
GrColor color = paint.getColor();
if (!GrOvalRenderer::DrawDRRect(fDrawTarget,
if (!GrOvalRenderer::DrawDRRect(this->getDrawTarget(),
pipelineBuilder,
color,
viewMatrix,
@ -477,7 +495,7 @@ void GrDrawContext::drawDRRect(const GrClip& clip,
path.setFillType(SkPath::kEvenOdd_FillType);
GrStrokeInfo fillRec(SkStrokeRec::kFill_InitStyle);
this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color,
this->internalDrawPath(this->getDrawTarget(), &pipelineBuilder, viewMatrix, color,
paint.isAntiAlias(), path, fillRec);
}
}
@ -509,7 +527,7 @@ void GrDrawContext::drawOval(const GrClip& clip,
GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
GrColor color = paint.getColor();
if (!GrOvalRenderer::DrawOval(fDrawTarget,
if (!GrOvalRenderer::DrawOval(this->getDrawTarget(),
pipelineBuilder,
color,
viewMatrix,
@ -519,7 +537,7 @@ void GrDrawContext::drawOval(const GrClip& clip,
SkPath path;
path.setIsVolatile(true);
path.addOval(oval);
this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color,
this->internalDrawPath(this->getDrawTarget(), &pipelineBuilder, viewMatrix, color,
paint.isAntiAlias(), path, strokeInfo);
}
}
@ -582,7 +600,7 @@ void GrDrawContext::drawBatch(const GrClip& clip,
AutoCheckFlush acf(fContext);
GrPipelineBuilder pipelineBuilder(paint, fRenderTarget, clip);
fDrawTarget->drawBatch(pipelineBuilder, batch);
this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
}
void GrDrawContext::drawPath(const GrClip& clip,
@ -621,7 +639,7 @@ void GrDrawContext::drawPath(const GrClip& clip,
if (is_nested_rects(viewMatrix, path, strokeInfo, rects)) {
SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateAAFillNestedRects(
color, viewMatrix, rects));
fDrawTarget->drawBatch(pipelineBuilder, batch);
this->getDrawTarget()->drawBatch(pipelineBuilder, batch);
return;
}
}
@ -629,7 +647,7 @@ void GrDrawContext::drawPath(const GrClip& clip,
bool isOval = path.isOval(&ovalRect);
if (isOval && !path.isInverseFillType()) {
if (GrOvalRenderer::DrawOval(fDrawTarget,
if (GrOvalRenderer::DrawOval(this->getDrawTarget(),
pipelineBuilder,
color,
viewMatrix,
@ -640,8 +658,8 @@ void GrDrawContext::drawPath(const GrClip& clip,
}
}
}
this->internalDrawPath(fDrawTarget, &pipelineBuilder, viewMatrix, color, paint.isAntiAlias(),
path, strokeInfo);
this->internalDrawPath(this->getDrawTarget(), &pipelineBuilder, viewMatrix, color,
paint.isAntiAlias(), path, strokeInfo);
}
void GrDrawContext::internalDrawPath(GrDrawTarget* target,
@ -736,5 +754,5 @@ void GrDrawContext::drawBatch(GrPipelineBuilder* pipelineBuilder, GrDrawBatch* b
RETURN_IF_ABANDONED
SkDEBUGCODE(this->validate();)
fDrawTarget->drawBatch(*pipelineBuilder, batch);
this->getDrawTarget()->drawBatch(*pipelineBuilder, batch);
}

View File

@ -37,7 +37,8 @@ GrDrawTarget::GrDrawTarget(GrGpu* gpu, GrResourceProvider* resourceProvider)
, fResourceProvider(resourceProvider)
, fFlushState(fGpu, fResourceProvider, 0)
, fFlushing(false)
, fFirstUnpreparedBatch(0) {
, fFirstUnpreparedBatch(0)
, fClosed(false) {
// TODO: Stop extracting the context (currently needed by GrClipMaskManager)
fContext = fGpu->getContext();
fClipMaskManager.reset(new GrClipMaskManager(this));
@ -118,6 +119,12 @@ void GrDrawTarget::flush() {
}
fFlushing = true;
// Semi-usually the drawTargets are already closed at this point, but sometimes Ganesh
// needs to flush mid-draw. In that case, the SkGpuDevice's drawTargets won't be closed
// but need to be flushed anyway. Closing such drawTargets here will mean new
// drawTargets will be created to replace them if the SkGpuDevice(s) write to them again.
this->makeClosed();
// Loop over all batches and generate geometry
for (; fFirstUnpreparedBatch < fBatches.count(); ++fFirstUnpreparedBatch) {
fBatches[fFirstUnpreparedBatch]->prepare(&fFlushState);
@ -406,6 +413,9 @@ 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);
// Check if there is a Batch Draw we can batch with by linearly searching back until we either
// 1) check every draw
// 2) intersect with something

View File

@ -49,6 +49,15 @@ public:
~GrDrawTarget() override;
void makeClosed() {
// 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;
#endif
}
bool isClosed() const { return fClosed; }
/**
* Empties the draw buffer of any queued up draws.
*/
@ -235,6 +244,8 @@ private:
bool fFlushing;
int fFirstUnpreparedBatch;
bool fClosed;
typedef SkRefCnt INHERITED;
};

View File

@ -11,6 +11,7 @@
#include "GrContext.h"
#include "GrDrawContext.h"
#include "GrDrawTarget.h"
#include "GrGpu.h"
#include "GrRenderTargetPriv.h"
#include "GrStencilAttachment.h"
@ -56,16 +57,26 @@ void GrRenderTarget::overrideResolveRect(const SkIRect rect) {
void GrRenderTarget::onRelease() {
SkSafeSetNull(fStencilAttachment);
fLastDrawTarget = nullptr;
INHERITED::onRelease();
}
void GrRenderTarget::onAbandon() {
SkSafeSetNull(fStencilAttachment);
fLastDrawTarget = nullptr;
INHERITED::onAbandon();
}
void GrRenderTarget::setLastDrawTarget(GrDrawTarget* dt) {
if (fLastDrawTarget) {
SkASSERT(fLastDrawTarget->isClosed());
}
fLastDrawTarget = dt;
}
///////////////////////////////////////////////////////////////////////////////
bool GrRenderTargetPriv::attachStencilAttachment(GrStencilAttachment* stencil) {

View File

@ -54,7 +54,8 @@ void GrContext::getTestTarget(GrTestTarget* tar) {
// then disconnects. This would help prevent test writers from mixing using the returned
// GrDrawTarget and regular drawing. We could also assert or fail in GrContext drawing methods
// until ~GrTestTarget().
tar->init(this, fDrawingMgr.fDrawTarget);
SkAutoTUnref<GrDrawTarget> dt(fDrawingMgr.newDrawTarget(nullptr));
tar->init(this, dt);
}
void GrContext::setTextBlobCacheLimit_ForTesting(size_t bytes) {