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/MtlGraphiteTypesPriv.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 MtlTextureSpec mtlSpec = TextureInfos::GetMtlTextureSpec(info); 31 SkASSERT(!mtlSpec.fFramebufferOnly); 32 33 if (mtlSpec.fUsage & MTLTextureUsageShaderRead && !caps->isTexturable(info)) { 34 return nullptr; 35 } 36 37 if (mtlSpec.fUsage & MTLTextureUsageRenderTarget && 38 !(caps->isRenderable(info) || MtlFormatIsDepthOrStencil(mtlSpec.fFormat))) { 39 return nullptr; 40 } 41 42 if (mtlSpec.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 = mtlSpec.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 = mtlSpec.fUsage; 61 (*desc).storageMode = mtlSpec.fStorageMode; 62 63 sk_cfp<id<MTLTexture>> texture([sharedContext->device() newTextureWithDescriptor:desc.get()]); 64 return texture; 65} 66 67MtlTexture::MtlTexture(const MtlSharedContext* sharedContext, 68 SkISize dimensions, 69 const TextureInfo& info, 70 sk_cfp<id<MTLTexture>> texture, 71 Ownership ownership, 72 skgpu::Budgeted budgeted) 73 : Texture(sharedContext, 74 dimensions, 75 info, 76 /*mutableState=*/nullptr, 77 ownership, 78 budgeted) 79 , fTexture(std::move(texture)) {} 80 81sk_sp<Texture> MtlTexture::Make(const MtlSharedContext* sharedContext, 82 SkISize dimensions, 83 const TextureInfo& info, 84 skgpu::Budgeted budgeted) { 85 sk_cfp<id<MTLTexture>> texture = MakeMtlTexture(sharedContext, dimensions, info); 86 if (!texture) { 87 return nullptr; 88 } 89 return sk_sp<Texture>(new MtlTexture(sharedContext, 90 dimensions, 91 info, 92 std::move(texture), 93 Ownership::kOwned, 94 budgeted)); 95} 96 97sk_sp<Texture> MtlTexture::MakeWrapped(const MtlSharedContext* sharedContext, 98 SkISize dimensions, 99 const TextureInfo& info, 100 sk_cfp<id<MTLTexture>> texture) { 101 return sk_sp<Texture>(new MtlTexture(sharedContext, 102 dimensions, 103 info, 104 std::move(texture), 105 Ownership::kWrapped, 106 skgpu::Budgeted::kNo)); 107} 108 109void MtlTexture::freeGpuData() { 110 fTexture.reset(); 111} 112 113 114void MtlTexture::setBackendLabel(char const* label) { 115 SkASSERT(label); 116#ifdef SK_ENABLE_MTL_DEBUG_INFO 117 NSString* labelStr = @(label); 118 this->mtlTexture().label = labelStr; 119#endif 120} 121 122} // namespace skgpu::graphite 123 124