xref: /aosp_15_r20/external/skia/src/gpu/ganesh/mtl/GrMtlBackendSurface.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker/*
2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2024 Google LLC
3*c8dee2aaSAndroid Build Coastguard Worker *
4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker */
7*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ganesh/mtl/GrMtlBackendSurface.h"
8*c8dee2aaSAndroid Build Coastguard Worker
9*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ganesh/GrTypes.h"
10*c8dee2aaSAndroid Build Coastguard Worker#include "include/gpu/ganesh/mtl/GrMtlTypes.h"
11*c8dee2aaSAndroid Build Coastguard Worker#include "include/private/base/SkAssert.h"
12*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/GrBackendSurfacePriv.h"
13*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlCppUtil.h"
14*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/ganesh/mtl/GrMtlUtil.h"
15*c8dee2aaSAndroid Build Coastguard Worker#include "src/gpu/mtl/MtlUtilsPriv.h"
16*c8dee2aaSAndroid Build Coastguard Worker
17*c8dee2aaSAndroid Build Coastguard Worker#if !__has_feature(objc_arc)
18*c8dee2aaSAndroid Build Coastguard Worker#error This file must be compiled with Arc. Use -fobjc-arc flag
19*c8dee2aaSAndroid Build Coastguard Worker#endif
20*c8dee2aaSAndroid Build Coastguard Worker
21*c8dee2aaSAndroid Build Coastguard Workerclass GrMtlBackendFormatData final : public GrBackendFormatData {
22*c8dee2aaSAndroid Build Coastguard Workerpublic:
23*c8dee2aaSAndroid Build Coastguard Worker    GrMtlBackendFormatData(GrMTLPixelFormat format) : fFormat((MTLPixelFormat)format) {}
24*c8dee2aaSAndroid Build Coastguard Worker
25*c8dee2aaSAndroid Build Coastguard Worker    GrMTLPixelFormat asMtlFormat() const { return (GrMTLPixelFormat)fFormat; }
26*c8dee2aaSAndroid Build Coastguard Worker
27*c8dee2aaSAndroid Build Coastguard Workerprivate:
28*c8dee2aaSAndroid Build Coastguard Worker    SkTextureCompressionType compressionType() const override {
29*c8dee2aaSAndroid Build Coastguard Worker        return GrMtlFormatToCompressionType(fFormat);
30*c8dee2aaSAndroid Build Coastguard Worker    }
31*c8dee2aaSAndroid Build Coastguard Worker
32*c8dee2aaSAndroid Build Coastguard Worker    size_t bytesPerBlock() const override { return skgpu::MtlFormatBytesPerBlock(fFormat); }
33*c8dee2aaSAndroid Build Coastguard Worker
34*c8dee2aaSAndroid Build Coastguard Worker    int stencilBits() const override { return GrMtlFormatStencilBits(fFormat); }
35*c8dee2aaSAndroid Build Coastguard Worker
36*c8dee2aaSAndroid Build Coastguard Worker    uint32_t channelMask() const override { return skgpu::MtlFormatChannels(fFormat); }
37*c8dee2aaSAndroid Build Coastguard Worker
38*c8dee2aaSAndroid Build Coastguard Worker    GrColorFormatDesc desc() const override { return GrMtlFormatDesc(fFormat); }
39*c8dee2aaSAndroid Build Coastguard Worker
40*c8dee2aaSAndroid Build Coastguard Worker    bool equal(const GrBackendFormatData* that) const override {
41*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(!that || that->type() == GrBackendApi::kMetal);
42*c8dee2aaSAndroid Build Coastguard Worker        if (auto otherMtl = static_cast<const GrMtlBackendFormatData*>(that)) {
43*c8dee2aaSAndroid Build Coastguard Worker            return fFormat == otherMtl->fFormat;
44*c8dee2aaSAndroid Build Coastguard Worker        }
45*c8dee2aaSAndroid Build Coastguard Worker        return false;
46*c8dee2aaSAndroid Build Coastguard Worker    }
47*c8dee2aaSAndroid Build Coastguard Worker
48*c8dee2aaSAndroid Build Coastguard Worker    std::string toString() const override {
49*c8dee2aaSAndroid Build Coastguard Worker#if defined(SK_DEBUG) || GPU_TEST_UTILS
50*c8dee2aaSAndroid Build Coastguard Worker        return skgpu::MtlFormatToString(fFormat);
51*c8dee2aaSAndroid Build Coastguard Worker#else
52*c8dee2aaSAndroid Build Coastguard Worker        return "";
53*c8dee2aaSAndroid Build Coastguard Worker#endif
54*c8dee2aaSAndroid Build Coastguard Worker    }
55*c8dee2aaSAndroid Build Coastguard Worker
56*c8dee2aaSAndroid Build Coastguard Worker    void copyTo(AnyFormatData& formatData) const override {
57*c8dee2aaSAndroid Build Coastguard Worker        formatData.emplace<GrMtlBackendFormatData>(fFormat);
58*c8dee2aaSAndroid Build Coastguard Worker    }
59*c8dee2aaSAndroid Build Coastguard Worker
60*c8dee2aaSAndroid Build Coastguard Worker#if defined(SK_DEBUG)
61*c8dee2aaSAndroid Build Coastguard Worker    GrBackendApi type() const override { return GrBackendApi::kMetal; }
62*c8dee2aaSAndroid Build Coastguard Worker#endif
63*c8dee2aaSAndroid Build Coastguard Worker
64*c8dee2aaSAndroid Build Coastguard Worker    MTLPixelFormat fFormat;
65*c8dee2aaSAndroid Build Coastguard Worker};
66*c8dee2aaSAndroid Build Coastguard Worker
67*c8dee2aaSAndroid Build Coastguard Workerstatic const GrMtlBackendFormatData* get_and_cast_data(const GrBackendFormat& format) {
68*c8dee2aaSAndroid Build Coastguard Worker    auto data = GrBackendSurfacePriv::GetBackendData(format);
69*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(!data || data->type() == GrBackendApi::kMetal);
70*c8dee2aaSAndroid Build Coastguard Worker    return static_cast<const GrMtlBackendFormatData*>(data);
71*c8dee2aaSAndroid Build Coastguard Worker}
72*c8dee2aaSAndroid Build Coastguard Worker
73*c8dee2aaSAndroid Build Coastguard Workernamespace GrBackendFormats {
74*c8dee2aaSAndroid Build Coastguard Worker
75*c8dee2aaSAndroid Build Coastguard WorkerGrBackendFormat MakeMtl(GrMTLPixelFormat format) {
76*c8dee2aaSAndroid Build Coastguard Worker    return GrBackendSurfacePriv::MakeGrBackendFormat(
77*c8dee2aaSAndroid Build Coastguard Worker            GrTextureType::k2D, GrBackendApi::kMetal, GrMtlBackendFormatData(format));
78*c8dee2aaSAndroid Build Coastguard Worker}
79*c8dee2aaSAndroid Build Coastguard Worker
80*c8dee2aaSAndroid Build Coastguard WorkerGrMTLPixelFormat AsMtlFormat(const GrBackendFormat& format) {
81*c8dee2aaSAndroid Build Coastguard Worker    if (format.isValid() && format.backend() == GrBackendApi::kMetal) {
82*c8dee2aaSAndroid Build Coastguard Worker        const GrMtlBackendFormatData* data = get_and_cast_data(format);
83*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(data);
84*c8dee2aaSAndroid Build Coastguard Worker        return data->asMtlFormat();
85*c8dee2aaSAndroid Build Coastguard Worker    }
86*c8dee2aaSAndroid Build Coastguard Worker    // MTLPixelFormatInvalid == 0
87*c8dee2aaSAndroid Build Coastguard Worker    return GrMTLPixelFormat(0);
88*c8dee2aaSAndroid Build Coastguard Worker}
89*c8dee2aaSAndroid Build Coastguard Worker
90*c8dee2aaSAndroid Build Coastguard Worker}  // namespace GrBackendFormats
91*c8dee2aaSAndroid Build Coastguard Worker
92*c8dee2aaSAndroid Build Coastguard Workerclass GrMtlBackendTextureData final : public GrBackendTextureData {
93*c8dee2aaSAndroid Build Coastguard Workerpublic:
94*c8dee2aaSAndroid Build Coastguard Worker    GrMtlBackendTextureData(const GrMtlTextureInfo& info) : fTexInfo(info) {}
95*c8dee2aaSAndroid Build Coastguard Worker
96*c8dee2aaSAndroid Build Coastguard Worker    const GrMtlTextureInfo& info() const { return fTexInfo; }
97*c8dee2aaSAndroid Build Coastguard Worker
98*c8dee2aaSAndroid Build Coastguard Workerprivate:
99*c8dee2aaSAndroid Build Coastguard Worker    void copyTo(AnyTextureData& textureData) const override {
100*c8dee2aaSAndroid Build Coastguard Worker        textureData.emplace<GrMtlBackendTextureData>(fTexInfo);
101*c8dee2aaSAndroid Build Coastguard Worker    }
102*c8dee2aaSAndroid Build Coastguard Worker
103*c8dee2aaSAndroid Build Coastguard Worker    bool isProtected() const override { return false; }
104*c8dee2aaSAndroid Build Coastguard Worker
105*c8dee2aaSAndroid Build Coastguard Worker    bool equal(const GrBackendTextureData* that) const override {
106*c8dee2aaSAndroid Build Coastguard Worker        return this->isSameTexture(that);
107*c8dee2aaSAndroid Build Coastguard Worker    }
108*c8dee2aaSAndroid Build Coastguard Worker
109*c8dee2aaSAndroid Build Coastguard Worker    bool isSameTexture(const GrBackendTextureData* that) const override {
110*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(!that || that->type() == GrBackendApi::kMetal);
111*c8dee2aaSAndroid Build Coastguard Worker        if (auto otherMtl = static_cast<const GrMtlBackendTextureData*>(that)) {
112*c8dee2aaSAndroid Build Coastguard Worker            return fTexInfo == otherMtl->fTexInfo;
113*c8dee2aaSAndroid Build Coastguard Worker        }
114*c8dee2aaSAndroid Build Coastguard Worker        return false;
115*c8dee2aaSAndroid Build Coastguard Worker    }
116*c8dee2aaSAndroid Build Coastguard Worker
117*c8dee2aaSAndroid Build Coastguard Worker    GrBackendFormat getBackendFormat() const override {
118*c8dee2aaSAndroid Build Coastguard Worker        return GrBackendFormats::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(fTexInfo));
119*c8dee2aaSAndroid Build Coastguard Worker    }
120*c8dee2aaSAndroid Build Coastguard Worker
121*c8dee2aaSAndroid Build Coastguard Worker#if defined(SK_DEBUG)
122*c8dee2aaSAndroid Build Coastguard Worker    GrBackendApi type() const override { return GrBackendApi::kMetal; }
123*c8dee2aaSAndroid Build Coastguard Worker#endif
124*c8dee2aaSAndroid Build Coastguard Worker
125*c8dee2aaSAndroid Build Coastguard Worker    GrMtlTextureInfo fTexInfo;
126*c8dee2aaSAndroid Build Coastguard Worker};
127*c8dee2aaSAndroid Build Coastguard Worker
128*c8dee2aaSAndroid Build Coastguard Workerstatic const GrMtlBackendTextureData* get_and_cast_data(const GrBackendTexture& texture) {
129*c8dee2aaSAndroid Build Coastguard Worker    auto data = GrBackendSurfacePriv::GetBackendData(texture);
130*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(!data || data->type() == GrBackendApi::kMetal);
131*c8dee2aaSAndroid Build Coastguard Worker    return static_cast<const GrMtlBackendTextureData*>(data);
132*c8dee2aaSAndroid Build Coastguard Worker}
133*c8dee2aaSAndroid Build Coastguard Worker
134*c8dee2aaSAndroid Build Coastguard Workernamespace GrBackendTextures {
135*c8dee2aaSAndroid Build Coastguard Worker
136*c8dee2aaSAndroid Build Coastguard WorkerGrBackendTexture MakeMtl(int width,
137*c8dee2aaSAndroid Build Coastguard Worker                         int height,
138*c8dee2aaSAndroid Build Coastguard Worker                         skgpu::Mipmapped mipmapped,
139*c8dee2aaSAndroid Build Coastguard Worker                         const GrMtlTextureInfo& mtlInfo,
140*c8dee2aaSAndroid Build Coastguard Worker                         std::string_view label) {
141*c8dee2aaSAndroid Build Coastguard Worker    return GrBackendSurfacePriv::MakeGrBackendTexture(width,
142*c8dee2aaSAndroid Build Coastguard Worker                                                      height,
143*c8dee2aaSAndroid Build Coastguard Worker                                                      label,
144*c8dee2aaSAndroid Build Coastguard Worker                                                      mipmapped,
145*c8dee2aaSAndroid Build Coastguard Worker                                                      GrBackendApi::kMetal,
146*c8dee2aaSAndroid Build Coastguard Worker                                                      GrTextureType::k2D,
147*c8dee2aaSAndroid Build Coastguard Worker                                                      GrMtlBackendTextureData(mtlInfo));
148*c8dee2aaSAndroid Build Coastguard Worker}
149*c8dee2aaSAndroid Build Coastguard Worker
150*c8dee2aaSAndroid Build Coastguard Workerbool GetMtlTextureInfo(const GrBackendTexture& tex, GrMtlTextureInfo* outInfo) {
151*c8dee2aaSAndroid Build Coastguard Worker    if (!tex.isValid() || tex.backend() != GrBackendApi::kMetal) {
152*c8dee2aaSAndroid Build Coastguard Worker        return false;
153*c8dee2aaSAndroid Build Coastguard Worker    }
154*c8dee2aaSAndroid Build Coastguard Worker    const GrMtlBackendTextureData* data = get_and_cast_data(tex);
155*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(data);
156*c8dee2aaSAndroid Build Coastguard Worker    *outInfo = data->info();
157*c8dee2aaSAndroid Build Coastguard Worker    return true;
158*c8dee2aaSAndroid Build Coastguard Worker}
159*c8dee2aaSAndroid Build Coastguard Worker
160*c8dee2aaSAndroid Build Coastguard Worker}  // namespace GrBackendTextures
161*c8dee2aaSAndroid Build Coastguard Worker
162*c8dee2aaSAndroid Build Coastguard Workerclass GrMtlBackendRenderTargetData final : public GrBackendRenderTargetData {
163*c8dee2aaSAndroid Build Coastguard Workerpublic:
164*c8dee2aaSAndroid Build Coastguard Worker    GrMtlBackendRenderTargetData(const GrMtlTextureInfo& info) : fTexInfo(info) {}
165*c8dee2aaSAndroid Build Coastguard Worker
166*c8dee2aaSAndroid Build Coastguard Worker    const GrMtlTextureInfo& info() const { return fTexInfo; }
167*c8dee2aaSAndroid Build Coastguard Worker
168*c8dee2aaSAndroid Build Coastguard Workerprivate:
169*c8dee2aaSAndroid Build Coastguard Worker    GrBackendFormat getBackendFormat() const override {
170*c8dee2aaSAndroid Build Coastguard Worker        return GrBackendFormats::MakeMtl(GrGetMTLPixelFormatFromMtlTextureInfo(fTexInfo));
171*c8dee2aaSAndroid Build Coastguard Worker    }
172*c8dee2aaSAndroid Build Coastguard Worker
173*c8dee2aaSAndroid Build Coastguard Worker    bool isProtected() const override { return false; }
174*c8dee2aaSAndroid Build Coastguard Worker
175*c8dee2aaSAndroid Build Coastguard Worker    bool equal(const GrBackendRenderTargetData* that) const override {
176*c8dee2aaSAndroid Build Coastguard Worker        SkASSERT(!that || that->type() == GrBackendApi::kMetal);
177*c8dee2aaSAndroid Build Coastguard Worker        if (auto otherMtl = static_cast<const GrMtlBackendRenderTargetData*>(that)) {
178*c8dee2aaSAndroid Build Coastguard Worker            return fTexInfo == otherMtl->fTexInfo;
179*c8dee2aaSAndroid Build Coastguard Worker        }
180*c8dee2aaSAndroid Build Coastguard Worker        return false;
181*c8dee2aaSAndroid Build Coastguard Worker    }
182*c8dee2aaSAndroid Build Coastguard Worker
183*c8dee2aaSAndroid Build Coastguard Worker    void copyTo(AnyRenderTargetData& rtData) const override {
184*c8dee2aaSAndroid Build Coastguard Worker        rtData.emplace<GrMtlBackendRenderTargetData>(fTexInfo);
185*c8dee2aaSAndroid Build Coastguard Worker    }
186*c8dee2aaSAndroid Build Coastguard Worker
187*c8dee2aaSAndroid Build Coastguard Worker#if defined(SK_DEBUG)
188*c8dee2aaSAndroid Build Coastguard Worker    GrBackendApi type() const override { return GrBackendApi::kMetal; }
189*c8dee2aaSAndroid Build Coastguard Worker#endif
190*c8dee2aaSAndroid Build Coastguard Worker
191*c8dee2aaSAndroid Build Coastguard Worker    GrMtlTextureInfo fTexInfo;
192*c8dee2aaSAndroid Build Coastguard Worker};
193*c8dee2aaSAndroid Build Coastguard Worker
194*c8dee2aaSAndroid Build Coastguard Workerstatic const GrMtlBackendRenderTargetData* get_and_cast_data(const GrBackendRenderTarget& rt) {
195*c8dee2aaSAndroid Build Coastguard Worker    auto data = GrBackendSurfacePriv::GetBackendData(rt);
196*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(!data || data->type() == GrBackendApi::kMetal);
197*c8dee2aaSAndroid Build Coastguard Worker    return static_cast<const GrMtlBackendRenderTargetData*>(data);
198*c8dee2aaSAndroid Build Coastguard Worker}
199*c8dee2aaSAndroid Build Coastguard Worker
200*c8dee2aaSAndroid Build Coastguard Workernamespace GrBackendRenderTargets {
201*c8dee2aaSAndroid Build Coastguard Worker
202*c8dee2aaSAndroid Build Coastguard WorkerGrBackendRenderTarget MakeMtl(int width, int height, const GrMtlTextureInfo& mtlInfo) {
203*c8dee2aaSAndroid Build Coastguard Worker    return GrBackendSurfacePriv::MakeGrBackendRenderTarget(
204*c8dee2aaSAndroid Build Coastguard Worker            width,
205*c8dee2aaSAndroid Build Coastguard Worker            height,
206*c8dee2aaSAndroid Build Coastguard Worker            std::max(1, GrMtlTextureInfoSampleCount(mtlInfo)),
207*c8dee2aaSAndroid Build Coastguard Worker            /*stencilBits=*/0,
208*c8dee2aaSAndroid Build Coastguard Worker            GrBackendApi::kMetal,
209*c8dee2aaSAndroid Build Coastguard Worker            /*framebufferOnly=*/false,  // TODO: set this from mtlInfo.fTexture->framebufferOnly
210*c8dee2aaSAndroid Build Coastguard Worker            GrMtlBackendRenderTargetData(mtlInfo));
211*c8dee2aaSAndroid Build Coastguard Worker}
212*c8dee2aaSAndroid Build Coastguard Worker
213*c8dee2aaSAndroid Build Coastguard Workerbool GetMtlTextureInfo(const GrBackendRenderTarget& rt, GrMtlTextureInfo* outInfo) {
214*c8dee2aaSAndroid Build Coastguard Worker    if (!rt.isValid() || rt.backend() != GrBackendApi::kMetal) {
215*c8dee2aaSAndroid Build Coastguard Worker        return false;
216*c8dee2aaSAndroid Build Coastguard Worker    }
217*c8dee2aaSAndroid Build Coastguard Worker    const GrMtlBackendRenderTargetData* data = get_and_cast_data(rt);
218*c8dee2aaSAndroid Build Coastguard Worker    SkASSERT(data);
219*c8dee2aaSAndroid Build Coastguard Worker    *outInfo = data->info();
220*c8dee2aaSAndroid Build Coastguard Worker    return true;
221*c8dee2aaSAndroid Build Coastguard Worker}
222*c8dee2aaSAndroid Build Coastguard Worker
223*c8dee2aaSAndroid Build Coastguard Worker}  // namespace GrBackendRenderTargets
224