/* * 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/ganesh/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(that)) { return fFormat == otherMtl->fFormat; } return false; } std::string toString() const override { #if defined(SK_DEBUG) || GPU_TEST_UTILS return skgpu::MtlFormatToString(fFormat); #else return ""; #endif } void copyTo(AnyFormatData& formatData) const override { formatData.emplace(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(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(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(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(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(that)) { return fTexInfo == otherMtl->fTexInfo; } return false; } void copyTo(AnyRenderTargetData& rtData) const override { rtData.emplace(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(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