• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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