From 297c303e88416274d3d2c14b5f6abf1c850c3cf8 Mon Sep 17 00:00:00 2001 From: Bruno de Oliveira Abinader Date: Sun, 6 Nov 2016 13:04:59 +0200 Subject: [core] Refactor HeadlessDisplay --- platform/linux/config.cmake | 5 +- platform/linux/src/headless_backend_glx.cpp | 67 ++++++++++++++++++++++++ platform/linux/src/headless_display_glx.cpp | 79 +++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 platform/linux/src/headless_backend_glx.cpp create mode 100644 platform/linux/src/headless_display_glx.cpp (limited to 'platform/linux') 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 +#include + +#include + +// #include + +#include + +namespace mbgl { + +gl::glProc HeadlessBackend::initializeExtension(const char* name) { + return glXGetProcAddress(reinterpret_cast(name)); +} + +void HeadlessBackend::createContext() { + xDisplay = display->attribute(); + fbConfigs = display->attribute(); + + 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 + +#include + +#include +#include +#include + +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(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()) { +} + +HeadlessDisplay::~HeadlessDisplay() { +} + +} // namespace mbgl -- cgit v1.2.1