diff options
author | Bruno de Oliveira Abinader <bruno@mapbox.com> | 2016-11-06 13:04:59 +0200 |
---|---|---|
committer | Bruno de Oliveira Abinader <bruno@mapbox.com> | 2016-11-08 18:02:38 +0200 |
commit | 297c303e88416274d3d2c14b5f6abf1c850c3cf8 (patch) | |
tree | 7be5fb4768733727423871d8329a9a94ea1bd214 /platform/linux | |
parent | 5a828cb80fb69f88840d3085b79c9e756bf0e66d (diff) | |
download | qtlocation-mapboxgl-297c303e88416274d3d2c14b5f6abf1c850c3cf8.tar.gz |
[core] Refactor HeadlessDisplay
Diffstat (limited to 'platform/linux')
-rw-r--r-- | platform/linux/config.cmake | 5 | ||||
-rw-r--r-- | platform/linux/src/headless_backend_glx.cpp | 67 | ||||
-rw-r--r-- | platform/linux/src/headless_display_glx.cpp | 79 |
3 files changed, 149 insertions, 2 deletions
diff --git a/platform/linux/config.cmake b/platform/linux/config.cmake index 8acb6e7e14..76be2dddc3 100644 --- a/platform/linux/config.cmake +++ b/platform/linux/config.cmake @@ -14,7 +14,8 @@ include(cmake/loop-uv.cmake) macro(use_glx_backend _TARGET) target_sources(${_TARGET} - PRIVATE platform/default/headless_backend_glx.cpp + PRIVATE platform/linux/src/headless_backend_glx.cpp + PRIVATE platform/linux/src/headless_display_glx.cpp ) target_link_libraries(${_TARGET} @@ -26,6 +27,7 @@ endmacro() macro(use_osmesa_backend _TARGET) target_sources(${_TARGET} PRIVATE platform/default/headless_backend_osmesa.cpp + PRIVATE platform/default/headless_display.cpp ) target_add_mason_package(${_TARGET} @@ -70,7 +72,6 @@ macro(mbgl_platform_core) # Headless view PRIVATE platform/default/headless_backend.cpp - PRIVATE platform/default/headless_display.cpp PRIVATE platform/default/offscreen_view.cpp # Thread pool diff --git a/platform/linux/src/headless_backend_glx.cpp b/platform/linux/src/headless_backend_glx.cpp new file mode 100644 index 0000000000..929eb73f5a --- /dev/null +++ b/platform/linux/src/headless_backend_glx.cpp @@ -0,0 +1,67 @@ +#include <mbgl/platform/default/headless_backend.hpp> +#include <mbgl/platform/default/headless_display.hpp> + +#include <mbgl/platform/log.hpp> + +// #include <cassert> + +#include <GL/glx.h> + +namespace mbgl { + +gl::glProc HeadlessBackend::initializeExtension(const char* name) { + return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name)); +} + +void HeadlessBackend::createContext() { + xDisplay = display->attribute<Display*>(); + fbConfigs = display->attribute<GLXFBConfig*>(); + + if (!glContext) { + // Try to create a legacy context + glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, None, True); + if (glContext) { + if (!glXIsDirect(xDisplay, glContext)) { + Log::Error(Event::OpenGL, "failed to create direct OpenGL Legacy context"); + glXDestroyContext(xDisplay, glContext); + glContext = nullptr; + } + } + } + + if (glContext == nullptr) { + throw std::runtime_error("Error creating GL context object."); + } + + // Create a dummy pbuffer. We will render to framebuffers anyway, but we need a pbuffer to + // activate the context. + int pbufferAttributes[] = { + GLX_PBUFFER_WIDTH, 8, + GLX_PBUFFER_HEIGHT, 8, + None + }; + glxPbuffer = glXCreatePbuffer(xDisplay, fbConfigs[0], pbufferAttributes); +} + +void HeadlessBackend::destroyContext() { + if (glxPbuffer) { + glXDestroyPbuffer(xDisplay, glxPbuffer); + glxPbuffer = 0; + } + + glXDestroyContext(xDisplay, glContext); +} + +void HeadlessBackend::activateContext() { + if (!glXMakeContextCurrent(xDisplay, glxPbuffer, glxPbuffer, glContext)) { + throw std::runtime_error("Switching OpenGL context failed.\n"); + } +} + +void HeadlessBackend::deactivateContext() { + if (!glXMakeContextCurrent(xDisplay, 0, 0, nullptr)) { + throw std::runtime_error("Removing OpenGL context failed.\n"); + } +} + +} // namespace mbgl diff --git a/platform/linux/src/headless_display_glx.cpp b/platform/linux/src/headless_display_glx.cpp new file mode 100644 index 0000000000..2023d4dcd2 --- /dev/null +++ b/platform/linux/src/headless_display_glx.cpp @@ -0,0 +1,79 @@ +#include <mbgl/platform/default/headless_display.hpp> + +#include <GL/glx.h> + +#include <cstring> +#include <stdexcept> +#include <string> + +namespace mbgl { + +class HeadlessDisplay::Impl { +public: + Impl(); + ~Impl(); + + Display* xDisplay = nullptr; + GLXFBConfig* fbConfigs = nullptr; +}; + +HeadlessDisplay::Impl::Impl() { + if (!XInitThreads()) { + throw std::runtime_error("Failed to XInitThreads."); + } + + xDisplay = XOpenDisplay(nullptr); + if (xDisplay == nullptr) { + throw std::runtime_error("Failed to open X display."); + } + + const char *extensions = reinterpret_cast<const char *>(glXQueryServerString(xDisplay, DefaultScreen(xDisplay), GLX_EXTENSIONS)); + if (!extensions) { + throw std::runtime_error("Cannot read GLX extensions."); + } + if (!strstr(extensions,"GLX_SGIX_fbconfig")) { + throw std::runtime_error("Extension GLX_SGIX_fbconfig was not found."); + } + if (!strstr(extensions, "GLX_SGIX_pbuffer")) { + throw std::runtime_error("Cannot find glXCreateContextAttribsARB."); + } + + // We're creating a dummy pbuffer anyway that we're not using. + static int pixelFormat[] = { + GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT, + None + }; + + int configs = 0; + fbConfigs = glXChooseFBConfig(xDisplay, DefaultScreen(xDisplay), pixelFormat, &configs); + if (fbConfigs == nullptr) { + throw std::runtime_error("Failed to glXChooseFBConfig."); + } + if (configs <= 0) { + throw std::runtime_error("No Framebuffer configurations."); + } +} + +HeadlessDisplay::Impl::~Impl() { + XFree(fbConfigs); + XCloseDisplay(xDisplay); +} + +template <> +Display* HeadlessDisplay::attribute() const { + return impl->xDisplay; +} + +template <> +GLXFBConfig* HeadlessDisplay::attribute() const { + return impl->fbConfigs; +} + +HeadlessDisplay::HeadlessDisplay() + : impl(std::make_unique<Impl>()) { +} + +HeadlessDisplay::~HeadlessDisplay() { +} + +} // namespace mbgl |