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