| /* | |
| * Copyright 2026 Google LLC | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "include/gpu/ganesh/d3d/GrD3DBackendSurface.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/core/SkTextureCompressionType.h" | |
| #include "include/gpu/ganesh/d3d/GrD3DTypes.h" | |
| #include "include/private/SkAssert.h" | |
| #include "src/gpu/ganesh/GrBackendSurfacePriv.h" | |
| #include "src/gpu/ganesh/d3d/GrD3DBackendSurfacePriv.h" | |
| #include "src/gpu/ganesh/d3d/GrD3DResourceState.h" | |
| #include "src/gpu/ganesh/d3d/GrD3DUtil.h" | |
| class GrD3DBackendFormatData final : public GrBackendFormatData { | |
| public: | |
| GrD3DBackendFormatData(DXGI_FORMAT format) : fFormat(format) {} | |
| DXGI_FORMAT asDxgiFormat() const { return fFormat; } | |
| private: | |
| SkTextureCompressionType compressionType() const override { | |
| switch (fFormat) { | |
| case DXGI_FORMAT_BC1_UNORM: | |
| return SkTextureCompressionType::kBC1_RGBA8_UNORM; | |
| default: | |
| return SkTextureCompressionType::kNone; | |
| } | |
| } | |
| size_t bytesPerBlock() const override { return GrDxgiFormatBytesPerBlock(fFormat); } | |
| int stencilBits() const override { return GrDxgiFormatStencilBits(fFormat); } | |
| uint32_t channelMask() const override { return GrDxgiFormatChannels(fFormat); } | |
| GrColorFormatDesc desc() const override { return GrDxgiFormatDesc(fFormat); } | |
| bool equal(const GrBackendFormatData* that) const override { | |
| SkASSERT(!that || that->type() == GrBackendApi::kDirect3D); | |
| if (auto otherD3D = static_cast<const GrD3DBackendFormatData*>(that)) { | |
| return fFormat == otherD3D->fFormat; | |
| } | |
| return false; | |
| } | |
| std::string toString() const override { | |
| #if defined(SK_DEBUG) || defined(GPU_TEST_UTILS) | |
| return GrDxgiFormatToStr(fFormat); | |
| #else | |
| return ""; | |
| #endif | |
| } | |
| void copyTo(AnyFormatData& formatData) const override { | |
| formatData.emplace<GrD3DBackendFormatData>(fFormat); | |
| } | |
| #if defined(SK_DEBUG) | |
| GrBackendApi type() const override { return GrBackendApi::kDirect3D; } | |
| #endif | |
| DXGI_FORMAT fFormat; | |
| }; | |
| static const GrD3DBackendFormatData* get_and_cast_data(const GrBackendFormat& format) { | |
| auto data = GrBackendSurfacePriv::GetBackendData(format); | |
| SkASSERT(!data || data->type() == GrBackendApi::kDirect3D); | |
| return static_cast<const GrD3DBackendFormatData*>(data); | |
| } | |
| namespace GrBackendFormats { | |
| GrBackendFormat MakeD3D(DXGI_FORMAT format) { | |
| return GrBackendSurfacePriv::MakeGrBackendFormat( | |
| GrTextureType::k2D, GrBackendApi::kDirect3D, GrD3DBackendFormatData(format)); | |
| } | |
| DXGI_FORMAT AsDxgiFormat(const GrBackendFormat& format) { | |
| if (!format.isValid() || format.backend() != GrBackendApi::kDirect3D) { | |
| SkDEBUGFAIL("Mismatching backend or uninitialized GrBackendFormat\n"); | |
| return DXGI_FORMAT_UNKNOWN; | |
| } | |
| const GrD3DBackendFormatData* data = get_and_cast_data(format); | |
| SkASSERT(data); | |
| return data->asDxgiFormat(); | |
| } | |
| } // namespace GrBackendFormats | |
| class GrD3DBackendTextureData final : public GrBackendTextureData { | |
| public: | |
| GrD3DBackendTextureData(const GrD3DTextureResourceInfo& info, sk_sp<GrD3DResourceState> state) | |
| : fInfo(info, std::move(state)) {} | |
| GrD3DTextureResourceInfo snapTextureResourceInfo() const { | |
| return fInfo.snapTextureResourceInfo(); | |
| } | |
| void setResourceState(GrD3DResourceStateEnum state) { fInfo.setResourceState(state); } | |
| sk_sp<GrD3DResourceState> getResourceState() const { return fInfo.getResourceState(); } | |
| private: | |
| void copyTo(AnyTextureData& textureData) const override { | |
| textureData.emplace<GrD3DBackendTextureData>(this->snapTextureResourceInfo(), | |
| this->getResourceState()); | |
| } | |
| bool isProtected() const override { return false; } | |
| #if defined(GPU_TEST_UTILS) | |
| bool equal(const GrBackendTextureData* that) const override { | |
| SkASSERT(!that || that->type() == GrBackendApi::kDirect3D); | |
| if (auto otherD3D = static_cast<const GrD3DBackendTextureData*>(that)) { | |
| return fInfo == otherD3D->fInfo; | |
| } | |
| return false; | |
| } | |
| #endif | |
| bool isSameTexture(const GrBackendTextureData* that) const override { | |
| SkASSERT(!that || that->type() == GrBackendApi::kDirect3D); | |
| if (auto otherD3D = static_cast<const GrD3DBackendTextureData*>(that)) { | |
| return fInfo.snapTextureResourceInfo().fResource == | |
| otherD3D->snapTextureResourceInfo().fResource; | |
| } | |
| return false; | |
| } | |
| GrBackendFormat getBackendFormat() const override { | |
| auto d3dInfo = this->snapTextureResourceInfo(); | |
| return GrBackendFormats::MakeD3D(d3dInfo.fFormat); | |
| } | |
| #if defined(SK_DEBUG) | |
| GrBackendApi type() const override { return GrBackendApi::kDirect3D; } | |
| #endif | |
| GrD3DBackendSurfaceInfo fInfo; | |
| }; | |
| static const GrD3DBackendTextureData* get_and_cast_data(const GrBackendTexture& texture) { | |
| auto data = GrBackendSurfacePriv::GetBackendData(texture); | |
| SkASSERT(!data || data->type() == GrBackendApi::kDirect3D); | |
| return static_cast<const GrD3DBackendTextureData*>(data); | |
| } | |
| static GrD3DBackendTextureData* get_and_cast_data(GrBackendTexture* texture) { | |
| auto data = GrBackendSurfacePriv::GetBackendData(texture); | |
| SkASSERT(!data || data->type() == GrBackendApi::kDirect3D); | |
| return static_cast<GrD3DBackendTextureData*>(data); | |
| } | |
| namespace GrBackendTextures { | |
| GrBackendTexture MakeD3D(int width, | |
| int height, | |
| const GrD3DTextureResourceInfo& d3dInfo, | |
| std::string_view label) { | |
| GrD3DBackendTextureData data( | |
| d3dInfo, | |
| sk_sp<GrD3DResourceState>(new GrD3DResourceState( | |
| static_cast<D3D12_RESOURCE_STATES>(d3dInfo.fResourceState)))); | |
| return GrBackendSurfacePriv::MakeGrBackendTexture(width, | |
| height, | |
| label, | |
| skgpu::Mipmapped(d3dInfo.fLevelCount > 1), | |
| GrBackendApi::kDirect3D, | |
| GrTextureType::k2D, | |
| data); | |
| } | |
| GrBackendTexture MakeD3D(int width, | |
| int height, | |
| const GrD3DTextureResourceInfo& d3dInfo, | |
| sk_sp<GrD3DResourceState> state, | |
| std::string_view label) { | |
| return GrBackendSurfacePriv::MakeGrBackendTexture( | |
| width, | |
| height, | |
| label, | |
| skgpu::Mipmapped(d3dInfo.fLevelCount > 1), | |
| GrBackendApi::kDirect3D, | |
| GrTextureType::k2D, | |
| GrD3DBackendTextureData(d3dInfo, std::move(state))); | |
| } | |
| GrD3DTextureResourceInfo GetD3DTextureResourceInfo(const GrBackendTexture& tex) { | |
| if (!tex.isValid() || tex.backend() != GrBackendApi::kDirect3D) { | |
| SkDEBUGFAIL("Mismatching backend or uninitialized GrBackendTexture\n"); | |
| return {}; | |
| } | |
| const GrD3DBackendTextureData* data = get_and_cast_data(tex); | |
| SkASSERT(data); | |
| return data->snapTextureResourceInfo(); | |
| } | |
| void SetD3DResourceState(GrBackendTexture* tex, GrD3DResourceStateEnum state) { | |
| SkASSERT(tex); | |
| if (!tex->isValid() || tex->backend() != GrBackendApi::kDirect3D) { | |
| SkDEBUGFAIL("Mismatching backend or uninitialized GrBackendTexture\n"); | |
| return; | |
| } | |
| GrD3DBackendTextureData* data = get_and_cast_data(tex); | |
| SkASSERT(data); | |
| data->setResourceState(state); | |
| } | |
| sk_sp<GrD3DResourceState> GetD3DResourceState(const GrBackendTexture& tex) { | |
| if (!tex.isValid() || tex.backend() != GrBackendApi::kDirect3D) { | |
| SkDEBUGFAIL("Mismatching backend or uninitialized GrBackendTexture\n"); | |
| return nullptr; | |
| } | |
| const GrD3DBackendTextureData* data = get_and_cast_data(tex); | |
| SkASSERT(data); | |
| return data->getResourceState(); | |
| } | |
| } // namespace GrBackendTextures | |
| class GrD3DBackendRenderTargetData final : public GrBackendRenderTargetData { | |
| public: | |
| GrD3DBackendRenderTargetData(const GrD3DTextureResourceInfo& info, | |
| sk_sp<GrD3DResourceState> state) | |
| : fInfo(info, std::move(state)) {} | |
| GrD3DTextureResourceInfo snapTextureResourceInfo() const { | |
| return fInfo.snapTextureResourceInfo(); | |
| } | |
| void setResourceState(GrD3DResourceStateEnum state) { fInfo.setResourceState(state); } | |
| sk_sp<GrD3DResourceState> getResourceState() const { return fInfo.getResourceState(); } | |
| private: | |
| void copyTo(AnyRenderTargetData& rtData) const override { | |
| rtData.emplace<GrD3DBackendRenderTargetData>(this->snapTextureResourceInfo(), | |
| this->getResourceState()); | |
| } | |
| bool isProtected() const override { return false; } | |
| #if defined(GPU_TEST_UTILS) | |
| bool equal(const GrBackendRenderTargetData* that) const override { | |
| SkASSERT(!that || that->type() == GrBackendApi::kDirect3D); | |
| if (auto otherD3D = static_cast<const GrD3DBackendRenderTargetData*>(that)) { | |
| return fInfo == otherD3D->fInfo; | |
| } | |
| return false; | |
| } | |
| #endif | |
| GrBackendFormat getBackendFormat() const override { | |
| auto d3dInfo = this->snapTextureResourceInfo(); | |
| return GrBackendFormats::MakeD3D(d3dInfo.fFormat); | |
| } | |
| #if defined(SK_DEBUG) | |
| GrBackendApi type() const override { return GrBackendApi::kDirect3D; } | |
| #endif | |
| GrD3DBackendSurfaceInfo fInfo; | |
| }; | |
| static const GrD3DBackendRenderTargetData* get_and_cast_data(const GrBackendRenderTarget& texture) { | |
| auto data = GrBackendSurfacePriv::GetBackendData(texture); | |
| SkASSERT(!data || data->type() == GrBackendApi::kDirect3D); | |
| return static_cast<const GrD3DBackendRenderTargetData*>(data); | |
| } | |
| static GrD3DBackendRenderTargetData* get_and_cast_data(GrBackendRenderTarget* texture) { | |
| auto data = GrBackendSurfacePriv::GetBackendData(texture); | |
| SkASSERT(!data || data->type() == GrBackendApi::kDirect3D); | |
| return static_cast<GrD3DBackendRenderTargetData*>(data); | |
| } | |
| namespace GrBackendRenderTargets { | |
| GrBackendRenderTarget MakeD3D(int width, int height, const GrD3DTextureResourceInfo& d3dInfo) { | |
| GrD3DBackendRenderTargetData data( | |
| d3dInfo, | |
| sk_sp<GrD3DResourceState>(new GrD3DResourceState( | |
| static_cast<D3D12_RESOURCE_STATES>(d3dInfo.fResourceState)))); | |
| return GrBackendSurfacePriv::MakeGrBackendRenderTarget(width, | |
| height, | |
| std::max(1U, d3dInfo.fSampleCount), | |
| 0, /*stencilBits*/ | |
| GrBackendApi::kDirect3D, | |
| false, /*framebufferOnly*/ | |
| data); | |
| } | |
| GrBackendRenderTarget MakeD3D(int width, | |
| int height, | |
| const GrD3DTextureResourceInfo& d3dInfo, | |
| sk_sp<GrD3DResourceState> state) { | |
| return GrBackendSurfacePriv::MakeGrBackendRenderTarget( | |
| width, | |
| height, | |
| std::max(1U, d3dInfo.fSampleCount), | |
| 0, /*stencilBits*/ | |
| GrBackendApi::kDirect3D, | |
| false, /*framebufferOnly*/ | |
| GrD3DBackendRenderTargetData(d3dInfo, std::move(state))); | |
| } | |
| GrD3DTextureResourceInfo GetD3DTextureResourceInfo(const GrBackendRenderTarget& rt) { | |
| if (!rt.isValid() || rt.backend() != GrBackendApi::kDirect3D) { | |
| SkDEBUGFAIL("Mismatching backend or uninitialized GrBackendRenderTarget\n"); | |
| return {}; | |
| } | |
| const GrD3DBackendRenderTargetData* data = get_and_cast_data(rt); | |
| SkASSERT(data); | |
| return data->snapTextureResourceInfo(); | |
| } | |
| void SetD3DResourceState(GrBackendRenderTarget* rt, GrD3DResourceStateEnum state) { | |
| SkASSERT(rt); | |
| if (!rt->isValid() || rt->backend() != GrBackendApi::kDirect3D) { | |
| SkDEBUGFAIL("Mismatching backend or uninitialized GrBackendRenderTarget\n"); | |
| return; | |
| } | |
| GrD3DBackendRenderTargetData* data = get_and_cast_data(rt); | |
| SkASSERT(data); | |
| data->setResourceState(state); | |
| } | |
| sk_sp<GrD3DResourceState> GetD3DResourceState(const GrBackendRenderTarget& rt) { | |
| if (!rt.isValid() || rt.backend() != GrBackendApi::kDirect3D) { | |
| SkDEBUGFAIL("Mismatching backend or uninitialized GrBackendRenderTarget\n"); | |
| return nullptr; | |
| } | |
| const GrD3DBackendRenderTargetData* data = get_and_cast_data(rt); | |
| SkASSERT(data); | |
| return data->getResourceState(); | |
| } | |
| } // namespace GrBackendRenderTargets |