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