Files
MapLibreParticleLab/common/headless_view.cpp
2014-07-07 16:52:23 -07:00

190 lines
4.8 KiB
C++

#include "headless_view.hpp"
#include <llmr/util/timer.hpp>
#include <llmr/platform/platform.hpp>
namespace llmr {
namespace platform {
void notify_map_change(MapChange change) {
// no-op
}
}
HeadlessView::HeadlessView() {
#if LLMR_USE_CGL
// 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,
(CGLPixelFormatAttribute) kCGLOGLPVersion_Legacy,
kCGLPFAAccelerated,
(CGLPixelFormatAttribute) 0
};
CGLPixelFormatObj pixelFormat;
GLint num;
CGLError error = CGLChoosePixelFormat(attributes, &pixelFormat, &num);
if (error) {
fprintf(stderr, "Error pixel format\n");
return;
}
error = CGLCreateContext(pixelFormat, NULL, &gl_context);
CGLDestroyPixelFormat(pixelFormat);
if (error) {
fprintf(stderr, "Error creating GL context object\n");
return;
}
#endif
#if LLMR_USE_GLX
x_display = XOpenDisplay(0);
if (x_display == nullptr) {
throw std::runtime_error("Failed to open X display");
}
static int pixelFormat[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8,
None
};
x_info = glXChooseVisual(x_display, DefaultScreen(x_display), pixelFormat);
if (x_info == nullptr) {
throw std::runtime_error("Error pixel format");
}
gl_context = glXCreateContext(x_display, x_info, 0, GL_TRUE);
if (gl_context == nullptr) {
throw std::runtime_error("Error creating GL context object");
}
#endif
}
void HeadlessView::resize(int width, int height) {
clear_buffers();
#if LLMR_USE_CGL
make_active();
// Create depth/stencil buffer
glGenRenderbuffersEXT(1, &fbo_depth_stencil);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo_depth_stencil);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glGenRenderbuffersEXT(1, &fbo_color);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo_color);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
glGenFramebuffersEXT(1, &fbo);
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_RENDERBUFFER_EXT, fbo_color);
glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER_EXT, fbo_depth_stencil);
GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
fprintf(stderr, "Couldn't create framebuffer: ");
switch (status) {
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: fprintf(stderr, "incomplete attachment\n"); break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: fprintf(stderr, "incomplete missing attachment\n"); break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: fprintf(stderr, "incomplete draw buffer\n"); break;
case GL_FRAMEBUFFER_UNSUPPORTED: fprintf(stderr, "unsupported\n"); break;
default: fprintf(stderr, "other\n"); break;
}
return;
}
#endif
#if LLMR_USE_GLX
x_pixmap = XCreatePixmap(x_display, DefaultRootWindow(x_display), width, height, 32);
glx_pixmap = glXCreateGLXPixmap(x_display, x_info, x_pixmap);
make_active();
#endif
}
void HeadlessView::clear_buffers() {
#if LLMR_USE_CGL
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
if (fbo) {
glDeleteFramebuffersEXT(1, &fbo);
fbo = 0;
}
if (fbo_color) {
glDeleteTextures(1, &fbo_color);
fbo_color = 0;
}
if (fbo_depth_stencil) {
glDeleteRenderbuffersEXT(1, &fbo_depth_stencil);
fbo_depth_stencil = 0;
}
#endif
#if LLMR_USE_GLX
if (glx_pixmap) {
glXDestroyGLXPixmap(x_display, glx_pixmap);
glx_pixmap = 0;
}
if (x_pixmap) {
XFreePixmap(x_display, x_pixmap);
x_pixmap = 0;
}
#endif
}
HeadlessView::~HeadlessView() {
clear_buffers();
#if LLMR_USE_CGL
CGLDestroyContext(gl_context);
#endif
}
void HeadlessView::make_active() {
#if LLMR_USE_CGL
CGLError error = CGLSetCurrentContext(gl_context);
if (error) {
fprintf(stderr, "Switching OpenGL context failed\n");
}
#endif
#if LLMR_USE_GLX
if (!glXMakeCurrent(x_display, glx_pixmap, gl_context)) {
fprintf(stderr, "Switching OpenGL context failed\n");
}
#endif
}
void HeadlessView::swap() {}
unsigned int HeadlessView::root_fbo() {
#if LLMR_USE_CGL
return fbo;
#endif
return 0;
}
}