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/ganesh/gl/GrGLInterface.h" 10#include "tools/window/GLWindowContext.h" 11#include "tools/window/ios/WindowContextFactory_ios.h" 12#include "include/gpu/ganesh/gl/ios/GrGLMakeIOSInterface.h" 13 14#import <OpenGLES/ES3/gl.h> 15#import <UIKit/UIKit.h> 16 17using skwindow::DisplayParams; 18using skwindow::IOSWindowInfo; 19using skwindow::internal::GLWindowContext; 20 21@interface GLView : MainView 22@end 23 24@implementation GLView 25+ (Class) layerClass { 26 return [CAEAGLLayer class]; 27} 28@end 29 30namespace { 31 32class GLWindowContext_ios : public GLWindowContext { 33public: 34 GLWindowContext_ios(const IOSWindowInfo&, std::unique_ptr<const DisplayParams>); 35 36 ~GLWindowContext_ios() override; 37 38 sk_sp<const GrGLInterface> onInitializeContext() override; 39 void onDestroyContext() override; 40 41 void resize(int w, int h) override; 42 43private: 44 void onSwapBuffers() override; 45 46 sk_app::Window_ios* fWindow; 47 UIViewController* fViewController; 48 GLView* fGLView; 49 EAGLContext* fGLContext; 50 GLuint fFramebuffer; 51 GLuint fRenderbuffer; 52}; 53 54GLWindowContext_ios::GLWindowContext_ios(const IOSWindowInfo& info, 55 std::unique_ptr<const DisplayParams> params) 56 : GLWindowContext(std::move(params)) 57 , fWindow(info.fWindow) 58 , fViewController(info.fViewController) 59 , fGLContext(nil) { 60 // iOS test apps currently ignore MSAA settings. 61 62 this->initializeContext(); 63} 64 65GLWindowContext_ios::~GLWindowContext_ios() { 66 this->destroyContext(); 67 [fGLView removeFromSuperview]; 68 [fGLView release]; 69} 70 71sk_sp<const GrGLInterface> GLWindowContext_ios::onInitializeContext() { 72 SkASSERT(nil != fViewController); 73 SkASSERT(!fGLContext); 74 75 CGRect frameRect = [fViewController.view frame]; 76 fGLView = [[[GLView alloc] initWithFrame:frameRect] initWithWindow:fWindow]; 77 [fViewController.view addSubview:fGLView]; 78 79 fGLContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; 80 81 if (!fGLContext) 82 { 83 SkDebugf("Could Not Create OpenGL ES Context\n"); 84 return nullptr; 85 } 86 87 if (![EAGLContext setCurrentContext:fGLContext]) { 88 SkDebugf("Could Not Set OpenGL ES Context As Current\n"); 89 this->onDestroyContext(); 90 return nullptr; 91 } 92 93 // Set up EAGLLayer 94 CAEAGLLayer* eaglLayer = (CAEAGLLayer*)fGLView.layer; 95 eaglLayer.drawableProperties = @{kEAGLDrawablePropertyRetainedBacking : @NO, 96 kEAGLDrawablePropertyColorFormat : kEAGLColorFormatRGBA8 }; 97 eaglLayer.opaque = YES; 98 eaglLayer.frame = frameRect; 99 eaglLayer.contentsGravity = kCAGravityTopLeft; 100 101 // Set up framebuffer 102 glGenFramebuffers(1, &fFramebuffer); 103 glBindFramebuffer(GL_FRAMEBUFFER, fFramebuffer); 104 105 glGenRenderbuffers(1, &fRenderbuffer); 106 glBindRenderbuffer(GL_RENDERBUFFER, fRenderbuffer); 107 glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, fRenderbuffer); 108 109 [fGLContext renderbufferStorage:GL_RENDERBUFFER fromDrawable:eaglLayer]; 110 111 GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 112 if (status != GL_FRAMEBUFFER_COMPLETE) { 113 SkDebugf("Invalid Framebuffer\n"); 114 this->onDestroyContext(); 115 return nullptr; 116 } 117 118 glClearStencil(0); 119 glClearColor(0, 0, 0, 255); 120 glStencilMask(0xffffffff); 121 glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 122 123 fStencilBits = 8; 124 fSampleCount = 1; // TODO: handle multisampling 125 126 fWidth = fViewController.view.frame.size.width; 127 fHeight = fViewController.view.frame.size.height; 128 129 glViewport(0, 0, fWidth, fHeight); 130 131 return GrGLInterfaces::MakeIOS(); 132} 133 134void GLWindowContext_ios::onDestroyContext() { 135 glDeleteFramebuffers(1, &fFramebuffer); 136 glDeleteRenderbuffers(1, &fRenderbuffer); 137 [EAGLContext setCurrentContext:nil]; 138 [fGLContext release]; 139 fGLContext = nil; 140} 141 142void GLWindowContext_ios::onSwapBuffers() { 143 glBindRenderbuffer(GL_RENDERBUFFER, fRenderbuffer); 144 [fGLContext presentRenderbuffer:GL_RENDERBUFFER]; 145} 146 147void GLWindowContext_ios::resize(int w, int h) { 148 GLWindowContext::resize(w, h); 149} 150 151} // anonymous namespace 152 153namespace skwindow { 154 155std::unique_ptr<WindowContext> MakeGLForIOS(const IOSWindowInfo& info, 156 std::unique_ptr<const DisplayParams> params) { 157 std::unique_ptr<WindowContext> ctx(new GLWindowContext_ios(info, std::move(params))); 158 if (!ctx->isValid()) { 159 return nullptr; 160 } 161 return ctx; 162} 163 164} // namespace skwindow 165