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/core/SkCanvas.h" 10cb93a386Sopenharmony_ci#include "include/core/SkColorFilter.h" 11cb93a386Sopenharmony_ci#include "include/gpu/gl/GrGLInterface.h" 12cb93a386Sopenharmony_ci#include "tools/ToolUtils.h" 13cb93a386Sopenharmony_ci#include "tools/sk_app/GLWindowContext.h" 14cb93a386Sopenharmony_ci#include "tools/sk_app/mac/WindowContextFactory_mac.h" 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_ci#include <OpenGL/gl.h> 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci#include <Cocoa/Cocoa.h> 19cb93a386Sopenharmony_ci 20cb93a386Sopenharmony_ciusing sk_app::DisplayParams; 21cb93a386Sopenharmony_ciusing sk_app::window_context_factory::MacWindowInfo; 22cb93a386Sopenharmony_ciusing sk_app::GLWindowContext; 23cb93a386Sopenharmony_ci 24cb93a386Sopenharmony_cinamespace { 25cb93a386Sopenharmony_ci 26cb93a386Sopenharmony_ci// TODO: This still uses GL to handle the update rather than using a purely raster backend, 27cb93a386Sopenharmony_ci// for historical reasons. Writing a pure raster backend would be better in the long run. 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ciclass RasterWindowContext_mac : public GLWindowContext { 30cb93a386Sopenharmony_cipublic: 31cb93a386Sopenharmony_ci RasterWindowContext_mac(const MacWindowInfo&, const DisplayParams&); 32cb93a386Sopenharmony_ci 33cb93a386Sopenharmony_ci ~RasterWindowContext_mac() override; 34cb93a386Sopenharmony_ci 35cb93a386Sopenharmony_ci sk_sp<SkSurface> getBackbufferSurface() override; 36cb93a386Sopenharmony_ci 37cb93a386Sopenharmony_ci void onSwapBuffers() override; 38cb93a386Sopenharmony_ci 39cb93a386Sopenharmony_ci sk_sp<const GrGLInterface> onInitializeContext() override; 40cb93a386Sopenharmony_ci void onDestroyContext() override {} 41cb93a386Sopenharmony_ci 42cb93a386Sopenharmony_ci void resize(int w, int h) override; 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ciprivate: 45cb93a386Sopenharmony_ci NSView* fMainView; 46cb93a386Sopenharmony_ci NSOpenGLContext* fGLContext; 47cb93a386Sopenharmony_ci NSOpenGLPixelFormat* fPixelFormat; 48cb93a386Sopenharmony_ci sk_sp<SkSurface> fBackbufferSurface; 49cb93a386Sopenharmony_ci 50cb93a386Sopenharmony_ci using INHERITED = GLWindowContext; 51cb93a386Sopenharmony_ci}; 52cb93a386Sopenharmony_ci 53cb93a386Sopenharmony_ciRasterWindowContext_mac::RasterWindowContext_mac(const MacWindowInfo& info, 54cb93a386Sopenharmony_ci const DisplayParams& params) 55cb93a386Sopenharmony_ci : INHERITED(params) 56cb93a386Sopenharmony_ci , fMainView(info.fMainView) 57cb93a386Sopenharmony_ci , fGLContext(nil) { 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ci // any config code here (particularly for msaa)? 60cb93a386Sopenharmony_ci 61cb93a386Sopenharmony_ci this->initializeContext(); 62cb93a386Sopenharmony_ci} 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ciRasterWindowContext_mac::~RasterWindowContext_mac() { 65cb93a386Sopenharmony_ci [NSOpenGLContext clearCurrentContext]; 66cb93a386Sopenharmony_ci [fPixelFormat release]; 67cb93a386Sopenharmony_ci fPixelFormat = nil; 68cb93a386Sopenharmony_ci [fGLContext release]; 69cb93a386Sopenharmony_ci fGLContext = nil; 70cb93a386Sopenharmony_ci} 71cb93a386Sopenharmony_ci 72cb93a386Sopenharmony_cisk_sp<const GrGLInterface> RasterWindowContext_mac::onInitializeContext() { 73cb93a386Sopenharmony_ci SkASSERT(nil != fMainView); 74cb93a386Sopenharmony_ci 75cb93a386Sopenharmony_ci if (!fGLContext) { 76cb93a386Sopenharmony_ci // set up pixel format 77cb93a386Sopenharmony_ci constexpr int kMaxAttributes = 18; 78cb93a386Sopenharmony_ci NSOpenGLPixelFormatAttribute attributes[kMaxAttributes]; 79cb93a386Sopenharmony_ci int numAttributes = 0; 80cb93a386Sopenharmony_ci attributes[numAttributes++] = NSOpenGLPFAAccelerated; 81cb93a386Sopenharmony_ci attributes[numAttributes++] = NSOpenGLPFAClosestPolicy; 82cb93a386Sopenharmony_ci attributes[numAttributes++] = NSOpenGLPFADoubleBuffer; 83cb93a386Sopenharmony_ci attributes[numAttributes++] = NSOpenGLPFAOpenGLProfile; 84cb93a386Sopenharmony_ci attributes[numAttributes++] = NSOpenGLProfileVersion3_2Core; 85cb93a386Sopenharmony_ci attributes[numAttributes++] = NSOpenGLPFAColorSize; 86cb93a386Sopenharmony_ci attributes[numAttributes++] = 24; 87cb93a386Sopenharmony_ci attributes[numAttributes++] = NSOpenGLPFAAlphaSize; 88cb93a386Sopenharmony_ci attributes[numAttributes++] = 8; 89cb93a386Sopenharmony_ci attributes[numAttributes++] = NSOpenGLPFADepthSize; 90cb93a386Sopenharmony_ci attributes[numAttributes++] = 0; 91cb93a386Sopenharmony_ci attributes[numAttributes++] = NSOpenGLPFAStencilSize; 92cb93a386Sopenharmony_ci attributes[numAttributes++] = 8; 93cb93a386Sopenharmony_ci if (fDisplayParams.fMSAASampleCount > 1) { 94cb93a386Sopenharmony_ci attributes[numAttributes++] = NSOpenGLPFASampleBuffers; 95cb93a386Sopenharmony_ci attributes[numAttributes++] = 1; 96cb93a386Sopenharmony_ci attributes[numAttributes++] = NSOpenGLPFASamples; 97cb93a386Sopenharmony_ci attributes[numAttributes++] = fDisplayParams.fMSAASampleCount; 98cb93a386Sopenharmony_ci } else { 99cb93a386Sopenharmony_ci attributes[numAttributes++] = NSOpenGLPFASampleBuffers; 100cb93a386Sopenharmony_ci attributes[numAttributes++] = 0; 101cb93a386Sopenharmony_ci } 102cb93a386Sopenharmony_ci attributes[numAttributes++] = 0; 103cb93a386Sopenharmony_ci SkASSERT(numAttributes <= kMaxAttributes); 104cb93a386Sopenharmony_ci 105cb93a386Sopenharmony_ci fPixelFormat = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]; 106cb93a386Sopenharmony_ci if (nil == fPixelFormat) { 107cb93a386Sopenharmony_ci return nullptr; 108cb93a386Sopenharmony_ci } 109cb93a386Sopenharmony_ci 110cb93a386Sopenharmony_ci // create context 111cb93a386Sopenharmony_ci fGLContext = [[NSOpenGLContext alloc] initWithFormat:fPixelFormat shareContext:nil]; 112cb93a386Sopenharmony_ci if (nil == fGLContext) { 113cb93a386Sopenharmony_ci [fPixelFormat release]; 114cb93a386Sopenharmony_ci fPixelFormat = nil; 115cb93a386Sopenharmony_ci return nullptr; 116cb93a386Sopenharmony_ci } 117cb93a386Sopenharmony_ci 118cb93a386Sopenharmony_ci [fMainView setWantsBestResolutionOpenGLSurface:YES]; 119cb93a386Sopenharmony_ci [fGLContext setView:fMainView]; 120cb93a386Sopenharmony_ci 121cb93a386Sopenharmony_ci GLint swapInterval = fDisplayParams.fDisableVsync ? 0 : 1; 122cb93a386Sopenharmony_ci [fGLContext setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; 123cb93a386Sopenharmony_ci } 124cb93a386Sopenharmony_ci 125cb93a386Sopenharmony_ci // make context current 126cb93a386Sopenharmony_ci [fGLContext makeCurrentContext]; 127cb93a386Sopenharmony_ci 128cb93a386Sopenharmony_ci glClearStencil(0); 129cb93a386Sopenharmony_ci glClearColor(0, 0, 0, 255); 130cb93a386Sopenharmony_ci glStencilMask(0xffffffff); 131cb93a386Sopenharmony_ci glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_ci GLint stencilBits; 134cb93a386Sopenharmony_ci [fPixelFormat getValues:&stencilBits forAttribute:NSOpenGLPFAStencilSize forVirtualScreen:0]; 135cb93a386Sopenharmony_ci fStencilBits = stencilBits; 136cb93a386Sopenharmony_ci GLint sampleCount; 137cb93a386Sopenharmony_ci [fPixelFormat getValues:&sampleCount forAttribute:NSOpenGLPFASamples forVirtualScreen:0]; 138cb93a386Sopenharmony_ci fSampleCount = sampleCount; 139cb93a386Sopenharmony_ci fSampleCount = std::max(fSampleCount, 1); 140cb93a386Sopenharmony_ci 141cb93a386Sopenharmony_ci CGFloat backingScaleFactor = sk_app::GetBackingScaleFactor(fMainView); 142cb93a386Sopenharmony_ci fWidth = fMainView.bounds.size.width * backingScaleFactor; 143cb93a386Sopenharmony_ci fHeight = fMainView.bounds.size.height * backingScaleFactor; 144cb93a386Sopenharmony_ci glViewport(0, 0, fWidth, fHeight); 145cb93a386Sopenharmony_ci 146cb93a386Sopenharmony_ci // make the offscreen image 147cb93a386Sopenharmony_ci SkImageInfo info = SkImageInfo::Make(fWidth, fHeight, fDisplayParams.fColorType, 148cb93a386Sopenharmony_ci kPremul_SkAlphaType, fDisplayParams.fColorSpace); 149cb93a386Sopenharmony_ci fBackbufferSurface = SkSurface::MakeRaster(info); 150cb93a386Sopenharmony_ci return GrGLMakeNativeInterface(); 151cb93a386Sopenharmony_ci} 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_cisk_sp<SkSurface> RasterWindowContext_mac::getBackbufferSurface() { return fBackbufferSurface; } 154cb93a386Sopenharmony_ci 155cb93a386Sopenharmony_civoid RasterWindowContext_mac::onSwapBuffers() { 156cb93a386Sopenharmony_ci if (fBackbufferSurface) { 157cb93a386Sopenharmony_ci // We made/have an off-screen surface. Get the contents as an SkImage: 158cb93a386Sopenharmony_ci sk_sp<SkImage> snapshot = fBackbufferSurface->makeImageSnapshot(); 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci sk_sp<SkSurface> gpuSurface = INHERITED::getBackbufferSurface(); 161cb93a386Sopenharmony_ci SkCanvas* gpuCanvas = gpuSurface->getCanvas(); 162cb93a386Sopenharmony_ci gpuCanvas->drawImage(snapshot, 0, 0); 163cb93a386Sopenharmony_ci gpuCanvas->flush(); 164cb93a386Sopenharmony_ci 165cb93a386Sopenharmony_ci [fGLContext flushBuffer]; 166cb93a386Sopenharmony_ci } 167cb93a386Sopenharmony_ci} 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_civoid RasterWindowContext_mac::resize(int w, int h) { 170cb93a386Sopenharmony_ci [fGLContext update]; 171cb93a386Sopenharmony_ci 172cb93a386Sopenharmony_ci // The super class always recreates the context. 173cb93a386Sopenharmony_ci INHERITED::resize(0, 0); 174cb93a386Sopenharmony_ci} 175cb93a386Sopenharmony_ci 176cb93a386Sopenharmony_ci} // anonymous namespace 177cb93a386Sopenharmony_ci 178cb93a386Sopenharmony_cinamespace sk_app { 179cb93a386Sopenharmony_cinamespace window_context_factory { 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_cistd::unique_ptr<WindowContext> MakeRasterForMac(const MacWindowInfo& info, 182cb93a386Sopenharmony_ci const DisplayParams& params) { 183cb93a386Sopenharmony_ci std::unique_ptr<WindowContext> ctx(new RasterWindowContext_mac(info, params)); 184cb93a386Sopenharmony_ci if (!ctx->isValid()) { 185cb93a386Sopenharmony_ci return nullptr; 186cb93a386Sopenharmony_ci } 187cb93a386Sopenharmony_ci return ctx; 188cb93a386Sopenharmony_ci} 189cb93a386Sopenharmony_ci 190cb93a386Sopenharmony_ci} // namespace window_context_factory 191cb93a386Sopenharmony_ci} // namespace sk_app 192