1/* 2 * Copyright 2019 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 "include/core/SkRefCnt.h" 9#include "include/core/SkSurface.h" 10#include "include/gpu/GrBackendSurface.h" 11#include "include/gpu/mtl/GrMtlTypes.h" 12#include "src/gpu/GrProxyProvider.h" 13#include "src/gpu/GrRecordingContextPriv.h" 14#include "src/gpu/GrResourceProvider.h" 15#include "src/gpu/GrResourceProviderPriv.h" 16#include "src/gpu/v1/SurfaceDrawContext_v1.h" 17#include "src/image/SkSurface_Gpu.h" 18 19#if SK_SUPPORT_GPU 20 21#include "src/gpu/GrSurface.h" 22#include "src/gpu/mtl/GrMtlTextureRenderTarget.h" 23 24#ifdef SK_METAL 25#import <Metal/Metal.h> 26#import <QuartzCore/CAMetalLayer.h> 27#import <MetalKit/MetalKit.h> 28 29sk_sp<SkSurface> SkSurface::MakeFromCAMetalLayer(GrRecordingContext* rContext, 30 GrMTLHandle layer, 31 GrSurfaceOrigin origin, 32 int sampleCnt, 33 SkColorType colorType, 34 sk_sp<SkColorSpace> colorSpace, 35 const SkSurfaceProps* surfaceProps, 36 GrMTLHandle* drawable) { 37 GrProxyProvider* proxyProvider = rContext->priv().proxyProvider(); 38 39 CAMetalLayer* metalLayer = (__bridge CAMetalLayer*)layer; 40 GrBackendFormat backendFormat = GrBackendFormat::MakeMtl(metalLayer.pixelFormat); 41 42 GrColorType grColorType = SkColorTypeToGrColorType(colorType); 43 44 SkISize dims = {(int)metalLayer.drawableSize.width, (int)metalLayer.drawableSize.height}; 45 46 GrProxyProvider::TextureInfo texInfo; 47 texInfo.fMipmapped = GrMipmapped::kNo; 48 texInfo.fTextureType = GrTextureType::k2D; 49 50 sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy( 51 [layer, drawable](GrResourceProvider* resourceProvider, 52 const GrSurfaceProxy::LazySurfaceDesc& desc) { 53 CAMetalLayer* metalLayer = (__bridge CAMetalLayer*)layer; 54 id<CAMetalDrawable> currentDrawable = [metalLayer nextDrawable]; 55 56 GrMtlGpu* mtlGpu = (GrMtlGpu*) resourceProvider->priv().gpu(); 57 sk_sp<GrRenderTarget> surface; 58 if (metalLayer.framebufferOnly) { 59 surface = GrMtlRenderTarget::MakeWrappedRenderTarget( 60 mtlGpu, desc.fDimensions, desc.fSampleCnt, currentDrawable.texture); 61 } else { 62 surface = GrMtlTextureRenderTarget::MakeWrappedTextureRenderTarget( 63 mtlGpu, desc.fDimensions, desc.fSampleCnt, currentDrawable.texture, 64 GrWrapCacheable::kNo); 65 } 66 if (surface && desc.fSampleCnt > 1) { 67 surface->setRequiresManualMSAAResolve(); 68 } 69 70 *drawable = (__bridge_retained GrMTLHandle) currentDrawable; 71 return GrSurfaceProxy::LazyCallbackResult(std::move(surface)); 72 }, 73 backendFormat, 74 dims, 75 sampleCnt, 76 sampleCnt > 1 ? GrInternalSurfaceFlags::kRequiresManualMSAAResolve 77 : GrInternalSurfaceFlags::kNone, 78 metalLayer.framebufferOnly ? nullptr : &texInfo, 79 GrMipmapStatus::kNotAllocated, 80 SkBackingFit::kExact, 81 SkBudgeted::kYes, 82 GrProtected::kNo, 83 false, 84 GrSurfaceProxy::UseAllocator::kYes); 85 86 auto device = rContext->priv().createDevice(grColorType, 87 std::move(proxy), 88 std::move(colorSpace), 89 origin, 90 SkSurfacePropsCopyOrDefault(surfaceProps), 91 skgpu::BaseDevice::InitContents::kUninit); 92 if (!device) { 93 return nullptr; 94 } 95 96 return sk_make_sp<SkSurface_Gpu>(std::move(device)); 97} 98 99sk_sp<SkSurface> SkSurface::MakeFromMTKView(GrRecordingContext* rContext, 100 GrMTLHandle view, 101 GrSurfaceOrigin origin, 102 int sampleCnt, 103 SkColorType colorType, 104 sk_sp<SkColorSpace> colorSpace, 105 const SkSurfaceProps* surfaceProps) { 106 GrProxyProvider* proxyProvider = rContext->priv().proxyProvider(); 107 108 MTKView* mtkView = (__bridge MTKView*)view; 109 GrBackendFormat backendFormat = GrBackendFormat::MakeMtl(mtkView.colorPixelFormat); 110 111 GrColorType grColorType = SkColorTypeToGrColorType(colorType); 112 113 SkISize dims = {(int)mtkView.drawableSize.width, (int)mtkView.drawableSize.height}; 114 115 GrProxyProvider::TextureInfo texInfo; 116 texInfo.fMipmapped = GrMipmapped::kNo; 117 texInfo.fTextureType = GrTextureType::k2D; 118 119 sk_sp<GrRenderTargetProxy> proxy = proxyProvider->createLazyRenderTargetProxy( 120 [view](GrResourceProvider* resourceProvider, 121 const GrSurfaceProxy::LazySurfaceDesc& desc) { 122 MTKView* mtkView = (__bridge MTKView*)view; 123 id<CAMetalDrawable> currentDrawable = [mtkView currentDrawable]; 124 125 GrMtlGpu* mtlGpu = (GrMtlGpu*) resourceProvider->priv().gpu(); 126 sk_sp<GrRenderTarget> surface; 127 if (mtkView.framebufferOnly) { 128 surface = GrMtlRenderTarget::MakeWrappedRenderTarget( 129 mtlGpu, desc.fDimensions, desc.fSampleCnt, currentDrawable.texture); 130 } else { 131 surface = GrMtlTextureRenderTarget::MakeWrappedTextureRenderTarget( 132 mtlGpu, desc.fDimensions, desc.fSampleCnt, currentDrawable.texture, 133 GrWrapCacheable::kNo); 134 } 135 if (surface && desc.fSampleCnt > 1) { 136 surface->setRequiresManualMSAAResolve(); 137 } 138 139 return GrSurfaceProxy::LazyCallbackResult(std::move(surface)); 140 }, 141 backendFormat, 142 dims, 143 sampleCnt, 144 sampleCnt > 1 ? GrInternalSurfaceFlags::kRequiresManualMSAAResolve 145 : GrInternalSurfaceFlags::kNone, 146 mtkView.framebufferOnly ? nullptr : &texInfo, 147 GrMipmapStatus::kNotAllocated, 148 SkBackingFit::kExact, 149 SkBudgeted::kYes, 150 GrProtected::kNo, 151 false, 152 GrSurfaceProxy::UseAllocator::kYes); 153 154 155 auto device = rContext->priv().createDevice(grColorType, 156 std::move(proxy), 157 std::move(colorSpace), 158 origin, 159 SkSurfacePropsCopyOrDefault(surfaceProps), 160 skgpu::BaseDevice::InitContents::kUninit); 161 if (!device) { 162 return nullptr; 163 } 164 165 return sk_make_sp<SkSurface_Gpu>(std::move(device)); 166} 167 168#endif 169 170#endif 171