Add a deferred copy surface (take 3)
This CL forces all GrSurface copies to go through a GrSurfaceContext (rather than GrContext).
There is a bit of goofiness going on here until read/writePixels is also consolidated in GrSurfaceContext and a proxy-backed SkImage/SkSurface is added.
This is a reland of https://skia-review.googlesource.com/c/5773/ (Add a deferred copy surface)
Change-Id: Ib8fd96d0569274ef781366eb900ed8ee839ae9bd
Reviewed-on: https://skia-review.googlesource.com/6109
Reviewed-by: Brian Salomon <bsalomon@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index de80b68..147cf5c 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -301,25 +301,6 @@
uint32_t pixelOpsFlags = 0);
/**
- * Copies a rectangle of texels from src to dst.
- * @param dst the surface to copy to.
- * @param src the surface to copy from.
- * @param srcRect the rectangle of the src that should be copied.
- * @param dstPoint the translation applied when writing the srcRect's pixels to the dst.
- */
- bool copySurface(GrSurface* dst,
- GrSurface* src,
- const SkIRect& srcRect,
- const SkIPoint& dstPoint);
-
- /** Helper that copies the whole surface but fails when the two surfaces are not identically
- sized. */
- bool copySurface(GrSurface* dst, GrSurface* src) {
- return this->copySurface(dst, src, SkIRect::MakeWH(dst->width(), dst->height()),
- SkIPoint::Make(0,0));
- }
-
- /**
* After this returns any pending writes to the surface will have been issued to the backend 3D API.
*/
void flushSurfaceWrites(GrSurface* surface);
diff --git a/include/gpu/GrRenderTargetContext.h b/include/gpu/GrRenderTargetContext.h
index 864055b..b86b626 100644
--- a/include/gpu/GrRenderTargetContext.h
+++ b/include/gpu/GrRenderTargetContext.h
@@ -50,8 +50,6 @@
public:
~GrRenderTargetContext() override;
- bool copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
-
// TODO: it is odd that we need both the SkPaint in the following 3 methods.
// We should extract the text parameters from SkPaint and pass them separately
// akin to GrStyle (GrTextInfo?)
@@ -469,6 +467,8 @@
const SkPath&,
const GrStyle&);
+ bool onCopy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
+
// This entry point allows the GrTextContext-derived classes to add their ops to the GrOpList.
void addDrawOp(const GrPipelineBuilder&, const GrClip&, sk_sp<GrDrawOp>);
diff --git a/include/gpu/GrSurfaceContext.h b/include/gpu/GrSurfaceContext.h
index f966086..a772d19 100644
--- a/include/gpu/GrSurfaceContext.h
+++ b/include/gpu/GrSurfaceContext.h
@@ -8,6 +8,8 @@
#ifndef GrSurfaceContext_DEFINED
#define GrSurfaceContext_DEFINED
+#include "../private/GrSurfaceProxy.h"
+
#include "SkRefCnt.h"
class GrAuditTrail;
@@ -28,7 +30,27 @@
public:
~GrSurfaceContext() override {}
- virtual bool copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) = 0;
+ /*
+ * Copy 'src' into the proxy backing this context
+ * @param src src of pixels
+ * @param srcRect the subset of 'src' to copy
+ * @param dstPoint the origin of the 'srcRect' in the destination coordinate space
+ * @return true if the copy succeeded; false otherwise
+ *
+ * Note: Notionally, 'srcRect' is clipped to 'src's extent with 'dstPoint' being adjusted.
+ * Then the 'srcRect' offset by 'dstPoint' is clipped against the dst's extent.
+ * The end result is only valid src pixels and dst pixels will be touched but the copied
+ * regions will not be shifted.
+ */
+ bool copy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) {
+ return this->onCopy(src, srcRect, dstPoint);
+ }
+
+ bool copy(GrSurfaceProxy* src) {
+ return this->onCopy(src,
+ SkIRect::MakeWH(src->width(), src->height()),
+ SkIPoint::Make(0, 0));
+ }
// TODO: this is virtual b.c. this object doesn't have a pointer to the wrapped GrSurfaceProxy?
virtual GrSurfaceProxy* asDeferredSurface() = 0;
@@ -55,6 +77,10 @@
SkDEBUGCODE(mutable GrSingleOwner* fSingleOwner;)
private:
+ virtual bool onCopy(GrSurfaceProxy* src,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint) = 0;
+
typedef SkRefCnt INHERITED;
};
diff --git a/include/gpu/GrTextureContext.h b/include/gpu/GrTextureContext.h
index 28fe63d..ef9613f 100644
--- a/include/gpu/GrTextureContext.h
+++ b/include/gpu/GrTextureContext.h
@@ -27,8 +27,6 @@
public:
~GrTextureContext() override;
- bool copySurface(GrSurface* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
-
GrSurfaceProxy* asDeferredSurface() override { return fTextureProxy.get(); }
GrTextureProxy* asDeferredTexture() override { return fTextureProxy.get(); }
GrRenderTargetProxy* asDeferredRenderTarget() override;
@@ -44,6 +42,8 @@
private:
friend class GrDrawingManager; // for ctor
+ bool onCopy(GrSurfaceProxy* src, const SkIRect& srcRect, const SkIPoint& dstPoint) override;
+
GrTextureOpList* getOpList();
GrDrawingManager* fDrawingManager;
@@ -52,6 +52,8 @@
// In MDB-mode the GrOpList can be closed by some other renderTargetContext that has picked
// it up. For this reason, the GrOpList should only ever be accessed via 'getOpList'.
GrTextureOpList* fOpList;
+
+ typedef GrSurfaceContext INHERITED;
};
#endif
diff --git a/include/private/GrRenderTargetProxy.h b/include/private/GrRenderTargetProxy.h
index 83107da..7f026ba 100644
--- a/include/private/GrRenderTargetProxy.h
+++ b/include/private/GrRenderTargetProxy.h
@@ -53,6 +53,9 @@
GrRenderTarget::Flags testingOnly_getFlags() const;
+ // TODO: move this to a priv class!
+ bool refsWrappedObjects() const;
+
protected:
friend class GrSurfaceProxy; // for ctors
diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h
index 731603b..12972c2 100644
--- a/include/private/GrSurfaceProxy.h
+++ b/include/private/GrSurfaceProxy.h
@@ -266,6 +266,20 @@
return fGpuMemorySize;
}
+ // Helper function that creates a temporary SurfaceContext to perform the copy
+ static sk_sp<GrSurfaceProxy> Copy(GrContext*, GrSurfaceProxy* src,
+ SkIRect srcRect, SkBudgeted);
+
+ // Copy the entire 'src'
+ static sk_sp<GrSurfaceProxy> Copy(GrContext* context, GrSurfaceProxy* src,
+ SkBudgeted budgeted) {
+ return Copy(context, src, SkIRect::MakeWH(src->width(), src->height()), budgeted);
+ }
+
+ // Test-only entry point - should decrease in use as proxies propagate
+ static sk_sp<GrSurfaceProxy> TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
+ GrTexture* srcTexture, SkBudgeted budgeted);
+
bool isWrapped_ForTesting() const;
SkDEBUGCODE(void validate(GrContext*) const;)