diff --git a/include/llmr/map/map.hpp b/include/llmr/map/map.hpp index 6ffb0b804..1af6b3c54 100644 --- a/include/llmr/map/map.hpp +++ b/include/llmr/map/map.hpp @@ -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; diff --git a/include/llmr/map/view.hpp b/include/llmr/map/view.hpp index 47ea24459..d032f783c 100644 --- a/include/llmr/map/view.hpp +++ b/include/llmr/map/view.hpp @@ -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; }; diff --git a/ios/mapbox-gl-cocoa b/ios/mapbox-gl-cocoa index 8269f98e8..698f31b3c 160000 --- a/ios/mapbox-gl-cocoa +++ b/ios/mapbox-gl-cocoa @@ -1 +1 @@ -Subproject commit 8269f98e8bbfe8522c9440e989eb7436995f1af4 +Subproject commit 698f31b3c777b50839aa116340614f6f18d5087a diff --git a/src/renderer/painter_framebuffers.cpp b/src/renderer/painter_framebuffers.cpp index a9dacf207..c7d9059dd 100644 --- a/src/renderer/painter_framebuffers.cpp +++ b/src/renderer/painter_framebuffers.cpp @@ -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); diff --git a/test/headless.cpp b/test/headless.cpp index 34a3f1db7..297b3f28e 100644 --- a/test/headless.cpp +++ b/test/headless.cpp @@ -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"); }