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