xref: /aosp_15_r20/external/skia/src/gpu/ganesh/mtl/GrMtlTextureRenderTarget.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1/*
2 * Copyright 2018 Google Inc.
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 "src/gpu/ganesh/mtl/GrMtlTextureRenderTarget.h"
8
9#include "include/gpu/ganesh/mtl/GrMtlBackendSurface.h"
10#include "src/gpu/ganesh/GrDirectContextPriv.h"
11#include "src/gpu/ganesh/GrResourceProvider.h"
12#include "src/gpu/ganesh/mtl/GrMtlGpu.h"
13#include "src/gpu/ganesh/mtl/GrMtlUtil.h"
14
15#if !__has_feature(objc_arc)
16#error This file must be compiled with Arc. Use -fobjc-arc flag
17#endif
18
19GR_NORETAIN_BEGIN
20
21GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu,
22                                                   skgpu::Budgeted budgeted,
23                                                   SkISize dimensions,
24                                                   sk_sp<GrMtlAttachment> texture,
25                                                   sk_sp<GrMtlAttachment> colorAttachment,
26                                                   sk_sp<GrMtlAttachment> resolveAttachment,
27                                                   GrMipmapStatus mipmapStatus,
28                                                   std::string_view label)
29        : GrSurface(gpu, dimensions, GrProtected::kNo, label)
30        , GrMtlTexture(gpu, dimensions, std::move(texture), mipmapStatus, label)
31        , GrMtlRenderTarget(gpu, dimensions, std::move(colorAttachment),
32                            std::move(resolveAttachment), label) {
33    this->registerWithCache(budgeted);
34}
35
36GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu,
37                                                   SkISize dimensions,
38                                                   sk_sp<GrMtlAttachment> texture,
39                                                   sk_sp<GrMtlAttachment> colorAttachment,
40                                                   sk_sp<GrMtlAttachment> resolveAttachment,
41                                                   GrMipmapStatus mipmapStatus,
42                                                   GrWrapCacheable cacheable,
43                                                   std::string_view label)
44        : GrSurface(gpu, dimensions, GrProtected::kNo, label)
45        , GrMtlTexture(gpu, dimensions, std::move(texture), mipmapStatus, label)
46        , GrMtlRenderTarget(gpu, dimensions, std::move(colorAttachment),
47                            std::move(resolveAttachment), label) {
48    this->registerWithCacheWrapped(cacheable);
49}
50
51bool create_rt_attachments(GrMtlGpu* gpu, SkISize dimensions, MTLPixelFormat format, int sampleCnt,
52                           sk_sp<GrMtlAttachment> texture, sk_sp<GrMtlAttachment>* colorAttachment,
53                           sk_sp<GrMtlAttachment>* resolveAttachment) {
54    if (sampleCnt > 1) {
55        auto rp = gpu->getContext()->priv().resourceProvider();
56        sk_sp<GrAttachment> msaaAttachment =
57                rp->makeMSAAAttachment(dimensions,
58                                       GrBackendFormats::MakeMtl(format),
59                                       sampleCnt,
60                                       GrProtected::kNo,
61                                       GrMemoryless::kNo);
62        if (!msaaAttachment) {
63            return false;
64        }
65        *colorAttachment =
66                sk_sp<GrMtlAttachment>(static_cast<GrMtlAttachment*>(msaaAttachment.release()));
67        *resolveAttachment = std::move(texture);
68    } else {
69        *colorAttachment = std::move(texture);
70    }
71    return true;
72}
73
74sk_sp<GrMtlTextureRenderTarget> GrMtlTextureRenderTarget::MakeNewTextureRenderTarget(
75        GrMtlGpu* gpu,
76        skgpu::Budgeted budgeted,
77        SkISize dimensions,
78        int sampleCnt,
79        MTLPixelFormat format,
80        uint32_t mipLevels,
81        GrMipmapStatus mipmapStatus,
82        std::string_view label) {
83    sk_sp<GrMtlAttachment> textureAttachment =
84            GrMtlAttachment::MakeTexture(gpu, dimensions, format, mipLevels, GrRenderable::kYes,
85                                         /*numSamples=*/1, budgeted);
86    if (!textureAttachment) {
87        return nullptr;
88    }
89    if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
90        SkASSERT((MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget) &
91                 textureAttachment->mtlTexture().usage);
92    }
93
94    sk_sp<GrMtlAttachment> colorAttachment;
95    sk_sp<GrMtlAttachment> resolveAttachment;
96    if (!create_rt_attachments(gpu, dimensions, format, sampleCnt, textureAttachment,
97                               &colorAttachment, &resolveAttachment)) {
98        return nullptr;
99    }
100    SkASSERT(colorAttachment);
101    SkASSERT(sampleCnt == 1 || resolveAttachment);
102
103    return sk_sp<GrMtlTextureRenderTarget>(new GrMtlTextureRenderTarget(
104            gpu, budgeted, dimensions, std::move(textureAttachment), std::move(colorAttachment),
105            std::move(resolveAttachment), mipmapStatus, label));
106}
107
108sk_sp<GrMtlTextureRenderTarget> GrMtlTextureRenderTarget::MakeWrappedTextureRenderTarget(
109        GrMtlGpu* gpu,
110        SkISize dimensions,
111        int sampleCnt,
112        id<MTLTexture> texture,
113        GrWrapCacheable cacheable) {
114    SkASSERT(nil != texture);
115    if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
116        SkASSERT((MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget) & texture.usage);
117    }
118    GrMipmapStatus mipmapStatus = texture.mipmapLevelCount > 1
119                                            ? GrMipmapStatus::kDirty
120                                            : GrMipmapStatus::kNotAllocated;
121    GrAttachment::UsageFlags textureUsageFlags = GrAttachment::UsageFlags::kTexture |
122                                                 GrAttachment::UsageFlags::kColorAttachment;
123    sk_sp<GrMtlAttachment> textureAttachment =
124            GrMtlAttachment::MakeWrapped(gpu, dimensions, texture, textureUsageFlags, cacheable,
125                                         /*label=*/"MtlAttachment_TextureAttachment");
126    if (!textureAttachment) {
127        return nullptr;
128    }
129
130    sk_sp<GrMtlAttachment> colorAttachment;
131    sk_sp<GrMtlAttachment> resolveAttachment;
132    if (!create_rt_attachments(gpu, dimensions, texture.pixelFormat, sampleCnt, textureAttachment,
133                               &colorAttachment, &resolveAttachment)) {
134        return nullptr;
135    }
136    SkASSERT(colorAttachment);
137    SkASSERT(sampleCnt == 1 || resolveAttachment);
138
139    return sk_sp<GrMtlTextureRenderTarget>(new GrMtlTextureRenderTarget(
140            gpu, dimensions, std::move(textureAttachment), std::move(colorAttachment),
141            std::move(resolveAttachment), mipmapStatus, cacheable,
142                      /*label=*/"MtlWrappedTextureRenderTarget"));
143}
144
145size_t GrMtlTextureRenderTarget::onGpuMemorySize() const {
146    // The GrTexture[RenderTarget] is built up by a bunch of attachments each of which are their
147    // own GrGpuResource. Ideally the GrRenderTarget would not be a GrGpuResource and the GrTexture
148    // would just merge with the new GrSurface/Attachment world. Then we could just depend on each
149    // attachment to give its own size since we don't have GrGpuResources owning other
150    // GrGpuResources. Until we get to that point we need to live in some hybrid world. We will let
151    // the msaa and stencil attachments track their own size because they do get cached separately.
152    // For all GrTexture* based things we will continue to to use the GrTexture* to report size and
153    // the owned attachments will have no size and be uncached.
154#ifdef SK_DEBUG
155    // The nonMSAA attachment (either color or resolve depending on numSamples should have size of
156    // zero since it is a texture attachment.
157    SkASSERT(this->nonMSAAAttachment()->gpuMemorySize() == 0);
158    if (this->numSamples() > 1) {
159        // Msaa attachment should have a valid size
160        SkASSERT(this->colorAttachment()->gpuMemorySize() ==
161                 GrSurface::ComputeSize(this->backendFormat(),
162                                        this->dimensions(),
163                                        this->numSamples(),
164                                        skgpu::Mipmapped::kNo));
165    }
166#endif
167    return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
168                                  1 /*colorSamplesPerPixel*/, this->mipmapped());
169}
170
171void GrMtlTextureRenderTarget::onSetLabel() {
172    GrMtlRenderTarget::onSetLabel();
173    GrMtlTexture::onSetLabel();
174}
175
176GR_NORETAIN_END
177