xref: /aosp_15_r20/external/skia/src/gpu/graphite/mtl/MtlTextureInfo.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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