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