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/mtl/GrMtlRenderTarget.h"
9
10#include "src/gpu/mtl/GrMtlGpu.h"
11#include "src/gpu/mtl/GrMtlUtil.h"
12
13#if !__has_feature(objc_arc)
14#error This file must be compiled with Arc. Use -fobjc-arc flag
15#endif
16
17// Called for wrapped non-texture render targets.
18GrMtlRenderTarget::GrMtlRenderTarget(GrMtlGpu* gpu,
19                                     SkISize dimensions,
20                                     int sampleCnt,
21                                     id<MTLTexture> colorTexture,
22                                     id<MTLTexture> resolveTexture,
23                                     Wrapped)
24        : GrSurface(gpu, dimensions, GrProtected::kNo)
25        , GrRenderTarget(gpu, dimensions, sampleCnt, GrProtected::kNo)
26        , fColorTexture(colorTexture)
27        , fResolveTexture(resolveTexture) {
28    SkASSERT(sampleCnt > 1);
29    this->registerWithCacheWrapped(GrWrapCacheable::kNo);
30}
31
32GrMtlRenderTarget::GrMtlRenderTarget(GrMtlGpu* gpu,
33                                     SkISize dimensions,
34                                     id<MTLTexture> colorTexture,
35                                     Wrapped)
36        : GrSurface(gpu, dimensions, GrProtected::kNo)
37        , GrRenderTarget(gpu, dimensions, 1, GrProtected::kNo)
38        , fColorTexture(colorTexture)
39        , fResolveTexture(nil) {
40    this->registerWithCacheWrapped(GrWrapCacheable::kNo);
41}
42
43// Called by subclass constructors.
44GrMtlRenderTarget::GrMtlRenderTarget(GrMtlGpu* gpu,
45                                     SkISize dimensions,
46                                     int sampleCnt,
47                                     id<MTLTexture> colorTexture,
48                                     id<MTLTexture> resolveTexture)
49        : GrSurface(gpu, dimensions, GrProtected::kNo)
50        , GrRenderTarget(gpu, dimensions, sampleCnt, GrProtected::kNo)
51        , fColorTexture(colorTexture)
52        , fResolveTexture(resolveTexture) {
53    SkASSERT(sampleCnt > 1);
54}
55
56GrMtlRenderTarget::GrMtlRenderTarget(GrMtlGpu* gpu, SkISize dimensions, id<MTLTexture> colorTexture)
57        : GrSurface(gpu, dimensions, GrProtected::kNo)
58        , GrRenderTarget(gpu, dimensions, 1, GrProtected::kNo)
59        , fColorTexture(colorTexture)
60        , fResolveTexture(nil) {}
61
62sk_sp<GrMtlRenderTarget> GrMtlRenderTarget::MakeWrappedRenderTarget(GrMtlGpu* gpu,
63                                                                    SkISize dimensions,
64                                                                    int sampleCnt,
65                                                                    id<MTLTexture> texture) {
66    SkASSERT(nil != texture);
67    SkASSERT(1 == texture.mipmapLevelCount);
68    if (@available(macOS 10.11, iOS 9.0, *)) {
69        SkASSERT(MTLTextureUsageRenderTarget & texture.usage);
70    }
71
72    GrMtlRenderTarget* mtlRT;
73    if (sampleCnt > 1) {
74        MTLPixelFormat format = texture.pixelFormat;
75        if (!gpu->mtlCaps().isFormatRenderable(format, sampleCnt)) {
76            return nullptr;
77        }
78        MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init];
79        texDesc.textureType = MTLTextureType2DMultisample;
80        texDesc.pixelFormat = format;
81        texDesc.width = dimensions.fWidth;
82        texDesc.height = dimensions.fHeight;
83        texDesc.depth = 1;
84        texDesc.mipmapLevelCount = 1;
85        texDesc.sampleCount = sampleCnt;
86        texDesc.arrayLength = 1;
87        if (@available(macOS 10.11, iOS 9.0, *)) {
88            texDesc.storageMode = MTLStorageModePrivate;
89            texDesc.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget;
90        }
91
92        id<MTLTexture> colorTexture = [gpu->device() newTextureWithDescriptor:texDesc];
93        if (!colorTexture) {
94            return nullptr;
95        }
96        if (@available(macOS 10.11, iOS 9.0, *)) {
97            SkASSERT((MTLTextureUsageShaderRead|MTLTextureUsageRenderTarget) & colorTexture.usage);
98        }
99        mtlRT = new GrMtlRenderTarget(gpu, dimensions, sampleCnt, colorTexture, texture, kWrapped);
100    } else {
101        mtlRT = new GrMtlRenderTarget(gpu, dimensions, texture, kWrapped);
102    }
103
104    return sk_sp<GrMtlRenderTarget>(mtlRT);
105}
106
107GrMtlRenderTarget::~GrMtlRenderTarget() {
108    SkASSERT(nil == fColorTexture);
109    SkASSERT(nil == fResolveTexture);
110}
111
112GrBackendRenderTarget GrMtlRenderTarget::getBackendRenderTarget() const {
113    GrMtlTextureInfo info;
114    info.fTexture.reset(GrRetainPtrFromId(fColorTexture));
115    return GrBackendRenderTarget(this->width(), this->height(), fColorTexture.sampleCount, info);
116}
117
118GrBackendFormat GrMtlRenderTarget::backendFormat() const {
119    return GrBackendFormat::MakeMtl(fColorTexture.pixelFormat);
120}
121
122GrMtlGpu* GrMtlRenderTarget::getMtlGpu() const {
123    SkASSERT(!this->wasDestroyed());
124    return static_cast<GrMtlGpu*>(this->getGpu());
125}
126
127void GrMtlRenderTarget::onAbandon() {
128    fColorTexture = nil;
129    fResolveTexture = nil;
130    INHERITED::onAbandon();
131}
132
133void GrMtlRenderTarget::onRelease() {
134    fColorTexture = nil;
135    fResolveTexture = nil;
136    INHERITED::onRelease();
137}
138
139bool GrMtlRenderTarget::completeStencilAttachment() {
140    return true;
141}
142
143