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