1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2021 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/SkSurface.h"
9cb93a386Sopenharmony_ci#include "src/core/SkMathPriv.h"
10cb93a386Sopenharmony_ci#include "tools/sk_app/GraphiteMetalWindowContext.h"
11cb93a386Sopenharmony_ci
12cb93a386Sopenharmony_ci#include "experimental/graphite/include/Context.h"
13cb93a386Sopenharmony_ci#include "experimental/graphite/include/mtl/MtlBackendContext.h"
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_ciusing sk_app::DisplayParams;
16cb93a386Sopenharmony_ciusing sk_app::GraphiteMetalWindowContext;
17cb93a386Sopenharmony_ci
18cb93a386Sopenharmony_cinamespace sk_app {
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_ciGraphiteMetalWindowContext::GraphiteMetalWindowContext(const DisplayParams& params)
21cb93a386Sopenharmony_ci        : WindowContext(params)
22cb93a386Sopenharmony_ci        , fValid(false)
23cb93a386Sopenharmony_ci        , fDrawableHandle(nil) {
24cb93a386Sopenharmony_ci    fDisplayParams.fMSAASampleCount = GrNextPow2(fDisplayParams.fMSAASampleCount);
25cb93a386Sopenharmony_ci}
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_civoid GraphiteMetalWindowContext::initializeContext() {
28cb93a386Sopenharmony_ci    SkASSERT(!fContext);
29cb93a386Sopenharmony_ci    SkASSERT(!fGraphiteContext);
30cb93a386Sopenharmony_ci
31cb93a386Sopenharmony_ci    fDevice.reset(MTLCreateSystemDefaultDevice());
32cb93a386Sopenharmony_ci    fQueue.reset([*fDevice newCommandQueue]);
33cb93a386Sopenharmony_ci
34cb93a386Sopenharmony_ci    if (fDisplayParams.fMSAASampleCount > 1) {
35cb93a386Sopenharmony_ci        if (@available(macOS 10.11, iOS 9.0, *)) {
36cb93a386Sopenharmony_ci            if (![*fDevice supportsTextureSampleCount:fDisplayParams.fMSAASampleCount]) {
37cb93a386Sopenharmony_ci                return;
38cb93a386Sopenharmony_ci            }
39cb93a386Sopenharmony_ci        } else {
40cb93a386Sopenharmony_ci            return;
41cb93a386Sopenharmony_ci        }
42cb93a386Sopenharmony_ci    }
43cb93a386Sopenharmony_ci    fSampleCount = fDisplayParams.fMSAASampleCount;
44cb93a386Sopenharmony_ci    fStencilBits = 8;
45cb93a386Sopenharmony_ci
46cb93a386Sopenharmony_ci    fValid = this->onInitializeContext();
47cb93a386Sopenharmony_ci
48cb93a386Sopenharmony_ci    skgpu::mtl::BackendContext backendContext = {};
49cb93a386Sopenharmony_ci    backendContext.fDevice.retain((GrMTLHandle)fDevice.get());
50cb93a386Sopenharmony_ci    backendContext.fQueue.retain((GrMTLHandle)fQueue.get());
51cb93a386Sopenharmony_ci    fGraphiteContext = skgpu::Context::MakeMetal(backendContext);
52cb93a386Sopenharmony_ci    // TODO
53cb93a386Sopenharmony_ci//    if (!fGraphiteContext && fDisplayParams.fMSAASampleCount > 1) {
54cb93a386Sopenharmony_ci//        fDisplayParams.fMSAASampleCount /= 2;
55cb93a386Sopenharmony_ci//        this->initializeContext();
56cb93a386Sopenharmony_ci//        return;
57cb93a386Sopenharmony_ci//    }
58cb93a386Sopenharmony_ci}
59cb93a386Sopenharmony_ci
60cb93a386Sopenharmony_civoid GraphiteMetalWindowContext::destroyContext() {
61cb93a386Sopenharmony_ci    if (fGraphiteContext) {
62cb93a386Sopenharmony_ci        // TODO?
63cb93a386Sopenharmony_ci        // in case we have outstanding refs to this (lua?)
64cb93a386Sopenharmony_ci        // fGraphiteContext->abandonContext();
65cb93a386Sopenharmony_ci        fGraphiteContext.reset();
66cb93a386Sopenharmony_ci    }
67cb93a386Sopenharmony_ci
68cb93a386Sopenharmony_ci    this->onDestroyContext();
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    fMetalLayer = nil;
71cb93a386Sopenharmony_ci    fValid = false;
72cb93a386Sopenharmony_ci
73cb93a386Sopenharmony_ci#if GR_METAL_SDK_VERSION >= 230
74cb93a386Sopenharmony_ci    if (@available(macOS 11.0, iOS 14.0, *)) {
75cb93a386Sopenharmony_ci        [fPipelineArchive release];
76cb93a386Sopenharmony_ci    }
77cb93a386Sopenharmony_ci#endif
78cb93a386Sopenharmony_ci    fQueue.reset();
79cb93a386Sopenharmony_ci    fDevice.reset();
80cb93a386Sopenharmony_ci}
81cb93a386Sopenharmony_ci
82cb93a386Sopenharmony_cisk_sp<SkSurface> GraphiteMetalWindowContext::getBackbufferSurface() {
83cb93a386Sopenharmony_ci    sk_sp<SkSurface> surface;
84cb93a386Sopenharmony_ci    id<CAMetalDrawable> currentDrawable = [fMetalLayer nextDrawable];
85cb93a386Sopenharmony_ci
86cb93a386Sopenharmony_ci    // TODO
87cb93a386Sopenharmony_ci//    GrMtlTextureInfo fbInfo;
88cb93a386Sopenharmony_ci//    fbInfo.fTexture.retain(currentDrawable.texture);
89cb93a386Sopenharmony_ci//
90cb93a386Sopenharmony_ci//    GrBackendRenderTarget backendRT(fWidth,
91cb93a386Sopenharmony_ci//                                    fHeight,
92cb93a386Sopenharmony_ci//                                    fSampleCount,
93cb93a386Sopenharmony_ci//                                    fbInfo);
94cb93a386Sopenharmony_ci//
95cb93a386Sopenharmony_ci//    surface = SkSurface::MakeFromBackendRenderTarget(fContext.get(), backendRT,
96cb93a386Sopenharmony_ci//                                                     kTopLeft_GrSurfaceOrigin,
97cb93a386Sopenharmony_ci//                                                     kBGRA_8888_SkColorType,
98cb93a386Sopenharmony_ci//                                                     fDisplayParams.fColorSpace,
99cb93a386Sopenharmony_ci//                                                     &fDisplayParams.fSurfaceProps);
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci    fDrawableHandle = CFRetain((GrMTLHandle) currentDrawable);
102cb93a386Sopenharmony_ci
103cb93a386Sopenharmony_ci    return surface;
104cb93a386Sopenharmony_ci}
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_civoid GraphiteMetalWindowContext::swapBuffers() {
107cb93a386Sopenharmony_ci    id<CAMetalDrawable> currentDrawable = (id<CAMetalDrawable>)fDrawableHandle;
108cb93a386Sopenharmony_ci
109cb93a386Sopenharmony_ci    id<MTLCommandBuffer> commandBuffer([*fQueue commandBuffer]);
110cb93a386Sopenharmony_ci    commandBuffer.label = @"Present";
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_ci    [commandBuffer presentDrawable:currentDrawable];
113cb93a386Sopenharmony_ci    [commandBuffer commit];
114cb93a386Sopenharmony_ci    // ARC is off in sk_app, so we need to release the CF ref manually
115cb93a386Sopenharmony_ci    CFRelease(fDrawableHandle);
116cb93a386Sopenharmony_ci    fDrawableHandle = nil;
117cb93a386Sopenharmony_ci}
118cb93a386Sopenharmony_ci
119cb93a386Sopenharmony_civoid GraphiteMetalWindowContext::setDisplayParams(const DisplayParams& params) {
120cb93a386Sopenharmony_ci    this->destroyContext();
121cb93a386Sopenharmony_ci    fDisplayParams = params;
122cb93a386Sopenharmony_ci    this->initializeContext();
123cb93a386Sopenharmony_ci}
124cb93a386Sopenharmony_ci
125cb93a386Sopenharmony_civoid GraphiteMetalWindowContext::activate(bool isActive) {}
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_ci}   //namespace sk_app
128