/* * 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 "include/core/SkTypes.h" #include "tools/gpu/gl/GLTestContext.h" #include #include #include namespace { std::function 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 onPlatformMakeNotCurrent() const override; void onPlatformMakeCurrent() const override; std::function onPlatformGetAutoContextRestore() const override; GrGLFuncPtr onPlatformGetProcAddress(const char*) const override; CGLContextObj fContext; void* fGLLibrary; }; MacGLTestContext::MacGLTestContext(MacGLTestContext* shareContext) : fContext(nullptr) , fGLLibrary(RTLD_DEFAULT) { // We first try to request a Radeon eGPU if one is available. // This will be a Radeon HD7000 and up, which includes all eGPU configs. // If that fails, we try again with only the base parameters. CGLPixelFormatAttribute attributes[] = { // base parameters #if MAC_OS_X_VERSION_10_7 kCGLPFAOpenGLProfile, (CGLPixelFormatAttribute) kCGLOGLPVersion_3_2_Core, #endif kCGLPFADoubleBuffer, #if MAC_OS_X_VERSION_10_8 // eGPU parameters kCGLPFAAllowOfflineRenderers, // Enables e-GPU. kCGLPFANoRecovery, // Disallows software rendering. kCGLPFARendererID, (CGLPixelFormatAttribute)kCGLRendererATIRadeonX4000ID, // Select Radeon #endif (CGLPixelFormatAttribute)NULL }; #if MAC_OS_X_VERSION_10_8 static const int kFirstEGPUParameter = 3; SkASSERT(kCGLPFAAllowOfflineRenderers == attributes[kFirstEGPUParameter]); #endif CGLPixelFormatObj pixFormat; GLint npix; CGLChoosePixelFormat(attributes, &pixFormat, &npix); #if MAC_OS_X_VERSION_10_8 if (nullptr == pixFormat) { // Move the NULL-termination up to remove the eGPU parameters and try again attributes[kFirstEGPUParameter] = (CGLPixelFormatAttribute)NULL; CGLChoosePixelFormat(attributes, &pixFormat, &npix); } #endif 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::onPlatformMakeNotCurrent() const { CGLSetCurrentContext(nullptr); } void MacGLTestContext::onPlatformMakeCurrent() const { CGLSetCurrentContext(fContext); } std::function MacGLTestContext::onPlatformGetAutoContextRestore() const { if (CGLGetCurrentContext() == fContext) { return nullptr; } return context_restorer(); } GrGLFuncPtr MacGLTestContext::onPlatformGetProcAddress(const char* procName) const { void* handle = (nullptr == fGLLibrary) ? RTLD_DEFAULT : fGLLibrary; return reinterpret_cast(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(shareContext); MacGLTestContext* ctx = new MacGLTestContext(macShareContext); if (!ctx->isValid()) { delete ctx; return nullptr; } return ctx; } } // namespace sk_gpu_test