Merge branch 'master' of github.com:mapbox/mapbox-gl-native into android-mason
Conflicts: Makefile platform/default/headless_view.cpp src/mbgl/map/map.cpp
This commit is contained in:
15
Makefile
15
Makefile
@@ -53,6 +53,10 @@ build/linux/Makefile: linux/mapboxgl-app.gyp config.gypi
|
||||
build/macosx/Makefile: macosx/mapboxgl-app.gyp config.gypi
|
||||
deps/run_gyp macosx/mapboxgl-app.gyp -Iconfig.gypi -Dplatform=osx --depth=. -Goutput_dir=.. --generator-output=./build/macosx -f make
|
||||
|
||||
.PHONY: build/render/Makefile
|
||||
build/render/Makefile: bin/render.gyp config.gypi
|
||||
deps/run_gyp bin/render.gyp -Iconfig.gypi -Dplatform=$(PLATFORM) --depth=. -Goutput_dir=.. --generator-output=./build/render -f make
|
||||
|
||||
.PHONY: build/test/test.xcodeproj
|
||||
build/test/test.xcodeproj: test/test.gyp config.gypi
|
||||
deps/run_gyp test/test.gyp -Iconfig.gypi -Dplatform=$(PLATFORM) --depth=. -Goutput_dir=.. --generator-output=./build -f xcode
|
||||
@@ -69,6 +73,10 @@ build/ios/mapbox-gl-cocoa/app/mapboxgl-app.xcodeproj: ios/mapbox-gl-cocoa/app/ma
|
||||
build/linux/mapboxgl-app.xcodeproj: linux/mapboxgl-app.gyp config.gypi
|
||||
deps/run_gyp linux/mapboxgl-app.gyp -Iconfig.gypi -Dplatform=linux --depth=. --generator-output=./build -f xcode
|
||||
|
||||
.PHONY: build/bin/render.xcodeproj
|
||||
build/bin/render.xcodeproj: bin/render.gyp config.gypi
|
||||
deps/run_gyp bin/render.gyp -Iconfig.gypi -Dplatform=$(PLATFORM) --depth=. --generator-output=./build -f xcode
|
||||
|
||||
.PHONY: android
|
||||
android:
|
||||
./scripts/local_mason.sh && \
|
||||
@@ -126,6 +134,10 @@ osx: build/macosx/Makefile
|
||||
run-osx: osx
|
||||
build/$(BUILDTYPE)/Mapbox\ GL.app/Contents/MacOS/MAPBOX\ GL
|
||||
|
||||
# Builds the CLI render app
|
||||
render: build/render/Makefile
|
||||
$(MAKE) -C build/render BUILDTYPE=$(BUILDTYPE) V=$(V) mbgl-render
|
||||
|
||||
##### Xcode projects ###########################################################
|
||||
|
||||
clear_xcode_cache:
|
||||
@@ -145,6 +157,9 @@ xproj: build/macosx/mapboxgl-app.xcodeproj
|
||||
iproj: build/ios/mapbox-gl-cocoa/app/mapboxgl-app.xcodeproj
|
||||
open ./build/ios/mapbox-gl-cocoa/app/mapboxgl-app.xcodeproj
|
||||
|
||||
rproj: build/bin/render.xcodeproj
|
||||
open ./build/bin/render.xcodeproj
|
||||
|
||||
# build Linux project for Xcode (Runs on Mac OS X too, but without platform-specific code)
|
||||
lproj: build/linux/mapboxgl-app.xcodeproj
|
||||
open ./build/linux/mapboxgl-app.xcodeproj
|
||||
|
||||
115
bin/render.cpp
Normal file
115
bin/render.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/util/image.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
#include <mbgl/util/io.hpp>
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/writer.h>
|
||||
#include <rapidjson/stringbuffer.h>
|
||||
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/storage/caching_http_file_source.hpp>
|
||||
|
||||
#if __APPLE__
|
||||
#include <mbgl/platform/darwin/log_nslog.hpp>
|
||||
#else
|
||||
#include <mbgl/platform/default/log_stderr.hpp>
|
||||
#endif
|
||||
|
||||
#include <boost/program_options.hpp>
|
||||
namespace po = boost::program_options;
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
std::string style_path;
|
||||
double lat = 0, lon = 0;
|
||||
double zoom = 0;
|
||||
double bearing = 0;
|
||||
|
||||
int width = 256;
|
||||
int height = 256;
|
||||
double pixelRatio = 1.0;
|
||||
std::string output = "out.png";
|
||||
std::string cache = "cache.sqlite";
|
||||
std::vector<std::string> classes;
|
||||
std::string token;
|
||||
|
||||
po::options_description desc("Allowed options");
|
||||
desc.add_options()
|
||||
("style,s", po::value(&style_path)->required()->value_name("json"), "Map stylesheet")
|
||||
("lon,x", po::value(&lon)->value_name("degrees")->default_value(lon), "Longitude")
|
||||
("lat,y", po::value(&lat)->value_name("degrees")->default_value(lat), "Latitude in degrees")
|
||||
("zoom,z", po::value(&zoom)->value_name("number")->default_value(zoom), "Zoom level")
|
||||
("bearing,b", po::value(&bearing)->value_name("degrees")->default_value(bearing), "Bearing")
|
||||
("width,w", po::value(&width)->value_name("pixels")->default_value(width), "Image width")
|
||||
("height,h", po::value(&height)->value_name("pixels")->default_value(height), "Image height")
|
||||
("class,c", po::value(&classes)->value_name("name"), "Class name")
|
||||
("token,t", po::value(&token)->value_name("key")->default_value(token), "Mapbox access token")
|
||||
("output,o", po::value(&output)->value_name("file")->default_value(output), "Output file name")
|
||||
("cache,d", po::value(&cache)->value_name("file")->default_value(cache), "Cache database file name")
|
||||
;
|
||||
|
||||
try {
|
||||
po::variables_map vm;
|
||||
po::store(po::parse_command_line(argc, argv, desc), vm);
|
||||
po::notify(vm);
|
||||
} catch(std::exception& e) {
|
||||
std::cout << "Error: " << e.what() << std::endl << desc;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
std::string style = mbgl::util::read_file(style_path);
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
|
||||
#if __APPLE__
|
||||
Log::Set<NSLogBackend>();
|
||||
#else
|
||||
Log::Set<StderrLogBackend>();
|
||||
#endif
|
||||
|
||||
CachingHTTPFileSource fileSource(cache);
|
||||
|
||||
// Try to load the token from the environment.
|
||||
if (!token.size()) {
|
||||
const char *token_ptr = getenv("MAPBOX_ACCESS_TOKEN");
|
||||
if (token_ptr) {
|
||||
token = token_ptr;
|
||||
}
|
||||
}
|
||||
|
||||
// Set access token if present
|
||||
if (token.size()) {
|
||||
fileSource.setAccessToken(std::string(token));
|
||||
}
|
||||
|
||||
HeadlessView view;
|
||||
Map map(view, fileSource);
|
||||
|
||||
map.setStyleJSON(style, ".");
|
||||
map.setAppliedClasses(classes);
|
||||
|
||||
view.resize(width, height, pixelRatio);
|
||||
map.resize(width, height, pixelRatio);
|
||||
map.setLonLatZoom(lon, lat, zoom);
|
||||
map.setBearing(bearing);
|
||||
|
||||
std::unique_ptr<uint32_t[]> pixels;
|
||||
|
||||
// Run the loop. It will terminate when we don't have any further listeners.
|
||||
map.run();
|
||||
|
||||
// Get the data from the GPU.
|
||||
pixels = view.readPixels();
|
||||
|
||||
const unsigned int w = width * pixelRatio;
|
||||
const unsigned int h = height * pixelRatio;
|
||||
const std::string image = util::compress_png(w, h, pixels.get());
|
||||
util::write_file(output, image);
|
||||
}
|
||||
53
bin/render.gyp
Normal file
53
bin/render.gyp
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
'includes': [
|
||||
'../gyp/common.gypi',
|
||||
],
|
||||
'targets': [
|
||||
{
|
||||
'target_name': 'mbgl-render',
|
||||
'product_name': 'mbgl-render',
|
||||
'type': 'executable',
|
||||
'sources': [
|
||||
'./render.cpp',
|
||||
],
|
||||
'variables' : {
|
||||
'cflags': [
|
||||
'<@(uv_cflags)',
|
||||
'<@(png_cflags)',
|
||||
'-I<(boost_root)/include',
|
||||
],
|
||||
'ldflags': [
|
||||
'<@(glfw3_ldflags)',
|
||||
'<@(uv_ldflags)',
|
||||
'<@(sqlite3_ldflags)',
|
||||
'<@(curl_ldflags)',
|
||||
'<@(png_ldflags)',
|
||||
'<@(uv_static_libs)',
|
||||
'-L<(boost_root)/lib',
|
||||
'-lboost_program_options'
|
||||
],
|
||||
},
|
||||
'conditions': [
|
||||
# add libuv include path and OpenGL libs
|
||||
['OS == "mac"',
|
||||
{
|
||||
'xcode_settings': {
|
||||
'OTHER_CPLUSPLUSFLAGS': ['<@(cflags)'],
|
||||
'OTHER_LDFLAGS': ['<@(ldflags)'],
|
||||
},
|
||||
},
|
||||
{
|
||||
'cflags': ['<@(cflags)'],
|
||||
'libraries': ['<@(ldflags)'],
|
||||
}],
|
||||
],
|
||||
'include_dirs': [ '../src' ],
|
||||
'dependencies': [
|
||||
'../mapboxgl.gyp:mbgl-standalone',
|
||||
'../mapboxgl.gyp:mbgl-headless',
|
||||
'../mapboxgl.gyp:mbgl-<(platform)',
|
||||
'../mapboxgl.gyp:copy_certificate_bundle',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -148,7 +148,14 @@ private:
|
||||
// Unconditionally performs a render with the current map state.
|
||||
void render();
|
||||
|
||||
bool async = false;
|
||||
enum class Mode : uint8_t {
|
||||
None, // we're not doing any processing
|
||||
Continuous, // continually updating map
|
||||
Static, // a once-off static image.
|
||||
};
|
||||
|
||||
Mode mode = Mode::None;
|
||||
|
||||
std::unique_ptr<uv::loop> loop;
|
||||
std::unique_ptr<uv::worker> workers;
|
||||
std::thread thread;
|
||||
|
||||
@@ -152,12 +152,16 @@ void GLFWView::initialize(mbgl::Map *map_) {
|
||||
}
|
||||
|
||||
if (extensions.find("GL_ARB_get_program_binary") != std::string::npos) {
|
||||
gl::GetProgramBinary = (gl::PFNGLGETPROGRAMBINARYPROC)glfwGetProcAddress("glGetProgramBinary");
|
||||
gl::ProgramBinary = (gl::PFNGLPROGRAMBINARYPROC)glfwGetProcAddress("glProgramBinary");
|
||||
gl::ProgramParameteri = (gl::PFNGLPROGRAMPARAMETERIPROC)glfwGetProcAddress("glProgramParameteri");
|
||||
assert(gl::GetProgramBinary != nullptr);
|
||||
assert(gl::ProgramBinary != nullptr);
|
||||
assert(gl::ProgramParameteri != nullptr);
|
||||
GLint numBinaryFormats;
|
||||
MBGL_CHECK_ERROR(glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS, &numBinaryFormats));
|
||||
if (numBinaryFormats > 0) {
|
||||
gl::GetProgramBinary = (gl::PFNGLGETPROGRAMBINARYPROC)glfwGetProcAddress("glGetProgramBinary");
|
||||
gl::ProgramBinary = (gl::PFNGLPROGRAMBINARYPROC)glfwGetProcAddress("glProgramBinary");
|
||||
gl::ProgramParameteri = (gl::PFNGLPROGRAMPARAMETERIPROC)glfwGetProcAddress("glProgramParameteri");
|
||||
assert(gl::GetProgramBinary != nullptr);
|
||||
assert(gl::ProgramBinary != nullptr);
|
||||
assert(gl::ProgramParameteri != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
// Require packed depth stencil
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
#include <mbgl/util/std.hpp>
|
||||
|
||||
@@ -9,12 +10,6 @@
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#if MBGL_USE_GLX
|
||||
#ifdef GLX_ARB_create_context
|
||||
static PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB = nullptr;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MBGL_USE_CGL
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
@@ -53,47 +48,36 @@ HeadlessView::HeadlessView(std::shared_ptr<HeadlessDisplay> display)
|
||||
void HeadlessView::loadExtensions() {
|
||||
make_active();
|
||||
|
||||
std::string extensions;
|
||||
if (usingGl3OrNewer) {
|
||||
#ifdef GL_VERSION_3_0
|
||||
GLuint num_extensions = 0;
|
||||
MBGL_CHECK_ERROR(glGetIntegerv(GL_NUM_EXTENSIONS, reinterpret_cast<GLint *>(&num_extensions)));
|
||||
for (GLuint i = 0; i < num_extensions; i++) {
|
||||
std::string extension = MBGL_CHECK_ERROR(reinterpret_cast<const char *>(glGetStringi(GL_EXTENSIONS, i)));
|
||||
extensions.append(extension);
|
||||
extensions.append(" ");
|
||||
}
|
||||
#else
|
||||
throw std::runtime_error("Using GL 3.0+ context with out correct headers.\n");
|
||||
#endif
|
||||
} else {
|
||||
extensions = MBGL_CHECK_ERROR(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS)));
|
||||
}
|
||||
const char *extensionPtr = (char *)MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS));
|
||||
|
||||
if (extensionPtr) {
|
||||
const std::string extensions = extensionPtr;
|
||||
|
||||
#ifdef MBGL_USE_CGL
|
||||
if (extensions.find("GL_APPLE_vertex_array_object") != std::string::npos) {
|
||||
gl::BindVertexArray = (gl::PFNGLBINDVERTEXARRAYPROC)CGLGetProcAddress("glBindVertexArrayAPPLE");
|
||||
gl::DeleteVertexArrays = (gl::PFNGLDELETEVERTEXARRAYSPROC)CGLGetProcAddress("glDeleteVertexArraysAPPLE");
|
||||
gl::GenVertexArrays = (gl::PFNGLGENVERTEXARRAYSPROC)CGLGetProcAddress("glGenVertexArraysAPPLE");
|
||||
gl::IsVertexArray = (gl::PFNGLISVERTEXARRAYPROC)CGLGetProcAddress("glIsVertexArrayAPPLE");
|
||||
assert(gl::BindVertexArray != nullptr);
|
||||
assert(gl::DeleteVertexArrays != nullptr);
|
||||
assert(gl::GenVertexArrays != nullptr);
|
||||
assert(gl::IsVertexArray != nullptr);
|
||||
}
|
||||
if (extensions.find("GL_APPLE_vertex_array_object") != std::string::npos) {
|
||||
gl::BindVertexArray = (gl::PFNGLBINDVERTEXARRAYPROC)CGLGetProcAddress("glBindVertexArrayAPPLE");
|
||||
gl::DeleteVertexArrays = (gl::PFNGLDELETEVERTEXARRAYSPROC)CGLGetProcAddress("glDeleteVertexArraysAPPLE");
|
||||
gl::GenVertexArrays = (gl::PFNGLGENVERTEXARRAYSPROC)CGLGetProcAddress("glGenVertexArraysAPPLE");
|
||||
gl::IsVertexArray = (gl::PFNGLISVERTEXARRAYPROC)CGLGetProcAddress("glIsVertexArrayAPPLE");
|
||||
assert(gl::BindVertexArray != nullptr);
|
||||
assert(gl::DeleteVertexArrays != nullptr);
|
||||
assert(gl::GenVertexArrays != nullptr);
|
||||
assert(gl::IsVertexArray != nullptr);
|
||||
}
|
||||
#endif
|
||||
#ifdef MBGL_USE_GLX
|
||||
if (extensions.find("GL_ARB_vertex_array_object") != std::string::npos) {
|
||||
gl::BindVertexArray = (gl::PFNGLBINDVERTEXARRAYPROC)glXGetProcAddress((const GLubyte *)"glBindVertexArray");
|
||||
gl::DeleteVertexArrays = (gl::PFNGLDELETEVERTEXARRAYSPROC)glXGetProcAddress((const GLubyte *)"glDeleteVertexArrays");
|
||||
gl::GenVertexArrays = (gl::PFNGLGENVERTEXARRAYSPROC)glXGetProcAddress((const GLubyte *)"glGenVertexArrays");
|
||||
gl::IsVertexArray = (gl::PFNGLISVERTEXARRAYPROC)glXGetProcAddress((const GLubyte *)"glIsVertexArray");
|
||||
assert(gl::BindVertexArray != nullptr);
|
||||
assert(gl::DeleteVertexArrays != nullptr);
|
||||
assert(gl::GenVertexArrays != nullptr);
|
||||
assert(gl::IsVertexArray != nullptr);
|
||||
}
|
||||
if (extensions.find("GL_ARB_vertex_array_object") != std::string::npos) {
|
||||
gl::BindVertexArray = (gl::PFNGLBINDVERTEXARRAYPROC)glXGetProcAddress((const GLubyte *)"glBindVertexArray");
|
||||
gl::DeleteVertexArrays = (gl::PFNGLDELETEVERTEXARRAYSPROC)glXGetProcAddress((const GLubyte *)"glDeleteVertexArrays");
|
||||
gl::GenVertexArrays = (gl::PFNGLGENVERTEXARRAYSPROC)glXGetProcAddress((const GLubyte *)"glGenVertexArrays");
|
||||
gl::IsVertexArray = (gl::PFNGLISVERTEXARRAYPROC)glXGetProcAddress((const GLubyte *)"glIsVertexArray");
|
||||
assert(gl::BindVertexArray != nullptr);
|
||||
assert(gl::DeleteVertexArrays != nullptr);
|
||||
assert(gl::GenVertexArrays != nullptr);
|
||||
assert(gl::IsVertexArray != nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// HeadlessView requires packed depth stencil
|
||||
gl::isPackedDepthStencilSupported = true;
|
||||
@@ -102,64 +86,6 @@ void HeadlessView::loadExtensions() {
|
||||
make_inactive();
|
||||
}
|
||||
|
||||
|
||||
#if MBGL_USE_GLX
|
||||
#ifdef GLX_ARB_create_context
|
||||
|
||||
// These are all of the OpenGL Core profile version that we know about.
|
||||
struct core_profile_version { int major, minor; };
|
||||
static const core_profile_version coreProfileVersions[] = {
|
||||
{4, 5},
|
||||
{4, 4},
|
||||
{4, 3},
|
||||
{4, 2},
|
||||
{4, 1},
|
||||
{4, 0},
|
||||
{3, 3},
|
||||
{3, 2},
|
||||
{3, 1},
|
||||
{3, 0},
|
||||
{0, 0},
|
||||
};
|
||||
|
||||
GLXContext createCoreProfile(Display *dpy, GLXFBConfig fbConfig, bool& usingGl3OrNewer) {
|
||||
static bool contextCreationFailed = false;
|
||||
GLXContext ctx = 0;
|
||||
|
||||
// Set the Error Handler to avoid crashing the program when the context creation fails.
|
||||
// It is expected that some context creation attempts fail, e.g. because the OpenGL
|
||||
// implementation does not support the version we're requesting.
|
||||
int (*previousErrorHandler)(Display *, XErrorEvent *) = XSetErrorHandler([](Display *, XErrorEvent *) {
|
||||
contextCreationFailed = true;
|
||||
return 0;
|
||||
});
|
||||
|
||||
// Try to create core profiles from the highest known version on down.
|
||||
int i = 0;
|
||||
for (; !ctx && coreProfileVersions[i].major; i++) {
|
||||
contextCreationFailed = false;
|
||||
const int contextFlags[] = {
|
||||
GLX_CONTEXT_MAJOR_VERSION_ARB, coreProfileVersions[i].major,
|
||||
GLX_CONTEXT_MINOR_VERSION_ARB, coreProfileVersions[i].minor,
|
||||
0
|
||||
};
|
||||
ctx = glXCreateContextAttribsARB(dpy, fbConfig, 0, True, contextFlags);
|
||||
if (contextCreationFailed) {
|
||||
ctx = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (coreProfileVersions[i].major >= 3) {
|
||||
usingGl3OrNewer = true;
|
||||
}
|
||||
|
||||
// Restore the old error handler.
|
||||
XSetErrorHandler(previousErrorHandler);
|
||||
return ctx;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void HeadlessView::createContext() {
|
||||
#if MBGL_USE_CGL
|
||||
CGLError error = CGLCreateContext(display_->pixelFormat, NULL, &glContext);
|
||||
@@ -174,27 +100,15 @@ void HeadlessView::createContext() {
|
||||
#endif
|
||||
|
||||
#if MBGL_USE_GLX
|
||||
#ifdef GLX_ARB_create_context
|
||||
if (glXCreateContextAttribsARB == nullptr) {
|
||||
glXCreateContextAttribsARB = (PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddressARB((const GLubyte *)"glXCreateContextAttribsARB");
|
||||
}
|
||||
#endif
|
||||
|
||||
xDisplay = display_->xDisplay;
|
||||
fbConfigs = display_->fbConfigs;
|
||||
|
||||
#ifdef GLX_ARB_create_context
|
||||
if (glXCreateContextAttribsARB) {
|
||||
// Try to create a core profile context.
|
||||
glContext = createCoreProfile(xDisplay, fbConfigs[0], usingGl3OrNewer);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (glContext == 0) {
|
||||
if (!glContext) {
|
||||
// Try to create a legacy context
|
||||
glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, 0, True);
|
||||
if (glContext) {
|
||||
if (!glXIsDirect(xDisplay, glContext)) {
|
||||
mbgl::Log::Error(mbgl::Event::OpenGL, "Failed to create direct OpenGL Legacy context");
|
||||
glXDestroyContext(xDisplay, glContext);
|
||||
glContext = 0;
|
||||
}
|
||||
|
||||
@@ -96,6 +96,7 @@ Map::Map(View& view_, FileSource& fileSource_)
|
||||
view(view_),
|
||||
#ifndef NDEBUG
|
||||
mainThread(std::this_thread::get_id()),
|
||||
mapThread(mainThread),
|
||||
#endif
|
||||
transform(view_),
|
||||
fileSource(fileSource_),
|
||||
@@ -113,7 +114,7 @@ Map::Map(View& view_, FileSource& fileSource_)
|
||||
}
|
||||
|
||||
Map::~Map() {
|
||||
if (async) {
|
||||
if (mode == Mode::Continuous) {
|
||||
stop();
|
||||
}
|
||||
|
||||
@@ -137,11 +138,11 @@ uv::worker &Map::getWorker() {
|
||||
|
||||
void Map::start(bool startPaused) {
|
||||
assert(std::this_thread::get_id() == mainThread);
|
||||
assert(!async);
|
||||
assert(mode == Mode::None);
|
||||
|
||||
// When starting map rendering in another thread, we perform async/continuously
|
||||
// updated rendering. Only in these cases, we attach the async handlers.
|
||||
async = true;
|
||||
mode = Mode::Continuous;
|
||||
|
||||
// Reset the flag.
|
||||
isStopped = false;
|
||||
@@ -212,7 +213,7 @@ void Map::start(bool startPaused) {
|
||||
void Map::stop(std::function<void ()> callback) {
|
||||
assert(std::this_thread::get_id() == mainThread);
|
||||
assert(mainThread != mapThread);
|
||||
assert(async);
|
||||
assert(mode == Mode::Continuous);
|
||||
|
||||
asyncTerminate->send();
|
||||
|
||||
@@ -234,12 +235,12 @@ void Map::stop(std::function<void ()> callback) {
|
||||
// already finished executing.
|
||||
thread.join();
|
||||
|
||||
async = false;
|
||||
mode = Mode::None;
|
||||
}
|
||||
|
||||
void Map::pause(bool waitForPause) {
|
||||
assert(std::this_thread::get_id() == mainThread);
|
||||
assert(async);
|
||||
assert(mode == Mode::Continuous);
|
||||
mutexRun.lock();
|
||||
pausing = true;
|
||||
mutexRun.unlock();
|
||||
@@ -257,7 +258,7 @@ void Map::pause(bool waitForPause) {
|
||||
|
||||
void Map::resume() {
|
||||
assert(std::this_thread::get_id() == mainThread);
|
||||
assert(async);
|
||||
assert(mode == Mode::Continuous);
|
||||
|
||||
mutexRun.lock();
|
||||
pausing = false;
|
||||
@@ -270,21 +271,22 @@ void Map::run() {
|
||||
COFFEE_TRY() {
|
||||
#endif
|
||||
|
||||
if (mode == Mode::None) {
|
||||
#ifndef NDEBUG
|
||||
if (!async) {
|
||||
mapThread = mainThread;
|
||||
}
|
||||
#endif
|
||||
mode = Mode::Static;
|
||||
}
|
||||
assert(std::this_thread::get_id() == mapThread);
|
||||
|
||||
if (async) {
|
||||
if (mode == Mode::Continuous) {
|
||||
checkForPause();
|
||||
}
|
||||
|
||||
setup();
|
||||
prepare();
|
||||
|
||||
if (async) {
|
||||
if (mode == Mode::Continuous) {
|
||||
terminating = false;
|
||||
while(!terminating) {
|
||||
uv_run(**loop, UV_RUN_DEFAULT);
|
||||
@@ -299,11 +301,13 @@ void Map::run() {
|
||||
|
||||
// If the map rendering wasn't started asynchronously, we perform one render
|
||||
// *after* all events have been processed.
|
||||
if (!async) {
|
||||
if (mode == Mode::Static) {
|
||||
render();
|
||||
#ifndef NDEBUG
|
||||
mapThread = std::thread::id();
|
||||
#endif
|
||||
mode = Mode::None;
|
||||
fileSource.clearLoop();
|
||||
}
|
||||
#ifdef __ANDROID__
|
||||
} COFFEE_CATCH() {
|
||||
@@ -334,9 +338,12 @@ void Map::checkForPause() {
|
||||
}
|
||||
|
||||
void Map::rerender() {
|
||||
// We only send render events if we want to continuously update the map
|
||||
// (== async rendering).
|
||||
if (async) {
|
||||
if (mode == Mode::Static) {
|
||||
prepare();
|
||||
} else if (mode == Mode::Continuous) {
|
||||
// We only send render events if we want to continuously update the map
|
||||
// (== async rendering).
|
||||
assert(asyncRender);
|
||||
asyncRender->send();
|
||||
}
|
||||
}
|
||||
@@ -373,7 +380,7 @@ void Map::setStyleURL(const std::string &url) {
|
||||
// TODO: Make threadsafe.
|
||||
|
||||
styleURL = url;
|
||||
if (async) {
|
||||
if (mode == Mode::Continuous) {
|
||||
stop();
|
||||
start();
|
||||
}
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
@@ -25,35 +26,26 @@ Shader::Shader(const char *name_, const GLchar *vertSource, const GLchar *fragSo
|
||||
// Load binary shader if it exists
|
||||
bool skipCompile = false;
|
||||
if (!binaryFileName.empty() && (gl::ProgramBinary != nullptr)) {
|
||||
FILE *binaryFile = fopen(binaryFileName.c_str(), "rb");
|
||||
if (binaryFile != nullptr) {
|
||||
GLsizei binaryLength;
|
||||
GLenum binaryFormat;
|
||||
bool lengthOk = fread(&binaryLength, sizeof(binaryLength), 1, binaryFile) == 1;
|
||||
bool formatOk = fread(&binaryFormat, sizeof(binaryFormat), 1, binaryFile) == 1;
|
||||
std::ifstream binaryFile(binaryFileName, std::ios::in | std::ios::binary);
|
||||
|
||||
if (lengthOk && formatOk && binaryLength > 0) {
|
||||
std::unique_ptr<char[]> binary = mbgl::util::make_unique<char[]>(binaryLength);
|
||||
GLsizei binaryLength;
|
||||
GLenum binaryFormat;
|
||||
binaryFile.read(reinterpret_cast<char *>(&binaryLength), sizeof(binaryLength));
|
||||
binaryFile.read(reinterpret_cast<char *>(&binaryFormat), sizeof(binaryFormat));
|
||||
|
||||
if (binary != nullptr) {
|
||||
bool binaryOk = fread(binary.get(), binaryLength, 1, binaryFile) == 1;
|
||||
std::unique_ptr<char[]> binary = mbgl::util::make_unique<char[]>(binaryLength);
|
||||
binaryFile.read(binary.get(), binaryLength);
|
||||
|
||||
if (binaryOk) {
|
||||
MBGL_CHECK_ERROR(gl::ProgramBinary(program, binaryFormat, binary.get(), binaryLength));
|
||||
MBGL_CHECK_ERROR(gl::ProgramBinary(program, binaryFormat, binary.get(), binaryLength));
|
||||
|
||||
// Check if the binary was valid
|
||||
GLint status;
|
||||
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_LINK_STATUS, &status));
|
||||
if (status == GL_TRUE) {
|
||||
skipCompile = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose(binaryFile);
|
||||
binaryFile = nullptr;
|
||||
// Check if the binary was valid
|
||||
GLint status;
|
||||
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_LINK_STATUS, &status));
|
||||
if (status == GL_TRUE) {
|
||||
skipCompile = true;
|
||||
}
|
||||
|
||||
binaryFile.close();
|
||||
}
|
||||
|
||||
GLuint vertShader = 0;
|
||||
@@ -150,7 +142,7 @@ bool Shader::compileShader(GLuint *shader, GLenum type, const GLchar *source) {
|
||||
|
||||
*shader = MBGL_CHECK_ERROR(glCreateShader(type));
|
||||
const GLchar *strings[] = { source };
|
||||
const GLsizei lengths[] = { (GLsizei)strlen(source) };
|
||||
const GLsizei lengths[] = { (GLsizei)std::strlen(source) };
|
||||
MBGL_CHECK_ERROR(glShaderSource(*shader, 1, strings, lengths));
|
||||
|
||||
MBGL_CHECK_ERROR(glCompileShader(*shader));
|
||||
@@ -189,19 +181,14 @@ Shader::~Shader() {
|
||||
MBGL_CHECK_ERROR(glGetProgramiv(program, GL_PROGRAM_BINARY_LENGTH, &binaryLength));
|
||||
if (binaryLength > 0) {
|
||||
std::unique_ptr<char[]> binary = mbgl::util::make_unique<char[]>(binaryLength);
|
||||
if (binary != nullptr) {
|
||||
MBGL_CHECK_ERROR(gl::GetProgramBinary(program, binaryLength, NULL, &binaryFormat, binary.get()));
|
||||
MBGL_CHECK_ERROR(gl::GetProgramBinary(program, binaryLength, NULL, &binaryFormat, binary.get()));
|
||||
|
||||
// Write the binary to a file
|
||||
FILE *binaryFile = fopen(binaryFileName.c_str(), "wb");
|
||||
if (binaryFile != nullptr) {
|
||||
fwrite(&binaryLength, sizeof(binaryLength), 1, binaryFile);
|
||||
fwrite(&binaryFormat, sizeof(binaryFormat), 1, binaryFile);
|
||||
fwrite(binary.get(), binaryLength, 1, binaryFile);
|
||||
fclose(binaryFile);
|
||||
binaryFile = nullptr;
|
||||
}
|
||||
}
|
||||
// Write the binary to a file
|
||||
std::ofstream binaryFile(binaryFileName, std::ios::out | std::ios::trunc | std::ios::binary);
|
||||
binaryFile.write(reinterpret_cast<char *>(&binaryLength), sizeof(binaryLength));
|
||||
binaryFile.write(reinterpret_cast<char *>(&binaryFormat), sizeof(binaryFormat));
|
||||
binaryFile.write(binary.get(), binaryLength);
|
||||
binaryFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user