1
2 /*
3 * Copyright 2011 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 #include "include/core/SkTypes.h"
9
10 #include "tools/gpu/gl/GLTestContext.h"
11 #include "AvailabilityMacros.h"
12
13 #include <OpenGL/OpenGL.h>
14 #include <dlfcn.h>
15
16 namespace {
17
context_restorer()18 std::function<void()> context_restorer() {
19 auto context = CGLGetCurrentContext();
20 return [context] { CGLSetCurrentContext(context); };
21 }
22
23 class MacGLTestContext : public sk_gpu_test::GLTestContext {
24 public:
25 MacGLTestContext(MacGLTestContext* shareContext);
26 ~MacGLTestContext() override;
27
28 private:
29 void destroyGLContext();
30
31 void onPlatformMakeCurrent() const override;
32 std::function<void()> onPlatformGetAutoContextRestore() const override;
33 void onPlatformSwapBuffers() const override;
34 GrGLFuncPtr onPlatformGetProcAddress(const char*) const override;
35
36 CGLContextObj fContext;
37 void* fGLLibrary;
38 };
39
MacGLTestContext(MacGLTestContext * shareContext)40 MacGLTestContext::MacGLTestContext(MacGLTestContext* shareContext)
41 : fContext(nullptr)
42 , fGLLibrary(RTLD_DEFAULT) {
43 CGLPixelFormatAttribute attributes[] = {
44 #if MAC_OS_X_VERSION_10_7
45 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core,
46 #endif
47 kCGLPFADoubleBuffer,
48 (CGLPixelFormatAttribute)0
49 };
50 CGLPixelFormatObj pixFormat;
51 GLint npix;
52
53 CGLChoosePixelFormat(attributes, &pixFormat, &npix);
54
55 if (nullptr == pixFormat) {
56 SkDebugf("CGLChoosePixelFormat failed.");
57 return;
58 }
59
60 CGLCreateContext(pixFormat, shareContext ? shareContext->fContext : nullptr, &fContext);
61 CGLReleasePixelFormat(pixFormat);
62
63 if (nullptr == fContext) {
64 SkDebugf("CGLCreateContext failed.");
65 return;
66 }
67
68 SkScopeExit restorer(context_restorer());
69 CGLSetCurrentContext(fContext);
70
71 auto gl = GrGLMakeNativeInterface();
72 if (!gl) {
73 SkDebugf("Context could not create GL interface.\n");
74 this->destroyGLContext();
75 return;
76 }
77 if (!gl->validate()) {
78 SkDebugf("Context could not validate GL interface.\n");
79 this->destroyGLContext();
80 return;
81 }
82
83 fGLLibrary = dlopen(
84 "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib",
85 RTLD_LAZY);
86
87 this->init(std::move(gl));
88 }
89
~MacGLTestContext()90 MacGLTestContext::~MacGLTestContext() {
91 this->teardown();
92 this->destroyGLContext();
93 }
94
destroyGLContext()95 void MacGLTestContext::destroyGLContext() {
96 if (fContext) {
97 if (CGLGetCurrentContext() == fContext) {
98 // This will ensure that the context is immediately deleted.
99 CGLSetCurrentContext(nullptr);
100 }
101 CGLReleaseContext(fContext);
102 fContext = nullptr;
103 }
104 if (nullptr != fGLLibrary) {
105 dlclose(fGLLibrary);
106 }
107 }
108
onPlatformMakeCurrent() const109 void MacGLTestContext::onPlatformMakeCurrent() const {
110 CGLSetCurrentContext(fContext);
111 }
112
onPlatformGetAutoContextRestore() const113 std::function<void()> MacGLTestContext::onPlatformGetAutoContextRestore() const {
114 if (CGLGetCurrentContext() == fContext) {
115 return nullptr;
116 }
117 return context_restorer();
118 }
119
onPlatformSwapBuffers() const120 void MacGLTestContext::onPlatformSwapBuffers() const {
121 CGLFlushDrawable(fContext);
122 }
123
onPlatformGetProcAddress(const char * procName) const124 GrGLFuncPtr MacGLTestContext::onPlatformGetProcAddress(const char* procName) const {
125 void* handle = (nullptr == fGLLibrary) ? RTLD_DEFAULT : fGLLibrary;
126 return reinterpret_cast<GrGLFuncPtr>(dlsym(handle, procName));
127 }
128
129 } // anonymous namespace
130
131 namespace sk_gpu_test {
CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,GLTestContext * shareContext)132 GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
133 GLTestContext* shareContext) {
134 if (kGLES_GrGLStandard == forcedGpuAPI) {
135 return nullptr;
136 }
137 MacGLTestContext* macShareContext = reinterpret_cast<MacGLTestContext*>(shareContext);
138 MacGLTestContext* ctx = new MacGLTestContext(macShareContext);
139 if (!ctx->isValid()) {
140 delete ctx;
141 return nullptr;
142 }
143 return ctx;
144 }
145 } // namespace sk_gpu_test
146