summaryrefslogtreecommitdiff
path: root/platform/default
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2016-02-17 18:23:23 +0100
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-03-22 11:56:01 -0700
commit61920071cd221d0d0627e01893185f0f19b55a98 (patch)
treee07358ba8bc9867ae979fd958d4eed3a7164230a /platform/default
parent1dd81d9776baf9b9ef61b05d29f7acbb0f2a1508 (diff)
downloadqtlocation-mapboxgl-61920071cd221d0d0627e01893185f0f19b55a98.tar.gz
[core] split headless_view.cpp into implementation-specific files
also adds a EAGL implementation for iOS
Diffstat (limited to 'platform/default')
-rw-r--r--platform/default/headless_view.cpp218
-rw-r--r--platform/default/headless_view_glx.cpp128
2 files changed, 150 insertions, 196 deletions
diff --git a/platform/default/headless_view.cpp b/platform/default/headless_view.cpp
index 7fd3c37f3a..9465f8ba9b 100644
--- a/platform/default/headless_view.cpp
+++ b/platform/default/headless_view.cpp
@@ -1,19 +1,8 @@
#include <mbgl/platform/default/headless_view.hpp>
#include <mbgl/platform/default/headless_display.hpp>
-#include <mbgl/platform/log.hpp>
-#include <stdexcept>
-#include <sstream>
-#include <string>
-#include <cstring>
#include <cassert>
-#include <utility>
-
-#ifdef MBGL_USE_CGL
-#include <CoreFoundation/CoreFoundation.h>
-#elif MBGL_USE_GLX
-#include <GL/glx.h>
-#endif
+#include <cstring>
namespace mbgl {
@@ -30,136 +19,30 @@ HeadlessView::HeadlessView(std::shared_ptr<HeadlessDisplay> display_,
resize(width, height);
}
+HeadlessView::~HeadlessView() {
+ activate();
+ clearBuffers();
+ deactivate();
+
+ destroyContext();
+}
+
+
void HeadlessView::loadExtensions() {
if (extensionsLoaded) {
return;
}
-#ifdef MBGL_USE_CGL
- gl::InitializeExtensions([](const char * name) {
- static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
- if (!framework) {
- throw std::runtime_error("Failed to load OpenGL framework.");
- }
-
- CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
- void* symbol = CFBundleGetFunctionPointerForName(framework, str);
- CFRelease(str);
-
- return reinterpret_cast<gl::glProc>(symbol);
- });
-#endif
-
-#ifdef MBGL_USE_GLX
- gl::InitializeExtensions([](const char * name) {
- return glXGetProcAddress(reinterpret_cast<const GLubyte *>(name));
- });
-#endif
+ gl::InitializeExtensions(initializeExtension);
extensionsLoaded = true;
}
-void HeadlessView::createContext() {
- if (!display) {
- throw std::runtime_error("Display is not set");
- }
-
-#if MBGL_USE_CGL
- CGLError error = CGLCreateContext(display->pixelFormat, NULL, &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");
- }
-#endif
-
-#if MBGL_USE_GLX
- xDisplay = display->xDisplay;
- fbConfigs = display->fbConfigs;
-
- 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 = 0;
- }
- }
- }
-
- if (glContext == 0) {
- 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);
-#endif
-}
bool HeadlessView::isActive() const {
return std::this_thread::get_id() == thread;
}
-void HeadlessView::resizeFramebuffer() {
- assert(isActive());
-
- if (!needsResize) return;
-
- clearBuffers();
-
- const unsigned int w = dimensions[0] * pixelRatio;
- const unsigned int h = dimensions[1] * pixelRatio;
-
- // Create depth/stencil buffer
- MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboDepthStencil));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fboDepthStencil));
- MBGL_CHECK_ERROR(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, w, h));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
-
- MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboColor));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fboColor));
- MBGL_CHECK_ERROR(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, w, h));
- MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
-
- MBGL_CHECK_ERROR(glGenFramebuffersEXT(1, &fbo));
- MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo));
-
- MBGL_CHECK_ERROR(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, fboColor));
- MBGL_CHECK_ERROR(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER_EXT, fboDepthStencil));
-
- GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
-
- if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
- std::string error("Couldn't create framebuffer: ");
- switch (status) {
- case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: (error += "incomplete attachment"); break;
- case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: error += "incomplete missing attachment"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: error += "incomplete dimensions"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: error += "incomplete formats"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: error += "incomplete draw buffer"; break;
- case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: error += "incomplete read buffer"; break;
- case GL_FRAMEBUFFER_UNSUPPORTED: error += "unsupported"; break;
- default: error += "other"; break;
- }
- throw std::runtime_error(error);
- }
-
- MBGL_CHECK_ERROR(glViewport(0, 0, w, h));
-
- needsResize = false;
-}
-
void HeadlessView::resize(const uint16_t width, const uint16_t height) {
if(dimensions[0] == width &&
dimensions[1] == height) {
@@ -178,7 +61,7 @@ PremultipliedImage HeadlessView::readStillImage() {
PremultipliedImage image { w, h };
MBGL_CHECK_ERROR(glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, image.data.get()));
- const int stride = image.stride();
+ const auto stride = image.stride();
auto tmp = std::make_unique<uint8_t[]>(stride);
uint8_t* rgba = image.data.get();
for (int i = 0, j = h - 1; i < j; i++, j--) {
@@ -189,47 +72,6 @@ PremultipliedImage HeadlessView::readStillImage() {
return image;
}
-
-void HeadlessView::clearBuffers() {
- assert(isActive());
-
- MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
-
- if (fbo) {
- MBGL_CHECK_ERROR(glDeleteFramebuffersEXT(1, &fbo));
- fbo = 0;
- }
-
- if (fboColor) {
- MBGL_CHECK_ERROR(glDeleteRenderbuffersEXT(1, &fboColor));
- fboColor = 0;
- }
-
- if (fboDepthStencil) {
- MBGL_CHECK_ERROR(glDeleteRenderbuffersEXT(1, &fboDepthStencil));
- fboDepthStencil = 0;
- }
-}
-
-HeadlessView::~HeadlessView() {
- activate();
- clearBuffers();
- deactivate();
-
-#if MBGL_USE_CGL
- CGLDestroyContext(glContext);
-#endif
-
-#if MBGL_USE_GLX
- if (glxPbuffer) {
- glXDestroyPbuffer(xDisplay, glxPbuffer);
- glxPbuffer = 0;
- }
-
- glXDestroyContext(xDisplay, glContext);
-#endif
-}
-
void HeadlessView::notify() {
// no-op
}
@@ -254,22 +96,13 @@ void HeadlessView::activate() {
thread = std::this_thread::get_id();
if (!glContext) {
+ if (!display) {
+ throw std::runtime_error("Display is not set");
+ }
createContext();
}
-#if MBGL_USE_CGL
- CGLError error = CGLSetCurrentContext(glContext);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Switching OpenGL context failed:") + CGLErrorString(error) + "\n");
- }
-#endif
-
-#if MBGL_USE_GLX
- if (!glXMakeContextCurrent(xDisplay, glxPbuffer, glxPbuffer, glContext)) {
- throw std::runtime_error("Switching OpenGL context failed.\n");
- }
-#endif
-
+ activateContext();
loadExtensions();
}
@@ -279,18 +112,7 @@ void HeadlessView::deactivate() {
}
thread = std::thread::id();
-#if MBGL_USE_CGL
- CGLError error = CGLSetCurrentContext(nullptr);
- if (error != kCGLNoError) {
- throw std::runtime_error(std::string("Removing OpenGL context failed:") + CGLErrorString(error) + "\n");
- }
-#endif
-
-#if MBGL_USE_GLX
- if (!glXMakeContextCurrent(xDisplay, 0, 0, nullptr)) {
- throw std::runtime_error("Removing OpenGL context failed.\n");
- }
-#endif
+ deactivateContext();
}
void HeadlessView::invalidate() {
@@ -298,7 +120,11 @@ void HeadlessView::invalidate() {
}
void HeadlessView::beforeRender() {
- resizeFramebuffer();
+ if (needsResize) {
+ clearBuffers();
+ resizeFramebuffer();
+ needsResize = false;
+ }
}
void HeadlessView::afterRender() {
diff --git a/platform/default/headless_view_glx.cpp b/platform/default/headless_view_glx.cpp
new file mode 100644
index 0000000000..d7ad9f5e55
--- /dev/null
+++ b/platform/default/headless_view_glx.cpp
@@ -0,0 +1,128 @@
+#include <mbgl/platform/default/headless_view.hpp>
+#include <mbgl/platform/default/headless_display.hpp>
+#include <mbgl/platform/log.hpp>
+
+#include <cassert>
+
+#include <GL/glx.h>
+
+namespace mbgl {
+
+gl::glProc HeadlessView::initializeExtension(const char* name) {
+ return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
+}
+
+void HeadlessView::createContext() {
+ xDisplay = display->xDisplay;
+ fbConfigs = display->fbConfigs;
+
+ 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 = 0;
+ }
+ }
+ }
+
+ if (glContext == 0) {
+ 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 HeadlessView::destroyContext() {
+ if (glxPbuffer) {
+ glXDestroyPbuffer(xDisplay, glxPbuffer);
+ glxPbuffer = 0;
+ }
+
+ glXDestroyContext(xDisplay, glContext);
+}
+
+void HeadlessView::resizeFramebuffer() {
+ const unsigned int w = dimensions[0] * pixelRatio;
+ const unsigned int h = dimensions[1] * pixelRatio;
+
+ // Create depth/stencil buffer
+ MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboDepthStencil));
+ MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fboDepthStencil));
+ MBGL_CHECK_ERROR(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, w, h));
+ MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
+
+ MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboColor));
+ MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fboColor));
+ MBGL_CHECK_ERROR(glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, w, h));
+ MBGL_CHECK_ERROR(glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0));
+
+ MBGL_CHECK_ERROR(glGenFramebuffersEXT(1, &fbo));
+ MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo));
+
+ MBGL_CHECK_ERROR(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, fboColor));
+ MBGL_CHECK_ERROR(glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER_EXT, fboDepthStencil));
+
+ GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
+
+ if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
+ std::string error("Couldn't create framebuffer: ");
+ switch (status) {
+ case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: (error += "incomplete attachment"); break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: error += "incomplete missing attachment"; break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: error += "incomplete dimensions"; break;
+ case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: error += "incomplete formats"; break;
+ case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: error += "incomplete draw buffer"; break;
+ case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: error += "incomplete read buffer"; break;
+ case GL_FRAMEBUFFER_UNSUPPORTED: error += "unsupported"; break;
+ default: error += "other"; break;
+ }
+ throw std::runtime_error(error);
+ }
+
+ MBGL_CHECK_ERROR(glViewport(0, 0, w, h));
+}
+
+void HeadlessView::clearBuffers() {
+ assert(isActive());
+
+ MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
+
+ if (fbo) {
+ MBGL_CHECK_ERROR(glDeleteFramebuffersEXT(1, &fbo));
+ fbo = 0;
+ }
+
+ if (fboColor) {
+ MBGL_CHECK_ERROR(glDeleteRenderbuffersEXT(1, &fboColor));
+ fboColor = 0;
+ }
+
+ if (fboDepthStencil) {
+ MBGL_CHECK_ERROR(glDeleteRenderbuffersEXT(1, &fboDepthStencil));
+ fboDepthStencil = 0;
+ }
+}
+
+void HeadlessView::activateContext() {
+ if (!glXMakeContextCurrent(xDisplay, glxPbuffer, glxPbuffer, glContext)) {
+ throw std::runtime_error("Switching OpenGL context failed.\n");
+ }
+}
+
+void HeadlessView::deactivateContext() {
+ if (!glXMakeContextCurrent(xDisplay, 0, 0, nullptr)) {
+ throw std::runtime_error("Removing OpenGL context failed.\n");
+ }
+}
+
+} // namespace mbgl