xref: /aosp_15_r20/external/skia/tools/window/ios/GLWindowContext_ios.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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