1cb93a386Sopenharmony_ci
2cb93a386Sopenharmony_ci/*
3cb93a386Sopenharmony_ci * Copyright 2019 Google Inc.
4cb93a386Sopenharmony_ci *
5cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
6cb93a386Sopenharmony_ci * found in the LICENSE file.
7cb93a386Sopenharmony_ci */
8cb93a386Sopenharmony_ci
9cb93a386Sopenharmony_ci#include "include/gpu/gl/GrGLInterface.h"
10cb93a386Sopenharmony_ci#include "tools/sk_app/GLWindowContext.h"
11cb93a386Sopenharmony_ci#include "tools/sk_app/mac/WindowContextFactory_mac.h"
12cb93a386Sopenharmony_ci
13cb93a386Sopenharmony_ci#include <OpenGL/gl.h>
14cb93a386Sopenharmony_ci#include <Cocoa/Cocoa.h>
15cb93a386Sopenharmony_ci
16cb93a386Sopenharmony_ciusing sk_app::DisplayParams;
17cb93a386Sopenharmony_ciusing sk_app::window_context_factory::MacWindowInfo;
18cb93a386Sopenharmony_ciusing sk_app::GLWindowContext;
19cb93a386Sopenharmony_ci
20cb93a386Sopenharmony_cinamespace {
21cb93a386Sopenharmony_ci
22cb93a386Sopenharmony_ciclass GLWindowContext_mac : public GLWindowContext {
23cb93a386Sopenharmony_cipublic:
24cb93a386Sopenharmony_ci    GLWindowContext_mac(const MacWindowInfo&, const DisplayParams&);
25cb93a386Sopenharmony_ci
26cb93a386Sopenharmony_ci    ~GLWindowContext_mac() override;
27cb93a386Sopenharmony_ci
28cb93a386Sopenharmony_ci    void onSwapBuffers() override;
29cb93a386Sopenharmony_ci
30cb93a386Sopenharmony_ci    sk_sp<const GrGLInterface> onInitializeContext() override;
31cb93a386Sopenharmony_ci    void onDestroyContext() override;
32cb93a386Sopenharmony_ci
33cb93a386Sopenharmony_ci    void resize(int w, int h) override;
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ciprivate:
36cb93a386Sopenharmony_ci    void teardownContext();
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_ci    NSView*              fMainView;
39cb93a386Sopenharmony_ci    NSOpenGLContext*     fGLContext;
40cb93a386Sopenharmony_ci    NSOpenGLPixelFormat* fPixelFormat;
41cb93a386Sopenharmony_ci
42cb93a386Sopenharmony_ci    using INHERITED = GLWindowContext;
43cb93a386Sopenharmony_ci};
44cb93a386Sopenharmony_ci
45cb93a386Sopenharmony_ciGLWindowContext_mac::GLWindowContext_mac(const MacWindowInfo& info, const DisplayParams& params)
46cb93a386Sopenharmony_ci    : INHERITED(params)
47cb93a386Sopenharmony_ci    , fMainView(info.fMainView)
48cb93a386Sopenharmony_ci    , fGLContext(nil) {
49cb93a386Sopenharmony_ci
50cb93a386Sopenharmony_ci    // any config code here (particularly for msaa)?
51cb93a386Sopenharmony_ci
52cb93a386Sopenharmony_ci    this->initializeContext();
53cb93a386Sopenharmony_ci}
54cb93a386Sopenharmony_ci
55cb93a386Sopenharmony_ciGLWindowContext_mac::~GLWindowContext_mac() {
56cb93a386Sopenharmony_ci    teardownContext();
57cb93a386Sopenharmony_ci}
58cb93a386Sopenharmony_ci
59cb93a386Sopenharmony_civoid GLWindowContext_mac::teardownContext() {
60cb93a386Sopenharmony_ci    [NSOpenGLContext clearCurrentContext];
61cb93a386Sopenharmony_ci    [fPixelFormat release];
62cb93a386Sopenharmony_ci    fPixelFormat = nil;
63cb93a386Sopenharmony_ci    [fGLContext release];
64cb93a386Sopenharmony_ci    fGLContext = nil;
65cb93a386Sopenharmony_ci}
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_cisk_sp<const GrGLInterface> GLWindowContext_mac::onInitializeContext() {
68cb93a386Sopenharmony_ci    SkASSERT(nil != fMainView);
69cb93a386Sopenharmony_ci
70cb93a386Sopenharmony_ci    if (!fGLContext) {
71cb93a386Sopenharmony_ci        // set up pixel format
72cb93a386Sopenharmony_ci        constexpr int kMaxAttributes = 19;
73cb93a386Sopenharmony_ci        NSOpenGLPixelFormatAttribute attributes[kMaxAttributes];
74cb93a386Sopenharmony_ci        int numAttributes = 0;
75cb93a386Sopenharmony_ci        attributes[numAttributes++] = NSOpenGLPFAAccelerated;
76cb93a386Sopenharmony_ci        attributes[numAttributes++] = NSOpenGLPFAClosestPolicy;
77cb93a386Sopenharmony_ci        attributes[numAttributes++] = NSOpenGLPFADoubleBuffer;
78cb93a386Sopenharmony_ci        attributes[numAttributes++] = NSOpenGLPFAOpenGLProfile;
79cb93a386Sopenharmony_ci        attributes[numAttributes++] = NSOpenGLProfileVersion3_2Core;
80cb93a386Sopenharmony_ci        attributes[numAttributes++] = NSOpenGLPFAColorSize;
81cb93a386Sopenharmony_ci        attributes[numAttributes++] = 24;
82cb93a386Sopenharmony_ci        attributes[numAttributes++] = NSOpenGLPFAAlphaSize;
83cb93a386Sopenharmony_ci        attributes[numAttributes++] = 8;
84cb93a386Sopenharmony_ci        attributes[numAttributes++] = NSOpenGLPFADepthSize;
85cb93a386Sopenharmony_ci        attributes[numAttributes++] = 0;
86cb93a386Sopenharmony_ci        attributes[numAttributes++] = NSOpenGLPFAStencilSize;
87cb93a386Sopenharmony_ci        attributes[numAttributes++] = 8;
88cb93a386Sopenharmony_ci        if (fDisplayParams.fMSAASampleCount > 1) {
89cb93a386Sopenharmony_ci            attributes[numAttributes++] = NSOpenGLPFAMultisample;
90cb93a386Sopenharmony_ci            attributes[numAttributes++] = NSOpenGLPFASampleBuffers;
91cb93a386Sopenharmony_ci            attributes[numAttributes++] = 1;
92cb93a386Sopenharmony_ci            attributes[numAttributes++] = NSOpenGLPFASamples;
93cb93a386Sopenharmony_ci            attributes[numAttributes++] = fDisplayParams.fMSAASampleCount;
94cb93a386Sopenharmony_ci        } else {
95cb93a386Sopenharmony_ci            attributes[numAttributes++] = NSOpenGLPFASampleBuffers;
96cb93a386Sopenharmony_ci            attributes[numAttributes++] = 0;
97cb93a386Sopenharmony_ci        }
98cb93a386Sopenharmony_ci        attributes[numAttributes++] = 0;
99cb93a386Sopenharmony_ci        SkASSERT(numAttributes <= kMaxAttributes);
100cb93a386Sopenharmony_ci
101cb93a386Sopenharmony_ci        fPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
102cb93a386Sopenharmony_ci        if (nil == fPixelFormat) {
103cb93a386Sopenharmony_ci            return nullptr;
104cb93a386Sopenharmony_ci        }
105cb93a386Sopenharmony_ci
106cb93a386Sopenharmony_ci        // create context
107cb93a386Sopenharmony_ci        fGLContext = [[NSOpenGLContext alloc] initWithFormat:fPixelFormat shareContext:nil];
108cb93a386Sopenharmony_ci        if (nil == fGLContext) {
109cb93a386Sopenharmony_ci            [fPixelFormat release];
110cb93a386Sopenharmony_ci            fPixelFormat = nil;
111cb93a386Sopenharmony_ci            return nullptr;
112cb93a386Sopenharmony_ci        }
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_ci        [fMainView setWantsBestResolutionOpenGLSurface:YES];
115cb93a386Sopenharmony_ci        [fGLContext setView:fMainView];
116cb93a386Sopenharmony_ci    }
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci    GLint swapInterval = fDisplayParams.fDisableVsync ? 0 : 1;
119cb93a386Sopenharmony_ci    [fGLContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval];
120cb93a386Sopenharmony_ci
121cb93a386Sopenharmony_ci    // make context current
122cb93a386Sopenharmony_ci    [fGLContext makeCurrentContext];
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci    glClearStencil(0);
125cb93a386Sopenharmony_ci    glClearColor(0, 0, 0, 255);
126cb93a386Sopenharmony_ci    glStencilMask(0xffffffff);
127cb93a386Sopenharmony_ci    glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
128cb93a386Sopenharmony_ci
129cb93a386Sopenharmony_ci    GLint stencilBits;
130cb93a386Sopenharmony_ci    [fPixelFormat getValues:&stencilBits forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:0];
131cb93a386Sopenharmony_ci    fStencilBits = stencilBits;
132cb93a386Sopenharmony_ci    GLint sampleCount;
133cb93a386Sopenharmony_ci    [fPixelFormat getValues:&sampleCount forAttribute:NSOpenGLPFASamples forVirtualScreen:0];
134cb93a386Sopenharmony_ci    fSampleCount = sampleCount;
135cb93a386Sopenharmony_ci    fSampleCount = std::max(fSampleCount, 1);
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ci    CGFloat backingScaleFactor = sk_app::GetBackingScaleFactor(fMainView);
138cb93a386Sopenharmony_ci    fWidth = fMainView.bounds.size.width * backingScaleFactor;
139cb93a386Sopenharmony_ci    fHeight = fMainView.bounds.size.height * backingScaleFactor;
140cb93a386Sopenharmony_ci    glViewport(0, 0, fWidth, fHeight);
141cb93a386Sopenharmony_ci
142cb93a386Sopenharmony_ci    return GrGLMakeNativeInterface();
143cb93a386Sopenharmony_ci}
144cb93a386Sopenharmony_ci
145cb93a386Sopenharmony_civoid GLWindowContext_mac::onDestroyContext() {
146cb93a386Sopenharmony_ci    // We only need to tear down the GLContext if we've changed the sample count.
147cb93a386Sopenharmony_ci    if (fGLContext && fSampleCount != fDisplayParams.fMSAASampleCount) {
148cb93a386Sopenharmony_ci        teardownContext();
149cb93a386Sopenharmony_ci    }
150cb93a386Sopenharmony_ci}
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_civoid GLWindowContext_mac::onSwapBuffers() {
153cb93a386Sopenharmony_ci    [fGLContext flushBuffer];
154cb93a386Sopenharmony_ci}
155cb93a386Sopenharmony_ci
156cb93a386Sopenharmony_civoid GLWindowContext_mac::resize(int w, int h) {
157cb93a386Sopenharmony_ci    [fGLContext update];
158cb93a386Sopenharmony_ci
159cb93a386Sopenharmony_ci    // The super class always recreates the context.
160cb93a386Sopenharmony_ci    INHERITED::resize(0, 0);
161cb93a386Sopenharmony_ci}
162cb93a386Sopenharmony_ci
163cb93a386Sopenharmony_ci
164cb93a386Sopenharmony_ci}  // anonymous namespace
165cb93a386Sopenharmony_ci
166cb93a386Sopenharmony_cinamespace sk_app {
167cb93a386Sopenharmony_cinamespace window_context_factory {
168cb93a386Sopenharmony_ci
169cb93a386Sopenharmony_cistd::unique_ptr<WindowContext> MakeGLForMac(const MacWindowInfo& info,
170cb93a386Sopenharmony_ci                                            const DisplayParams& params) {
171cb93a386Sopenharmony_ci    std::unique_ptr<WindowContext> ctx(new GLWindowContext_mac(info, params));
172cb93a386Sopenharmony_ci    if (!ctx->isValid()) {
173cb93a386Sopenharmony_ci        return nullptr;
174cb93a386Sopenharmony_ci    }
175cb93a386Sopenharmony_ci    return ctx;
176cb93a386Sopenharmony_ci}
177cb93a386Sopenharmony_ci
178cb93a386Sopenharmony_ci}  // namespace window_context_factory
179cb93a386Sopenharmony_ci}  // namespace sk_app
180