blob: f91f9daf44d620690986176386b7678223155a18 [file] [log] [blame]
/*
* Copyright 2017 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "src/gpu/ganesh/mtl/GrMtlRenderTarget.h"
#include "include/gpu/ganesh/mtl/GrMtlBackendSurface.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/mtl/GrMtlFramebuffer.h"
#include "src/gpu/ganesh/mtl/GrMtlGpu.h"
#include "src/gpu/ganesh/mtl/GrMtlUtil.h"
#if !__has_feature(objc_arc)
#error This file must be compiled with Arc. Use -fobjc-arc flag
#endif
GR_NORETAIN_BEGIN
// Called for wrapped non-texture render targets.
GrMtlRenderTarget::GrMtlRenderTarget(GrMtlGpu* gpu,
SkISize dimensions,
sk_sp<GrMtlAttachment> colorAttachment,
sk_sp<GrMtlAttachment> resolveAttachment,
Wrapped,
std::string_view label)
: GrSurface(gpu, dimensions, GrProtected::kNo, label)
, GrRenderTarget(gpu, dimensions, colorAttachment->numSamples(), GrProtected::kNo, label)
, fColorAttachment(std::move(colorAttachment))
, fResolveAttachment(std::move(resolveAttachment)) {
this->registerWithCacheWrapped(GrWrapCacheable::kNo);
}
// Called by subclass constructors.
GrMtlRenderTarget::GrMtlRenderTarget(GrMtlGpu* gpu,
SkISize dimensions,
sk_sp<GrMtlAttachment> colorAttachment,
sk_sp<GrMtlAttachment> resolveAttachment,
std::string_view label)
: GrSurface(gpu, dimensions, GrProtected::kNo, label)
, GrRenderTarget(gpu, dimensions, colorAttachment->numSamples(), GrProtected::kNo, label)
, fColorAttachment(std::move(colorAttachment))
, fResolveAttachment(std::move(resolveAttachment)) {
}
sk_sp<GrMtlRenderTarget> GrMtlRenderTarget::MakeWrappedRenderTarget(GrMtlGpu* gpu,
SkISize dimensions,
int sampleCnt,
id<MTLTexture> texture) {
SkASSERT(nil != texture);
SkASSERT(1 == texture.mipmapLevelCount);
if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
SkASSERT(MTLTextureUsageRenderTarget & texture.usage);
}
sk_sp<GrMtlAttachment> textureAttachment =
GrMtlAttachment::MakeWrapped(gpu, dimensions, texture,
GrAttachment::UsageFlags::kColorAttachment,
GrWrapCacheable::kNo,
/*label=*/"MtlAttachment_TextureAttachment");
GrMtlRenderTarget* mtlRT;
if (sampleCnt > 1) {
if ([texture sampleCount] == 1) {
MTLPixelFormat format = texture.pixelFormat;
if (!gpu->mtlCaps().isFormatRenderable(format, sampleCnt)) {
return nullptr;
}
auto rp = gpu->getContext()->priv().resourceProvider();
sk_sp<GrAttachment> msaaAttachment =
rp->makeMSAAAttachment(dimensions,
GrBackendFormats::MakeMtl(format),
sampleCnt,
GrProtected::kNo,
GrMemoryless::kNo);
if (!msaaAttachment) {
return nullptr;
}
sk_sp<GrMtlAttachment> colorAttachment =
sk_sp<GrMtlAttachment>(static_cast<GrMtlAttachment*>(msaaAttachment.release()));
mtlRT = new GrMtlRenderTarget(
gpu, dimensions, std::move(colorAttachment), std::move(textureAttachment),
kWrapped, /*label=*/"MakeWrappedRenderTargetWithOneTextureSampleCount");
mtlRT->setRequiresManualMSAAResolve();
} else {
SkASSERT(sampleCnt == static_cast<int>([texture sampleCount]));
mtlRT = new GrMtlRenderTarget(gpu, dimensions, std::move(textureAttachment), nil,
kWrapped,
/*label=*/"MakeWrappedRenderTargetWithManySampleCount");
}
} else {
mtlRT = new GrMtlRenderTarget(gpu, dimensions, std::move(textureAttachment), nil,
kWrapped,
/*label=*/"MakeWrappedRenderTargetWithOneOrLessSampleCount");
}
return sk_sp<GrMtlRenderTarget>(mtlRT);
}
GrMtlRenderTarget::~GrMtlRenderTarget() {
SkASSERT(nil == fColorAttachment);
SkASSERT(nil == fResolveAttachment);
}
GrBackendRenderTarget GrMtlRenderTarget::getBackendRenderTarget() const {
GrMtlTextureInfo info;
info.fTexture.reset(GrRetainPtrFromId(fColorAttachment->mtlTexture()));
return GrBackendRenderTargets::MakeMtl(this->width(), this->height(), info);
}
GrBackendFormat GrMtlRenderTarget::backendFormat() const {
return GrBackendFormats::MakeMtl(fColorAttachment->mtlFormat());
}
static int renderpass_features_to_index(bool hasResolve, bool hasStencil) {
int index = 0;
if (hasResolve) {
index += 1;
}
if (hasStencil) {
index += 2;
}
return index;
}
const GrMtlFramebuffer* GrMtlRenderTarget::getFramebuffer(bool withResolve,
bool withStencil) {
int cacheIndex =
renderpass_features_to_index(withResolve, withStencil);
SkASSERT(cacheIndex < GrMtlRenderTarget::kNumCachedFramebuffers);
if (fCachedFramebuffers[cacheIndex]) {
return fCachedFramebuffers[cacheIndex].get();
}
GrMtlAttachment* resolve = withResolve ? this->resolveAttachment() : nullptr;
GrMtlAttachment* colorAttachment = this->colorAttachment();
// Stencil attachment view is stored in the base RT stencil attachment
GrMtlAttachment* stencil =
withStencil ? static_cast<GrMtlAttachment*>(this->getStencilAttachment())
: nullptr;
fCachedFramebuffers[cacheIndex] =
GrMtlFramebuffer::Make(colorAttachment, resolve, stencil);
return fCachedFramebuffers[cacheIndex].get();
}
GrMtlGpu* GrMtlRenderTarget::getMtlGpu() const {
SkASSERT(!this->wasDestroyed());
return static_cast<GrMtlGpu*>(this->getGpu());
}
void GrMtlRenderTarget::onAbandon() {
fColorAttachment = nil;
fResolveAttachment = nil;
INHERITED::onAbandon();
}
void GrMtlRenderTarget::onRelease() {
fColorAttachment = nil;
fResolveAttachment = nil;
INHERITED::onRelease();
}
bool GrMtlRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMSAASurface) {
SkASSERT(useMSAASurface == (this->numSamples() > 1));
return true;
}
void GrMtlRenderTarget::onSetLabel() {
SkASSERT(fColorAttachment);
if (!this->getLabel().empty()) {
NSString* labelStr = @(this->getLabel().c_str());
if (fResolveAttachment) {
fColorAttachment->mtlTexture().label =
[@"_Skia_MSAA_" stringByAppendingString:labelStr];
fResolveAttachment->mtlTexture().label =
[@"_Skia_Resolve_" stringByAppendingString:labelStr];
} else {
fColorAttachment->mtlTexture().label = [@"_Skia_" stringByAppendingString:labelStr];
}
}
}
GR_NORETAIN_END