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/GrDirectContextPriv.h" 11#include "src/gpu/GrResourceProvider.h" 12#include "src/gpu/mtl/GrMtlFramebuffer.h" 13#include "src/gpu/mtl/GrMtlGpu.h" 14#include "src/gpu/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 : GrSurface(gpu, dimensions, GrProtected::kNo) 29 , GrRenderTarget(gpu, dimensions, colorAttachment->numSamples(), GrProtected::kNo) 30 , fColorAttachment(std::move(colorAttachment)) 31 , fResolveAttachment(std::move(resolveAttachment)) { 32 this->registerWithCacheWrapped(GrWrapCacheable::kNo); 33} 34 35// Called by subclass constructors. 36GrMtlRenderTarget::GrMtlRenderTarget(GrMtlGpu* gpu, 37 SkISize dimensions, 38 sk_sp<GrMtlAttachment> colorAttachment, 39 sk_sp<GrMtlAttachment> resolveAttachment) 40 : GrSurface(gpu, dimensions, GrProtected::kNo) 41 , GrRenderTarget(gpu, dimensions, colorAttachment->numSamples(), GrProtected::kNo) 42 , fColorAttachment(std::move(colorAttachment)) 43 , fResolveAttachment(std::move(resolveAttachment)) { 44} 45 46sk_sp<GrMtlRenderTarget> GrMtlRenderTarget::MakeWrappedRenderTarget(GrMtlGpu* gpu, 47 SkISize dimensions, 48 int sampleCnt, 49 id<MTLTexture> texture) { 50 SkASSERT(nil != texture); 51 SkASSERT(1 == texture.mipmapLevelCount); 52 if (@available(macOS 10.11, iOS 9.0, *)) { 53 SkASSERT(MTLTextureUsageRenderTarget & texture.usage); 54 } 55 56 sk_sp<GrMtlAttachment> textureAttachment = 57 GrMtlAttachment::MakeWrapped(gpu, dimensions, texture, 58 GrAttachment::UsageFlags::kColorAttachment, 59 GrWrapCacheable::kNo); 60 61 GrMtlRenderTarget* mtlRT; 62 if (sampleCnt > 1) { 63 if ([texture sampleCount] == 1) { 64 MTLPixelFormat format = texture.pixelFormat; 65 if (!gpu->mtlCaps().isFormatRenderable(format, sampleCnt)) { 66 return nullptr; 67 } 68 auto rp = gpu->getContext()->priv().resourceProvider(); 69 sk_sp<GrAttachment> msaaAttachment = rp->makeMSAAAttachment( 70 dimensions, GrBackendFormat::MakeMtl(format), sampleCnt, GrProtected::kNo, 71 GrMemoryless::kNo); 72 if (!msaaAttachment) { 73 return nullptr; 74 } 75 sk_sp<GrMtlAttachment> colorAttachment = 76 sk_sp<GrMtlAttachment>(static_cast<GrMtlAttachment*>(msaaAttachment.release())); 77 mtlRT = new GrMtlRenderTarget( 78 gpu, dimensions, std::move(colorAttachment), std::move(textureAttachment), 79 kWrapped); 80 mtlRT->setRequiresManualMSAAResolve(); 81 } else { 82 SkASSERT(sampleCnt == static_cast<int>([texture sampleCount])); 83 mtlRT = new GrMtlRenderTarget(gpu, dimensions, std::move(textureAttachment), nil, 84 kWrapped); 85 } 86 } else { 87 mtlRT = new GrMtlRenderTarget(gpu, dimensions, std::move(textureAttachment), nil, 88 kWrapped); 89 } 90 91 return sk_sp<GrMtlRenderTarget>(mtlRT); 92} 93 94GrMtlRenderTarget::~GrMtlRenderTarget() { 95 SkASSERT(nil == fColorAttachment); 96 SkASSERT(nil == fResolveAttachment); 97} 98 99GrBackendRenderTarget GrMtlRenderTarget::getBackendRenderTarget() const { 100 GrMtlTextureInfo info; 101 info.fTexture.reset(GrRetainPtrFromId(fColorAttachment->mtlTexture())); 102 return GrBackendRenderTarget(this->width(), this->height(), info); 103} 104 105GrBackendFormat GrMtlRenderTarget::backendFormat() const { 106 return GrBackendFormat::MakeMtl(fColorAttachment->mtlFormat()); 107} 108 109static int renderpass_features_to_index(bool hasResolve, bool hasStencil) { 110 int index = 0; 111 if (hasResolve) { 112 index += 1; 113 } 114 if (hasStencil) { 115 index += 2; 116 } 117 return index; 118} 119 120const GrMtlFramebuffer* GrMtlRenderTarget::getFramebuffer(bool withResolve, 121 bool withStencil) { 122 int cacheIndex = 123 renderpass_features_to_index(withResolve, withStencil); 124 SkASSERT(cacheIndex < GrMtlRenderTarget::kNumCachedFramebuffers); 125 126 if (fCachedFramebuffers[cacheIndex]) { 127 return fCachedFramebuffers[cacheIndex].get(); 128 } 129 130 GrMtlAttachment* resolve = withResolve ? this->resolveAttachment() : nullptr; 131 GrMtlAttachment* colorAttachment = this->colorAttachment(); 132 133 // Stencil attachment view is stored in the base RT stencil attachment 134 GrMtlAttachment* stencil = 135 withStencil ? static_cast<GrMtlAttachment*>(this->getStencilAttachment()) 136 : nullptr; 137 fCachedFramebuffers[cacheIndex] = 138 GrMtlFramebuffer::Make(colorAttachment, resolve, stencil); 139 return fCachedFramebuffers[cacheIndex].get(); 140} 141 142GrMtlGpu* GrMtlRenderTarget::getMtlGpu() const { 143 SkASSERT(!this->wasDestroyed()); 144 return static_cast<GrMtlGpu*>(this->getGpu()); 145} 146 147void GrMtlRenderTarget::onAbandon() { 148 fColorAttachment = nil; 149 fResolveAttachment = nil; 150 INHERITED::onAbandon(); 151} 152 153void GrMtlRenderTarget::onRelease() { 154 fColorAttachment = nil; 155 fResolveAttachment = nil; 156 INHERITED::onRelease(); 157} 158 159bool GrMtlRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) { 160 SkASSERT(useMSAASurface == (this->numSamples() > 1)); 161 return true; 162} 163 164GR_NORETAIN_END 165