| /* |
| * Copyright 2017 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #include "SkDeferredDisplayListRecorder.h" |
| |
| #include "SkDeferredDisplayList.h" |
| #include "SkSurface.h" |
| #include "SkSurfaceCharacterization.h" |
| |
| #if !SK_SUPPORT_GPU |
| SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&) {} |
| |
| SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {} |
| |
| bool SkDeferredDisplayListRecorder::init() { return false; } |
| |
| SkCanvas* SkDeferredDisplayListRecorder::getCanvas() { return nullptr; } |
| |
| std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() { return nullptr; } |
| |
| sk_sp<SkImage> SkDeferredDisplayListRecorder::makePromiseTexture( |
| const GrBackendFormat& backendFormat, |
| int width, |
| int height, |
| GrMipMapped mipMapped, |
| GrSurfaceOrigin origin, |
| SkColorType colorType, |
| SkAlphaType alphaType, |
| sk_sp<SkColorSpace> colorSpace, |
| TextureFulfillProc textureFulfillProc, |
| TextureReleaseProc textureReleaseProc, |
| PromiseDoneProc promiseDoneProc, |
| TextureContext textureContext) { |
| return nullptr; |
| } |
| |
| #else |
| |
| #include "GrContextPriv.h" |
| #include "GrProxyProvider.h" |
| #include "GrTexture.h" |
| |
| #include "SkGr.h" |
| #include "SkImage_Gpu.h" |
| #include "SkSurface_Gpu.h" |
| |
| SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization& c) |
| : fCharacterization(c) { |
| if (fCharacterization.isValid()) { |
| fContext = GrContextPriv::MakeDDL(fCharacterization.refContextInfo()); |
| } |
| } |
| |
| SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() { |
| if (fContext) { |
| auto proxyProvider = fContext->contextPriv().proxyProvider(); |
| |
| // DDL TODO: Remove this. DDL contexts should allow for deletion while still having live |
| // uniquely keyed proxies. |
| proxyProvider->removeAllUniqueKeys(); |
| } |
| } |
| |
| |
| bool SkDeferredDisplayListRecorder::init() { |
| SkASSERT(fContext); |
| SkASSERT(!fLazyProxyData); |
| SkASSERT(!fSurface); |
| |
| if (!fCharacterization.isValid()) { |
| return false; |
| } |
| |
| fLazyProxyData = sk_sp<SkDeferredDisplayList::LazyProxyData>( |
| new SkDeferredDisplayList::LazyProxyData); |
| |
| auto proxyProvider = fContext->contextPriv().proxyProvider(); |
| |
| GrSurfaceDesc desc; |
| desc.fFlags = kRenderTarget_GrSurfaceFlag; |
| desc.fWidth = fCharacterization.width(); |
| desc.fHeight = fCharacterization.height(); |
| desc.fConfig = fCharacterization.config(); |
| desc.fSampleCnt = fCharacterization.stencilCount(); |
| |
| sk_sp<SkDeferredDisplayList::LazyProxyData> lazyProxyData = fLazyProxyData; |
| |
| // What we're doing here is we're creating a lazy proxy to back the SkSurface. The lazy |
| // proxy, when instantiated, will use the GrRenderTarget that backs the SkSurface that the |
| // DDL is being replayed into. |
| |
| GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone; |
| if (fContext->caps()->usesMixedSamples() && desc.fSampleCnt > 1) { |
| surfaceFlags |= GrInternalSurfaceFlags::kMixedSampled; |
| } |
| if (fContext->caps()->maxWindowRectangles() > 0) { |
| surfaceFlags |= GrInternalSurfaceFlags::kWindowRectsSupport; |
| } |
| |
| sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy( |
| [lazyProxyData](GrResourceProvider* resourceProvider) { |
| if (!resourceProvider) { |
| return sk_sp<GrSurface>(); |
| } |
| |
| // The proxy backing the destination surface had better have been instantiated |
| // prior to the proxy backing the DLL's surface. Steal its GrRenderTarget. |
| SkASSERT(lazyProxyData->fReplayDest->priv().peekSurface()); |
| return sk_ref_sp<GrSurface>(lazyProxyData->fReplayDest->priv().peekSurface()); |
| }, |
| desc, |
| fCharacterization.origin(), |
| surfaceFlags, |
| GrProxyProvider::Textureable(fCharacterization.isTextureable()), |
| GrMipMapped::kNo, |
| SkBackingFit::kExact, |
| SkBudgeted::kYes); |
| |
| sk_sp<GrSurfaceContext> c = fContext->contextPriv().makeWrappedSurfaceContext( |
| std::move(proxy), |
| fCharacterization.refColorSpace(), |
| &fCharacterization.surfaceProps()); |
| fSurface = SkSurface_Gpu::MakeWrappedRenderTarget(fContext.get(), |
| sk_ref_sp(c->asRenderTargetContext())); |
| return SkToBool(fSurface.get()); |
| } |
| |
| SkCanvas* SkDeferredDisplayListRecorder::getCanvas() { |
| if (!fContext) { |
| return nullptr; |
| } |
| |
| if (!fSurface && !this->init()) { |
| return nullptr; |
| } |
| |
| return fSurface->getCanvas(); |
| } |
| |
| std::unique_ptr<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() { |
| if (!fContext) { |
| return nullptr; |
| } |
| |
| auto ddl = std::unique_ptr<SkDeferredDisplayList>( |
| new SkDeferredDisplayList(fCharacterization, std::move(fLazyProxyData))); |
| |
| fContext->contextPriv().moveOpListsToDDL(ddl.get()); |
| return ddl; |
| } |
| |
| sk_sp<SkImage> SkDeferredDisplayListRecorder::makePromiseTexture( |
| const GrBackendFormat& backendFormat, |
| int width, |
| int height, |
| GrMipMapped mipMapped, |
| GrSurfaceOrigin origin, |
| SkColorType colorType, |
| SkAlphaType alphaType, |
| sk_sp<SkColorSpace> colorSpace, |
| TextureFulfillProc textureFulfillProc, |
| TextureReleaseProc textureReleaseProc, |
| PromiseDoneProc promiseDoneProc, |
| TextureContext textureContext) { |
| if (!fContext) { |
| return nullptr; |
| } |
| |
| return SkImage_Gpu::MakePromiseTexture(fContext.get(), |
| backendFormat, |
| width, |
| height, |
| mipMapped, |
| origin, |
| colorType, |
| alphaType, |
| std::move(colorSpace), |
| textureFulfillProc, |
| textureReleaseProc, |
| promiseDoneProc, |
| textureContext); |
| } |
| |
| #endif |