xref: /aosp_15_r20/external/skia/tools/gpu/gl/iOS/CreatePlatformGLTestContext_iOS.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1
2/*
3 * Copyright 2012 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/ios/GrGLMakeIOSInterface.h"
10#include "include/ports/SkCFObject.h"
11#include "tools/gpu/gl/GLTestContext.h"
12
13#import <OpenGLES/EAGL.h>
14#include <dlfcn.h>
15
16#define EAGLCTX ((EAGLContext*)(fEAGLContext))
17
18namespace {
19
20std::function<void()> context_restorer() {
21    EAGLContext* context = [EAGLContext currentContext];
22    return [context] { [EAGLContext setCurrentContext:context]; };
23}
24
25class IOSGLTestContext : public sk_gpu_test::GLTestContext {
26public:
27    IOSGLTestContext(IOSGLTestContext* shareContext);
28    ~IOSGLTestContext() override;
29
30private:
31    void destroyGLContext();
32
33    void onPlatformMakeNotCurrent() const override;
34    void onPlatformMakeCurrent() const override;
35    std::function<void()> onPlatformGetAutoContextRestore() const override;
36    GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
37
38    sk_cfp<EAGLContext*> fEAGLContext;
39    void* fGLLibrary;
40};
41
42IOSGLTestContext::IOSGLTestContext(IOSGLTestContext* shareContext)
43    : fGLLibrary(RTLD_DEFAULT) {
44
45    if (shareContext) {
46        EAGLContext* iosShareContext = shareContext->fEAGLContext.get();
47        fEAGLContext.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3
48                                                 sharegroup:[iosShareContext sharegroup]]);
49        if (!fEAGLContext) {
50            fEAGLContext.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2
51                                                     sharegroup:[iosShareContext sharegroup]]);
52        }
53    } else {
54        fEAGLContext.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]);
55        if (!fEAGLContext) {
56            fEAGLContext.reset([[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2]);
57        }
58    }
59    SkScopeExit restorer(context_restorer());
60    [EAGLContext setCurrentContext:fEAGLContext.get()];
61
62    sk_sp<const GrGLInterface> gl = GrGLInterfaces::MakeIOS();
63    if (nullptr == gl.get()) {
64        SkDebugf("Failed to create gl interface");
65        this->destroyGLContext();
66        return;
67    }
68    if (!gl->validate()) {
69        SkDebugf("Failed to validate gl interface");
70        this->destroyGLContext();
71        return;
72    }
73
74    fGLLibrary = dlopen(
75        "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib",
76        RTLD_LAZY);
77
78    this->init(std::move(gl));
79}
80
81IOSGLTestContext::~IOSGLTestContext() {
82    this->teardown();
83    this->destroyGLContext();
84}
85
86void IOSGLTestContext::destroyGLContext() {
87    if (fEAGLContext) {
88        if ([EAGLContext currentContext] == fEAGLContext.get()) {
89            // This will ensure that the context is immediately deleted.
90            [EAGLContext setCurrentContext:nil];
91        }
92        fEAGLContext.reset();
93    }
94    if (nullptr != fGLLibrary) {
95        dlclose(fGLLibrary);
96    }
97}
98
99void IOSGLTestContext::onPlatformMakeNotCurrent() const {
100    if (![EAGLContext setCurrentContext:nil]) {
101        SkDebugf("Could not reset the context.\n");
102    }
103}
104
105void IOSGLTestContext::onPlatformMakeCurrent() const {
106    if (![EAGLContext setCurrentContext:fEAGLContext.get()]) {
107        SkDebugf("Could not set the context.\n");
108    }
109}
110
111std::function<void()> IOSGLTestContext::onPlatformGetAutoContextRestore() const {
112    if ([EAGLContext currentContext] == fEAGLContext.get()) {
113        return nullptr;
114    }
115    return context_restorer();
116}
117
118GrGLFuncPtr IOSGLTestContext::onPlatformGetProcAddress(const char* procName) const {
119    void* handle = (nullptr == fGLLibrary) ? RTLD_DEFAULT : fGLLibrary;
120    return reinterpret_cast<GrGLFuncPtr>(dlsym(handle, procName));
121}
122
123}  // anonymous namespace
124
125namespace sk_gpu_test {
126GLTestContext *CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
127                                           GLTestContext *shareContext) {
128    if (kGL_GrGLStandard == forcedGpuAPI) {
129        return NULL;
130    }
131    IOSGLTestContext* iosShareContext = reinterpret_cast<IOSGLTestContext*>(shareContext);
132    IOSGLTestContext *ctx = new IOSGLTestContext(iosShareContext);
133    if (!ctx->isValid()) {
134        delete ctx;
135        return NULL;
136    }
137    return ctx;
138}
139}
140