1/* 2 * Copyright 2021 Google LLC 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 "experimental/graphite/src/mtl/MtlTexture.h" 9 10#include "experimental/graphite/include/mtl/MtlTypes.h" 11#include "experimental/graphite/include/private/MtlTypesPriv.h" 12#include "experimental/graphite/src/mtl/MtlCaps.h" 13#include "experimental/graphite/src/mtl/MtlGpu.h" 14#include "experimental/graphite/src/mtl/MtlUtils.h" 15 16namespace skgpu::mtl { 17 18sk_cfp<id<MTLTexture>> Texture::MakeMtlTexture(const Gpu* gpu, 19 SkISize dimensions, 20 const skgpu::TextureInfo& info) { 21 const skgpu::Caps* caps = gpu->caps(); 22 if (dimensions.width() > caps->maxTextureSize() || 23 dimensions.height() > caps->maxTextureSize()) { 24 return nullptr; 25 } 26 27 const TextureSpec& mtlSpec = info.mtlTextureSpec(); 28 SkASSERT(!mtlSpec.fFramebufferOnly); 29 30 if (mtlSpec.fUsage & MTLTextureUsageShaderRead && !caps->isTexturable(info)) { 31 return nullptr; 32 } 33 34 if (mtlSpec.fUsage & MTLTextureUsageRenderTarget && 35 !(caps->isRenderable(info) || FormatIsDepthOrStencil((MTLPixelFormat)mtlSpec.fFormat))) { 36 return nullptr; 37 } 38 39 sk_cfp<MTLTextureDescriptor*> desc([[MTLTextureDescriptor alloc] init]); 40 (*desc).textureType = (info.numSamples() > 1) ? MTLTextureType2DMultisample : MTLTextureType2D; 41 (*desc).pixelFormat = (MTLPixelFormat)mtlSpec.fFormat; 42 (*desc).width = dimensions.width(); 43 (*desc).height = dimensions.height(); 44 (*desc).depth = 1; 45 (*desc).mipmapLevelCount = info.numMipLevels(); 46 (*desc).sampleCount = info.numSamples(); 47 (*desc).arrayLength = 1; 48 (*desc).usage = mtlSpec.fUsage; 49 (*desc).storageMode = (MTLStorageMode)mtlSpec.fStorageMode; 50 51 sk_cfp<id<MTLTexture>> texture([gpu->device() newTextureWithDescriptor:desc.get()]); 52#ifdef SK_ENABLE_MTL_DEBUG_INFO 53 if (mtlSpec.fUsage & MTLTextureUsageRenderTarget) { 54 if (FormatIsDepthOrStencil((MTLPixelFormat)mtlSpec.fFormat)) { 55 (*texture).label = @"DepthStencil"; 56 } else { 57 if (info.numSamples() > 1) { 58 if (mtlSpec.fUsage & MTLTextureUsageShaderRead) { 59 (*texture).label = @"MSAA SampledTexture-ColorAttachment"; 60 } else { 61 (*texture).label = @"MSAA ColorAttachment"; 62 } 63 } else { 64 if (mtlSpec.fUsage & MTLTextureUsageShaderRead) { 65 (*texture).label = @"SampledTexture-ColorAttachment"; 66 } else { 67 (*texture).label = @"ColorAttachment"; 68 } 69 } 70 } 71 } else { 72 SkASSERT(mtlSpec.fUsage & MTLTextureUsageShaderRead); 73 (*texture).label = @"SampledTexture"; 74 } 75#endif 76 77 return texture; 78} 79 80Texture::Texture(const Gpu* gpu, 81 SkISize dimensions, 82 const skgpu::TextureInfo& info, 83 sk_cfp<id<MTLTexture>> texture, 84 Ownership ownership) 85 : skgpu::Texture(gpu, dimensions, info, ownership) 86 , fTexture(std::move(texture)) {} 87 88sk_sp<Texture> Texture::Make(const Gpu* gpu, 89 SkISize dimensions, 90 const skgpu::TextureInfo& info) { 91 sk_cfp<id<MTLTexture>> texture = MakeMtlTexture(gpu, dimensions, info); 92 if (!texture) { 93 return nullptr; 94 } 95 return sk_sp<Texture>(new Texture(gpu, 96 dimensions, 97 info, 98 std::move(texture), 99 Ownership::kOwned)); 100} 101 102sk_sp<Texture> Texture::MakeWrapped(const Gpu* gpu, 103 SkISize dimensions, 104 const skgpu::TextureInfo& info, 105 sk_cfp<id<MTLTexture>> texture) { 106 return sk_sp<Texture>(new Texture(gpu, 107 dimensions, 108 info, 109 std::move(texture), 110 Ownership::kWrapped)); 111} 112 113void Texture::onFreeGpuData() { 114 fTexture.reset(); 115} 116 117} // namespace skgpu::mtl 118 119