blob: a2e27fdfd41ed8b2c7af425939278802db880ee8 [file] [log] [blame]
/*
* Copyright 2018 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/GrMtlAttachment.h"
#include "include/gpu/GpuTypes.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/ganesh/mtl/GrMtlBackendSurface.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
GrMtlAttachment::GrMtlAttachment(GrMtlGpu* gpu,
SkISize dimensions,
UsageFlags supportedUsages,
id<MTLTexture> texture,
skgpu::Budgeted budgeted,
std::string_view label)
: GrAttachment(
gpu,
dimensions,
supportedUsages,
texture.sampleCount,
texture.mipmapLevelCount > 1 ? skgpu::Mipmapped::kYes : skgpu::Mipmapped::kNo,
GrProtected::kNo,
label)
, fTexture(texture) {
this->registerWithCache(budgeted);
}
GrMtlAttachment::GrMtlAttachment(GrMtlGpu* gpu,
SkISize dimensions,
UsageFlags supportedUsages,
id<MTLTexture> texture,
GrWrapCacheable cacheable,
std::string_view label)
: GrAttachment(
gpu,
dimensions,
supportedUsages,
texture.sampleCount,
texture.mipmapLevelCount > 1 ? skgpu::Mipmapped::kYes : skgpu::Mipmapped::kNo,
GrProtected::kNo,
label)
, fTexture(texture) {
this->registerWithCacheWrapped(cacheable);
}
sk_sp<GrMtlAttachment> GrMtlAttachment::MakeStencil(GrMtlGpu* gpu,
SkISize dimensions,
int sampleCnt,
MTLPixelFormat format) {
int textureUsage = 0;
int storageMode = 0;
if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
textureUsage = MTLTextureUsageRenderTarget;
storageMode = MTLStorageModePrivate;
}
return GrMtlAttachment::Make(gpu, dimensions, UsageFlags::kStencilAttachment, sampleCnt, format,
/*mipLevels=*/1, textureUsage, storageMode, skgpu::Budgeted::kYes);
}
sk_sp<GrMtlAttachment> GrMtlAttachment::MakeMSAA(GrMtlGpu* gpu,
SkISize dimensions,
int sampleCnt,
MTLPixelFormat format) {
int textureUsage = 0;
int storageMode = 0;
if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
textureUsage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget;
storageMode = MTLStorageModePrivate;
}
return GrMtlAttachment::Make(gpu, dimensions, UsageFlags::kColorAttachment, sampleCnt, format,
/*mipLevels=*/1, textureUsage, storageMode, skgpu::Budgeted::kYes);
}
sk_sp<GrMtlAttachment> GrMtlAttachment::MakeTexture(GrMtlGpu* gpu,
SkISize dimensions,
MTLPixelFormat format,
uint32_t mipLevels,
GrRenderable renderable,
int numSamples,
skgpu::Budgeted budgeted) {
int textureUsage = 0;
int storageMode = 0;
if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
textureUsage = MTLTextureUsageShaderRead;
storageMode = MTLStorageModePrivate;
}
UsageFlags usageFlags = UsageFlags::kTexture;
if (renderable == GrRenderable::kYes) {
usageFlags |= UsageFlags::kColorAttachment;
if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
textureUsage |= MTLTextureUsageRenderTarget;
}
}
return GrMtlAttachment::Make(gpu, dimensions, usageFlags, numSamples, format, mipLevels,
textureUsage, storageMode, budgeted);
}
sk_sp<GrMtlAttachment> GrMtlAttachment::Make(GrMtlGpu* gpu,
SkISize dimensions,
UsageFlags attachmentUsages,
int sampleCnt,
MTLPixelFormat format,
uint32_t mipLevels,
int mtlTextureUsage,
int mtlStorageMode,
skgpu::Budgeted budgeted) {
auto desc = [[MTLTextureDescriptor alloc] init];
desc.textureType = (sampleCnt > 1) ? MTLTextureType2DMultisample : MTLTextureType2D;
desc.pixelFormat = format;
desc.width = dimensions.width();
desc.height = dimensions.height();
desc.depth = 1;
desc.mipmapLevelCount = mipLevels;
desc.sampleCount = sampleCnt;
desc.arrayLength = 1;
if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
desc.usage = mtlTextureUsage;
desc.storageMode = (MTLStorageMode)mtlStorageMode;
}
id<MTLTexture> texture = [gpu->device() newTextureWithDescriptor:desc];
#ifdef SK_ENABLE_MTL_DEBUG_INFO
if (attachmentUsages == UsageFlags::kStencilAttachment) {
texture.label = @"Stencil";
} else if (SkToBool(attachmentUsages & UsageFlags::kColorAttachment)) {
if (sampleCnt > 1) {
if (SkToBool(attachmentUsages & UsageFlags::kTexture)) {
texture.label = @"MSAA TextureRenderTarget";
} else {
texture.label = @"MSAA RenderTarget";
}
} else {
if (SkToBool(attachmentUsages & UsageFlags::kTexture)) {
texture.label = @"TextureRenderTarget";
} else {
texture.label = @"RenderTarget";
}
}
} else {
SkASSERT(attachmentUsages == UsageFlags::kTexture);
texture.label = @"Texture";
}
#endif
return sk_sp<GrMtlAttachment>(new GrMtlAttachment(gpu, dimensions, attachmentUsages,
texture, budgeted,
/*label=*/"MakeMtlAttachment"));
}
sk_sp<GrMtlAttachment> GrMtlAttachment::MakeWrapped(
GrMtlGpu* gpu,
SkISize dimensions,
id<MTLTexture> texture,
UsageFlags attachmentUsages,
GrWrapCacheable cacheable,
std::string_view label) {
return sk_sp<GrMtlAttachment>(new GrMtlAttachment(gpu, dimensions, attachmentUsages, texture,
cacheable, label));
}
GrMtlAttachment::~GrMtlAttachment() {
// should have been released or abandoned first
SkASSERT(!fTexture);
}
GrBackendFormat GrMtlAttachment::backendFormat() const {
return GrBackendFormats::MakeMtl(SkToU32(fTexture.pixelFormat));
}
void GrMtlAttachment::onRelease() {
fTexture = nil;
GrAttachment::onRelease();
}
void GrMtlAttachment::onAbandon() {
fTexture = nil;
GrAttachment::onAbandon();
}
GrMtlGpu* GrMtlAttachment::getMtlGpu() const {
SkASSERT(!this->wasDestroyed());
return static_cast<GrMtlGpu*>(this->getGpu());
}
void GrMtlAttachment::onSetLabel() {
SkASSERT(fTexture);
if (!this->getLabel().empty()) {
NSString* labelStr = @(this->getLabel().c_str());
fTexture.label = [@"_Skia_" stringByAppendingString:labelStr];
}
}
GR_NORETAIN_END