• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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