blob: 2b3bdd07996881be69015353a9af846b5f5ef84e [file] [log] [blame]
/*
* Copyright 2021 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "experimental/graphite/src/mtl/MtlTexture.h"
#include "experimental/graphite/include/mtl/MtlTypes.h"
#include "experimental/graphite/include/private/MtlTypesPriv.h"
#include "experimental/graphite/src/mtl/MtlCaps.h"
#include "experimental/graphite/src/mtl/MtlGpu.h"
#include "experimental/graphite/src/mtl/MtlUtils.h"
namespace skgpu::mtl {
sk_cfp<id<MTLTexture>> Texture::MakeMtlTexture(const Gpu* gpu,
SkISize dimensions,
const skgpu::TextureInfo& info) {
const skgpu::Caps* caps = gpu->caps();
if (dimensions.width() > caps->maxTextureSize() ||
dimensions.height() > caps->maxTextureSize()) {
return nullptr;
}
const TextureSpec& mtlSpec = info.mtlTextureSpec();
SkASSERT(!mtlSpec.fFramebufferOnly);
if (mtlSpec.fUsage & MTLTextureUsageShaderRead && !caps->isTexturable(info)) {
return nullptr;
}
if (mtlSpec.fUsage & MTLTextureUsageRenderTarget &&
!(caps->isRenderable(info) || FormatIsDepthOrStencil((MTLPixelFormat)mtlSpec.fFormat))) {
return nullptr;
}
sk_cfp<MTLTextureDescriptor*> desc([[MTLTextureDescriptor alloc] init]);
(*desc).textureType = (info.numSamples() > 1) ? MTLTextureType2DMultisample : MTLTextureType2D;
(*desc).pixelFormat = (MTLPixelFormat)mtlSpec.fFormat;
(*desc).width = dimensions.width();
(*desc).height = dimensions.height();
(*desc).depth = 1;
(*desc).mipmapLevelCount = info.numMipLevels();
(*desc).sampleCount = info.numSamples();
(*desc).arrayLength = 1;
(*desc).usage = mtlSpec.fUsage;
(*desc).storageMode = (MTLStorageMode)mtlSpec.fStorageMode;
sk_cfp<id<MTLTexture>> texture([gpu->device() newTextureWithDescriptor:desc.get()]);
#ifdef SK_ENABLE_MTL_DEBUG_INFO
if (mtlSpec.fUsage & MTLTextureUsageRenderTarget) {
if (FormatIsDepthOrStencil((MTLPixelFormat)mtlSpec.fFormat)) {
(*texture).label = @"DepthStencil";
} else {
if (info.numSamples() > 1) {
if (mtlSpec.fUsage & MTLTextureUsageShaderRead) {
(*texture).label = @"MSAA SampledTexture-ColorAttachment";
} else {
(*texture).label = @"MSAA ColorAttachment";
}
} else {
if (mtlSpec.fUsage & MTLTextureUsageShaderRead) {
(*texture).label = @"SampledTexture-ColorAttachment";
} else {
(*texture).label = @"ColorAttachment";
}
}
}
} else {
SkASSERT(mtlSpec.fUsage & MTLTextureUsageShaderRead);
(*texture).label = @"SampledTexture";
}
#endif
return texture;
}
Texture::Texture(const Gpu* gpu,
SkISize dimensions,
const skgpu::TextureInfo& info,
sk_cfp<id<MTLTexture>> texture,
Ownership ownership)
: skgpu::Texture(gpu, dimensions, info, ownership)
, fTexture(std::move(texture)) {}
sk_sp<Texture> Texture::Make(const Gpu* gpu,
SkISize dimensions,
const skgpu::TextureInfo& info) {
sk_cfp<id<MTLTexture>> texture = MakeMtlTexture(gpu, dimensions, info);
if (!texture) {
return nullptr;
}
return sk_sp<Texture>(new Texture(gpu,
dimensions,
info,
std::move(texture),
Ownership::kOwned));
}
sk_sp<Texture> Texture::MakeWrapped(const Gpu* gpu,
SkISize dimensions,
const skgpu::TextureInfo& info,
sk_cfp<id<MTLTexture>> texture) {
return sk_sp<Texture>(new Texture(gpu,
dimensions,
info,
std::move(texture),
Ownership::kWrapped));
}
void Texture::onFreeGpuData() {
fTexture.reset();
}
} // namespace skgpu::mtl