| /* | |
| * Copyright 2020 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "src/gpu/ganesh/GrRecordingContextPriv.h" | |
| #include "include/core/SkAlphaType.h" | |
| #include "include/core/SkColorSpace.h" | |
| #include "include/core/SkSize.h" | |
| #include "include/core/SkSurfaceProps.h" | |
| #include "include/gpu/ganesh/GrBackendSurface.h" | |
| #include "include/gpu/ganesh/GrContextOptions.h" | |
| #include "include/private/gpu/ganesh/GrContext_Base.h" | |
| #include "include/private/gpu/ganesh/GrTypesPriv.h" | |
| #include "src/gpu/RefCntedCallback.h" | |
| #include "src/gpu/Swizzle.h" | |
| #include "src/gpu/ganesh/Device.h" | |
| #include "src/gpu/ganesh/GrCaps.h" | |
| #include "src/gpu/ganesh/GrDrawingManager.h" | |
| #include "src/gpu/ganesh/GrImageInfo.h" | |
| #include "src/gpu/ganesh/GrProxyProvider.h" | |
| #include "src/gpu/ganesh/GrShaderCaps.h" | |
| #include "src/gpu/ganesh/GrSurfaceProxy.h" | |
| #include "src/gpu/ganesh/GrSurfaceProxyView.h" | |
| #include "src/gpu/ganesh/GrTextureProxy.h" | |
| #include "src/gpu/ganesh/SurfaceContext.h" | |
| #include "src/gpu/ganesh/SurfaceDrawContext.h" | |
| #include "src/gpu/ganesh/SurfaceFillContext.h" | |
| #include <utility> | |
| void GrRecordingContextPriv::addOnFlushCallbackObject(GrOnFlushCallbackObject* onFlushCBObject) { | |
| this->context()->addOnFlushCallbackObject(onFlushCBObject); | |
| } | |
| sk_sp<skgpu::ganesh::Device> GrRecordingContextPriv::createDevice( | |
| GrColorType colorType, | |
| sk_sp<GrSurfaceProxy> proxy, | |
| sk_sp<SkColorSpace> colorSpace, | |
| GrSurfaceOrigin origin, | |
| const SkSurfaceProps& props, | |
| skgpu::ganesh::Device::InitContents init) { | |
| return skgpu::ganesh::Device::Make(this->context(), | |
| colorType, | |
| std::move(proxy), | |
| std::move(colorSpace), | |
| origin, | |
| props, | |
| init); | |
| } | |
| sk_sp<skgpu::ganesh::Device> GrRecordingContextPriv::createDevice( | |
| skgpu::Budgeted budgeted, | |
| const SkImageInfo& ii, | |
| SkBackingFit fit, | |
| int sampleCount, | |
| skgpu::Mipmapped mipmapped, | |
| GrProtected isProtected, | |
| GrSurfaceOrigin origin, | |
| const SkSurfaceProps& props, | |
| skgpu::ganesh::Device::InitContents init) { | |
| return skgpu::ganesh::Device::Make(this->context(), | |
| budgeted, | |
| ii, | |
| fit, | |
| sampleCount, | |
| mipmapped, | |
| isProtected, | |
| origin, | |
| props, | |
| init); | |
| } | |
| void GrRecordingContextPriv::moveRenderTasksToDDL(GrDeferredDisplayList* ddl) { | |
| this->context()->drawingManager()->moveRenderTasksToDDL(ddl); | |
| } | |
| sktext::gpu::SubRunControl GrRecordingContextPriv::getSubRunControl( | |
| bool useSDFTForSmallText) const { | |
| #if !defined(SK_DISABLE_SDF_TEXT) | |
| return sktext::gpu::SubRunControl{ | |
| this->caps()->shaderCaps()->supportsDistanceFieldText(), | |
| useSDFTForSmallText, | |
| !this->caps()->disablePerspectiveSDFText(), | |
| this->options().fMinDistanceFieldFontSize, | |
| this->options().fGlyphsAsPathsFontSize}; | |
| #else | |
| return sktext::gpu::SubRunControl{}; | |
| #endif | |
| } | |
| std::unique_ptr<skgpu::ganesh::SurfaceContext> GrRecordingContextPriv::makeSC( | |
| GrSurfaceProxyView readView, const GrColorInfo& info) { | |
| // It is probably not necessary to check if the context is abandoned here since uses of the | |
| // SurfaceContext which need the context will mostly likely fail later on w/o an issue. | |
| // However having this here adds some reassurance in case there is a path that doesn't | |
| // handle an abandoned context correctly. It also lets us early out of some extra work. | |
| if (this->context()->abandoned()) { | |
| return nullptr; | |
| } | |
| GrSurfaceProxy* proxy = readView.proxy(); | |
| SkASSERT(proxy && proxy->asTextureProxy()); | |
| std::unique_ptr<skgpu::ganesh::SurfaceContext> sc; | |
| if (proxy->asRenderTargetProxy()) { | |
| // Will we ever want a swizzle that is not the default write swizzle for the format and | |
| // colorType here? If so we will need to manually pass that in. | |
| skgpu::Swizzle writeSwizzle; | |
| if (info.colorType() != GrColorType::kUnknown) { | |
| writeSwizzle = this->caps()->getWriteSwizzle(proxy->backendFormat(), | |
| info.colorType()); | |
| } | |
| GrSurfaceProxyView writeView(readView.refProxy(), readView.origin(), writeSwizzle); | |
| if (info.alphaType() == kPremul_SkAlphaType || | |
| info.alphaType() == kOpaque_SkAlphaType) { | |
| sc = std::make_unique<skgpu::ganesh::SurfaceDrawContext>(this->context(), | |
| std::move(readView), | |
| std::move(writeView), | |
| info.colorType(), | |
| info.refColorSpace(), | |
| SkSurfaceProps()); | |
| } else { | |
| sc = std::make_unique<skgpu::ganesh::SurfaceFillContext>( | |
| this->context(), std::move(readView), std::move(writeView), info); | |
| } | |
| } else { | |
| sc = std::make_unique<skgpu::ganesh::SurfaceContext>( | |
| this->context(), std::move(readView), info); | |
| } | |
| SkDEBUGCODE(sc->validate();) | |
| return sc; | |
| } | |
| std::unique_ptr<skgpu::ganesh::SurfaceContext> GrRecordingContextPriv::makeSC( | |
| const GrImageInfo& info, | |
| const GrBackendFormat& format, | |
| std::string_view label, | |
| SkBackingFit fit, | |
| GrSurfaceOrigin origin, | |
| GrRenderable renderable, | |
| int sampleCount, | |
| skgpu::Mipmapped mipmapped, | |
| GrProtected isProtected, | |
| skgpu::Budgeted budgeted) { | |
| SkASSERT(renderable == GrRenderable::kYes || sampleCount == 1); | |
| if (this->abandoned()) { | |
| return nullptr; | |
| } | |
| sk_sp<GrTextureProxy> proxy = | |
| this->proxyProvider()->createProxy(format, | |
| info.dimensions(), | |
| renderable, | |
| sampleCount, | |
| mipmapped, | |
| fit, | |
| budgeted, | |
| isProtected, | |
| label); | |
| if (!proxy) { | |
| return nullptr; | |
| } | |
| skgpu::Swizzle swizzle; | |
| if (info.colorType() != GrColorType::kUnknown && | |
| !this->caps()->isFormatCompressed(format)) { | |
| swizzle = this->caps()->getReadSwizzle(format, info.colorType()); | |
| } | |
| GrSurfaceProxyView view(std::move(proxy), origin, swizzle); | |
| return this->makeSC(std::move(view), info.colorInfo()); | |
| } | |
| std::unique_ptr<skgpu::ganesh::SurfaceFillContext> GrRecordingContextPriv::makeSFC( | |
| GrImageInfo info, | |
| std::string_view label, | |
| SkBackingFit fit, | |
| int sampleCount, | |
| skgpu::Mipmapped mipmapped, | |
| GrProtected isProtected, | |
| GrSurfaceOrigin origin, | |
| skgpu::Budgeted budgeted) { | |
| if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) { | |
| return skgpu::ganesh::SurfaceDrawContext::Make(this->context(), | |
| info.colorType(), | |
| info.refColorSpace(), | |
| fit, | |
| info.dimensions(), | |
| SkSurfaceProps(), | |
| label, | |
| sampleCount, | |
| mipmapped, | |
| isProtected, | |
| origin, | |
| budgeted); | |
| } | |
| GrBackendFormat format = this->caps()->getDefaultBackendFormat(info.colorType(), | |
| GrRenderable::kYes); | |
| sk_sp<GrTextureProxy> proxy = | |
| this->proxyProvider()->createProxy(format, | |
| info.dimensions(), | |
| GrRenderable::kYes, | |
| sampleCount, | |
| mipmapped, | |
| fit, | |
| budgeted, | |
| isProtected, | |
| label); | |
| if (!proxy) { | |
| return nullptr; | |
| } | |
| skgpu::Swizzle readSwizzle = this->caps()->getReadSwizzle (format, info.colorType()); | |
| skgpu::Swizzle writeSwizzle = this->caps()->getWriteSwizzle(format, info.colorType()); | |
| GrSurfaceProxyView readView( proxy, origin, readSwizzle); | |
| GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle); | |
| std::unique_ptr<skgpu::ganesh::SurfaceFillContext> sfc; | |
| sfc = std::make_unique<skgpu::ganesh::SurfaceFillContext>( | |
| this->context(), std::move(readView), std::move(writeView), info.colorInfo()); | |
| sfc->discard(); | |
| return sfc; | |
| } | |
| std::unique_ptr<skgpu::ganesh::SurfaceFillContext> GrRecordingContextPriv::makeSFC( | |
| SkAlphaType alphaType, | |
| sk_sp<SkColorSpace> colorSpace, | |
| SkISize dimensions, | |
| SkBackingFit fit, | |
| const GrBackendFormat& format, | |
| int sampleCount, | |
| skgpu::Mipmapped mipmapped, | |
| GrProtected isProtected, | |
| skgpu::Swizzle readSwizzle, | |
| skgpu::Swizzle writeSwizzle, | |
| GrSurfaceOrigin origin, | |
| skgpu::Budgeted budgeted, | |
| std::string_view label) { | |
| SkASSERT(!dimensions.isEmpty()); | |
| SkASSERT(sampleCount >= 1); | |
| SkASSERT(format.isValid() && format.backend() == fContext->backend()); | |
| if (alphaType == kPremul_SkAlphaType || alphaType == kOpaque_SkAlphaType) { | |
| return skgpu::ganesh::SurfaceDrawContext::Make(this->context(), | |
| std::move(colorSpace), | |
| fit, | |
| dimensions, | |
| format, | |
| sampleCount, | |
| mipmapped, | |
| isProtected, | |
| readSwizzle, | |
| writeSwizzle, | |
| origin, | |
| budgeted, | |
| SkSurfaceProps(), | |
| label); | |
| } | |
| sk_sp<GrTextureProxy> proxy = | |
| this->proxyProvider()->createProxy(format, | |
| dimensions, | |
| GrRenderable::kYes, | |
| sampleCount, | |
| mipmapped, | |
| fit, | |
| budgeted, | |
| isProtected, | |
| label); | |
| if (!proxy) { | |
| return nullptr; | |
| } | |
| GrImageInfo info(GrColorType::kUnknown, alphaType, std::move(colorSpace), dimensions); | |
| GrSurfaceProxyView readView( proxy, origin, readSwizzle); | |
| GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle); | |
| std::unique_ptr<skgpu::ganesh::SurfaceFillContext> sfc; | |
| sfc = std::make_unique<skgpu::ganesh::SurfaceFillContext>( | |
| this->context(), std::move(readView), std::move(writeView), info.colorInfo()); | |
| sfc->discard(); | |
| return sfc; | |
| } | |
| std::unique_ptr<skgpu::ganesh::SurfaceFillContext> GrRecordingContextPriv::makeSFCWithFallback( | |
| GrImageInfo info, | |
| SkBackingFit fit, | |
| int sampleCount, | |
| skgpu::Mipmapped mipmapped, | |
| GrProtected isProtected, | |
| GrSurfaceOrigin origin, | |
| skgpu::Budgeted budgeted) { | |
| if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) { | |
| return skgpu::ganesh::SurfaceDrawContext::MakeWithFallback(this->context(), | |
| info.colorType(), | |
| info.refColorSpace(), | |
| fit, | |
| info.dimensions(), | |
| SkSurfaceProps(), | |
| sampleCount, | |
| mipmapped, | |
| isProtected, | |
| origin, | |
| budgeted); | |
| } | |
| const GrCaps* caps = this->caps(); | |
| auto [ct, _] = caps->getFallbackColorTypeAndFormat(info.colorType(), sampleCount); | |
| if (ct == GrColorType::kUnknown) { | |
| return nullptr; | |
| } | |
| info = info.makeColorType(ct); | |
| return this->makeSFC(info, "MakeSurfaceContextWithFallback", | |
| fit, | |
| sampleCount, | |
| mipmapped, | |
| isProtected, | |
| origin, | |
| budgeted); | |
| } | |
| std::unique_ptr<skgpu::ganesh::SurfaceFillContext> | |
| GrRecordingContextPriv::makeSFCFromBackendTexture(GrColorInfo info, | |
| const GrBackendTexture& tex, | |
| int sampleCount, | |
| GrSurfaceOrigin origin, | |
| sk_sp<skgpu::RefCntedCallback> releaseHelper) { | |
| SkASSERT(sampleCount > 0); | |
| if (info.alphaType() == kPremul_SkAlphaType || info.alphaType() == kOpaque_SkAlphaType) { | |
| return skgpu::ganesh::SurfaceDrawContext::MakeFromBackendTexture(this->context(), | |
| info.colorType(), | |
| info.refColorSpace(), | |
| tex, | |
| sampleCount, | |
| origin, | |
| SkSurfaceProps(), | |
| std::move(releaseHelper)); | |
| } | |
| if (info.colorType() == GrColorType::kUnknown) { | |
| return nullptr; | |
| } | |
| const GrBackendFormat& format = tex.getBackendFormat(); | |
| if (!this->caps()->areColorTypeAndFormatCompatible(info.colorType(), format)) { | |
| return nullptr; | |
| } | |
| skgpu::Swizzle readSwizzle = this->caps()->getReadSwizzle (format, info.colorType()); | |
| skgpu::Swizzle writeSwizzle = this->caps()->getWriteSwizzle(format, info.colorType()); | |
| sk_sp<GrTextureProxy> proxy(this->proxyProvider()->wrapRenderableBackendTexture( | |
| tex, sampleCount, kBorrow_GrWrapOwnership, GrWrapCacheable::kNo, | |
| std::move(releaseHelper))); | |
| if (!proxy) { | |
| return nullptr; | |
| } | |
| GrSurfaceProxyView readView( proxy, origin, readSwizzle); | |
| GrSurfaceProxyView writeView(std::move(proxy), origin, writeSwizzle); | |
| return std::make_unique<skgpu::ganesh::SurfaceFillContext>( | |
| this->context(), std::move(readView), std::move(writeView), std::move(info)); | |
| } |