• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 onPlatformMakeNotCurrent() const override;
32     void onPlatformMakeCurrent() const override;
33     std::function<void()> onPlatformGetAutoContextRestore() 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     // We first try to request a Radeon eGPU if one is available.
44     // This will be a Radeon HD7000 and up, which includes all eGPU configs.
45     // If that fails, we try again with only the base parameters.
46     CGLPixelFormatAttribute attributes[] = {
47         // base parameters
48 #if MAC_OS_X_VERSION_10_7
49         kCGLPFAOpenGLProfile,
50         (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core,
51 #endif
52         kCGLPFADoubleBuffer,
53 
54 #if MAC_OS_X_VERSION_10_8
55         // eGPU parameters
56         kCGLPFAAllowOfflineRenderers,  // Enables e-GPU.
57         kCGLPFANoRecovery,  // Disallows software rendering.
58         kCGLPFARendererID, (CGLPixelFormatAttribute)kCGLRendererATIRadeonX4000ID, // Select Radeon
59 #endif
60         (CGLPixelFormatAttribute)NULL
61     };
62 #if MAC_OS_X_VERSION_10_8
63     static const int kFirstEGPUParameter = 3;
64     SkASSERT(kCGLPFAAllowOfflineRenderers == attributes[kFirstEGPUParameter]);
65 #endif
66 
67     CGLPixelFormatObj pixFormat;
68     GLint npix;
69     CGLChoosePixelFormat(attributes, &pixFormat, &npix);
70 
71 #if MAC_OS_X_VERSION_10_8
72     if (nullptr == pixFormat) {
73         // Move the NULL-termination up to remove the eGPU parameters and try again
74         attributes[kFirstEGPUParameter] = (CGLPixelFormatAttribute)NULL;
75         CGLChoosePixelFormat(attributes, &pixFormat, &npix);
76     }
77 #endif
78     if (nullptr == pixFormat) {
79         SkDebugf("CGLChoosePixelFormat failed.");
80         return;
81     }
82 
83     CGLCreateContext(pixFormat, shareContext ? shareContext->fContext : nullptr, &fContext);
84     CGLReleasePixelFormat(pixFormat);
85 
86     if (nullptr == fContext) {
87         SkDebugf("CGLCreateContext failed.");
88         return;
89     }
90 
91     SkScopeExit restorer(context_restorer());
92     CGLSetCurrentContext(fContext);
93 
94     auto gl = GrGLMakeNativeInterface();
95     if (!gl) {
96         SkDebugf("Context could not create GL interface.\n");
97         this->destroyGLContext();
98         return;
99     }
100     if (!gl->validate()) {
101         SkDebugf("Context could not validate GL interface.\n");
102         this->destroyGLContext();
103         return;
104     }
105 
106     fGLLibrary = dlopen(
107         "/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib",
108         RTLD_LAZY);
109 
110     this->init(std::move(gl));
111 }
112 
~MacGLTestContext()113 MacGLTestContext::~MacGLTestContext() {
114     this->teardown();
115     this->destroyGLContext();
116 }
117 
destroyGLContext()118 void MacGLTestContext::destroyGLContext() {
119     if (fContext) {
120         if (CGLGetCurrentContext() == fContext) {
121             // This will ensure that the context is immediately deleted.
122             CGLSetCurrentContext(nullptr);
123         }
124         CGLReleaseContext(fContext);
125         fContext = nullptr;
126     }
127     if (nullptr != fGLLibrary) {
128         dlclose(fGLLibrary);
129     }
130 }
131 
onPlatformMakeNotCurrent() const132 void MacGLTestContext::onPlatformMakeNotCurrent() const {
133     CGLSetCurrentContext(nullptr);
134 }
135 
onPlatformMakeCurrent() const136 void MacGLTestContext::onPlatformMakeCurrent() const {
137     CGLSetCurrentContext(fContext);
138 }
139 
onPlatformGetAutoContextRestore() const140 std::function<void()> MacGLTestContext::onPlatformGetAutoContextRestore() const {
141     if (CGLGetCurrentContext() == fContext) {
142         return nullptr;
143     }
144     return context_restorer();
145 }
146 
onPlatformGetProcAddress(const char * procName) const147 GrGLFuncPtr MacGLTestContext::onPlatformGetProcAddress(const char* procName) const {
148     void* handle = (nullptr == fGLLibrary) ? RTLD_DEFAULT : fGLLibrary;
149     return reinterpret_cast<GrGLFuncPtr>(dlsym(handle, procName));
150 }
151 
152 }  // anonymous namespace
153 
154 namespace sk_gpu_test {
CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,GLTestContext * shareContext)155 GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
156                                            GLTestContext* shareContext) {
157     if (kGLES_GrGLStandard == forcedGpuAPI) {
158         return nullptr;
159     }
160     MacGLTestContext* macShareContext = reinterpret_cast<MacGLTestContext*>(shareContext);
161     MacGLTestContext* ctx = new MacGLTestContext(macShareContext);
162     if (!ctx->isValid()) {
163         delete ctx;
164         return nullptr;
165     }
166     return ctx;
167 }
168 }  // namespace sk_gpu_test
169