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 "SkTypes.h" 9 10#include "gl/GLTestContext.h" 11#include "AvailabilityMacros.h" 12 13#include <OpenGL/OpenGL.h> 14#include <dlfcn.h> 15 16namespace { 17 18std::function<void()> context_restorer() { 19 auto context = CGLGetCurrentContext(); 20 return [context] { CGLSetCurrentContext(context); }; 21} 22 23class MacGLTestContext : public sk_gpu_test::GLTestContext { 24public: 25 MacGLTestContext(MacGLTestContext* shareContext); 26 ~MacGLTestContext() override; 27 28private: 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 40MacGLTestContext::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 90MacGLTestContext::~MacGLTestContext() { 91 this->teardown(); 92 this->destroyGLContext(); 93} 94 95void 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 109void MacGLTestContext::onPlatformMakeCurrent() const { 110 CGLSetCurrentContext(fContext); 111} 112 113std::function<void()> MacGLTestContext::onPlatformGetAutoContextRestore() const { 114 if (CGLGetCurrentContext() == fContext) { 115 return nullptr; 116 } 117 return context_restorer(); 118} 119 120void MacGLTestContext::onPlatformSwapBuffers() const { 121 CGLFlushDrawable(fContext); 122} 123 124GrGLFuncPtr 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 131namespace sk_gpu_test { 132GLTestContext* 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