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 "src/gpu/graphite/mtl/MtlTexture.h" 9 10#include "include/gpu/MutableTextureState.h" 11#include "include/gpu/graphite/TextureInfo.h" 12#include "include/gpu/graphite/mtl/MtlGraphiteTypes.h" 13#include "src/core/SkMipmap.h" 14#include "src/gpu/graphite/mtl/MtlCaps.h" 15#include "src/gpu/graphite/mtl/MtlGraphiteUtils.h" 16#include "src/gpu/graphite/mtl/MtlSharedContext.h" 17#include "src/gpu/mtl/MtlUtilsPriv.h" 18 19namespace skgpu::graphite { 20 21sk_cfp<id<MTLTexture>> MtlTexture::MakeMtlTexture(const MtlSharedContext* sharedContext, 22 SkISize dimensions, 23 const TextureInfo& info) { 24 const Caps* caps = sharedContext->caps(); 25 if (dimensions.width() > caps->maxTextureSize() || 26 dimensions.height() > caps->maxTextureSize()) { 27 return nullptr; 28 } 29 30 const auto& mtlInfo = TextureInfoPriv::Get<MtlTextureInfo>(info); 31 SkASSERT(!mtlInfo.fFramebufferOnly); 32 33 if (mtlInfo.fUsage & MTLTextureUsageShaderRead && !caps->isTexturable(info)) { 34 return nullptr; 35 } 36 37 if (mtlInfo.fUsage & MTLTextureUsageRenderTarget && 38 !(caps->isRenderable(info) || MtlFormatIsDepthOrStencil(mtlInfo.fFormat))) { 39 return nullptr; 40 } 41 42 if (mtlInfo.fUsage & MTLTextureUsageShaderWrite && !caps->isStorage(info)) { 43 return nullptr; 44 } 45 46 int numMipLevels = 1; 47 if (info.mipmapped() == Mipmapped::kYes) { 48 numMipLevels = SkMipmap::ComputeLevelCount(dimensions.width(), dimensions.height()) + 1; 49 } 50 51 sk_cfp<MTLTextureDescriptor*> desc([[MTLTextureDescriptor alloc] init]); 52 (*desc).textureType = (info.numSamples() > 1) ? MTLTextureType2DMultisample : MTLTextureType2D; 53 (*desc).pixelFormat = mtlInfo.fFormat; 54 (*desc).width = dimensions.width(); 55 (*desc).height = dimensions.height(); 56 (*desc).depth = 1; 57 (*desc).mipmapLevelCount = numMipLevels; 58 (*desc).sampleCount = info.numSamples(); 59 (*desc).arrayLength = 1; 60 (*desc).usage = mtlInfo.fUsage; 61 (*desc).storageMode = mtlInfo.fStorageMode; 62 63 sk_cfp<id<MTLTexture>> texture([sharedContext->device() newTextureWithDescriptor:desc.get()]); 64 return texture; 65} 66 67static bool has_transient_usage(const TextureInfo& info) { 68 if (@available(macOS 11.0, iOS 10.0, tvOS 10.0, *)) { 69 const auto& mtlInfo = TextureInfoPriv::Get<MtlTextureInfo>(info); 70 return mtlInfo.fStorageMode == MTLStorageModeMemoryless; 71 } 72 return false; 73} 74 75MtlTexture::MtlTexture(const MtlSharedContext* sharedContext, 76 SkISize dimensions, 77 const TextureInfo& info, 78 sk_cfp<id<MTLTexture>> texture, 79 Ownership ownership) 80 : Texture(sharedContext, 81 dimensions, 82 info, 83 has_transient_usage(info), 84 /*mutableState=*/nullptr, 85 ownership) 86 , fTexture(std::move(texture)) {} 87 88sk_sp<Texture> MtlTexture::Make(const MtlSharedContext* sharedContext, 89 SkISize dimensions, 90 const TextureInfo& info) { 91 sk_cfp<id<MTLTexture>> texture = MakeMtlTexture(sharedContext, dimensions, info); 92 if (!texture) { 93 return nullptr; 94 } 95 return sk_sp<Texture>(new MtlTexture(sharedContext, 96 dimensions, 97 info, 98 std::move(texture), 99 Ownership::kOwned)); 100} 101 102sk_sp<Texture> MtlTexture::MakeWrapped(const MtlSharedContext* sharedContext, 103 SkISize dimensions, 104 const TextureInfo& info, 105 sk_cfp<id<MTLTexture>> texture) { 106 return sk_sp<Texture>(new MtlTexture(sharedContext, 107 dimensions, 108 info, 109 std::move(texture), 110 Ownership::kWrapped)); 111} 112 113void MtlTexture::freeGpuData() { 114 fTexture.reset(); 115} 116 117 118void MtlTexture::setBackendLabel(char const* label) { 119 SkASSERT(label); 120#ifdef SK_ENABLE_MTL_DEBUG_INFO 121 NSString* labelStr = @(label); 122 this->mtlTexture().label = labelStr; 123#endif 124} 125 126} // namespace skgpu::graphite 127