diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2017-11-27 16:34:52 +0100 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2017-11-29 15:48:51 +0100 |
commit | 335f04f7e13422ce53cbbf13cebb8283149faba8 (patch) | |
tree | 4542c71910cea2f626ac37325a32f9432f1d908b /platform/darwin/src/headless_backend_cgl.cpp | |
parent | 772b9090626731101b82eccacbc3adaa71cc428c (diff) | |
download | qtlocation-mapboxgl-335f04f7e13422ce53cbbf13cebb8283149faba8.tar.gz |
[core] fold HeadlessDisplay into the headless RenderBackend implementation
Diffstat (limited to 'platform/darwin/src/headless_backend_cgl.cpp')
-rw-r--r-- | platform/darwin/src/headless_backend_cgl.cpp | 99 |
1 files changed, 74 insertions, 25 deletions
diff --git a/platform/darwin/src/headless_backend_cgl.cpp b/platform/darwin/src/headless_backend_cgl.cpp index 3b0c3aaf35..6e19213f52 100644 --- a/platform/darwin/src/headless_backend_cgl.cpp +++ b/platform/darwin/src/headless_backend_cgl.cpp @@ -1,5 +1,5 @@ #include <mbgl/gl/headless_backend.hpp> -#include <mbgl/gl/headless_display.hpp> +#include <mbgl/util/logging.hpp> #include <OpenGL/OpenGL.h> #include <CoreFoundation/CoreFoundation.h> @@ -9,11 +9,78 @@ namespace mbgl { +// This class provides a singleton that contains information about the pixel format used for +// instantiating new headless rendering contexts. +class CGLDisplayConfig { +private: + // Key for singleton construction. + struct Key { explicit Key() = default; }; + +public: + CGLDisplayConfig(Key) { + // TODO: test if OpenGL 4.1 with GL_ARB_ES2_compatibility is supported + // If it is, use kCGLOGLPVersion_3_2_Core and enable that extension. + CGLPixelFormatAttribute attributes[] = { + kCGLPFAOpenGLProfile, static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_Legacy), + // Not adding kCGLPFAAccelerated, as this will make headless rendering impossible when running in VMs. + kCGLPFAClosestPolicy, + kCGLPFAAccumSize, static_cast<CGLPixelFormatAttribute>(32), + kCGLPFAColorSize, static_cast<CGLPixelFormatAttribute>(24), + kCGLPFAAlphaSize, static_cast<CGLPixelFormatAttribute>(8), + kCGLPFADepthSize, static_cast<CGLPixelFormatAttribute>(16), + kCGLPFAStencilSize, static_cast<CGLPixelFormatAttribute>(8), + kCGLPFASupportsAutomaticGraphicsSwitching, + kCGLPFAAllowOfflineRenderers, // Allows using the integrated GPU + static_cast<CGLPixelFormatAttribute>(0) + }; + + GLint num; + // TODO: obtain all configurations and choose the best one. + const CGLError error = CGLChoosePixelFormat(attributes, &pixelFormat, &num); + if (error != kCGLNoError) { + throw std::runtime_error(std::string("Error choosing pixel format:") + CGLErrorString(error) + "\n"); + } + if (num <= 0) { + throw std::runtime_error("No pixel formats found."); + } + } + + ~CGLDisplayConfig() { + const CGLError error = CGLDestroyPixelFormat(pixelFormat); + if (error != kCGLNoError) { + Log::Error(Event::OpenGL, std::string("Error destroying pixel format:") + CGLErrorString(error)); + } + } + + static std::shared_ptr<const CGLDisplayConfig> create() { + static std::weak_ptr<const CGLDisplayConfig> instance; + auto shared = instance.lock(); + if (!shared) { + instance = shared = std::make_shared<CGLDisplayConfig>(Key{}); + } + return shared; + } + +public: + CGLPixelFormatObj pixelFormat = nullptr; +}; + struct CGLImpl : public HeadlessBackend::Impl { - CGLImpl(CGLContextObj glContext_) : glContext(glContext_) { + CGLImpl() { + CGLError error = CGLCreateContext(cglDisplay->pixelFormat, nullptr, &glContext); + if (error != kCGLNoError) { + throw std::runtime_error(std::string("Error creating GL context object:") + + CGLErrorString(error) + "\n"); + } + + error = CGLEnable(glContext, kCGLCEMPEngine); + if (error != kCGLNoError) { + throw std::runtime_error(std::string("Error enabling OpenGL multithreading:") + + CGLErrorString(error) + "\n"); + } } - ~CGLImpl() { + ~CGLImpl() final { CGLDestroyContext(glContext); } @@ -33,10 +100,13 @@ struct CGLImpl : public HeadlessBackend::Impl { } } +private: + const std::shared_ptr<const CGLDisplayConfig> cglDisplay = CGLDisplayConfig::create(); CGLContextObj glContext = nullptr; }; gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { + assert(hasContext()); static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")); if (!framework) { throw std::runtime_error("Failed to load OpenGL framework."); @@ -49,30 +119,9 @@ gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) { return reinterpret_cast<gl::ProcAddress>(symbol); } -bool HeadlessBackend::hasDisplay() { - if (!display) { - display = HeadlessDisplay::create(); - } - return bool(display); -} - void HeadlessBackend::createContext() { assert(!hasContext()); - - CGLContextObj glContext = nullptr; - CGLError error = CGLCreateContext(display->attribute<CGLPixelFormatObj>(), nullptr, &glContext); - if (error != kCGLNoError) { - throw std::runtime_error(std::string("Error creating GL context object:") + - CGLErrorString(error) + "\n"); - } - - error = CGLEnable(glContext, kCGLCEMPEngine); - if (error != kCGLNoError) { - throw std::runtime_error(std::string("Error enabling OpenGL multithreading:") + - CGLErrorString(error) + "\n"); - } - - impl.reset(new CGLImpl(glContext)); + impl = std::make_unique<CGLImpl>(); } } // namespace mbgl |