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