1*c8dee2aaSAndroid Build Coastguard Worker/* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2024 Google LLC 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ganesh/mtl/GrMtlBackendSurface.h" 8*c8dee2aaSAndroid Build Coastguard Worker 9*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ganesh/GrTypes.h" 10*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ganesh/mtl/GrMtlTypes.h" 11*c8dee2aaSAndroid Build Coastguard Worker#include "include/private/base/SkAssert.h" 12*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/GrBackendSurfacePriv.h" 13*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlCppUtil.h" 14*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlUtil.h" 15*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/mtl/MtlUtilsPriv.h" 16*c8dee2aaSAndroid Build Coastguard Worker 17*c8dee2aaSAndroid Build Coastguard Worker#if !__has_feature(objc_arc) 18*c8dee2aaSAndroid Build Coastguard Worker#error This file must be compiled with Arc. Use -fobjc-arc flag 19*c8dee2aaSAndroid Build Coastguard Worker#endif 20*c8dee2aaSAndroid Build Coastguard Worker 21*c8dee2aaSAndroid Build Coastguard Workerclass GrMtlBackendFormatData final : public GrBackendFormatData { 22*c8dee2aaSAndroid Build Coastguard Workerpublic: 23*c8dee2aaSAndroid Build Coastguard Worker GrMtlBackendFormatData(GrMTLPixelFormat format) : fFormat((MTLPixelFormat)format) {} 24*c8dee2aaSAndroid Build Coastguard Worker 25*c8dee2aaSAndroid Build Coastguard Worker GrMTLPixelFormat asMtlFormat() const { return (GrMTLPixelFormat)fFormat; } 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Workerprivate: 28*c8dee2aaSAndroid Build Coastguard Worker SkTextureCompressionType compressionType() const override { 29*c8dee2aaSAndroid Build Coastguard Worker return GrMtlFormatToCompressionType(fFormat); 30*c8dee2aaSAndroid Build Coastguard Worker } 31*c8dee2aaSAndroid Build Coastguard Worker 32*c8dee2aaSAndroid Build Coastguard Worker size_t bytesPerBlock() const override { return skgpu::MtlFormatBytesPerBlock(fFormat); } 33*c8dee2aaSAndroid Build Coastguard Worker 34*c8dee2aaSAndroid Build Coastguard Worker int stencilBits() const override { return GrMtlFormatStencilBits(fFormat); } 35*c8dee2aaSAndroid Build Coastguard Worker 36*c8dee2aaSAndroid Build Coastguard Worker uint32_t channelMask() const override { return skgpu::MtlFormatChannels(fFormat); } 37*c8dee2aaSAndroid Build Coastguard Worker 38*c8dee2aaSAndroid Build Coastguard Worker GrColorFormatDesc desc() const override { return GrMtlFormatDesc(fFormat); } 39*c8dee2aaSAndroid Build Coastguard Worker 40*c8dee2aaSAndroid Build Coastguard Worker bool equal(const GrBackendFormatData* that) const override { 41*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!that || that->type() == GrBackendApi::kMetal); 42*c8dee2aaSAndroid Build Coastguard Worker if (auto otherMtl = static_cast<const GrMtlBackendFormatData*>(that)) { 43*c8dee2aaSAndroid Build Coastguard Worker return fFormat == otherMtl->fFormat; 44*c8dee2aaSAndroid Build Coastguard Worker } 45*c8dee2aaSAndroid Build Coastguard Worker return false; 46*c8dee2aaSAndroid Build Coastguard Worker } 47*c8dee2aaSAndroid Build Coastguard Worker 48*c8dee2aaSAndroid Build Coastguard Worker std::string toString() const override { 49*c8dee2aaSAndroid Build Coastguard Worker#if defined(SK_DEBUG) || GPU_TEST_UTILS 50*c8dee2aaSAndroid Build Coastguard Worker return skgpu::MtlFormatToString(fFormat); 51*c8dee2aaSAndroid Build Coastguard Worker#else 52*c8dee2aaSAndroid Build Coastguard Worker return ""; 53*c8dee2aaSAndroid Build Coastguard Worker#endif 54*c8dee2aaSAndroid Build Coastguard Worker } 55*c8dee2aaSAndroid Build Coastguard Worker 56*c8dee2aaSAndroid Build Coastguard Worker void copyTo(AnyFormatData& formatData) const override { 57*c8dee2aaSAndroid Build Coastguard Worker formatData.emplace<GrMtlBackendFormatData>(fFormat); 58*c8dee2aaSAndroid Build Coastguard Worker } 59*c8dee2aaSAndroid Build Coastguard Worker 60*c8dee2aaSAndroid Build Coastguard Worker#if defined(SK_DEBUG) 61*c8dee2aaSAndroid Build Coastguard Worker GrBackendApi type() const override { return GrBackendApi::kMetal; } 62*c8dee2aaSAndroid Build Coastguard Worker#endif 63*c8dee2aaSAndroid Build Coastguard Worker 64*c8dee2aaSAndroid Build Coastguard Worker MTLPixelFormat fFormat; 65*c8dee2aaSAndroid Build Coastguard Worker}; 66*c8dee2aaSAndroid Build Coastguard Worker 67*c8dee2aaSAndroid Build Coastguard Workerstatic const GrMtlBackendFormatData* get_and_cast_data(const GrBackendFormat& format) { 68*c8dee2aaSAndroid Build Coastguard Worker auto data = GrBackendSurfacePriv::GetBackendData(format); 69*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!data || data->type() == GrBackendApi::kMetal); 70*c8dee2aaSAndroid Build Coastguard Worker return static_cast<const GrMtlBackendFormatData*>(data); 71*c8dee2aaSAndroid Build Coastguard Worker} 72*c8dee2aaSAndroid Build Coastguard Worker 73*c8dee2aaSAndroid Build Coastguard Workernamespace GrBackendFormats { 74*c8dee2aaSAndroid Build Coastguard Worker 75*c8dee2aaSAndroid Build Coastguard WorkerGrBackendFormat MakeMtl(GrMTLPixelFormat format) { 76*c8dee2aaSAndroid Build Coastguard Worker return GrBackendSurfacePriv::MakeGrBackendFormat( 77*c8dee2aaSAndroid Build Coastguard Worker GrTextureType::k2D, GrBackendApi::kMetal, GrMtlBackendFormatData(format)); 78*c8dee2aaSAndroid Build Coastguard Worker} 79*c8dee2aaSAndroid Build Coastguard Worker 80*c8dee2aaSAndroid Build Coastguard WorkerGrMTLPixelFormat AsMtlFormat(const GrBackendFormat& format) { 81*c8dee2aaSAndroid Build Coastguard Worker if (format.isValid() && format.backend() == GrBackendApi::kMetal) { 82*c8dee2aaSAndroid Build Coastguard Worker const GrMtlBackendFormatData* data = get_and_cast_data(format); 83*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(data); 84*c8dee2aaSAndroid Build Coastguard Worker return data->asMtlFormat(); 85*c8dee2aaSAndroid Build Coastguard Worker } 86*c8dee2aaSAndroid Build Coastguard Worker // MTLPixelFormatInvalid == 0 87*c8dee2aaSAndroid Build Coastguard Worker return GrMTLPixelFormat(0); 88*c8dee2aaSAndroid Build Coastguard Worker} 89*c8dee2aaSAndroid Build Coastguard Worker 90*c8dee2aaSAndroid Build Coastguard Worker} // namespace GrBackendFormats 91*c8dee2aaSAndroid Build Coastguard Worker 92*c8dee2aaSAndroid Build Coastguard Workerclass GrMtlBackendTextureData final : public GrBackendTextureData { 93*c8dee2aaSAndroid Build Coastguard Workerpublic: 94*c8dee2aaSAndroid Build Coastguard Worker GrMtlBackendTextureData(const GrMtlTextureInfo& info) : fTexInfo(info) {} 95*c8dee2aaSAndroid Build Coastguard Worker 96*c8dee2aaSAndroid Build Coastguard Worker const GrMtlTextureInfo& info() const { return fTexInfo; } 97*c8dee2aaSAndroid Build Coastguard Worker 98*c8dee2aaSAndroid Build Coastguard Workerprivate: 99*c8dee2aaSAndroid Build Coastguard Worker void copyTo(AnyTextureData& textureData) const override { 100*c8dee2aaSAndroid Build Coastguard Worker textureData.emplace<GrMtlBackendTextureData>(fTexInfo); 101*c8dee2aaSAndroid Build Coastguard Worker } 102*c8dee2aaSAndroid Build Coastguard Worker 103*c8dee2aaSAndroid Build Coastguard Worker bool isProtected() const override { return false; } 104*c8dee2aaSAndroid Build Coastguard Worker 105*c8dee2aaSAndroid Build Coastguard Worker bool equal(const GrBackendTextureData* that) const override { 106*c8dee2aaSAndroid Build Coastguard Worker return this->isSameTexture(that); 107*c8dee2aaSAndroid Build Coastguard Worker } 108*c8dee2aaSAndroid Build Coastguard Worker 109*c8dee2aaSAndroid Build Coastguard Worker bool isSameTexture(const GrBackendTextureData* that) const override { 110*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!that || that->type() == GrBackendApi::kMetal); 111*c8dee2aaSAndroid Build Coastguard Worker if (auto otherMtl = static_cast<const GrMtlBackendTextureData*>(that)) { 112*c8dee2aaSAndroid Build Coastguard Worker return fTexInfo == otherMtl->fTexInfo; 113*c8dee2aaSAndroid Build Coastguard Worker } 114*c8dee2aaSAndroid Build Coastguard Worker return false; 115*c8dee2aaSAndroid Build Coastguard Worker } 116*c8dee2aaSAndroid Build Coastguard Worker 117*c8dee2aaSAndroid Build Coastguard Worker GrBackendFormat getBackendFormat() const override { 118*c8dee2aaSAndroid Build Coastguard Worker return GrBackendFormats::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(fTexInfo)); 119*c8dee2aaSAndroid Build Coastguard Worker } 120*c8dee2aaSAndroid Build Coastguard Worker 121*c8dee2aaSAndroid Build Coastguard Worker#if defined(SK_DEBUG) 122*c8dee2aaSAndroid Build Coastguard Worker GrBackendApi type() const override { return GrBackendApi::kMetal; } 123*c8dee2aaSAndroid Build Coastguard Worker#endif 124*c8dee2aaSAndroid Build Coastguard Worker 125*c8dee2aaSAndroid Build Coastguard Worker GrMtlTextureInfo fTexInfo; 126*c8dee2aaSAndroid Build Coastguard Worker}; 127*c8dee2aaSAndroid Build Coastguard Worker 128*c8dee2aaSAndroid Build Coastguard Workerstatic const GrMtlBackendTextureData* get_and_cast_data(const GrBackendTexture& texture) { 129*c8dee2aaSAndroid Build Coastguard Worker auto data = GrBackendSurfacePriv::GetBackendData(texture); 130*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!data || data->type() == GrBackendApi::kMetal); 131*c8dee2aaSAndroid Build Coastguard Worker return static_cast<const GrMtlBackendTextureData*>(data); 132*c8dee2aaSAndroid Build Coastguard Worker} 133*c8dee2aaSAndroid Build Coastguard Worker 134*c8dee2aaSAndroid Build Coastguard Workernamespace GrBackendTextures { 135*c8dee2aaSAndroid Build Coastguard Worker 136*c8dee2aaSAndroid Build Coastguard WorkerGrBackendTexture MakeMtl(int width, 137*c8dee2aaSAndroid Build Coastguard Worker int height, 138*c8dee2aaSAndroid Build Coastguard Worker skgpu::Mipmapped mipmapped, 139*c8dee2aaSAndroid Build Coastguard Worker const GrMtlTextureInfo& mtlInfo, 140*c8dee2aaSAndroid Build Coastguard Worker std::string_view label) { 141*c8dee2aaSAndroid Build Coastguard Worker return GrBackendSurfacePriv::MakeGrBackendTexture(width, 142*c8dee2aaSAndroid Build Coastguard Worker height, 143*c8dee2aaSAndroid Build Coastguard Worker label, 144*c8dee2aaSAndroid Build Coastguard Worker mipmapped, 145*c8dee2aaSAndroid Build Coastguard Worker GrBackendApi::kMetal, 146*c8dee2aaSAndroid Build Coastguard Worker GrTextureType::k2D, 147*c8dee2aaSAndroid Build Coastguard Worker GrMtlBackendTextureData(mtlInfo)); 148*c8dee2aaSAndroid Build Coastguard Worker} 149*c8dee2aaSAndroid Build Coastguard Worker 150*c8dee2aaSAndroid Build Coastguard Workerbool GetMtlTextureInfo(const GrBackendTexture& tex, GrMtlTextureInfo* outInfo) { 151*c8dee2aaSAndroid Build Coastguard Worker if (!tex.isValid() || tex.backend() != GrBackendApi::kMetal) { 152*c8dee2aaSAndroid Build Coastguard Worker return false; 153*c8dee2aaSAndroid Build Coastguard Worker } 154*c8dee2aaSAndroid Build Coastguard Worker const GrMtlBackendTextureData* data = get_and_cast_data(tex); 155*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(data); 156*c8dee2aaSAndroid Build Coastguard Worker *outInfo = data->info(); 157*c8dee2aaSAndroid Build Coastguard Worker return true; 158*c8dee2aaSAndroid Build Coastguard Worker} 159*c8dee2aaSAndroid Build Coastguard Worker 160*c8dee2aaSAndroid Build Coastguard Worker} // namespace GrBackendTextures 161*c8dee2aaSAndroid Build Coastguard Worker 162*c8dee2aaSAndroid Build Coastguard Workerclass GrMtlBackendRenderTargetData final : public GrBackendRenderTargetData { 163*c8dee2aaSAndroid Build Coastguard Workerpublic: 164*c8dee2aaSAndroid Build Coastguard Worker GrMtlBackendRenderTargetData(const GrMtlTextureInfo& info) : fTexInfo(info) {} 165*c8dee2aaSAndroid Build Coastguard Worker 166*c8dee2aaSAndroid Build Coastguard Worker const GrMtlTextureInfo& info() const { return fTexInfo; } 167*c8dee2aaSAndroid Build Coastguard Worker 168*c8dee2aaSAndroid Build Coastguard Workerprivate: 169*c8dee2aaSAndroid Build Coastguard Worker GrBackendFormat getBackendFormat() const override { 170*c8dee2aaSAndroid Build Coastguard Worker return GrBackendFormats::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(fTexInfo)); 171*c8dee2aaSAndroid Build Coastguard Worker } 172*c8dee2aaSAndroid Build Coastguard Worker 173*c8dee2aaSAndroid Build Coastguard Worker bool isProtected() const override { return false; } 174*c8dee2aaSAndroid Build Coastguard Worker 175*c8dee2aaSAndroid Build Coastguard Worker bool equal(const GrBackendRenderTargetData* that) const override { 176*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!that || that->type() == GrBackendApi::kMetal); 177*c8dee2aaSAndroid Build Coastguard Worker if (auto otherMtl = static_cast<const GrMtlBackendRenderTargetData*>(that)) { 178*c8dee2aaSAndroid Build Coastguard Worker return fTexInfo == otherMtl->fTexInfo; 179*c8dee2aaSAndroid Build Coastguard Worker } 180*c8dee2aaSAndroid Build Coastguard Worker return false; 181*c8dee2aaSAndroid Build Coastguard Worker } 182*c8dee2aaSAndroid Build Coastguard Worker 183*c8dee2aaSAndroid Build Coastguard Worker void copyTo(AnyRenderTargetData& rtData) const override { 184*c8dee2aaSAndroid Build Coastguard Worker rtData.emplace<GrMtlBackendRenderTargetData>(fTexInfo); 185*c8dee2aaSAndroid Build Coastguard Worker } 186*c8dee2aaSAndroid Build Coastguard Worker 187*c8dee2aaSAndroid Build Coastguard Worker#if defined(SK_DEBUG) 188*c8dee2aaSAndroid Build Coastguard Worker GrBackendApi type() const override { return GrBackendApi::kMetal; } 189*c8dee2aaSAndroid Build Coastguard Worker#endif 190*c8dee2aaSAndroid Build Coastguard Worker 191*c8dee2aaSAndroid Build Coastguard Worker GrMtlTextureInfo fTexInfo; 192*c8dee2aaSAndroid Build Coastguard Worker}; 193*c8dee2aaSAndroid Build Coastguard Worker 194*c8dee2aaSAndroid Build Coastguard Workerstatic const GrMtlBackendRenderTargetData* get_and_cast_data(const GrBackendRenderTarget& rt) { 195*c8dee2aaSAndroid Build Coastguard Worker auto data = GrBackendSurfacePriv::GetBackendData(rt); 196*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(!data || data->type() == GrBackendApi::kMetal); 197*c8dee2aaSAndroid Build Coastguard Worker return static_cast<const GrMtlBackendRenderTargetData*>(data); 198*c8dee2aaSAndroid Build Coastguard Worker} 199*c8dee2aaSAndroid Build Coastguard Worker 200*c8dee2aaSAndroid Build Coastguard Workernamespace GrBackendRenderTargets { 201*c8dee2aaSAndroid Build Coastguard Worker 202*c8dee2aaSAndroid Build Coastguard WorkerGrBackendRenderTarget MakeMtl(int width, int height, const GrMtlTextureInfo& mtlInfo) { 203*c8dee2aaSAndroid Build Coastguard Worker return GrBackendSurfacePriv::MakeGrBackendRenderTarget( 204*c8dee2aaSAndroid Build Coastguard Worker width, 205*c8dee2aaSAndroid Build Coastguard Worker height, 206*c8dee2aaSAndroid Build Coastguard Worker std::max(1, GrMtlTextureInfoSampleCount(mtlInfo)), 207*c8dee2aaSAndroid Build Coastguard Worker /*stencilBits=*/0, 208*c8dee2aaSAndroid Build Coastguard Worker GrBackendApi::kMetal, 209*c8dee2aaSAndroid Build Coastguard Worker /*framebufferOnly=*/false, // TODO: set this from mtlInfo.fTexture->framebufferOnly 210*c8dee2aaSAndroid Build Coastguard Worker GrMtlBackendRenderTargetData(mtlInfo)); 211*c8dee2aaSAndroid Build Coastguard Worker} 212*c8dee2aaSAndroid Build Coastguard Worker 213*c8dee2aaSAndroid Build Coastguard Workerbool GetMtlTextureInfo(const GrBackendRenderTarget& rt, GrMtlTextureInfo* outInfo) { 214*c8dee2aaSAndroid Build Coastguard Worker if (!rt.isValid() || rt.backend() != GrBackendApi::kMetal) { 215*c8dee2aaSAndroid Build Coastguard Worker return false; 216*c8dee2aaSAndroid Build Coastguard Worker } 217*c8dee2aaSAndroid Build Coastguard Worker const GrMtlBackendRenderTargetData* data = get_and_cast_data(rt); 218*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(data); 219*c8dee2aaSAndroid Build Coastguard Worker *outInfo = data->info(); 220*c8dee2aaSAndroid Build Coastguard Worker return true; 221*c8dee2aaSAndroid Build Coastguard Worker} 222*c8dee2aaSAndroid Build Coastguard Worker 223*c8dee2aaSAndroid Build Coastguard Worker} // namespace GrBackendRenderTargets 224