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