aboutsummaryrefslogtreecommitdiffhomepage
path: root/tools/gpu/gl/mac/CreatePlatformGLTestContext_mac.cpp
blob: 5b11227125fac6303da9f9b952be7fbe84690b7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145

/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SkTypes.h"

#include "gl/GLTestContext.h"
#include "AvailabilityMacros.h"

#include <OpenGL/OpenGL.h>
#include <dlfcn.h>

namespace {

std::function<void()> context_restorer() {
    auto context = CGLGetCurrentContext();
    return [context] { CGLSetCurrentContext(context); };
}

class MacGLTestContext : public sk_gpu_test::GLTestContext {
public:
    MacGLTestContext(MacGLTestContext* shareContext);
    ~MacGLTestContext() override;

private:
    void destroyGLContext();

    void onPlatformMakeCurrent() const override;
    std::function<void()> onPlatformGetAutoContextRestore() const override;
    void onPlatformSwapBuffers() const override;
    GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;

    CGLContextObj fContext;
    void* fGLLibrary;
};

MacGLTestContext::MacGLTestContext(MacGLTestContext* shareContext)
    : fContext(nullptr)
    , fGLLibrary(RTLD_DEFAULT) {
    CGLPixelFormatAttribute attributes[] = {
#if MAC_OS_X_VERSION_10_7
        kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core,
#endif
        kCGLPFADoubleBuffer,
        (CGLPixelFormatAttribute)0
    };
    CGLPixelFormatObj pixFormat;
    GLint npix;

    CGLChoosePixelFormat(attributes, &pixFormat, &npix);

    if (nullptr == pixFormat) {
        SkDebugf("CGLChoosePixelFormat failed.");
        return;
    }

    CGLCreateContext(pixFormat, shareContext ? shareContext->fContext : nullptr, &fContext);
    CGLReleasePixelFormat(pixFormat);

    if (nullptr == fContext) {
        SkDebugf("CGLCreateContext failed.");
        return;
    }

    SkScopeExit restorer(context_restorer());
    CGLSetCurrentContext(fContext);

    auto gl = GrGLMakeNativeInterface();
    if (!gl) {
        SkDebugf("Context could not create GL interface.\n");
        this->destroyGLContext();
        return;
    }
    if (!gl->validate()) {
        SkDebugf("Context could not validate GL interface.\n");
        this->destroyGLContext();
        return;
    }

    fGLLibrary = dlopen(
        "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib",
        RTLD_LAZY);

    this->init(std::move(gl));
}

MacGLTestContext::~MacGLTestContext() {
    this->teardown();
    this->destroyGLContext();
}

void MacGLTestContext::destroyGLContext() {
    if (fContext) {
        if (CGLGetCurrentContext() == fContext) {
            // This will ensure that the context is immediately deleted.
            CGLSetCurrentContext(nullptr);
        }
        CGLReleaseContext(fContext);
        fContext = nullptr;
    }
    if (nullptr != fGLLibrary) {
        dlclose(fGLLibrary);
    }
}

void MacGLTestContext::onPlatformMakeCurrent() const {
    CGLSetCurrentContext(fContext);
}

std::function<void()> MacGLTestContext::onPlatformGetAutoContextRestore() const {
    if (CGLGetCurrentContext() == fContext) {
        return nullptr;
    }
    return context_restorer();
}

void MacGLTestContext::onPlatformSwapBuffers() const {
    CGLFlushDrawable(fContext);
}

GrGLFuncPtr MacGLTestContext::onPlatformGetProcAddress(const char* procName) const {
    void* handle = (nullptr == fGLLibrary) ? RTLD_DEFAULT : fGLLibrary;
    return reinterpret_cast<GrGLFuncPtr>(dlsym(handle, procName));
}

}  // anonymous namespace

namespace sk_gpu_test {
GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
                                           GLTestContext* shareContext) {
    if (kGLES_GrGLStandard == forcedGpuAPI) {
        return nullptr;
    }
    MacGLTestContext* macShareContext = reinterpret_cast<MacGLTestContext*>(shareContext);
    MacGLTestContext* ctx = new MacGLTestContext(macShareContext);
    if (!ctx->isValid()) {
        delete ctx;
        return nullptr;
    }
    return ctx;
}
}  // namespace sk_gpu_test