| /* |
| * 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/GrBackendSurface.h" |
| #include "include/gpu/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<GrD3DResourceState> state, |
| const GrD3DTextureResourceInfo& msaaInfo, |
| sk_sp<GrD3DResourceState> 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<GrD3DResourceState> state, |
| const GrD3DTextureResourceInfo& msaaInfo, |
| sk_sp<GrD3DResourceState> 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<GrD3DResourceState> 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<GrD3DResourceState> 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> GrD3DRenderTarget::MakeWrappedRenderTarget( |
| GrD3DGpu* gpu, SkISize dimensions, int sampleCnt, const GrD3DTextureResourceInfo& info, |
| sk_sp<GrD3DResourceState> state) { |
| SkASSERT(info.fResource.get()); |
| SkASSERT(info.fLevelCount == 1); |
| SkASSERT(sampleCnt >= 1 && info.fSampleCount >= 1); |
| |
| int wrappedTextureSampleCnt = static_cast<int>(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<GrD3DResourceState> 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<GrD3DRenderTarget>(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<const GrD3DRenderTarget*>(this); |
| return const_cast<GrD3DTextureResource*>(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<GrD3DGpu*>(this->getGpu()); |
| } |
| |
| DXGI_FORMAT GrD3DRenderTarget::stencilDxgiFormat() const { |
| if (auto stencil = this->getStencilAttachment()) { |
| auto d3dStencil = static_cast<GrD3DAttachment*>(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()); |
| } |
| } |
| } |