From 116ad84d3126b0db22b2312ca59ed70e5c56f6fc Mon Sep 17 00:00:00 2001 From: "bsalomon@google.com" Date: Tue, 9 Apr 2013 15:38:19 +0000 Subject: [PATCH] Make GrIODB record and play back copySurface. Review URL: https://codereview.chromium.org/13581003 git-svn-id: http://skia.googlecode.com/svn/trunk@8574 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/gpu/GrDrawTarget.cpp | 105 ++++++++++++++++++++++++++++------------ src/gpu/GrDrawTarget.h | 16 ++++-- src/gpu/GrInOrderDrawBuffer.cpp | 39 +++++++++++++++ src/gpu/GrInOrderDrawBuffer.h | 32 +++++++++--- 4 files changed, 152 insertions(+), 40 deletions(-) diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index a0c15dd..d07d625 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -751,52 +751,76 @@ GrDrawTarget::AutoClipRestore::AutoClipRestore(GrDrawTarget* target, const SkIRe target->setClip(&fReplacementClip); } -bool GrDrawTarget::copySurface(GrSurface* dst, - GrSurface* src, +namespace { +// returns true if the read/written rect intersects the src/dst and false if not. +bool clip_srcrect_and_dstpoint(const GrSurface* dst, + const GrSurface* src, const SkIRect& srcRect, - const SkIPoint& dstPoint) { - SkIRect clippedSrcRect(srcRect); - SkIPoint clippedDstPoint(dstPoint); + const SkIPoint& dstPoint, + SkIRect* clippedSrcRect, + SkIPoint* clippedDstPoint) { + *clippedSrcRect = srcRect; + *clippedDstPoint = dstPoint; - // clip the left edge to src and dst bounds, adjusting dstPoint if neceessary - if (clippedSrcRect.fLeft < 0) { - clippedDstPoint.fX -= clippedSrcRect.fLeft; - clippedSrcRect.fLeft = 0; + // clip the left edge to src and dst bounds, adjusting dstPoint if necessary + if (clippedSrcRect->fLeft < 0) { + clippedDstPoint->fX -= clippedSrcRect->fLeft; + clippedSrcRect->fLeft = 0; } - if (clippedDstPoint.fX < 0) { - clippedSrcRect.fLeft -= clippedDstPoint.fX; - clippedDstPoint.fX = 0; + if (clippedDstPoint->fX < 0) { + clippedSrcRect->fLeft -= clippedDstPoint->fX; + clippedDstPoint->fX = 0; } - // clip the top edge to src and dst bounds, adjusting dstPoint if neceessary - if (clippedSrcRect.fTop < 0) { - clippedDstPoint.fY -= clippedSrcRect.fTop; - clippedSrcRect.fTop = 0; + // clip the top edge to src and dst bounds, adjusting dstPoint if necessary + if (clippedSrcRect->fTop < 0) { + clippedDstPoint->fY -= clippedSrcRect->fTop; + clippedSrcRect->fTop = 0; } - if (clippedDstPoint.fY < 0) { - clippedSrcRect.fTop -= clippedDstPoint.fY; - clippedDstPoint.fY = 0; + if (clippedDstPoint->fY < 0) { + clippedSrcRect->fTop -= clippedDstPoint->fY; + clippedDstPoint->fY = 0; } // clip the right edge to the src and dst bounds. - if (clippedSrcRect.fRight > src->width()) { - clippedSrcRect.fRight = src->width(); + if (clippedSrcRect->fRight > src->width()) { + clippedSrcRect->fRight = src->width(); } - if (clippedDstPoint.fX + clippedSrcRect.width() > dst->width()) { - clippedSrcRect.fRight = clippedSrcRect.fLeft + dst->width() - clippedDstPoint.fX; + if (clippedDstPoint->fX + clippedSrcRect->width() > dst->width()) { + clippedSrcRect->fRight = clippedSrcRect->fLeft + dst->width() - clippedDstPoint->fX; } // clip the bottom edge to the src and dst bounds. - if (clippedSrcRect.fBottom > src->height()) { - clippedSrcRect.fBottom = src->height(); + if (clippedSrcRect->fBottom > src->height()) { + clippedSrcRect->fBottom = src->height(); } - if (clippedDstPoint.fY + clippedSrcRect.height() > dst->height()) { - clippedSrcRect.fBottom = clippedSrcRect.fTop + dst->height() - clippedDstPoint.fY; + if (clippedDstPoint->fY + clippedSrcRect->height() > dst->height()) { + clippedSrcRect->fBottom = clippedSrcRect->fTop + dst->height() - clippedDstPoint->fY; } // The above clipping steps may have inverted the rect if it didn't intersect either the src or // dst bounds. - if (clippedSrcRect.isEmpty()) { + return !clippedSrcRect->isEmpty(); +} +} + +bool GrDrawTarget::copySurface(GrSurface* dst, + GrSurface* src, + const SkIRect& srcRect, + const SkIPoint& dstPoint) { + GrAssert(NULL != dst); + GrAssert(NULL != src); + + SkIRect clippedSrcRect; + SkIPoint clippedDstPoint; + // If the rect is outside the src or dst then we've already succeeded. + if (!clip_srcrect_and_dstpoint(dst, + src, + srcRect, + dstPoint, + &clippedSrcRect, + &clippedDstPoint)) { + GrAssert(this->canCopySurface(dst, src, srcRect, dstPoint)); return true; } @@ -809,6 +833,27 @@ bool GrDrawTarget::canCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) { + GrAssert(NULL != dst); + GrAssert(NULL != src); + + SkIRect clippedSrcRect; + SkIPoint clippedDstPoint; + // If the rect is outside the src or dst then we're guaranteed success + if (!clip_srcrect_and_dstpoint(dst, + src, + srcRect, + dstPoint, + &clippedSrcRect, + &clippedDstPoint)) { + return true; + } + return this->onCanCopySurface(dst, src, clippedSrcRect, clippedDstPoint); +} + +bool GrDrawTarget::onCanCopySurface(GrSurface* dst, + GrSurface* src, + const SkIRect& srcRect, + const SkIPoint& dstPoint) { // Check that the read/write rects are contained within the src/dst bounds. GrAssert(!srcRect.isEmpty()); GrAssert(SkIRect::MakeWH(src->width(), src->height()).contains(srcRect)); @@ -816,14 +861,14 @@ bool GrDrawTarget::canCopySurface(GrSurface* dst, GrAssert(dstPoint.fX + srcRect.width() <= dst->width() && dstPoint.fY + srcRect.height() <= dst->height()); - return NULL != dst->asRenderTarget() && NULL != src->asTexture(); + return !dst->isSameAs(src) && NULL != dst->asRenderTarget() && NULL != src->asTexture(); } bool GrDrawTarget::onCopySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) { - if (!GrDrawTarget::canCopySurface(dst, src, srcRect, dstPoint)) { + if (!GrDrawTarget::onCanCopySurface(dst, src, srcRect, dstPoint)) { return false; } diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index 99fb15f..13abee9 100644 --- a/src/gpu/GrDrawTarget.h +++ b/src/gpu/GrDrawTarget.h @@ -422,6 +422,14 @@ public: GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint); + /** + * Function that determines whether a copySurface call would succeed without + * performing the copy. + */ + bool canCopySurface(GrSurface* dst, + GrSurface* src, + const SkIRect& srcRect, + const SkIPoint& dstPoint); /** * Release any resources that are cached but not currently in use. This @@ -646,10 +654,10 @@ protected: // classes must keep this consistent with their implementation of onCopySurface(). The inputs // are the same as onCopySurface(), i.e. srcRect and dstPoint are clipped to be inside the src // and dst bounds. - virtual bool canCopySurface(GrSurface* dst, - GrSurface* src, - const SkIRect& srcRect, - const SkIPoint& dstPoint); + virtual bool onCanCopySurface(GrSurface* dst, + GrSurface* src, + const SkIRect& srcRect, + const SkIPoint& dstPoint); GrContext* getContext() { return fContext; } const GrContext* getContext() const { return fContext; } diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index 4377967..481a395 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -422,6 +422,7 @@ void GrInOrderDrawBuffer::reset() { fIndexPool.reset(); fClips.reset(); fClipOrigins.reset(); + fCopySurfaces.reset(); fClipSet = true; } @@ -456,6 +457,7 @@ bool GrInOrderDrawBuffer::flush() { int currClear = 0; int currDraw = 0; int currStencilPath = 0; + int currCopySurface = 0; for (int c = 0; c < numCmds; ++c) { switch (fCmds[c]) { @@ -492,6 +494,13 @@ bool GrInOrderDrawBuffer::flush() { fClears[currClear].fRenderTarget); ++currClear; break; + case kCopySurface_Cmd: + fDstGpu->copySurface(fCopySurfaces[currCopySurface].fDst.get(), + fCopySurfaces[currCopySurface].fSrc.get(), + fCopySurfaces[currCopySurface].fSrcRect, + fCopySurfaces[currCopySurface].fDstPoint); + ++currCopySurface; + break; } } // we should have consumed all the states, clips, etc. @@ -500,6 +509,7 @@ bool GrInOrderDrawBuffer::flush() { GrAssert(fClipOrigins.count() == currClip); GrAssert(fClears.count() == currClear); GrAssert(fDraws.count() == currDraw); + GrAssert(fCopySurfaces.count() == currCopySurface); fDstGpu->setDrawState(prevDrawState); prevDrawState->unref(); @@ -507,6 +517,29 @@ bool GrInOrderDrawBuffer::flush() { return true; } +bool GrInOrderDrawBuffer::onCopySurface(GrSurface* dst, + GrSurface* src, + const SkIRect& srcRect, + const SkIPoint& dstPoint) { + if (fDstGpu->canCopySurface(dst, src, srcRect, dstPoint)) { + CopySurface* cs = this->recordCopySurface(); + cs->fDst.reset(SkRef(dst)); + cs->fSrc.reset(SkRef(src)); + cs->fSrcRect = srcRect; + cs->fDstPoint = dstPoint; + return true; + } else { + return false; + } +} + +bool GrInOrderDrawBuffer::onCanCopySurface(GrSurface* dst, + GrSurface* src, + const SkIRect& srcRect, + const SkIPoint& dstPoint) { + return fDstGpu->canCopySurface(dst, src, srcRect, dstPoint); +} + void GrInOrderDrawBuffer::willReserveVertexAndIndexSpace( int vertexCount, int indexCount) { @@ -756,6 +789,12 @@ GrInOrderDrawBuffer::Clear* GrInOrderDrawBuffer::recordClear() { return &fClears.push_back(); } +GrInOrderDrawBuffer::CopySurface* GrInOrderDrawBuffer::recordCopySurface() { + fCmds.push_back(kCopySurface_Cmd); + return &fCopySurfaces.push_back(); +} + + void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) { INHERITED::clipWillBeSet(newClipData); fClipSet = true; diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h index ed9f884..37bb411 100644 --- a/src/gpu/GrInOrderDrawBuffer.h +++ b/src/gpu/GrInOrderDrawBuffer.h @@ -33,7 +33,7 @@ class GrVertexBufferAllocPool; * responsibility to ensure that all referenced textures, buffers, and render-targets are associated * in the GrGpu object that the buffer is played back into. The buffer requires VB and IB pools to * store geometry. - */ + */ class GrInOrderDrawBuffer : public GrDrawTarget { public: @@ -87,6 +87,7 @@ private: kSetState_Cmd = 3, kSetClip_Cmd = 4, kClear_Cmd = 5, + kCopySurface_Cmd = 6, }; class DrawRecord : public DrawInfo { @@ -96,7 +97,7 @@ private: const GrIndexBuffer* fIndexBuffer; }; - struct StencilPath { + struct StencilPath : GrNoncopyable { StencilPath(); SkAutoTUnref fPath; @@ -104,7 +105,7 @@ private: SkPath::FillType fFill; }; - struct Clear { + struct Clear : GrNoncopyable { Clear() : fRenderTarget(NULL) {} ~Clear() { GrSafeUnref(fRenderTarget); } @@ -113,6 +114,13 @@ private: GrRenderTarget* fRenderTarget; }; + struct CopySurface : GrNoncopyable { + SkAutoTUnref fDst; + SkAutoTUnref fSrc; + SkIRect fSrcRect; + SkIPoint fDstPoint; + }; + // overrides from GrDrawTarget virtual void onDraw(const DrawInfo&) SK_OVERRIDE; virtual void onDrawRect(const GrRect& rect, @@ -137,6 +145,15 @@ private: virtual void geometrySourceWillPop(const GeometrySrcState& restoredState) SK_OVERRIDE; virtual void willReserveVertexAndIndexSpace(int vertexCount, int indexCount) SK_OVERRIDE; + virtual bool onCopySurface(GrSurface* dst, + GrSurface* src, + const SkIRect& srcRect, + const SkIPoint& dstPoint) SK_OVERRIDE; + virtual bool onCanCopySurface(GrSurface* dst, + GrSurface* src, + const SkIRect& srcRect, + const SkIPoint& dstPoint) SK_OVERRIDE; + bool quickInsideClip(const SkRect& devBounds); // Attempts to concat instances from info onto the previous draw. info must represent an @@ -154,7 +171,9 @@ private: DrawRecord* recordDraw(const DrawInfo&); StencilPath* recordStencilPath(); Clear* recordClear(); + CopySurface* recordCopySurface(); + // TODO: Use a single allocator for commands and records enum { kCmdPreallocCnt = 32, kDrawPreallocCnt = 8, @@ -163,6 +182,7 @@ private: kClipPreallocCnt = 8, kClearPreallocCnt = 4, kGeoPoolStatePreAllocCnt = 4, + kCopySurfacePreallocCnt = 4, }; SkSTArray fCmds; @@ -170,9 +190,9 @@ private: GrSTAllocator fStencilPaths; GrSTAllocator fStates; GrSTAllocator fClears; - - GrSTAllocator fClips; - GrSTAllocator fClipOrigins; + GrSTAllocator fCopySurfaces; + GrSTAllocator fClips; + GrSTAllocator fClipOrigins; GrDrawTarget* fDstGpu; -- 2.7.4