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