/* * 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 SkDeferredDisplayListRecorder::detach() { return nullptr; } sk_sp SkDeferredDisplayListRecorder::makePromiseTexture( const GrBackendFormat& backendFormat, int width, int height, GrMipMapped mipMapped, GrSurfaceOrigin origin, SkColorType colorType, SkAlphaType alphaType, sk_sp 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( new SkDeferredDisplayList::LazyProxyData); auto proxyProvider = fContext->contextPriv().proxyProvider(); bool usesGLFBO0 = fCharacterization.usesGLFBO0(); if (usesGLFBO0) { if (kOpenGL_GrBackend != fContext->contextPriv().getBackend() || fCharacterization.isTextureable()) { return false; } } GrSurfaceDesc desc; desc.fFlags = kRenderTarget_GrSurfaceFlag; desc.fWidth = fCharacterization.width(); desc.fHeight = fCharacterization.height(); desc.fConfig = fCharacterization.config(); desc.fSampleCnt = fCharacterization.stencilCount(); sk_sp 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->contextPriv().caps()->usesMixedSamples() && desc.fSampleCnt > 1 && !usesGLFBO0) { // In GL, FBO 0 never supports mixed samples surfaceFlags |= GrInternalSurfaceFlags::kMixedSampled; } if (fContext->contextPriv().caps()->maxWindowRectangles() > 0 && !usesGLFBO0) { // In GL, FBO 0 never supports window rectangles surfaceFlags |= GrInternalSurfaceFlags::kWindowRectsSupport; } if (usesGLFBO0) { surfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0; } static constexpr GrProxyProvider::TextureInfo kTextureInfo{GrMipMapped::kNo, GrTextureType::k2D}; const GrProxyProvider::TextureInfo* optionalTextureInfo = nullptr; if (fCharacterization.isTextureable()) { optionalTextureInfo = &kTextureInfo; } sk_sp proxy = proxyProvider->createLazyRenderTargetProxy( [lazyProxyData](GrResourceProvider* resourceProvider) { if (!resourceProvider) { return sk_sp(); } // 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(lazyProxyData->fReplayDest->priv().peekSurface()); }, desc, fCharacterization.origin(), surfaceFlags, optionalTextureInfo, SkBackingFit::kExact, SkBudgeted::kYes); sk_sp 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 SkDeferredDisplayListRecorder::detach() { if (!fContext) { return nullptr; } auto ddl = std::unique_ptr( new SkDeferredDisplayList(fCharacterization, std::move(fLazyProxyData))); fContext->contextPriv().moveOpListsToDDL(ddl.get()); return ddl; } sk_sp SkDeferredDisplayListRecorder::makePromiseTexture( const GrBackendFormat& backendFormat, int width, int height, GrMipMapped mipMapped, GrSurfaceOrigin origin, SkColorType colorType, SkAlphaType alphaType, sk_sp 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