• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright 2017 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
8#include "src/gpu/ganesh/mtl/GrMtlRenderTarget.h"
9
10#include "src/gpu/ganesh/GrDirectContextPriv.h"
11#include "src/gpu/ganesh/GrResourceProvider.h"
12#include "src/gpu/ganesh/mtl/GrMtlFramebuffer.h"
13#include "src/gpu/ganesh/mtl/GrMtlGpu.h"
14#include "src/gpu/ganesh/mtl/GrMtlUtil.h"
15
16#if !__has_feature(objc_arc)
17#error This file must be compiled with Arc. Use -fobjc-arc flag
18#endif
19
20GR_NORETAIN_BEGIN
21
22// Called for wrapped non-texture render targets.
23GrMtlRenderTarget::GrMtlRenderTarget(GrMtlGpu* gpu,
24                                     SkISize dimensions,
25                                     sk_sp<GrMtlAttachment> colorAttachment,
26                                     sk_sp<GrMtlAttachment> resolveAttachment,
27                                     Wrapped,
28                                     std::string_view label)
29        : GrSurface(gpu, dimensions, GrProtected::kNo, label)
30        , GrRenderTarget(gpu, dimensions, colorAttachment->numSamples(), GrProtected::kNo, label)
31        , fColorAttachment(std::move(colorAttachment))
32        , fResolveAttachment(std::move(resolveAttachment)) {
33    this->registerWithCacheWrapped(GrWrapCacheable::kNo);
34}
35
36// Called by subclass constructors.
37GrMtlRenderTarget::GrMtlRenderTarget(GrMtlGpu* gpu,
38                                     SkISize dimensions,
39                                     sk_sp<GrMtlAttachment> colorAttachment,
40                                     sk_sp<GrMtlAttachment> resolveAttachment,
41                                     std::string_view label)
42        : GrSurface(gpu, dimensions, GrProtected::kNo, label)
43        , GrRenderTarget(gpu, dimensions, colorAttachment->numSamples(), GrProtected::kNo, label)
44        , fColorAttachment(std::move(colorAttachment))
45        , fResolveAttachment(std::move(resolveAttachment)) {
46}
47
48sk_sp<GrMtlRenderTarget> GrMtlRenderTarget::MakeWrappedRenderTarget(GrMtlGpu* gpu,
49                                                                    SkISize dimensions,
50                                                                    int sampleCnt,
51                                                                    id<MTLTexture> texture) {
52    SkASSERT(nil != texture);
53    SkASSERT(1 == texture.mipmapLevelCount);
54    if (@available(macOS 10.11, iOS 9.0, *)) {
55        SkASSERT(MTLTextureUsageRenderTarget & texture.usage);
56    }
57
58    sk_sp<GrMtlAttachment> textureAttachment =
59            GrMtlAttachment::MakeWrapped(gpu, dimensions, texture,
60                                         GrAttachment::UsageFlags::kColorAttachment,
61                                         GrWrapCacheable::kNo,
62                                         /*label=*/"MtlAttachment_TextureAttachment");
63
64    GrMtlRenderTarget* mtlRT;
65    if (sampleCnt > 1) {
66        if ([texture sampleCount] == 1) {
67            MTLPixelFormat format = texture.pixelFormat;
68            if (!gpu->mtlCaps().isFormatRenderable(format, sampleCnt)) {
69                return nullptr;
70            }
71            auto rp = gpu->getContext()->priv().resourceProvider();
72            sk_sp<GrAttachment> msaaAttachment = rp->makeMSAAAttachment(
73                    dimensions, GrBackendFormat::MakeMtl(format), sampleCnt, GrProtected::kNo,
74                    GrMemoryless::kNo);
75            if (!msaaAttachment) {
76                return nullptr;
77            }
78            sk_sp<GrMtlAttachment> colorAttachment =
79                    sk_sp<GrMtlAttachment>(static_cast<GrMtlAttachment*>(msaaAttachment.release()));
80            mtlRT = new GrMtlRenderTarget(
81                    gpu, dimensions, std::move(colorAttachment), std::move(textureAttachment),
82                    kWrapped, /*label=*/"MakeWrappedRenderTargetWithOneTextureSampleCount");
83            mtlRT->setRequiresManualMSAAResolve();
84        } else {
85            SkASSERT(sampleCnt == static_cast<int>([texture sampleCount]));
86            mtlRT = new GrMtlRenderTarget(gpu, dimensions, std::move(textureAttachment), nil,
87                                          kWrapped,
88                                          /*label=*/"MakeWrappedRenderTargetWithManySampleCount");
89        }
90    } else {
91        mtlRT = new GrMtlRenderTarget(gpu, dimensions, std::move(textureAttachment), nil,
92                                      kWrapped,
93                                      /*label=*/"MakeWrappedRenderTargetWithOneOrLessSampleCount");
94    }
95
96    return sk_sp<GrMtlRenderTarget>(mtlRT);
97}
98
99GrMtlRenderTarget::~GrMtlRenderTarget() {
100    SkASSERT(nil == fColorAttachment);
101    SkASSERT(nil == fResolveAttachment);
102}
103
104GrBackendRenderTarget GrMtlRenderTarget::getBackendRenderTarget() const {
105    GrMtlTextureInfo info;
106    info.fTexture.reset(GrRetainPtrFromId(fColorAttachment->mtlTexture()));
107    return GrBackendRenderTarget(this->width(), this->height(), info);
108}
109
110GrBackendFormat GrMtlRenderTarget::backendFormat() const {
111    return GrBackendFormat::MakeMtl(fColorAttachment->mtlFormat());
112}
113
114static int renderpass_features_to_index(bool hasResolve, bool hasStencil) {
115    int index = 0;
116    if (hasResolve) {
117        index += 1;
118    }
119    if (hasStencil) {
120        index += 2;
121    }
122    return index;
123}
124
125const GrMtlFramebuffer* GrMtlRenderTarget::getFramebuffer(bool withResolve,
126                                                          bool withStencil) {
127    int cacheIndex =
128            renderpass_features_to_index(withResolve, withStencil);
129    SkASSERT(cacheIndex < GrMtlRenderTarget::kNumCachedFramebuffers);
130
131    if (fCachedFramebuffers[cacheIndex]) {
132        return fCachedFramebuffers[cacheIndex].get();
133    }
134
135    GrMtlAttachment* resolve = withResolve ? this->resolveAttachment() : nullptr;
136    GrMtlAttachment* colorAttachment = this->colorAttachment();
137
138    // Stencil attachment view is stored in the base RT stencil attachment
139    GrMtlAttachment* stencil =
140            withStencil ? static_cast<GrMtlAttachment*>(this->getStencilAttachment())
141                        : nullptr;
142    fCachedFramebuffers[cacheIndex] =
143            GrMtlFramebuffer::Make(colorAttachment, resolve, stencil);
144    return fCachedFramebuffers[cacheIndex].get();
145}
146
147GrMtlGpu* GrMtlRenderTarget::getMtlGpu() const {
148    SkASSERT(!this->wasDestroyed());
149    return static_cast<GrMtlGpu*>(this->getGpu());
150}
151
152void GrMtlRenderTarget::onAbandon() {
153    fColorAttachment = nil;
154    fResolveAttachment = nil;
155    INHERITED::onAbandon();
156}
157
158void GrMtlRenderTarget::onRelease() {
159    fColorAttachment = nil;
160    fResolveAttachment = nil;
161    INHERITED::onRelease();
162}
163
164bool GrMtlRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) {
165    SkASSERT(useMSAASurface == (this->numSamples() > 1));
166    return true;
167}
168
169void GrMtlRenderTarget::onSetLabel() {
170    SkASSERT(fColorAttachment);
171    if (!this->getLabel().empty()) {
172        NSString* labelStr = @(this->getLabel().c_str());
173        if (fResolveAttachment) {
174            fColorAttachment->mtlTexture().label =
175                    [@"_Skia_MSAA_" stringByAppendingString:labelStr];
176            fResolveAttachment->mtlTexture().label =
177                    [@"_Skia_Resolve_" stringByAppendingString:labelStr];
178        } else {
179            fColorAttachment->mtlTexture().label = [@"_Skia_" stringByAppendingString:labelStr];
180        }
181    }
182}
183
184GR_NORETAIN_END
185