sk_sp<SkImage> SkSurface_Gpu::onNewImageSnapshot() { GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext(); if (!rtc) { return nullptr; } GrContext* ctx = fDevice->context(); if (!rtc->asSurfaceProxy()) { return nullptr; } SkBudgeted budgeted = rtc->asSurfaceProxy()->isBudgeted(); sk_sp<GrTextureProxy> srcProxy = rtc->asTextureProxyRef(); // 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 (!srcProxy || rtc->priv().refsWrappedObjects()) { SkASSERT(rtc->origin() == rtc->asSurfaceProxy()->origin()); srcProxy = GrSurfaceProxy::Copy(ctx, rtc->asSurfaceProxy(), rtc->mipMapped(), budgeted); } const SkImageInfo info = fDevice->imageInfo(); sk_sp<SkImage> image; if (srcProxy) { // The renderTargetContext coming out of SkGpuDevice should always be exact and the // above copy creates a kExact surfaceContext. SkASSERT(srcProxy->priv().isExact()); image = sk_make_sp<SkImage_Gpu>(ctx, kNeedNewImageUniqueID, info.alphaType(), std::move(srcProxy), info.refColorSpace(), budgeted); } return image; }
// Create a new render target and, if necessary, copy the contents of the old // render target into it. Note that this flushes the SkGpuDevice but // doesn't force an OpenGL flush. void SkSurface_Gpu::onCopyOnWrite(ContentChangeMode mode) { GrRenderTargetContext* rtc = fDevice->accessRenderTargetContext(); // are we sharing our backing proxy with the image? Note this call should never create a new // image because onCopyOnWrite is only called when there is a cached image. sk_sp<SkImage> image(this->refCachedImage()); SkASSERT(image); GrSurfaceProxy* imageProxy = ((SkImage_Base*) image.get())->peekProxy(); SkASSERT(imageProxy); if (rtc->asSurfaceProxy()->underlyingUniqueID() == imageProxy->underlyingUniqueID()) { fDevice->replaceRenderTargetContext(SkSurface::kRetain_ContentChangeMode == mode); } else if (kDiscard_ContentChangeMode == mode) { this->SkSurface_Gpu::onDiscard(); } }