1/* 2 * Copyright 2017 Google Inc. 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/ganesh/mtl/GrMtlTexture.h" 9 10#include "include/gpu/ganesh/mtl/GrMtlBackendSurface.h" 11#include "src/gpu/ganesh/GrTexture.h" 12#include "src/gpu/ganesh/mtl/GrMtlGpu.h" 13#include "src/gpu/mtl/MtlUtilsPriv.h" 14 15#if !__has_feature(objc_arc) 16#error This file must be compiled with Arc. Use -fobjc-arc flag 17#endif 18 19GR_NORETAIN_BEGIN 20 21GrMtlTexture::GrMtlTexture(GrMtlGpu* gpu, 22 skgpu::Budgeted budgeted, 23 SkISize dimensions, 24 sk_sp<GrMtlAttachment> texture, 25 GrMipmapStatus mipmapStatus, 26 std::string_view label) 27 : GrSurface(gpu, dimensions, GrProtected::kNo, label) 28 , INHERITED(gpu, dimensions, GrProtected::kNo, GrTextureType::k2D, mipmapStatus, label) 29 , fTexture(std::move(texture)) { 30 SkDEBUGCODE(id<MTLTexture> mtlTexture = fTexture->mtlTexture();) 31 SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == mtlTexture.mipmapLevelCount)); 32 if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) { 33 SkASSERT(SkToBool(mtlTexture.usage & MTLTextureUsageShaderRead)); 34 } 35 SkASSERT(!mtlTexture.framebufferOnly); 36 this->registerWithCache(budgeted); 37 if (skgpu::MtlFormatIsCompressed(fTexture->mtlFormat())) { 38 this->setReadOnly(); 39 } 40} 41 42GrMtlTexture::GrMtlTexture(GrMtlGpu* gpu, 43 Wrapped, 44 SkISize dimensions, 45 sk_sp<GrMtlAttachment> texture, 46 GrMipmapStatus mipmapStatus, 47 GrWrapCacheable cacheable, 48 GrIOType ioType, 49 std::string_view label) 50 : GrSurface(gpu, dimensions, GrProtected::kNo, label) 51 , INHERITED(gpu, dimensions, GrProtected::kNo, GrTextureType::k2D, mipmapStatus, label) 52 , fTexture(std::move(texture)) { 53 SkDEBUGCODE(id<MTLTexture> mtlTexture = fTexture->mtlTexture();) 54 SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == mtlTexture.mipmapLevelCount)); 55 if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) { 56 SkASSERT(SkToBool(mtlTexture.usage & MTLTextureUsageShaderRead)); 57 } 58 SkASSERT(!mtlTexture.framebufferOnly); 59 if (ioType == kRead_GrIOType) { 60 this->setReadOnly(); 61 } 62 this->registerWithCacheWrapped(cacheable); 63} 64 65GrMtlTexture::GrMtlTexture(GrMtlGpu* gpu, 66 SkISize dimensions, 67 sk_sp<GrMtlAttachment> texture, 68 GrMipmapStatus mipmapStatus, 69 std::string_view label) 70 : GrSurface(gpu, dimensions, GrProtected::kNo, label) 71 , INHERITED(gpu, dimensions, GrProtected::kNo, GrTextureType::k2D, mipmapStatus, label) 72 , fTexture(std::move(texture)) { 73 SkDEBUGCODE(id<MTLTexture> mtlTexture = fTexture->mtlTexture();) 74 SkASSERT((GrMipmapStatus::kNotAllocated == mipmapStatus) == (1 == mtlTexture.mipmapLevelCount)); 75 if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) { 76 SkASSERT(SkToBool(mtlTexture.usage & MTLTextureUsageShaderRead)); 77 } 78 SkASSERT(!mtlTexture.framebufferOnly); 79} 80 81sk_sp<GrMtlTexture> GrMtlTexture::MakeNewTexture(GrMtlGpu* gpu, 82 skgpu::Budgeted budgeted, 83 SkISize dimensions, 84 MTLPixelFormat format, 85 uint32_t mipLevels, 86 GrMipmapStatus mipmapStatus, 87 std::string_view label) { 88 sk_sp<GrMtlAttachment> texture = GrMtlAttachment::MakeTexture( 89 gpu, dimensions, format, mipLevels, GrRenderable::kNo, /*numSamples=*/1, budgeted); 90 91 if (!texture) { 92 return nullptr; 93 } 94 return sk_sp<GrMtlTexture>(new GrMtlTexture(gpu, budgeted, dimensions, std::move(texture), 95 mipmapStatus, label)); 96} 97 98sk_sp<GrMtlTexture> GrMtlTexture::MakeWrappedTexture(GrMtlGpu* gpu, 99 SkISize dimensions, 100 id<MTLTexture> texture, 101 GrWrapCacheable cacheable, 102 GrIOType ioType) { 103 SkASSERT(nil != texture); 104 if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) { 105 SkASSERT(SkToBool(texture.usage & MTLTextureUsageShaderRead)); 106 } 107 sk_sp<GrMtlAttachment> attachment = 108 GrMtlAttachment::MakeWrapped(gpu, dimensions, texture, 109 GrAttachment::UsageFlags::kTexture, cacheable, 110 /*label=*/"MtlAttachment_MakeWrapped"); 111 if (!attachment) { 112 return nullptr; 113 } 114 115 GrMipmapStatus mipmapStatus = texture.mipmapLevelCount > 1 ? GrMipmapStatus::kValid 116 : GrMipmapStatus::kNotAllocated; 117 return sk_sp<GrMtlTexture>( 118 new GrMtlTexture(gpu, kWrapped, dimensions, std::move(attachment), mipmapStatus, 119 cacheable, ioType, /*label=*/"MtlTextureWrappedTexture")); 120} 121 122GrMtlTexture::~GrMtlTexture() { 123 SkASSERT(nil == fTexture); 124} 125 126GrMtlGpu* GrMtlTexture::getMtlGpu() const { 127 SkASSERT(!this->wasDestroyed()); 128 return static_cast<GrMtlGpu*>(this->getGpu()); 129} 130 131GrBackendTexture GrMtlTexture::getBackendTexture() const { 132 skgpu::Mipmapped mipmapped = fTexture->mtlTexture().mipmapLevelCount > 1 133 ? skgpu::Mipmapped::kYes 134 : skgpu::Mipmapped::kNo; 135 GrMtlTextureInfo info; 136 info.fTexture.reset(GrRetainPtrFromId(fTexture->mtlTexture())); 137 return GrBackendTextures::MakeMtl(this->width(), this->height(), mipmapped, info); 138} 139 140GrBackendFormat GrMtlTexture::backendFormat() const { 141 return GrBackendFormats::MakeMtl(fTexture->mtlFormat()); 142} 143 144void GrMtlTexture::onSetLabel() { 145 SkASSERT(fTexture); 146 if (!this->getLabel().empty()) { 147 NSString* labelStr = @(this->getLabel().c_str()); 148 fTexture->mtlTexture().label = [@"_Skia_" stringByAppendingString:labelStr]; 149 } 150} 151 152GR_NORETAIN_END 153