blob: a90b4be927e5ee3cc3ebbd84febb515733054e0c [file] [log] [blame]
Jim Van Verthbe39f712019-02-08 15:36:14 -05001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkCanvas.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/core/SkMathPriv.h"
14#include "src/gpu/GrCaps.h"
15#include "src/gpu/GrContextPriv.h"
16#include "src/image/SkImage_Base.h"
17#include "tools/sk_app/MetalWindowContext.h"
Jim Van Verthbe39f712019-02-08 15:36:14 -050018
Jim Van Verthd063e8b2019-05-16 10:31:56 -040019using sk_app::DisplayParams;
20using sk_app::MetalWindowContext;
Jim Van Verthbe39f712019-02-08 15:36:14 -050021
Jim Van Verthd063e8b2019-05-16 10:31:56 -040022#ifdef SK_BUILD_FOR_MAC
23#import <QuartzCore/CAConstraintLayoutManager.h>
24#endif
25
26namespace sk_app {
Jim Van Verthbe39f712019-02-08 15:36:14 -050027
28MetalWindowContext::MetalWindowContext(const DisplayParams& params)
29 : WindowContext(params)
Jim Van Verthd063e8b2019-05-16 10:31:56 -040030 , fValid(false) {
31
Jim Van Verthbe39f712019-02-08 15:36:14 -050032 fDisplayParams.fMSAASampleCount = GrNextPow2(fDisplayParams.fMSAASampleCount);
33}
34
35void MetalWindowContext::initializeContext() {
36 SkASSERT(!fContext);
37
Jim Van Verthbe39f712019-02-08 15:36:14 -050038 fDevice = MTLCreateSystemDefaultDevice();
39 fQueue = [fDevice newCommandQueue];
40
Jim Van Verthd063e8b2019-05-16 10:31:56 -040041 if (fDisplayParams.fMSAASampleCount > 1) {
42 if (![fDevice supportsTextureSampleCount:fDisplayParams.fMSAASampleCount]) {
43 return;
44 }
45 }
46 // TODO: Multisampling not supported
47 fSampleCount = 1; //fDisplayParams.fMSAASampleCount;
48 fStencilBits = 8;
49
50 fMetalLayer = [CAMetalLayer layer];
51 fMetalLayer.device = fDevice;
52 fMetalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm;
53#ifdef SK_BUILD_FOR_MAC
54 BOOL useVsync = fDisplayParams.fDisableVsync ? NO : YES;
55 fMetalLayer.displaySyncEnabled = useVsync; // TODO: need solution for 10.12 or lower
56 fMetalLayer.layoutManager = [CAConstraintLayoutManager layoutManager];
57 fMetalLayer.autoresizingMask = kCALayerHeightSizable | kCALayerWidthSizable;
58 fMetalLayer.contentsGravity = kCAGravityTopLeft;
59#endif
Jim Van Verthbe39f712019-02-08 15:36:14 -050060
61 fValid = this->onInitializeContext();
Jim Van Verthd063e8b2019-05-16 10:31:56 -040062
Jim Van Verthbe39f712019-02-08 15:36:14 -050063 fContext = GrContext::MakeMetal(fDevice, fQueue, fDisplayParams.fGrContextOptions);
64 if (!fContext && fDisplayParams.fMSAASampleCount > 1) {
65 fDisplayParams.fMSAASampleCount /= 2;
66 this->initializeContext();
67 return;
68 }
69}
70
71void MetalWindowContext::destroyContext() {
Jim Van Verthbe39f712019-02-08 15:36:14 -050072 if (fContext) {
73 // in case we have outstanding refs to this guy (lua?)
74 fContext->abandonContext();
75 fContext.reset();
76 }
77
Jim Van Verthbe39f712019-02-08 15:36:14 -050078 this->onDestroyContext();
Jim Van Verthd063e8b2019-05-16 10:31:56 -040079
80 fMetalLayer = nil;
81 fValid = false;
82
83 // TODO: figure out why we can't release these
84 // [fQueue release];
85 // [fDevice release];
Jim Van Verthbe39f712019-02-08 15:36:14 -050086}
87
88sk_sp<SkSurface> MetalWindowContext::getBackbufferSurface() {
89 sk_sp<SkSurface> surface;
90 if (fContext) {
Jim Van Verth7a7a97d2019-04-17 09:44:32 -040091 // TODO: Apple recommends grabbing the drawable (which we're implicitly doing here)
92 // for as little time as possible. I'm not sure it matters for our test apps, but
93 // you can get better throughput by doing any offscreen renders, texture uploads, or
94 // other non-dependant tasks first before grabbing the drawable.
Jim Van Verthd063e8b2019-05-16 10:31:56 -040095 fCurrentDrawable = [fMetalLayer nextDrawable];
96
Jim Van Verthbe39f712019-02-08 15:36:14 -050097 GrMtlTextureInfo fbInfo;
Jim Van Verthd063e8b2019-05-16 10:31:56 -040098 fbInfo.fTexture = fCurrentDrawable.texture;
Jim Van Verthbe39f712019-02-08 15:36:14 -050099
100 GrBackendRenderTarget backendRT(fWidth,
101 fHeight,
102 fSampleCount,
103 fbInfo);
104
105 surface = SkSurface::MakeFromBackendRenderTarget(fContext.get(), backendRT,
Jim Van Verthd063e8b2019-05-16 10:31:56 -0400106 kTopLeft_GrSurfaceOrigin,
107 kBGRA_8888_SkColorType,
108 fDisplayParams.fColorSpace,
109 &fDisplayParams.fSurfaceProps);
Jim Van Verthbe39f712019-02-08 15:36:14 -0500110 }
111
112 return surface;
113}
114
115void MetalWindowContext::swapBuffers() {
Jim Van Verthbe39f712019-02-08 15:36:14 -0500116 id<MTLCommandBuffer> commandBuffer = [fQueue commandBuffer];
117 commandBuffer.label = @"Present";
118
Jim Van Verthd063e8b2019-05-16 10:31:56 -0400119 [commandBuffer presentDrawable:fCurrentDrawable];
Jim Van Verthbe39f712019-02-08 15:36:14 -0500120 [commandBuffer commit];
Jim Van Verthd063e8b2019-05-16 10:31:56 -0400121 fCurrentDrawable = nil;
Jim Van Verthbe39f712019-02-08 15:36:14 -0500122}
123
124void MetalWindowContext::setDisplayParams(const DisplayParams& params) {
125 this->destroyContext();
126 fDisplayParams = params;
127 this->initializeContext();
128}
129
130} //namespace sk_app