1/* 2 * Copyright 2018 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/mtl/GrMtlGpu.h" 9#include "src/gpu/mtl/GrMtlTextureRenderTarget.h" 10#include "src/gpu/mtl/GrMtlUtil.h" 11 12#if !__has_feature(objc_arc) 13#error This file must be compiled with Arc. Use -fobjc-arc flag 14#endif 15 16GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu, 17 SkBudgeted budgeted, 18 const GrSurfaceDesc& desc, 19 int sampleCnt, 20 id<MTLTexture> colorTexture, 21 id<MTLTexture> resolveTexture, 22 GrMipMapsStatus mipMapsStatus) 23 : GrSurface(gpu, {desc.fWidth, desc.fHeight}, desc.fConfig, GrProtected::kNo) 24 , GrMtlTexture(gpu, desc, resolveTexture, mipMapsStatus) 25 , GrMtlRenderTarget(gpu, desc, sampleCnt, colorTexture, resolveTexture) { 26 this->registerWithCache(budgeted); 27} 28 29GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu, 30 SkBudgeted budgeted, 31 const GrSurfaceDesc& desc, 32 id<MTLTexture> colorTexture, 33 GrMipMapsStatus mipMapsStatus) 34 : GrSurface(gpu, {desc.fWidth, desc.fHeight}, desc.fConfig, GrProtected::kNo) 35 , GrMtlTexture(gpu, desc, colorTexture, mipMapsStatus) 36 , GrMtlRenderTarget(gpu, desc, colorTexture) { 37 this->registerWithCache(budgeted); 38} 39 40GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu, 41 const GrSurfaceDesc& desc, 42 int sampleCnt, 43 id<MTLTexture> colorTexture, 44 id<MTLTexture> resolveTexture, 45 GrMipMapsStatus mipMapsStatus, 46 GrWrapCacheable cacheable) 47 : GrSurface(gpu, {desc.fWidth, desc.fHeight}, desc.fConfig, GrProtected::kNo) 48 , GrMtlTexture(gpu, desc, resolveTexture, mipMapsStatus) 49 , GrMtlRenderTarget(gpu, desc, sampleCnt, colorTexture, resolveTexture) { 50 this->registerWithCacheWrapped(cacheable); 51} 52 53GrMtlTextureRenderTarget::GrMtlTextureRenderTarget(GrMtlGpu* gpu, 54 const GrSurfaceDesc& desc, 55 id<MTLTexture> colorTexture, 56 GrMipMapsStatus mipMapsStatus, 57 GrWrapCacheable cacheable) 58 : GrSurface(gpu, {desc.fWidth, desc.fHeight}, desc.fConfig, GrProtected::kNo) 59 , GrMtlTexture(gpu, desc, colorTexture, mipMapsStatus) 60 , GrMtlRenderTarget(gpu, desc, colorTexture) { 61 this->registerWithCacheWrapped(cacheable); 62} 63 64id<MTLTexture> create_msaa_texture(GrMtlGpu* gpu, const GrSurfaceDesc& desc, int sampleCnt) { 65 MTLPixelFormat format; 66 if (!GrPixelConfigToMTLFormat(desc.fConfig, &format)) { 67 return nullptr; 68 } 69 MTLTextureDescriptor* texDesc = [[MTLTextureDescriptor alloc] init]; 70 texDesc.textureType = MTLTextureType2DMultisample; 71 texDesc.pixelFormat = format; 72 texDesc.width = desc.fWidth; 73 texDesc.height = desc.fHeight; 74 texDesc.depth = 1; 75 texDesc.mipmapLevelCount = 1; 76 texDesc.sampleCount = sampleCnt; 77 texDesc.arrayLength = 1; 78 texDesc.storageMode = MTLStorageModePrivate; 79 texDesc.usage = MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget; 80 81 return [gpu->device() newTextureWithDescriptor:texDesc]; 82} 83 84sk_sp<GrMtlTextureRenderTarget> GrMtlTextureRenderTarget::MakeNewTextureRenderTarget( 85 GrMtlGpu* gpu, 86 SkBudgeted budgeted, 87 const GrSurfaceDesc& desc, 88 int sampleCnt, 89 MTLTextureDescriptor* texDesc, 90 GrMipMapsStatus mipMapsStatus) { 91 id<MTLTexture> texture = [gpu->device() newTextureWithDescriptor:texDesc]; 92 if (!texture) { 93 return nullptr; 94 } 95 SkASSERT((MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget) & texture.usage); 96 97 if (sampleCnt > 1) { 98 id<MTLTexture> colorTexture = create_msaa_texture(gpu, desc, sampleCnt); 99 if (!colorTexture) { 100 return nullptr; 101 } 102 SkASSERT((MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget) & colorTexture.usage); 103 return sk_sp<GrMtlTextureRenderTarget>(new GrMtlTextureRenderTarget( 104 gpu, budgeted, desc, sampleCnt, colorTexture, texture, mipMapsStatus)); 105 } else { 106 return sk_sp<GrMtlTextureRenderTarget>( 107 new GrMtlTextureRenderTarget(gpu, budgeted, desc, texture, mipMapsStatus)); 108 } 109} 110 111sk_sp<GrMtlTextureRenderTarget> GrMtlTextureRenderTarget::MakeWrappedTextureRenderTarget( 112 GrMtlGpu* gpu, 113 const GrSurfaceDesc& desc, 114 int sampleCnt, 115 id<MTLTexture> texture, 116 GrWrapCacheable cacheable) { 117 SkASSERT(nil != texture); 118 SkASSERT((MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget) & texture.usage); 119 GrMipMapsStatus mipMapsStatus = texture.mipmapLevelCount > 1 120 ? GrMipMapsStatus::kDirty 121 : GrMipMapsStatus::kNotAllocated; 122 if (sampleCnt > 1) { 123 id<MTLTexture> colorTexture = create_msaa_texture(gpu, desc, sampleCnt); 124 if (!colorTexture) { 125 return nullptr; 126 } 127 SkASSERT((MTLTextureUsageShaderRead | MTLTextureUsageRenderTarget) & colorTexture.usage); 128 return sk_sp<GrMtlTextureRenderTarget>(new GrMtlTextureRenderTarget( 129 gpu, desc, sampleCnt, colorTexture, texture, mipMapsStatus, cacheable)); 130 } else { 131 return sk_sp<GrMtlTextureRenderTarget>( 132 new GrMtlTextureRenderTarget(gpu, desc, texture, mipMapsStatus, cacheable)); 133 } 134} 135