blob: 98d71e929e284bf230e33c216891ecc15170330f [file] [log] [blame] [edit]
/*
* 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/gpu/ganesh/d3d/GrD3DTypes.h"
#include "include/private/base/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; }
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;
}
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; }
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;
}
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