xref: /aosp_15_r20/external/skia/src/gpu/ganesh/mtl/GrMtlBackendSurface.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/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