make headless rendering work again by setting the correct fbo

This commit is contained in:
Konstantin Käfer
2014-07-07 12:39:03 -07:00
parent 853c9a5876
commit 59967fd709
5 changed files with 99 additions and 87 deletions

View File

@@ -150,8 +150,10 @@ private:
// ready for rendering.
std::atomic_flag is_rendered = ATOMIC_FLAG_INIT;
private:
public:
View &view;
private:
Transform transform;
TransformState state;

View File

@@ -20,6 +20,12 @@ public:
// renderer setup since the render thread doesn't switch the contexts.
virtual void make_active() = 0;
// Returns the base framebuffer object, if any, and 0 if using the system
// provided framebuffer.
virtual unsigned int root_fbo() {
return 0;
}
protected:
llmr::Map *map = nullptr;
};

View File

@@ -7,11 +7,7 @@ using namespace llmr;
void Painter::clearFramebuffers() {
#if TARGET_OS_IPHONE
glBindFramebuffer(GL_FRAMEBUFFER, 1);
#else
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
glBindFramebuffer(GL_FRAMEBUFFER, map.view.root_fbo());
// Delete any framebuffers that we might have allocated
glDeleteTextures((int)fbos_color.size(), fbos.data());
@@ -28,11 +24,7 @@ void Painter::clearFramebuffers() {
void Painter::bindFramebuffer() {
if (fbo_level < 0) {
#if TARGET_OS_IPHONE
glBindFramebuffer(GL_FRAMEBUFFER, 1);
#else
glBindFramebuffer(GL_FRAMEBUFFER, 0);
#endif
glBindFramebuffer(GL_FRAMEBUFFER, map.view.root_fbo());
} else if (fbos.size() > (size_t) fbo_level) {
GLuint fbo = fbos[fbo_level];
glBindFramebuffer(GL_FRAMEBUFFER, fbo);

View File

@@ -23,92 +23,104 @@ void notify_map_change(MapChange change) {
class View : public llmr::View {
public:
View(int width, int height) {
// 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;
}
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;
}
}
~View() {
glDeleteFramebuffersEXT(1, &fbo);
glDeleteTextures(1, &fbo_color);
glDeleteRenderbuffersEXT(1, &fbo_depth_stencil);
CGLDestroyContext(gl_context);
}
void make_active() {
CGLError error = CGLSetCurrentContext(gl_context);
if (error) {
fprintf(stderr, "Switching OpenGL context failed\n");
}
}
void swap() {}
CGLContextObj gl_context;
unsigned int root_fbo() {
return fbo;
}
private:
CGLContextObj gl_context;
GLuint fbo = 0;
GLuint fbo_depth_stencil = 0;
GLuint fbo_color = 0;
};
TEST(Headless, initialize) {
llmr::util::timer timer;
// Setup OpenGL
View view;
// 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, &view.gl_context);
CGLDestroyPixelFormat(pixelFormat);
if (error) {
fprintf(stderr, "Error creating GL context object\n");
return;
}
view.make_active();
timer.report("gl setup");
int width = 1024;
int height = 768;
// Create depth/stencil buffer
GLuint fbo_depth_stencil = 0;
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);
GLuint fbo_color = 0;
glGenRenderbuffersEXT(1, &fbo_color);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, fbo_color);
glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA8, width, height);
glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
GLuint fbo = 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;
}
timer.report("gl framebuffer");
// Setup OpenGL
View view(width, height);
timer.report("gl setup");
llmr::Map map(view);
@@ -121,6 +133,10 @@ TEST(Headless, initialize) {
map.setStyleJSON(stylejson.str());
map.setLonLatZoom(0, 0, 2);
map.setAngle(0);
map.setDebug(false);
timer.report("map resize");
// Run the loop. It will terminate when we don't have any further listeners.
@@ -130,6 +146,8 @@ TEST(Headless, initialize) {
uint32_t *pixels = new uint32_t[width * height];
view.make_active();
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
timer.report("gl readpixels");
@@ -146,11 +164,5 @@ TEST(Headless, initialize) {
delete[] pixels;
glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
glDeleteFramebuffersEXT(1, &fbo);
glDeleteTextures(1, &fbo_color);
glDeleteRenderbuffersEXT(1, &fbo_depth_stencil);
CGLDestroyContext(view.gl_context);
timer.report("destruct");
}