blob: 316902b8c164751dda5e3c9c36062c9f433a6a02 [file] [log] [blame]
/*
* Copyright 2024 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/mtl/GrMtlBackendSurface.h"
#include "include/gpu/GrTypes.h"
#include "include/gpu/ganesh/mtl/GrMtlTypes.h"
#include "include/private/base/SkAssert.h"
#include "src/gpu/ganesh/GrBackendSurfacePriv.h"
#include "src/gpu/ganesh/mtl/GrMtlCppUtil.h"
#include "src/gpu/ganesh/mtl/GrMtlUtil.h"
#include "src/gpu/mtl/MtlUtilsPriv.h"
#if !__has_feature(objc_arc)
#error This file must be compiled with Arc. Use -fobjc-arc flag
#endif
class GrMtlBackendFormatData final : public GrBackendFormatData {
public:
GrMtlBackendFormatData(GrMTLPixelFormat format) : fFormat((MTLPixelFormat)format) {}
GrMTLPixelFormat asMtlFormat() const { return (GrMTLPixelFormat)fFormat; }
private:
SkTextureCompressionType compressionType() const override {
return GrMtlFormatToCompressionType(fFormat);
}
size_t bytesPerBlock() const override { return skgpu::MtlFormatBytesPerBlock(fFormat); }
int stencilBits() const override { return GrMtlFormatStencilBits(fFormat); }
uint32_t channelMask() const override { return skgpu::MtlFormatChannels(fFormat); }
GrColorFormatDesc desc() const override { return GrMtlFormatDesc(fFormat); }
bool equal(const GrBackendFormatData* that) const override {
SkASSERT(!that || that->type() == GrBackendApi::kMetal);
if (auto otherMtl = static_cast<const GrMtlBackendFormatData*>(that)) {
return fFormat == otherMtl->fFormat;
}
return false;
}
std::string toString() const override {
#if defined(SK_DEBUG) || GR_TEST_UTILS
return skgpu::MtlFormatToString(fFormat);
#else
return "";
#endif
}
void copyTo(AnyFormatData& formatData) const override {
formatData.emplace<GrMtlBackendFormatData>(fFormat);
}
#if defined(SK_DEBUG)
GrBackendApi type() const override { return GrBackendApi::kMetal; }
#endif
MTLPixelFormat fFormat;
};
static const GrMtlBackendFormatData* get_and_cast_data(const GrBackendFormat& format) {
auto data = GrBackendSurfacePriv::GetBackendData(format);
SkASSERT(!data || data->type() == GrBackendApi::kMetal);
return static_cast<const GrMtlBackendFormatData*>(data);
}
namespace GrBackendFormats {
GrBackendFormat MakeMtl(GrMTLPixelFormat format) {
return GrBackendSurfacePriv::MakeGrBackendFormat(
GrTextureType::k2D, GrBackendApi::kMetal, GrMtlBackendFormatData(format));
}
GrMTLPixelFormat AsMtlFormat(const GrBackendFormat& format) {
if (format.isValid() && format.backend() == GrBackendApi::kMetal) {
const GrMtlBackendFormatData* data = get_and_cast_data(format);
SkASSERT(data);
return data->asMtlFormat();
}
// MTLPixelFormatInvalid == 0
return GrMTLPixelFormat(0);
}
} // namespace GrBackendFormats
class GrMtlBackendTextureData final : public GrBackendTextureData {
public:
GrMtlBackendTextureData(const GrMtlTextureInfo& info) : fTexInfo(info) {}
const GrMtlTextureInfo& info() const { return fTexInfo; }
private:
void copyTo(AnyTextureData& textureData) const override {
textureData.emplace<GrMtlBackendTextureData>(fTexInfo);
}
bool isProtected() const override { return false; }
bool equal(const GrBackendTextureData* that) const override {
return this->isSameTexture(that);
}
bool isSameTexture(const GrBackendTextureData* that) const override {
SkASSERT(!that || that->type() == GrBackendApi::kMetal);
if (auto otherMtl = static_cast<const GrMtlBackendTextureData*>(that)) {
return fTexInfo == otherMtl->fTexInfo;
}
return false;
}
GrBackendFormat getBackendFormat() const override {
return GrBackendFormats::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(fTexInfo));
}
#if defined(SK_DEBUG)
GrBackendApi type() const override { return GrBackendApi::kMetal; }
#endif
GrMtlTextureInfo fTexInfo;
};
static const GrMtlBackendTextureData* get_and_cast_data(const GrBackendTexture& texture) {
auto data = GrBackendSurfacePriv::GetBackendData(texture);
SkASSERT(!data || data->type() == GrBackendApi::kMetal);
return static_cast<const GrMtlBackendTextureData*>(data);
}
namespace GrBackendTextures {
GrBackendTexture MakeMtl(int width,
int height,
skgpu::Mipmapped mipmapped,
const GrMtlTextureInfo& mtlInfo,
std::string_view label) {
return GrBackendSurfacePriv::MakeGrBackendTexture(width,
height,
label,
mipmapped,
GrBackendApi::kMetal,
GrTextureType::k2D,
GrMtlBackendTextureData(mtlInfo));
}
bool GetMtlTextureInfo(const GrBackendTexture& tex, GrMtlTextureInfo* outInfo) {
if (!tex.isValid() || tex.backend() != GrBackendApi::kMetal) {
return false;
}
const GrMtlBackendTextureData* data = get_and_cast_data(tex);
SkASSERT(data);
*outInfo = data->info();
return true;
}
} // namespace GrBackendTextures
class GrMtlBackendRenderTargetData final : public GrBackendRenderTargetData {
public:
GrMtlBackendRenderTargetData(const GrMtlTextureInfo& info) : fTexInfo(info) {}
const GrMtlTextureInfo& info() const { return fTexInfo; }
private:
GrBackendFormat getBackendFormat() const override {
return GrBackendFormats::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(fTexInfo));
}
bool isProtected() const override { return false; }
bool equal(const GrBackendRenderTargetData* that) const override {
SkASSERT(!that || that->type() == GrBackendApi::kMetal);
if (auto otherMtl = static_cast<const GrMtlBackendRenderTargetData*>(that)) {
return fTexInfo == otherMtl->fTexInfo;
}
return false;
}
void copyTo(AnyRenderTargetData& rtData) const override {
rtData.emplace<GrMtlBackendRenderTargetData>(fTexInfo);
}
#if defined(SK_DEBUG)
GrBackendApi type() const override { return GrBackendApi::kMetal; }
#endif
GrMtlTextureInfo fTexInfo;
};
static const GrMtlBackendRenderTargetData* get_and_cast_data(const GrBackendRenderTarget& rt) {
auto data = GrBackendSurfacePriv::GetBackendData(rt);
SkASSERT(!data || data->type() == GrBackendApi::kMetal);
return static_cast<const GrMtlBackendRenderTargetData*>(data);
}
namespace GrBackendRenderTargets {
GrBackendRenderTarget MakeMtl(int width, int height, const GrMtlTextureInfo& mtlInfo) {
return GrBackendSurfacePriv::MakeGrBackendRenderTarget(
width,
height,
std::max(1, GrMtlTextureInfoSampleCount(mtlInfo)),
/*stencilBits=*/0,
GrBackendApi::kMetal,
/*framebufferOnly=*/false, // TODO: set this from mtlInfo.fTexture->framebufferOnly
GrMtlBackendRenderTargetData(mtlInfo));
}
bool GetMtlTextureInfo(const GrBackendRenderTarget& rt, GrMtlTextureInfo* outInfo) {
if (!rt.isValid() || rt.backend() != GrBackendApi::kMetal) {
return false;
}
const GrMtlBackendRenderTargetData* data = get_and_cast_data(rt);
SkASSERT(data);
*outInfo = data->info();
return true;
}
} // namespace GrBackendRenderTargets