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