/* * Copyright 2020 Google LLC * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "src/gpu/ganesh/d3d/GrD3DRenderTarget.h" #include "include/gpu/ganesh/GrBackendSurface.h" #include "include/gpu/ganesh/d3d/GrD3DTypes.h" #include "src/gpu/KeyBuilder.h" #include "src/gpu/ganesh/GrRenderTarget.h" #include "src/gpu/ganesh/d3d/GrD3DGpu.h" #include "src/gpu/ganesh/d3d/GrD3DResourceProvider.h" #include "src/gpu/ganesh/d3d/GrD3DTextureResource.h" #include "src/gpu/ganesh/d3d/GrD3DUtil.h" // We're virtually derived from GrSurface (via GrRenderTarget) so its // constructor must be explicitly called. GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp state, const GrD3DTextureResourceInfo& msaaInfo, sk_sp msaaState, const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView, const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView, Wrapped, std::string_view label) : GrSurface(gpu, dimensions, info.fProtected, label) , GrD3DTextureResource(info, std::move(state)) // for the moment we only support 1:1 color to stencil , GrRenderTarget(gpu, dimensions, msaaInfo.fSampleCount, info.fProtected, label) , fMSAATextureResource(new GrD3DTextureResource(msaaInfo, std::move(msaaState))) , fColorRenderTargetView(colorRenderTargetView) , fResolveRenderTargetView(resolveRenderTargetView) { SkASSERT(info.fProtected == msaaInfo.fProtected); SkASSERT(msaaInfo.fSampleCount > 1); this->registerWithCacheWrapped(GrWrapCacheable::kNo); } // We're virtually derived from GrSurface (via GrRenderTarget) so its // constructor must be explicitly called. GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp state, const GrD3DTextureResourceInfo& msaaInfo, sk_sp msaaState, const GrD3DDescriptorHeap::CPUHandle& colorRenderTargetView, const GrD3DDescriptorHeap::CPUHandle& resolveRenderTargetView, std::string_view label) : GrSurface(gpu, dimensions, info.fProtected, label) , GrD3DTextureResource(info, std::move(state)) // for the moment we only support 1:1 color to stencil , GrRenderTarget(gpu, dimensions, msaaInfo.fSampleCount, info.fProtected, label) , fMSAATextureResource(new GrD3DTextureResource(msaaInfo, std::move(msaaState))) , fColorRenderTargetView(colorRenderTargetView) , fResolveRenderTargetView(resolveRenderTargetView) { SkASSERT(info.fProtected == msaaInfo.fProtected); SkASSERT(msaaInfo.fSampleCount > 1); } // We're virtually derived from GrSurface (via GrRenderTarget) so its // constructor must be explicitly called. GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp state, const GrD3DDescriptorHeap::CPUHandle& renderTargetView, Wrapped, std::string_view label) : GrSurface(gpu, dimensions, info.fProtected, label) , GrD3DTextureResource(info, std::move(state)) , GrRenderTarget(gpu, dimensions, info.fSampleCount, info.fProtected, label) , fMSAATextureResource(nullptr) , fColorRenderTargetView(renderTargetView) { this->registerWithCacheWrapped(GrWrapCacheable::kNo); } // We're virtually derived from GrSurface (via GrRenderTarget) so its // constructor must be explicitly called. GrD3DRenderTarget::GrD3DRenderTarget(GrD3DGpu* gpu, SkISize dimensions, const GrD3DTextureResourceInfo& info, sk_sp state, const GrD3DDescriptorHeap::CPUHandle& renderTargetView, std::string_view label) : GrSurface(gpu, dimensions, info.fProtected, label) , GrD3DTextureResource(info, std::move(state)) , GrRenderTarget(gpu, dimensions, info.fSampleCount, info.fProtected, label) , fMSAATextureResource(nullptr) , fColorRenderTargetView(renderTargetView) {} sk_sp GrD3DRenderTarget::MakeWrappedRenderTarget( GrD3DGpu* gpu, SkISize dimensions, int sampleCnt, const GrD3DTextureResourceInfo& info, sk_sp state) { SkASSERT(info.fResource.get()); SkASSERT(info.fLevelCount == 1); SkASSERT(sampleCnt >= 1 && info.fSampleCount >= 1); int wrappedTextureSampleCnt = static_cast(info.fSampleCount); if (sampleCnt != wrappedTextureSampleCnt && wrappedTextureSampleCnt != 1) { return nullptr; } GrD3DDescriptorHeap::CPUHandle renderTargetView = gpu->resourceProvider().createRenderTargetView(info.fResource.get()); // create msaa surface if necessary GrD3DRenderTarget* d3dRT; if (sampleCnt != wrappedTextureSampleCnt) { GrD3DTextureResourceInfo msInfo; sk_sp msState; // for wrapped MSAA surface we assume clear to white SkColor4f clearColor = { 1, 1, 1, 1 }; std::tie(msInfo, msState) = GrD3DTextureResource::CreateMSAA(gpu, dimensions, sampleCnt, info, clearColor); GrD3DDescriptorHeap::CPUHandle msaaRenderTargetView = gpu->resourceProvider().createRenderTargetView(msInfo.fResource.get()); d3dRT = new GrD3DRenderTarget(gpu, dimensions, info, std::move(state), msInfo, std::move(msState), msaaRenderTargetView, renderTargetView, kWrapped, /*label=*/"MakeWrappedRenderTargetWithMSAASurface"); } else { d3dRT = new GrD3DRenderTarget( gpu, dimensions, info, std::move(state), renderTargetView, kWrapped, /*label=*/"MakeWrappedRenderTarget"); } return sk_sp(d3dRT); } GrD3DRenderTarget::~GrD3DRenderTarget() { // either release or abandon should have been called by the owner of this object. SkASSERT(!fMSAATextureResource); } const GrD3DTextureResource* GrD3DRenderTarget::msaaTextureResource() const { if (this->numSamples() == 1) { SkASSERT(!fMSAATextureResource); return nullptr; } if (fMSAATextureResource) { return fMSAATextureResource.get(); } SkASSERT(!fMSAATextureResource); return this; } GrD3DTextureResource* GrD3DRenderTarget::msaaTextureResource() { auto* constThis = const_cast(this); return const_cast(constThis->msaaTextureResource()); } void GrD3DRenderTarget::releaseInternalObjects() { GrD3DGpu* gpu = this->getD3DGpu(); if (fMSAATextureResource) { fMSAATextureResource->releaseResource(gpu); fMSAATextureResource.reset(); gpu->resourceProvider().recycleRenderTargetView(fResolveRenderTargetView); } gpu->resourceProvider().recycleRenderTargetView(fColorRenderTargetView); } void GrD3DRenderTarget::onRelease() { this->releaseInternalObjects(); this->releaseResource(this->getD3DGpu()); GrRenderTarget::onRelease(); } void GrD3DRenderTarget::onAbandon() { this->releaseInternalObjects(); this->releaseResource(this->getD3DGpu()); GrRenderTarget::onAbandon(); } GrBackendRenderTarget GrD3DRenderTarget::getBackendRenderTarget() const { return GrBackendRenderTarget(this->width(), this->height(), fInfo, this->grD3DResourceState()); } GrD3DGpu* GrD3DRenderTarget::getD3DGpu() const { SkASSERT(!this->wasDestroyed()); return static_cast(this->getGpu()); } DXGI_FORMAT GrD3DRenderTarget::stencilDxgiFormat() const { if (auto stencil = this->getStencilAttachment()) { auto d3dStencil = static_cast(stencil); return d3dStencil->dxgiFormat(); } return DXGI_FORMAT_UNKNOWN; } void GrD3DRenderTarget::genKey(skgpu::KeyBuilder* b) const { b->add32(this->dxgiFormat()); b->add32(this->numSamples()); b->add32(this->stencilDxgiFormat()); #ifdef SK_DEBUG if (const GrAttachment* stencil = this->getStencilAttachment()) { SkASSERT(stencil->numSamples() == this->numSamples()); } #endif b->add32(this->sampleQualityPattern()); } void GrD3DRenderTarget::onSetLabel() { SkASSERT(this->d3dResource()); if (!this->getLabel().empty()) { if (fMSAATextureResource) { SkASSERT(fMSAATextureResource->d3dResource()); const std::wstring suffix = GrD3DMultiByteToWide(this->getLabel()); const std::wstring msaaLabel = L"_Skia_MSAA_" + suffix; fMSAATextureResource->d3dResource()->SetName(msaaLabel.c_str()); const std::wstring resolveLabel = L"_Skia_Resolve_" + suffix; this->d3dResource()->SetName(resolveLabel.c_str()); } else { const std::wstring label = L"_Skia_" + GrD3DMultiByteToWide(this->getLabel()); this->d3dResource()->SetName(label.c_str()); } } }