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