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