/* * 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/d3d/GrD3DRenderTarget.h" #include "include/gpu/GrBackendSurface.h" #include "include/gpu/d3d/GrD3DTypes.h" #include "src/gpu/GrRenderTarget.h" #include "src/gpu/d3d/GrD3DGpu.h" #include "src/gpu/d3d/GrD3DResourceProvider.h" #include "src/gpu/d3d/GrD3DTextureResource.h" #include "src/gpu/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) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, std::move(state)) // for the moment we only support 1:1 color to stencil , GrRenderTarget(gpu, dimensions, msaaInfo.fSampleCount, info.fProtected) , 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) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, std::move(state)) // for the moment we only support 1:1 color to stencil , GrRenderTarget(gpu, dimensions, msaaInfo.fSampleCount, info.fProtected) , 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) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, std::move(state)) , GrRenderTarget(gpu, dimensions, info.fSampleCount, info.fProtected) , 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) : GrSurface(gpu, dimensions, info.fProtected) , GrD3DTextureResource(info, std::move(state)) , GrRenderTarget(gpu, dimensions, info.fSampleCount, info.fProtected) , 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); } else { d3dRT = new GrD3DRenderTarget(gpu, dimensions, info, std::move(state), renderTargetView, kWrapped); } 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(GrProcessorKeyBuilder* 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()); }