1/* 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 8#include "tools/window/mac/GaneshGLWindowContext_mac.h" 9 10#include "include/gpu/ganesh/gl/mac/GrGLMakeMacInterface.h" 11#include "include/gpu/ganesh/gl/GrGLInterface.h" 12#include "tools/window/GLWindowContext.h" 13#include "tools/window/mac/MacWindowGLUtils.h" 14#include "tools/window/mac/MacWindowInfo.h" 15 16#include <Cocoa/Cocoa.h> 17#include <OpenGL/gl.h> 18 19using skwindow::DisplayParams; 20using skwindow::MacWindowInfo; 21using skwindow::internal::GLWindowContext; 22 23namespace { 24 25class GLWindowContext_mac : public GLWindowContext { 26public: 27 GLWindowContext_mac(const MacWindowInfo&, std::unique_ptr<const DisplayParams>); 28 29 ~GLWindowContext_mac() override; 30 31 sk_sp<const GrGLInterface> onInitializeContext() override; 32 void onDestroyContext() override; 33 34 void resize(int w, int h) override; 35 36private: 37 void teardownContext(); 38 void onSwapBuffers() override; 39 40 NSView* fMainView; 41 NSOpenGLContext* fGLContext; 42 NSOpenGLPixelFormat* fPixelFormat; 43}; 44 45GLWindowContext_mac::GLWindowContext_mac(const MacWindowInfo& info, 46 std::unique_ptr<const DisplayParams> params) 47 : GLWindowContext(std::move(params)), fMainView(info.fMainView), fGLContext(nil) { 48 // any config code here (particularly for msaa)? 49 50 this->initializeContext(); 51} 52 53GLWindowContext_mac::~GLWindowContext_mac() { teardownContext(); } 54 55void GLWindowContext_mac::teardownContext() { 56 [NSOpenGLContext clearCurrentContext]; 57 [fPixelFormat release]; 58 fPixelFormat = nil; 59 [fGLContext release]; 60 fGLContext = nil; 61} 62 63sk_sp<const GrGLInterface> GLWindowContext_mac::onInitializeContext() { 64 SkASSERT(nil != fMainView); 65 66 if (!fGLContext) { 67 fPixelFormat = skwindow::GetGLPixelFormat(fDisplayParams->msaaSampleCount()); 68 if (nil == fPixelFormat) { 69 return nullptr; 70 } 71 72 // create context 73 fGLContext = [[NSOpenGLContext alloc] initWithFormat:fPixelFormat shareContext:nil]; 74 if (nil == fGLContext) { 75 [fPixelFormat release]; 76 fPixelFormat = nil; 77 return nullptr; 78 } 79 80 [fMainView setWantsBestResolutionOpenGLSurface:YES]; 81 [fGLContext setView:fMainView]; 82 } 83 84 GLint swapInterval = fDisplayParams->disableVsync() ? 0 : 1; 85 [fGLContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; 86 87 // make context current 88 [fGLContext makeCurrentContext]; 89 90 glClearStencil(0); 91 glClearColor(0, 0, 0, 255); 92 glStencilMask(0xffffffff); 93 glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 94 95 GLint stencilBits; 96 [fPixelFormat getValues:&stencilBits forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:0]; 97 fStencilBits = stencilBits; 98 GLint sampleCount; 99 [fPixelFormat getValues:&sampleCount forAttribute:NSOpenGLPFASamples forVirtualScreen:0]; 100 fSampleCount = sampleCount; 101 fSampleCount = std::max(fSampleCount, 1); 102 103 CGFloat backingScaleFactor = skwindow::GetBackingScaleFactor(fMainView); 104 fWidth = fMainView.bounds.size.width * backingScaleFactor; 105 fHeight = fMainView.bounds.size.height * backingScaleFactor; 106 glViewport(0, 0, fWidth, fHeight); 107 108 return GrGLInterfaces::MakeMac(); 109} 110 111void GLWindowContext_mac::onDestroyContext() { 112 // We only need to tear down the GLContext if we've changed the sample count. 113 if (fGLContext && fSampleCount != fDisplayParams->msaaSampleCount()) { 114 teardownContext(); 115 } 116} 117 118void GLWindowContext_mac::onSwapBuffers() { [fGLContext flushBuffer]; } 119 120void GLWindowContext_mac::resize(int w, int h) { 121 [fGLContext update]; 122 123 // The super class always recreates the context. 124 GLWindowContext::resize(0, 0); 125} 126 127} // anonymous namespace 128 129namespace skwindow { 130 131std::unique_ptr<WindowContext> MakeGaneshGLForMac(const MacWindowInfo& info, 132 std::unique_ptr<const DisplayParams> params) { 133 std::unique_ptr<WindowContext> ctx(new GLWindowContext_mac(info, std::move(params))); 134 if (!ctx->isValid()) { 135 return nullptr; 136 } 137 return ctx; 138} 139 140} // namespace skwindow 141