Make GrIODB record and play back copySurface.
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 9 Apr 2013 15:38:19 +0000 (15:38 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 9 Apr 2013 15:38:19 +0000 (15:38 +0000)
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
src/gpu/GrDrawTarget.h
src/gpu/GrInOrderDrawBuffer.cpp
src/gpu/GrInOrderDrawBuffer.h

index a0c15dd..d07d625 100644 (file)
@@ -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;
     }
 
index 99fb15f..13abee9 100644 (file)
@@ -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; }
index 4377967..481a395 100644 (file)
@@ -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;
index ed9f884..37bb411 100644 (file)
@@ -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<const GrPath>  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<GrSurface> fDst;
+        SkAutoTUnref<GrSurface> 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<kCmdPreallocCnt, uint8_t, true>                          fCmds;
@@ -170,9 +190,9 @@ private:
     GrSTAllocator<kStatePreallocCnt, StencilPath>                      fStencilPaths;
     GrSTAllocator<kStatePreallocCnt, GrDrawState::DeferredState>       fStates;
     GrSTAllocator<kClearPreallocCnt, Clear>                            fClears;
-
-    GrSTAllocator<kClipPreallocCnt, SkClipStack>        fClips;
-    GrSTAllocator<kClipPreallocCnt, SkIPoint>           fClipOrigins;
+    GrSTAllocator<kCopySurfacePreallocCnt, CopySurface>                fCopySurfaces;
+    GrSTAllocator<kClipPreallocCnt, SkClipStack>                       fClips;
+    GrSTAllocator<kClipPreallocCnt, SkIPoint>                          fClipOrigins;
 
     GrDrawTarget*                   fDstGpu;