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