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/core/SkString.h" 8#include "include/gpu/graphite/mtl/MtlGraphiteTypes.h" 9#include "include/gpu/graphite/mtl/MtlGraphiteTypesUtils.h" 10#include "src/gpu/graphite/TextureInfoPriv.h" 11#include "src/gpu/graphite/mtl/MtlGraphiteTypesPriv.h" 12#include "src/gpu/mtl/MtlUtilsPriv.h" 13 14#include <cstdint> 15 16#import <Metal/Metal.h> 17 18namespace skgpu::graphite { 19 20class MtlTextureInfoData final : public TextureInfoData { 21public: 22 MtlTextureInfoData(MtlTextureSpec m) : fMtlSpec(m) {} 23 24#if defined(SK_DEBUG) 25 skgpu::BackendApi type() const override { return skgpu::BackendApi::kMetal; } 26#endif 27 28 MtlTextureSpec spec() const { return fMtlSpec; } 29 30private: 31 MtlTextureSpec fMtlSpec; 32 33 size_t bytesPerPixel() const override { 34 return MtlFormatBytesPerBlock(fMtlSpec.fFormat); 35 } 36 37 SkTextureCompressionType compressionType() const override { 38 return MtlFormatToCompressionType(fMtlSpec.fFormat); 39 } 40 41 bool isMemoryless() const override { 42 if (@available(macOS 11.0, iOS 10.0, tvOS 10.0, *)) { 43 return fMtlSpec.fStorageMode == MTLStorageModeMemoryless; 44 } 45 return false; 46 } 47 48 SkString toString() const override { 49 return SkStringPrintf("Metal(%s,", fMtlSpec.toString().c_str()); 50 } 51 52 SkString toRPAttachmentString(uint32_t sampleCount) const override { 53 return SkStringPrintf( 54 "Metal(f=%u,s=%u)", static_cast<unsigned int>(fMtlSpec.fFormat), sampleCount); 55 } 56 57 void copyTo(AnyTextureInfoData& dstData) const override { 58 // Don't assert that dstData is a metal type because it could be 59 // uninitialized and that assert would fail. 60 dstData.emplace<MtlTextureInfoData>(fMtlSpec); 61 } 62 63 bool equal(const TextureInfoData* that) const override { 64 SkASSERT(!that || that->type() == skgpu::BackendApi::kMetal); 65 if (auto otherMtl = static_cast<const MtlTextureInfoData*>(that)) { 66 return fMtlSpec == otherMtl->fMtlSpec; 67 } 68 return false; 69 } 70 71 bool isCompatible(const TextureInfoData* that) const override { 72 SkASSERT(!that || that->type() == skgpu::BackendApi::kMetal); 73 if (auto otherMtl = static_cast<const MtlTextureInfoData*>(that)) { 74 return fMtlSpec.isCompatible(otherMtl->fMtlSpec); 75 } 76 return false; 77 } 78}; 79 80static const MtlTextureInfoData* get_and_cast_data(const TextureInfo& info) { 81 auto data = TextureInfoPriv::GetData(info); 82 SkASSERT(!data || data->type() == skgpu::BackendApi::kMetal); 83 return static_cast<const MtlTextureInfoData*>(data); 84} 85 86namespace TextureInfos { 87skgpu::graphite::TextureInfo MakeMetal(CFTypeRef mtlTexture) { 88 return MakeMetal(MtlTextureInfo(mtlTexture)); 89} 90 91skgpu::graphite::TextureInfo MakeMetal(const MtlTextureInfo& mtlInfo) { 92 return TextureInfoPriv::Make(skgpu::BackendApi::kMetal, 93 mtlInfo.fSampleCount, 94 mtlInfo.fMipmapped, 95 Protected::kNo, 96 MtlTextureInfoData(mtlInfo)); 97} 98 99bool GetMtlTextureInfo(const TextureInfo& info, MtlTextureInfo* out) { 100 if (!info.isValid() || info.backend() != skgpu::BackendApi::kMetal) { 101 return false; 102 } 103 SkASSERT(out); 104 const MtlTextureInfoData* mtlData = get_and_cast_data(info); 105 SkASSERT(mtlData); 106 *out = MtlTextureSpecToTextureInfo(mtlData->spec(), info.numSamples(), info.mipmapped()); 107 return true; 108} 109 110// This cannot return a const reference or we get a warning about returning 111// a reference to a temporary local variable. 112MtlTextureSpec GetMtlTextureSpec(const TextureInfo& info) { 113 SkASSERT(info.isValid() && info.backend() == skgpu::BackendApi::kMetal); 114 const MtlTextureInfoData* mtlData = get_and_cast_data(info); 115 SkASSERT(mtlData); 116 return mtlData->spec(); 117} 118 119MTLPixelFormat GetMTLPixelFormat(const TextureInfo& info) { 120 SkASSERT(info.isValid() && info.backend() == skgpu::BackendApi::kMetal); 121 const MtlTextureInfoData* mtlData = get_and_cast_data(info); 122 SkASSERT(mtlData); 123 return mtlData->spec().fFormat; 124} 125 126MTLTextureUsage GetMTLTextureUsage(const TextureInfo& info) { 127 SkASSERT(info.isValid() && info.backend() == skgpu::BackendApi::kMetal); 128 const MtlTextureInfoData* mtlData = get_and_cast_data(info); 129 SkASSERT(mtlData); 130 return mtlData->spec().fUsage; 131} 132 133bool GetMtlFramebufferOnly(const TextureInfo& info) { 134 SkASSERT(info.isValid() && info.backend() == skgpu::BackendApi::kMetal); 135 const MtlTextureInfoData* mtlData = get_and_cast_data(info); 136 SkASSERT(mtlData); 137 return mtlData->spec().fFramebufferOnly; 138} 139 140} // namespace TextureInfos 141 142} // namespace skgpu::graphite 143