• 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 "include/gpu/graphite/BackendTexture.h"
10#include "include/gpu/graphite/Context.h"
11#include "include/gpu/graphite/ContextOptions.h"
12#include "include/gpu/graphite/Recorder.h"
13#include "include/gpu/graphite/Recording.h"
14#include "include/gpu/graphite/Surface.h"
15#include "include/gpu/graphite/mtl/MtlBackendContext.h"
16#include "include/gpu/graphite/mtl/MtlGraphiteTypes.h"
17#include "include/gpu/graphite/mtl/MtlGraphiteUtils.h"
18#include "include/private/gpu/graphite/ContextOptionsPriv.h"
19#include "src/base/SkMathPriv.h"
20#include "tools/GpuToolUtils.h"
21#include "tools/window/GraphiteMetalWindowContext.h"
22
23using skwindow::DisplayParams;
24using skwindow::internal::GraphiteMetalWindowContext;
25
26namespace skwindow::internal {
27
28GraphiteMetalWindowContext::GraphiteMetalWindowContext(const DisplayParams& params)
29        : WindowContext(params)
30        , fValid(false)
31        , fDrawableHandle(nil) {
32    fDisplayParams.fMSAASampleCount = GrNextPow2(fDisplayParams.fMSAASampleCount);
33}
34
35void GraphiteMetalWindowContext::initializeContext() {
36    SkASSERT(!fContext);
37    SkASSERT(!fGraphiteContext);
38
39    fDevice.reset(MTLCreateSystemDefaultDevice());
40    fQueue.reset([*fDevice newCommandQueue]);
41
42    if (fDisplayParams.fMSAASampleCount > 1) {
43        if (@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)) {
44            if (![*fDevice supportsTextureSampleCount:fDisplayParams.fMSAASampleCount]) {
45                return;
46            }
47        } else {
48            return;
49        }
50    }
51    fSampleCount = fDisplayParams.fMSAASampleCount;
52    fStencilBits = 8;
53
54    fValid = this->onInitializeContext();
55
56    skgpu::graphite::MtlBackendContext backendContext = {};
57    backendContext.fDevice.retain((CFTypeRef)fDevice.get());
58    backendContext.fQueue.retain((CFTypeRef)fQueue.get());
59
60    fDisplayParams.fGraphiteContextOptions.fOptions.fDisableCachedGlyphUploads = true;
61    // Needed to make synchronous readPixels work:
62    fDisplayParams.fGraphiteContextOptions.fPriv.fStoreContextRefInRecorder = true;
63    fGraphiteContext = skgpu::graphite::ContextFactory::MakeMetal(
64            backendContext, fDisplayParams.fGraphiteContextOptions.fOptions);
65    fGraphiteRecorder = fGraphiteContext->makeRecorder(ToolUtils::CreateTestingRecorderOptions());
66    // TODO
67//    if (!fGraphiteContext && fDisplayParams.fMSAASampleCount > 1) {
68//        fDisplayParams.fMSAASampleCount /= 2;
69//        this->initializeContext();
70//        return;
71//    }
72}
73
74void GraphiteMetalWindowContext::destroyContext() {
75    if (fGraphiteContext) {
76        fGraphiteRecorder.reset();
77        fGraphiteContext.reset();
78    }
79
80    this->onDestroyContext();
81
82    fMetalLayer = nil;
83    fValid = false;
84
85    fQueue.reset();
86    fDevice.reset();
87}
88
89sk_sp<SkSurface> GraphiteMetalWindowContext::getBackbufferSurface() {
90    sk_sp<SkSurface> surface;
91    id<CAMetalDrawable> currentDrawable = [fMetalLayer nextDrawable];
92    if (currentDrawable == nil) {
93        return nullptr;
94    }
95
96    skgpu::graphite::BackendTexture backendTex(this->dimensions(),
97                                               (CFTypeRef)currentDrawable.texture);
98
99    surface = SkSurfaces::WrapBackendTexture(this->graphiteRecorder(),
100                                             backendTex,
101                                             kBGRA_8888_SkColorType,
102                                             fDisplayParams.fColorSpace,
103                                             &fDisplayParams.fSurfaceProps);
104    fDrawableHandle = CFRetain((CFTypeRef) currentDrawable);
105
106    return surface;
107}
108
109void GraphiteMetalWindowContext::onSwapBuffers() {
110    this->snapRecordingAndSubmit();
111
112    id<CAMetalDrawable> currentDrawable = (id<CAMetalDrawable>)fDrawableHandle;
113
114    id<MTLCommandBuffer> commandBuffer([*fQueue commandBuffer]);
115    commandBuffer.label = @"Present";
116
117    [commandBuffer presentDrawable:currentDrawable];
118    [commandBuffer commit];
119    // ARC is off in sk_app, so we need to release the CF ref manually
120    CFRelease(fDrawableHandle);
121    fDrawableHandle = nil;
122}
123
124void GraphiteMetalWindowContext::setDisplayParams(const DisplayParams& params) {
125    this->destroyContext();
126    fDisplayParams = params;
127    this->initializeContext();
128}
129
130void GraphiteMetalWindowContext::activate(bool isActive) {}
131
132}   //namespace skwindow::internal
133