aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar Robert Phillips <robertphillips@google.com>2016-12-15 09:23:05 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2016-12-15 15:07:39 +0000
commite2f7d1899d890c2f08571e1bd6c7fa2c5ea1be0b (patch)
treed290f1a9d5d5e828c7177d230f56356f9fc9bf2e /src
parentdb8f44f497f2b67b2500bbfc7b11ce7a510c5e5c (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/core/SkSpecialImage.cpp42
-rw-r--r--src/gpu/GrContext.cpp64
-rw-r--r--src/gpu/GrContextPriv.h2
-rw-r--r--src/gpu/GrRenderTargetContext.cpp16
-rw-r--r--src/gpu/GrRenderTargetContextPriv.h4
-rw-r--r--src/gpu/GrRenderTargetProxy.cpp8
-rw-r--r--src/gpu/GrSurfaceProxy.cpp53
-rw-r--r--src/gpu/GrTextureContext.cpp25
-rw-r--r--src/gpu/SkGpuDevice.cpp32
-rw-r--r--src/image/SkImage_Gpu.cpp27
-rw-r--r--src/image/SkSurface_Gpu.cpp33
11 files changed, 190 insertions, 116 deletions
diff --git a/src/core/SkSpecialImage.cpp b/src/core/SkSpecialImage.cpp
index 2567bf1804..4f48f7862b 100644
--- a/src/core/SkSpecialImage.cpp
+++ b/src/core/SkSpecialImage.cpp
@@ -17,6 +17,7 @@
#if SK_SUPPORT_GPU
#include "GrContext.h"
+#include "GrSurfaceContext.h"
#include "GrTexture.h"
#include "GrSamplerParams.h"
#include "GrTextureProxy.h"
@@ -346,6 +347,20 @@ sk_sp<SkSpecialImage> SkSpecialImage::MakeFromRaster(const SkIRect& subset,
#include "GrTexture.h"
#include "SkImage_Gpu.h"
+static sk_sp<SkImage> wrap_proxy_in_image(GrContext* context, GrSurfaceProxy* proxy,
+ SkAlphaType alphaType, sk_sp<SkColorSpace> colorSpace) {
+ // TODO: add GrTextureProxy-backed SkImage_Gpus
+ GrSurface* surf = proxy->instantiate(context->textureProvider());
+ if (!surf) {
+ return nullptr;
+ }
+
+ return sk_make_sp<SkImage_Gpu>(proxy->width(), proxy->height(),
+ kNeedNewImageUniqueID, alphaType,
+ sk_ref_sp(surf->asTexture()),
+ std::move(colorSpace), SkBudgeted::kYes);
+}
+
class SkSpecialImage_Gpu : public SkSpecialImage_Base {
public:
SkSpecialImage_Gpu(const SkIRect& subset,
@@ -478,34 +493,21 @@ public:
fAlphaType);
}
+ // TODO: move all the logic here into the subset-flavor GrSurfaceProxy::copy?
sk_sp<SkImage> onMakeTightSubset(const SkIRect& subset) const override {
- // TODO: add GrTextureProxy-backed SkImage_Gpus
- GrSurface* surf = fSurfaceProxy->instantiate(fContext->textureProvider());
- if (!surf) {
- return nullptr;
- }
-
+ // TODO: this is problematic since the surfaceProxy could be loose
if (0 == subset.fLeft && 0 == subset.fTop &&
fSurfaceProxy->width() == subset.width() &&
fSurfaceProxy->height() == subset.height()) {
// The existing GrTexture is already tight so reuse it in the SkImage
- return sk_make_sp<SkImage_Gpu>(surf->width(), surf->height(),
- kNeedNewImageUniqueID, fAlphaType,
- sk_ref_sp(surf->asTexture()),
- fColorSpace, SkBudgeted::kYes);
+ return wrap_proxy_in_image(fContext, fSurfaceProxy.get(),
+ fAlphaType, fColorSpace);
}
- GrSurfaceDesc desc = fSurfaceProxy->desc();
- desc.fWidth = subset.width();
- desc.fHeight = subset.height();
+ sk_sp<GrSurfaceProxy> subsetProxy(GrSurfaceProxy::Copy(fContext, fSurfaceProxy.get(),
+ subset, SkBudgeted::kYes));
- sk_sp<GrTexture> subTx(fContext->textureProvider()->createTexture(desc, SkBudgeted::kYes));
- if (!subTx) {
- return nullptr;
- }
- fContext->copySurface(subTx.get(), surf, subset, SkIPoint::Make(0, 0));
- return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
- fAlphaType, std::move(subTx), fColorSpace, SkBudgeted::kYes);
+ return wrap_proxy_in_image(fContext, subsetProxy.get(), fAlphaType, fColorSpace);
}
sk_sp<SkSurface> onMakeTightSurface(const SkImageFilter::OutputProperties& outProps,
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index bcb4f88980..3e3bc0e6a8 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -540,43 +540,6 @@ void GrContext::prepareSurfaceForExternalIO(GrSurface* surface) {
fDrawingManager->prepareSurfaceForExternalIO(surface);
}
-bool GrContext::copySurface(GrSurface* dst, GrSurface* src, const SkIRect& srcRect,
- const SkIPoint& dstPoint) {
- ASSERT_SINGLE_OWNER
- RETURN_FALSE_IF_ABANDONED
- GR_AUDIT_TRAIL_AUTO_FRAME(&fAuditTrail, "GrContext::copySurface");
-
- if (!src || !dst) {
- return false;
- }
- ASSERT_OWNED_RESOURCE(src);
- ASSERT_OWNED_RESOURCE(dst);
-
- // We don't allow conversion between integer configs and float/fixed configs.
- if (GrPixelConfigIsSint(dst->config()) != GrPixelConfigIsSint(src->config())) {
- return false;
- }
-
-#ifndef ENABLE_MDB
- // We can't yet fully defer copies to textures, so GrTextureContext::copySurface will
- // execute the copy immediately. Ensure the data is ready.
- src->flushWrites();
-#endif
-
- sk_sp<GrSurfaceContext> surfaceContext(
- this->contextPriv().makeWrappedSurfaceContext(sk_ref_sp(dst)));
-
- if (!surfaceContext) {
- return false;
- }
-
- if (!surfaceContext->copySurface(src, srcRect, dstPoint)) {
- return false;
- }
-
- return true;
-}
-
void GrContext::flushSurfaceWrites(GrSurface* surface) {
ASSERT_SINGLE_OWNER
RETURN_IF_ABANDONED
@@ -593,23 +556,6 @@ void GrContext::flushSurfaceIO(GrSurface* surface) {
}
}
-sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc,
- SkBackingFit fit,
- SkBudgeted isDstBudgeted) {
-
- sk_sp<GrSurfaceProxy> proxy = GrSurfaceProxy::MakeDeferred(*fContext->caps(), dstDesc,
- fit, isDstBudgeted);
-
- if (proxy->asRenderTargetProxy()) {
- return this->drawingManager()->makeRenderTargetContext(std::move(proxy), nullptr, nullptr);
- } else {
- SkASSERT(proxy->asTextureProxy());
- return this->drawingManager()->makeTextureContext(std::move(proxy));
- }
-
- return nullptr;
-}
-
////////////////////////////////////////////////////////////////////////////////
int GrContext::getRecommendedSampleCount(GrPixelConfig config,
SkScalar dpi) const {
@@ -661,6 +607,16 @@ sk_sp<GrSurfaceContext> GrContextPriv::makeWrappedSurfaceContext(sk_sp<GrSurface
return this->makeWrappedSurfaceContext(std::move(proxy));
}
+sk_sp<GrSurfaceContext> GrContextPriv::makeDeferredSurfaceContext(const GrSurfaceDesc& dstDesc,
+ SkBackingFit fit,
+ SkBudgeted isDstBudgeted) {
+
+ sk_sp<GrSurfaceProxy> proxy = GrSurfaceProxy::MakeDeferred(*fContext->caps(), dstDesc,
+ fit, isDstBudgeted);
+
+ return this->makeWrappedSurfaceContext(std::move(proxy));
+}
+
sk_sp<GrRenderTargetContext> GrContextPriv::makeBackendTextureRenderTargetContext(
const GrBackendTextureDesc& desc,
sk_sp<SkColorSpace> colorSpace,
diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h
index 75effa3848..e24a588d1d 100644
--- a/src/gpu/GrContextPriv.h
+++ b/src/gpu/GrContextPriv.h
@@ -11,6 +11,8 @@
#include "GrContext.h"
#include "GrSurfaceContext.h"
+class GrSurfaceProxy;
+
/** Class that adds methods to GrContext that are only intended for use internal to Skia.
This class is purely a privileged window into GrContext. It should never have additional
data members or virtual methods. */
diff --git a/src/gpu/GrRenderTargetContext.cpp b/src/gpu/GrRenderTargetContext.cpp
index 1ba66acac6..ee87dae13b 100644
--- a/src/gpu/GrRenderTargetContext.cpp
+++ b/src/gpu/GrRenderTargetContext.cpp
@@ -133,12 +133,20 @@ GrRenderTargetOpList* GrRenderTargetContext::getOpList() {
return fOpList;
}
-bool GrRenderTargetContext::copySurface(GrSurface* src, const SkIRect& srcRect,
- const SkIPoint& dstPoint) {
+// TODO: move this (and GrTextContext::copy) to GrSurfaceContext?
+bool GrRenderTargetContext::onCopy(GrSurfaceProxy* srcProxy,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint) {
ASSERT_SINGLE_OWNER
RETURN_FALSE_IF_ABANDONED
SkDEBUGCODE(this->validate();)
- GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::copySurface");
+ GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrRenderTargetContext::copy");
+
+ // TODO: defer instantiation until flush time
+ sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->textureProvider())));
+ if (!src) {
+ return false;
+ }
// TODO: this needs to be fixed up since it ends the deferrable of the GrRenderTarget
sk_sp<GrRenderTarget> rt(
@@ -147,7 +155,7 @@ bool GrRenderTargetContext::copySurface(GrSurface* src, const SkIRect& srcRect,
return false;
}
- return this->getOpList()->copySurface(rt.get(), src, srcRect, dstPoint);
+ return this->getOpList()->copySurface(rt.get(), src.get(), srcRect, dstPoint);
}
void GrRenderTargetContext::drawText(const GrClip& clip, const GrPaint& grPaint,
diff --git a/src/gpu/GrRenderTargetContextPriv.h b/src/gpu/GrRenderTargetContextPriv.h
index b3bd72a563..f1548cc9fa 100644
--- a/src/gpu/GrRenderTargetContextPriv.h
+++ b/src/gpu/GrRenderTargetContextPriv.h
@@ -114,6 +114,10 @@ public:
const GrUserStencilSettings* = nullptr,
bool snapToCenters = false);
+ bool refsWrappedObjects() const {
+ return fRenderTargetContext->fRenderTargetProxy->refsWrappedObjects();
+ }
+
private:
explicit GrRenderTargetContextPriv(GrRenderTargetContext* renderTargetContext)
: fRenderTargetContext(renderTargetContext) {}
diff --git a/src/gpu/GrRenderTargetProxy.cpp b/src/gpu/GrRenderTargetProxy.cpp
index 03637cf9af..882acf660c 100644
--- a/src/gpu/GrRenderTargetProxy.cpp
+++ b/src/gpu/GrRenderTargetProxy.cpp
@@ -8,6 +8,7 @@
#include "GrRenderTargetProxy.h"
#include "GrCaps.h"
+#include "GrGpuResourcePriv.h"
#include "GrRenderTargetOpList.h"
#include "GrRenderTargetPriv.h"
#include "GrTextureProvider.h"
@@ -63,3 +64,10 @@ size_t GrRenderTargetProxy::onGpuMemorySize() const {
return GrSurface::ComputeSize(fDesc, fDesc.fSampleCnt+1, false, SkBackingFit::kApprox == fFit);
}
+bool GrRenderTargetProxy::refsWrappedObjects() const {
+ if (!fTarget) {
+ return false;
+ }
+
+ return fTarget->resourcePriv().refsWrappedObjects();
+}
diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp
index 4a0c3480a4..780ff8aa44 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -8,8 +8,11 @@
#include "GrSurfaceProxy.h"
#include "GrCaps.h"
+#include "GrContext.h"
+#include "GrContextPriv.h"
#include "GrGpuResourcePriv.h"
#include "GrOpList.h"
+#include "GrSurfaceContext.h"
#include "GrTextureProvider.h"
#include "GrTextureRenderTargetProxy.h"
@@ -161,3 +164,53 @@ void GrSurfaceProxy::validate(GrContext* context) const {
INHERITED::validate();
}
#endif
+
+sk_sp<GrSurfaceProxy> GrSurfaceProxy::Copy(GrContext* context,
+ GrSurfaceProxy* src,
+ SkIRect srcRect,
+ SkBudgeted budgeted) {
+ if (!srcRect.intersect(SkIRect::MakeWH(src->width(), src->height()))) {
+ return nullptr;
+ }
+
+ GrSurfaceDesc dstDesc = src->desc();
+ dstDesc.fWidth = srcRect.width();
+ dstDesc.fHeight = srcRect.height();
+
+ sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
+ dstDesc,
+ SkBackingFit::kExact,
+ budgeted));
+ if (!dstContext) {
+ return nullptr;
+ }
+
+ if (!dstContext->copy(src, srcRect, SkIPoint::Make(0, 0))) {
+ return nullptr;
+ }
+
+ return sk_ref_sp(dstContext->asDeferredSurface());
+}
+
+sk_sp<GrSurfaceProxy> GrSurfaceProxy::TestCopy(GrContext* context, const GrSurfaceDesc& dstDesc,
+ GrTexture* srcTexture, SkBudgeted budgeted) {
+
+ sk_sp<GrSurfaceContext> dstContext(context->contextPriv().makeDeferredSurfaceContext(
+ dstDesc,
+ SkBackingFit::kExact,
+ budgeted));
+ if (!dstContext) {
+ return nullptr;
+ }
+
+ sk_sp<GrSurfaceProxy> srcProxy(GrSurfaceProxy::MakeWrapped(sk_ref_sp(srcTexture)));
+ if (!srcProxy) {
+ return nullptr;
+ }
+
+ if (!dstContext->copy(srcProxy.get())) {
+ return nullptr;
+ }
+
+ return sk_ref_sp(dstContext->asDeferredSurface());
+}
diff --git a/src/gpu/GrTextureContext.cpp b/src/gpu/GrTextureContext.cpp
index 59dae3f0f2..9f61551270 100644
--- a/src/gpu/GrTextureContext.cpp
+++ b/src/gpu/GrTextureContext.cpp
@@ -24,8 +24,7 @@ GrTextureContext::GrTextureContext(GrContext* context,
: GrSurfaceContext(context, auditTrail, singleOwner)
, fDrawingManager(drawingMgr)
, fTextureProxy(std::move(textureProxy))
- , fOpList(SkSafeRef(fTextureProxy->getLastTextureOpList()))
-{
+ , fOpList(SkSafeRef(fTextureProxy->getLastTextureOpList())) {
SkDEBUGCODE(this->validate();)
}
@@ -62,12 +61,26 @@ GrTextureOpList* GrTextureContext::getOpList() {
return fOpList;
}
-bool GrTextureContext::copySurface(GrSurface* src, const SkIRect& srcRect,
- const SkIPoint& dstPoint) {
+// TODO: move this (and GrRenderTargetContext::copy) to GrSurfaceContext?
+bool GrTextureContext::onCopy(GrSurfaceProxy* srcProxy,
+ const SkIRect& srcRect,
+ const SkIPoint& dstPoint) {
ASSERT_SINGLE_OWNER
RETURN_FALSE_IF_ABANDONED
SkDEBUGCODE(this->validate();)
- GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrTextureContext::copySurface");
+ GR_AUDIT_TRAIL_AUTO_FRAME(fAuditTrail, "GrTextureContext::copy");
+
+ // TODO: defer instantiation until flush time
+ sk_sp<GrSurface> src(sk_ref_sp(srcProxy->instantiate(fContext->textureProvider())));
+ if (!src) {
+ return false;
+ }
+
+#ifndef ENABLE_MDB
+ // We can't yet fully defer copies to textures, so GrTextureContext::copySurface will
+ // execute the copy immediately. Ensure the data is ready.
+ src->flushWrites();
+#endif
// TODO: this needs to be fixed up since it ends the deferrable of the GrTexture
sk_sp<GrTexture> tex(sk_ref_sp(fTextureProxy->instantiate(fContext->textureProvider())));
@@ -76,7 +89,7 @@ bool GrTextureContext::copySurface(GrSurface* src, const SkIRect& srcRect,
}
GrTextureOpList* opList = this->getOpList();
- bool result = opList->copySurface(tex.get(), src, srcRect, dstPoint);
+ bool result = opList->copySurface(tex.get(), src.get(), srcRect, dstPoint);
#ifndef ENABLE_MDB
GrOpFlushState flushState(fContext->getGpu(), nullptr);
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 8549b0ccf1..a623dd1fdb 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -15,6 +15,7 @@
#include "GrRenderTargetContextPriv.h"
#include "GrStyle.h"
#include "GrTextureAdjuster.h"
+#include "GrTextureProxy.h"
#include "GrTracing.h"
#include "SkCanvasPriv.h"
@@ -262,9 +263,7 @@ void SkGpuDevice::replaceRenderTargetContext(bool shouldRetainContent) {
if (fRenderTargetContext->wasAbandoned()) {
return;
}
- newRTC->copySurface(fRenderTargetContext->asTexture().get(),
- SkIRect::MakeWH(this->width(), this->height()),
- SkIPoint::Make(0, 0));
+ newRTC->copy(fRenderTargetContext->asDeferredSurface());
}
fRenderTargetContext = newRTC;
@@ -1332,19 +1331,15 @@ sk_sp<SkSpecialImage> SkGpuDevice::makeSpecial(const SkImage* image) {
}
sk_sp<SkSpecialImage> SkGpuDevice::snapSpecial() {
- sk_sp<GrTexture> texture(this->accessRenderTargetContext()->asTexture());
- if (!texture) {
+ sk_sp<GrSurfaceProxy> sProxy(sk_ref_sp(this->accessRenderTargetContext()->asDeferredTexture()));
+ if (!sProxy) {
// When the device doesn't have a texture, we create a temporary texture.
// TODO: we should actually only copy the portion of the source needed to apply the image
// filter
- texture.reset(fContext->textureProvider()->createTexture(
- this->accessRenderTargetContext()->desc(), SkBudgeted::kYes));
- if (!texture) {
- return nullptr;
- }
-
- if (!fContext->copySurface(texture.get(),
- this->accessRenderTargetContext()->accessRenderTarget())) {
+ sProxy = GrSurfaceProxy::Copy(fContext.get(),
+ this->accessRenderTargetContext()->asDeferredSurface(),
+ SkBudgeted::kYes);
+ if (!sProxy) {
return nullptr;
}
}
@@ -1352,11 +1347,12 @@ sk_sp<SkSpecialImage> SkGpuDevice::snapSpecial() {
const SkImageInfo ii = this->imageInfo();
const SkIRect srcRect = SkIRect::MakeWH(ii.width(), ii.height());
- return SkSpecialImage::MakeFromGpu(srcRect,
- kNeedNewImageUniqueID_SpecialImage,
- std::move(texture),
- sk_ref_sp(ii.colorSpace()),
- &this->surfaceProps());
+ return SkSpecialImage::MakeDeferredFromGpu(fContext.get(),
+ srcRect,
+ kNeedNewImageUniqueID_SpecialImage,
+ sProxy,
+ sk_ref_sp(ii.colorSpace()),
+ &this->surfaceProps());
}
void SkGpuDevice::drawDevice(const SkDraw& draw, SkBaseDevice* device,
diff --git a/src/image/SkImage_Gpu.cpp b/src/image/SkImage_Gpu.cpp
index cc11f6dcdb..c347a1f606 100644
--- a/src/image/SkImage_Gpu.cpp
+++ b/src/image/SkImage_Gpu.cpp
@@ -13,6 +13,7 @@
#include "GrBitmapTextureMaker.h"
#include "GrCaps.h"
#include "GrContext.h"
+#include "GrContextPriv.h"
#include "GrImageTextureMaker.h"
#include "GrRenderTargetContext.h"
#include "GrTextureAdjuster.h"
@@ -153,13 +154,33 @@ sk_sp<SkImage> SkImage_Gpu::onMakeSubset(const SkIRect& subset) const {
desc.fWidth = subset.width();
desc.fHeight = subset.height();
- sk_sp<GrTexture> subTx(ctx->textureProvider()->createTexture(desc, fBudgeted));
+ sk_sp<GrSurfaceContext> sContext(ctx->contextPriv().makeDeferredSurfaceContext(
+ desc,
+ SkBackingFit::kExact,
+ fBudgeted));
+ if (!sContext) {
+ return nullptr;
+ }
+
+ // TODO: make gpu images be proxy-backed so we don't need to do this
+ sk_sp<GrSurfaceProxy> tmpSrc(GrSurfaceProxy::MakeWrapped(fTexture));
+ if (!tmpSrc) {
+ return nullptr;
+ }
+
+ if (!sContext->copy(tmpSrc.get(), subset, SkIPoint::Make(0, 0))) {
+ return nullptr;
+ }
+
+ // TODO: make gpu images be proxy-backed so we don't need to do this
+ GrSurface* subTx = sContext->asDeferredSurface()->instantiate(ctx->textureProvider());
if (!subTx) {
return nullptr;
}
- ctx->copySurface(subTx.get(), fTexture.get(), subset, SkIPoint::Make(0, 0));
+
return sk_make_sp<SkImage_Gpu>(desc.fWidth, desc.fHeight, kNeedNewImageUniqueID,
- fAlphaType, std::move(subTx), fColorSpace, fBudgeted);
+ fAlphaType, sk_ref_sp(subTx->asTexture()),
+ fColorSpace, fBudgeted);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/image/SkSurface_Gpu.cpp b/src/image/SkSurface_Gpu.cpp
index f99d3c2102..c81c06ed53 100644
--- a/src/image/SkSurface_Gpu.cpp
+++ b/src/image/SkSurface_Gpu.cpp
@@ -14,6 +14,7 @@
#include "SkImage_Base.h"
#include "SkImage_Gpu.h"
#include "SkImagePriv.h"
+#include "GrRenderTargetContextPriv.h"
#include "SkSurface_Base.h"
#if SK_SUPPORT_GPU
@@ -82,29 +83,39 @@ sk_sp<SkSurface> SkSurface_Gpu::onNewSurface(const SkImageInfo& info) {
}
sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot(SkBudgeted budgeted, SkCopyPixelsMode cpm) {
- GrRenderTarget* rt = fDevice->accessRenderTargetContext()->accessRenderTarget();
- if (!rt) {
+ GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext();
+ if (!rtc) {
return nullptr;
}
- GrTexture* tex = rt->asTexture();
- sk_sp<GrTexture> copy;
+ GrContext* ctx = fDevice->context();
+
+ GrSurfaceProxy* srcProxy = rtc->asDeferredSurface();
+ sk_sp<GrSurfaceContext> copyCtx;
// If the original render target is a buffer originally created by the client, then we don't
// want to ever retarget the SkSurface at another buffer we create. Force a copy now to avoid
// copy-on-write.
- if (kAlways_SkCopyPixelsMode == cpm || !tex || rt->resourcePriv().refsWrappedObjects()) {
- GrSurfaceDesc desc = fDevice->accessRenderTargetContext()->desc();
- GrContext* ctx = fDevice->context();
+ if (kAlways_SkCopyPixelsMode == cpm || !srcProxy || rtc->priv().refsWrappedObjects()) {
+ GrSurfaceDesc desc = rtc->desc();
desc.fFlags = desc.fFlags & ~kRenderTarget_GrSurfaceFlag;
- copy.reset(ctx->textureProvider()->createTexture(desc, budgeted));
- if (!copy) {
+
+ copyCtx = ctx->contextPriv().makeDeferredSurfaceContext(desc,
+ SkBackingFit::kExact,
+ budgeted);
+ if (!copyCtx) {
return nullptr;
}
- if (!ctx->copySurface(copy.get(), rt)) {
+
+ if (!copyCtx->copy(srcProxy)) {
return nullptr;
}
- tex = copy.get();
+
+ srcProxy = copyCtx->asDeferredSurface();
}
+
+ // TODO: add proxy-backed SkImage_Gpu
+ GrTexture* tex = srcProxy->instantiate(ctx->textureProvider())->asTexture();
+
const SkImageInfo info = fDevice->imageInfo();
sk_sp<SkImage> image;
if (tex) {