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