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