Merge branch 'master' into shader-performance
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
|
||||
|
||||
##### Test cases ###############################################################
|
||||
|
||||
test: build/test/Makefile
|
||||
@@ -101,6 +109,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:
|
||||
@@ -120,6 +132,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
|
||||
|
||||
16
README.md
16
README.md
@@ -21,6 +21,11 @@ implemented in C++11, currently targeting iOS, OS X, and Ubuntu Linux.
|
||||
|
||||
We try to link to as many system-provided libraries as possible. When these are unavailable or too outdated, we run a thin build-script layer called [Mason](https://github.com/mapbox/mason) to automate builds, and load precompiled binary packages when possible.
|
||||
|
||||
Be sure to pull down all submodules first:
|
||||
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
## OS X
|
||||
|
||||
On OS X, we are using `zlib`, `SQLite3`, `libcurl` and `libpng` provided by the operating system. In addition to that, you need to have the Boost headers installed. To install all prerequisites, use [Homebrew](http://brew.sh/) and type `brew install pkg-config boost`.
|
||||
@@ -43,12 +48,7 @@ iOS makes use of a Cocoa-specific API called [`mapbox-gl-cocoa`](https://github.
|
||||
|
||||
If you intend to develop here, `mapbox-gl-cocoa` is included as a submodule of the overall build setup.
|
||||
|
||||
To pull down the submodule(s), run:
|
||||
|
||||
git submodule init
|
||||
git submodule update
|
||||
|
||||
Then, you can run `make iproj` to create and open an Xcode project with an iOS-specific view controller housing. This will automatically install required dependencies as well.
|
||||
You can run `make iproj` to create and open an Xcode project with an iOS-specific view controller housing. This will automatically install required dependencies as well.
|
||||
|
||||
Note that if you are doing OS X development as well, to toggle from OS X back to iOS, you will need to `make iproj` again.
|
||||
|
||||
@@ -117,9 +117,9 @@ The demo applications use Mapbox vector tiles, which **require a Mapbox account
|
||||
|
||||
For iOS and OS X use of the demo apps in Xcode, setup the access token by editing the scheme for the application target, then adding an environment variable with the name `MAPBOX_ACCESS_TOKEN`.
|
||||
|
||||

|
||||

|
||||
|
||||

|
||||

|
||||
|
||||
For Linux, set the environment variable `MAPBOX_ACCESS_TOKEN` to your token.
|
||||
|
||||
|
||||
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',
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
@@ -39,10 +39,13 @@
|
||||
'../platform/darwin/log_nslog.mm',
|
||||
'../platform/darwin/string_nsstring.mm',
|
||||
'../platform/darwin/http_request_baton_cocoa.mm',
|
||||
'../platform/darwin/application_root.mm',
|
||||
'../platform/darwin/image.mm',
|
||||
'../platform/default/asset_request_libuv.cpp',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../include',
|
||||
'../src',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'OTHER_CPLUSPLUSFLAGS': [ '<@(uv_cflags)' ],
|
||||
|
||||
@@ -34,7 +34,9 @@
|
||||
'../platform/default/shader_cache_tmp.cpp',
|
||||
'../platform/default/log_stderr.cpp',
|
||||
'../platform/default/string_stdlib.cpp',
|
||||
'../platform/default/asset_request_libuv.cpp',
|
||||
'../platform/default/http_request_baton_curl.cpp',
|
||||
'../platform/default/application_root.cpp',
|
||||
'../platform/default/image.cpp',
|
||||
'../platform/default/image_reader.cpp',
|
||||
'../platform/default/png_reader.cpp',
|
||||
@@ -42,6 +44,7 @@
|
||||
],
|
||||
'include_dirs': [
|
||||
'../include',
|
||||
'../src',
|
||||
],
|
||||
'link_settings': {
|
||||
'libraries': [
|
||||
|
||||
@@ -14,10 +14,13 @@
|
||||
'../platform/darwin/log_nslog.mm',
|
||||
'../platform/darwin/string_nsstring.mm',
|
||||
'../platform/darwin/http_request_baton_cocoa.mm',
|
||||
'../platform/darwin/application_root.mm',
|
||||
'../platform/darwin/image.mm',
|
||||
'../platform/default/asset_request_libuv.cpp',
|
||||
],
|
||||
'include_dirs': [
|
||||
'../include',
|
||||
'../src',
|
||||
],
|
||||
'xcode_settings': {
|
||||
'OTHER_CPLUSPLUSFLAGS': [ '<@(uv_cflags)' ],
|
||||
|
||||
@@ -18,9 +18,17 @@
|
||||
'type': 'none',
|
||||
'hard_dependency': 1,
|
||||
'dependencies': [ 'touch_styles' ], # required for xcode http://openradar.appspot.com/7232149
|
||||
'direct_dependent_settings': {
|
||||
'mac_bundle_resources': [ '../styles/styles' ],
|
||||
}
|
||||
'conditions': [
|
||||
['OS == "mac"', {
|
||||
'direct_dependent_settings': {
|
||||
'mac_bundle_resources': [ '../styles/styles' ],
|
||||
}
|
||||
}, {
|
||||
'direct_dependent_settings': {
|
||||
'copies': [{ 'files': [ '../styles/styles' ], 'destination': '<(PRODUCT_DIR)' }],
|
||||
}
|
||||
}]
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -136,7 +136,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;
|
||||
|
||||
@@ -33,18 +33,18 @@ public:
|
||||
// Called from the render thread. Makes the GL context active in the current
|
||||
// thread. This is typically just called once at the beginning of the
|
||||
// renderer setup since the render thread doesn't switch the contexts.
|
||||
virtual void make_active() = 0;
|
||||
virtual void activate() = 0;
|
||||
|
||||
// Called from the render thread. Makes the GL context inactive in the current
|
||||
// thread. This is called once just before the rendering thread terminates.
|
||||
virtual void make_inactive() = 0;
|
||||
virtual void deactivate() = 0;
|
||||
|
||||
virtual void notify() = 0;
|
||||
|
||||
// Notifies a watcher of map x/y/scale/rotation changes.
|
||||
// Must only be called from the same thread that caused the change.
|
||||
// Must not be called from the render thread.
|
||||
virtual void notify_map_change(MapChange change, timestamp delay = 0) = 0;
|
||||
virtual void notifyMapChange(MapChange change, timestamp delay = 0) = 0;
|
||||
|
||||
protected:
|
||||
mbgl::Map *map = nullptr;
|
||||
|
||||
@@ -16,16 +16,16 @@ public:
|
||||
|
||||
void initialize(mbgl::Map *map);
|
||||
void swap();
|
||||
void make_active();
|
||||
void make_inactive();
|
||||
void activate();
|
||||
void deactivate();
|
||||
void notify();
|
||||
void notify_map_change(mbgl::MapChange change, mbgl::timestamp delay = 0);
|
||||
void notifyMapChange(mbgl::MapChange change, mbgl::timestamp delay = 0);
|
||||
|
||||
static void key(GLFWwindow *window, int key, int scancode, int action, int mods);
|
||||
static void scroll(GLFWwindow *window, double xoffset, double yoffset);
|
||||
static void resize(GLFWwindow *window, int, int);
|
||||
static void mouseclick(GLFWwindow *window, int button, int action, int modifiers);
|
||||
static void mousemove(GLFWwindow *window, double x, double y);
|
||||
static void resize(GLFWwindow *window, int width, int height);
|
||||
static void mouseClick(GLFWwindow *window, int button, int action, int modifiers);
|
||||
static void mouseMove(GLFWwindow *window, double x, double y);
|
||||
|
||||
static void eventloop(void *arg);
|
||||
|
||||
@@ -35,12 +35,12 @@ public:
|
||||
public:
|
||||
bool fullscreen = false;
|
||||
|
||||
double last_x = 0, last_y = 0;
|
||||
double lastX = 0, lastY = 0;
|
||||
bool tracking = false;
|
||||
|
||||
bool rotating = false;
|
||||
|
||||
double last_click = -1;
|
||||
double lastClick = -1;
|
||||
|
||||
GLFWwindow *window = nullptr;
|
||||
};
|
||||
|
||||
@@ -31,13 +31,13 @@ public:
|
||||
std::unique_ptr<uint32_t[]> readPixels();
|
||||
|
||||
void notify();
|
||||
void notify_map_change(MapChange change, timestamp delay = 0);
|
||||
void make_active();
|
||||
void make_inactive();
|
||||
void notifyMapChange(MapChange change, timestamp delay = 0);
|
||||
void activate();
|
||||
void deactivate();
|
||||
void swap();
|
||||
|
||||
private:
|
||||
void clear_buffers();
|
||||
void clearBuffers();
|
||||
|
||||
private:
|
||||
std::shared_ptr<HeadlessDisplay> display_;
|
||||
|
||||
@@ -23,6 +23,8 @@ std::string defaultCacheDatabase();
|
||||
// Returns the path to the default shader cache on this system.
|
||||
std::string defaultShaderCache();
|
||||
|
||||
std::string applicationRoot();
|
||||
|
||||
// Shows an alpha image with the specified dimensions in a named window.
|
||||
void show_debug_image(std::string name, const char *data, size_t width, size_t height);
|
||||
|
||||
|
||||
27
include/mbgl/storage/asset_request.hpp
Normal file
27
include/mbgl/storage/asset_request.hpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#ifndef MBGL_STORAGE_ASSET_REQUEST
|
||||
#define MBGL_STORAGE_ASSET_REQUEST
|
||||
|
||||
#include <mbgl/storage/base_request.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
typedef struct uv_loop_s uv_loop_t;
|
||||
|
||||
struct AssetRequestBaton;
|
||||
|
||||
class AssetRequest : public BaseRequest {
|
||||
public:
|
||||
AssetRequest(const std::string &path, uv_loop_t *loop);
|
||||
~AssetRequest();
|
||||
|
||||
void cancel();
|
||||
|
||||
private:
|
||||
AssetRequestBaton *ptr = nullptr;
|
||||
|
||||
friend struct AssetRequestBaton;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
Submodule ios/mapbox-gl-cocoa updated: 1533d3288f...40b9b7b8e0
@@ -49,7 +49,7 @@ int main(int argc, char *argv[]) {
|
||||
// handle fullscreen_flag
|
||||
break;
|
||||
case 's':
|
||||
style = std::string("file://") + std::string(optarg);
|
||||
style = std::string("asset://") + std::string(optarg);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -83,7 +83,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// Load style
|
||||
if (style.empty())
|
||||
style = std::string("file://") + uv::cwd() + std::string("/../../styles/styles/bright-v6.json");
|
||||
style = std::string("asset://") + std::string("styles/bright-v6.json");
|
||||
|
||||
map.setStyleURL(style);
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@
|
||||
'dependencies': [
|
||||
'../mapboxgl.gyp:mbgl-standalone',
|
||||
'../mapboxgl.gyp:mbgl-linux',
|
||||
'../mapboxgl.gyp:bundle_styles',
|
||||
'../mapboxgl.gyp:copy_certificate_bundle',
|
||||
],
|
||||
'copies': [{
|
||||
|
||||
@@ -102,9 +102,7 @@ int main() {
|
||||
if (accessToken) fileSource.setAccessToken([accessToken cStringUsingEncoding:[NSString defaultCStringEncoding]]);
|
||||
|
||||
// Load style
|
||||
const std::string path([[[NSBundle mainBundle] pathForResource:@"bright-v6" ofType:@"json" inDirectory:@"styles/"] UTF8String]);
|
||||
|
||||
map.setStyleURL(std::string("file://") + path);
|
||||
map.setStyleURL("asset://styles/bright-v6.json");
|
||||
|
||||
int ret = view.run();
|
||||
|
||||
|
||||
18
platform/darwin/application_root.mm
Normal file
18
platform/darwin/application_root.mm
Normal file
@@ -0,0 +1,18 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace platform {
|
||||
|
||||
// Returns the path to the default shader cache on this system.
|
||||
std::string applicationRoot() {
|
||||
static const std::string root = []() -> std::string {
|
||||
NSString *path = [[[NSBundle mainBundle] resourceURL] path];
|
||||
return {[path cStringUsingEncoding : NSUTF8StringEncoding],
|
||||
[path lengthOfBytesUsingEncoding:NSUTF8StringEncoding]};
|
||||
}();
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
platform/default/application_root.cpp
Normal file
15
platform/default/application_root.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
|
||||
#include <mbgl/util/uv.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
namespace platform {
|
||||
|
||||
// Returns the path the application root.
|
||||
std::string applicationRoot() {
|
||||
static const std::string root = uv::cwd();
|
||||
return root;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,45 @@
|
||||
#include <mbgl/storage/file_request_baton.hpp>
|
||||
#include <mbgl/storage/file_request.hpp>
|
||||
#include <mbgl/storage/asset_request.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
#include <mbgl/platform/platform.hpp>
|
||||
#include <mbgl/util/std.hpp>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
FileRequestBaton::FileRequestBaton(FileRequest *request_, const std::string &path, uv_loop_t *loop)
|
||||
struct AssetRequestBaton {
|
||||
AssetRequestBaton(AssetRequest *request_, const std::string &path, uv_loop_t *loop);
|
||||
~AssetRequestBaton();
|
||||
|
||||
void cancel();
|
||||
static void file_opened(uv_fs_t *req);
|
||||
static void file_stated(uv_fs_t *req);
|
||||
static void file_read(uv_fs_t *req);
|
||||
static void file_closed(uv_fs_t *req);
|
||||
static void notify_error(uv_fs_t *req);
|
||||
static void cleanup(uv_fs_t *req);
|
||||
|
||||
const std::thread::id thread_id;
|
||||
AssetRequest *request = nullptr;
|
||||
uv_fs_t req;
|
||||
uv_file fd = -1;
|
||||
bool canceled = false;
|
||||
std::string body;
|
||||
uv_buf_t buffer;
|
||||
};
|
||||
|
||||
AssetRequestBaton::AssetRequestBaton(AssetRequest *request_, const std::string &path, uv_loop_t *loop)
|
||||
: thread_id(std::this_thread::get_id()), request(request_) {
|
||||
req.data = this;
|
||||
uv_fs_open(loop, &req, path.c_str(), O_RDONLY, S_IRUSR, file_opened);
|
||||
}
|
||||
|
||||
FileRequestBaton::~FileRequestBaton() {
|
||||
AssetRequestBaton::~AssetRequestBaton() {
|
||||
}
|
||||
|
||||
void FileRequestBaton::cancel() {
|
||||
void AssetRequestBaton::cancel() {
|
||||
canceled = true;
|
||||
|
||||
// uv_cancel fails frequently when the request has already been started.
|
||||
@@ -25,8 +48,8 @@ void FileRequestBaton::cancel() {
|
||||
uv_cancel((uv_req_t *)&req);
|
||||
}
|
||||
|
||||
void FileRequestBaton::notify_error(uv_fs_t *req) {
|
||||
FileRequestBaton *ptr = (FileRequestBaton *)req->data;
|
||||
void AssetRequestBaton::notify_error(uv_fs_t *req) {
|
||||
AssetRequestBaton *ptr = (AssetRequestBaton *)req->data;
|
||||
assert(ptr->thread_id == std::this_thread::get_id());
|
||||
|
||||
if (ptr->request && req->result < 0 && !ptr->canceled && req->result != UV_ECANCELED) {
|
||||
@@ -41,8 +64,8 @@ void FileRequestBaton::notify_error(uv_fs_t *req) {
|
||||
}
|
||||
}
|
||||
|
||||
void FileRequestBaton::file_opened(uv_fs_t *req) {
|
||||
FileRequestBaton *ptr = (FileRequestBaton *)req->data;
|
||||
void AssetRequestBaton::file_opened(uv_fs_t *req) {
|
||||
AssetRequestBaton *ptr = (AssetRequestBaton *)req->data;
|
||||
assert(ptr->thread_id == std::this_thread::get_id());
|
||||
|
||||
if (req->result < 0) {
|
||||
@@ -56,7 +79,7 @@ void FileRequestBaton::file_opened(uv_fs_t *req) {
|
||||
uv_fs_req_cleanup(req);
|
||||
|
||||
if (ptr->canceled || !ptr->request) {
|
||||
// Either the FileRequest object has been destructed, or the
|
||||
// Either the AssetRequest object has been destructed, or the
|
||||
// request was canceled.
|
||||
uv_fs_close(req->loop, req, fd, file_closed);
|
||||
} else {
|
||||
@@ -66,8 +89,8 @@ void FileRequestBaton::file_opened(uv_fs_t *req) {
|
||||
}
|
||||
}
|
||||
|
||||
void FileRequestBaton::file_stated(uv_fs_t *req) {
|
||||
FileRequestBaton *ptr = (FileRequestBaton *)req->data;
|
||||
void AssetRequestBaton::file_stated(uv_fs_t *req) {
|
||||
AssetRequestBaton *ptr = (AssetRequestBaton *)req->data;
|
||||
assert(ptr->thread_id == std::this_thread::get_id());
|
||||
|
||||
if (req->result != 0 || ptr->canceled || !ptr->request) {
|
||||
@@ -113,8 +136,8 @@ void FileRequestBaton::file_stated(uv_fs_t *req) {
|
||||
}
|
||||
}
|
||||
|
||||
void FileRequestBaton::file_read(uv_fs_t *req) {
|
||||
FileRequestBaton *ptr = (FileRequestBaton *)req->data;
|
||||
void AssetRequestBaton::file_read(uv_fs_t *req) {
|
||||
AssetRequestBaton *ptr = (AssetRequestBaton *)req->data;
|
||||
assert(ptr->thread_id == std::this_thread::get_id());
|
||||
|
||||
if (req->result < 0 || ptr->canceled || !ptr->request) {
|
||||
@@ -135,8 +158,8 @@ void FileRequestBaton::file_read(uv_fs_t *req) {
|
||||
uv_fs_close(req->loop, req, ptr->fd, file_closed);
|
||||
}
|
||||
|
||||
void FileRequestBaton::file_closed(uv_fs_t *req) {
|
||||
assert(((FileRequestBaton *)req->data)->thread_id == std::this_thread::get_id());
|
||||
void AssetRequestBaton::file_closed(uv_fs_t *req) {
|
||||
assert(((AssetRequestBaton *)req->data)->thread_id == std::this_thread::get_id());
|
||||
|
||||
if (req->result < 0) {
|
||||
// Closing the file failed. But there isn't anything we can do.
|
||||
@@ -145,8 +168,8 @@ void FileRequestBaton::file_closed(uv_fs_t *req) {
|
||||
cleanup(req);
|
||||
}
|
||||
|
||||
void FileRequestBaton::cleanup(uv_fs_t *req) {
|
||||
FileRequestBaton *ptr = (FileRequestBaton *)req->data;
|
||||
void AssetRequestBaton::cleanup(uv_fs_t *req) {
|
||||
AssetRequestBaton *ptr = (AssetRequestBaton *)req->data;
|
||||
assert(ptr->thread_id == std::this_thread::get_id());
|
||||
|
||||
if (ptr->request) {
|
||||
@@ -157,4 +180,43 @@ void FileRequestBaton::cleanup(uv_fs_t *req) {
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
|
||||
AssetRequest::AssetRequest(const std::string &path_, uv_loop_t *loop)
|
||||
: BaseRequest(path_) {
|
||||
if (!path.empty() && path[0] == '/') {
|
||||
// This is an absolute path. We don't allow this. Note that this is not a way to absolutely
|
||||
// prevent access to resources outside the application bundle; e.g. there could be symlinks
|
||||
// in the application bundle that link to outside. We don't care about these.
|
||||
response = util::make_unique<Response>();
|
||||
response->code = 403;
|
||||
response->message = "Path is outside the application bundle";
|
||||
notify();
|
||||
} else {
|
||||
// Note: The AssetRequestBaton object is deleted in AssetRequestBaton::cleanup().
|
||||
ptr = new AssetRequestBaton(this, platform::applicationRoot() + "/" + path, loop);
|
||||
}
|
||||
}
|
||||
|
||||
void AssetRequest::cancel() {
|
||||
assert(thread_id == std::this_thread::get_id());
|
||||
|
||||
if (ptr) {
|
||||
ptr->cancel();
|
||||
|
||||
// When deleting a AssetRequest object with a uv_fs_* call is in progress, we are making sure
|
||||
// that the callback doesn't accidentally reference this object again.
|
||||
ptr->request = nullptr;
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
notify();
|
||||
}
|
||||
|
||||
AssetRequest::~AssetRequest() {
|
||||
assert(thread_id == std::this_thread::get_id());
|
||||
cancel();
|
||||
|
||||
// Note: The AssetRequestBaton object is deleted in AssetRequestBaton::cleanup().
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
GLFWView::GLFWView(bool fullscreen_) : fullscreen(fullscreen_) {
|
||||
#ifdef NVIDIA
|
||||
glDiscardFramebufferEXT = (PFNGLDISCARDFRAMEBUFFEREXTPROC)glfwGetProcAddress("glDiscardFramebufferEXT");
|
||||
glDiscardFramebufferEXT = reinterpret_cast<PFNGLDISCARDFRAMEBUFFEREXTPROC>(glfwGetProcAddress("glDiscardFramebufferEXT"));
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -61,34 +61,34 @@ void GLFWView::initialize(mbgl::Map *map_) {
|
||||
|
||||
int width, height;
|
||||
glfwGetWindowSize(window, &width, &height);
|
||||
int fb_width, fb_height;
|
||||
glfwGetFramebufferSize(window, &fb_width, &fb_height);
|
||||
int fbWidth, fbHeight;
|
||||
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
|
||||
|
||||
resize(window, 0, 0);
|
||||
|
||||
glfwSetCursorPosCallback(window, mousemove);
|
||||
glfwSetMouseButtonCallback(window, mouseclick);
|
||||
glfwSetCursorPosCallback(window, mouseMove);
|
||||
glfwSetMouseButtonCallback(window, mouseClick);
|
||||
glfwSetWindowSizeCallback(window, resize);
|
||||
glfwSetFramebufferSizeCallback(window, resize);
|
||||
glfwSetScrollCallback(window, scroll);
|
||||
glfwSetKeyCallback(window, key);
|
||||
|
||||
const std::string extensions = (char *)MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS));
|
||||
const std::string extensions = reinterpret_cast<const char *>(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)));
|
||||
{
|
||||
using namespace mbgl;
|
||||
|
||||
if (extensions.find("GL_KHR_debug") != std::string::npos) {
|
||||
gl::DebugMessageControl = (gl::PFNGLDEBUGMESSAGECONTROLPROC)glfwGetProcAddress("glDebugMessageControl");
|
||||
gl::DebugMessageInsert = (gl::PFNGLDEBUGMESSAGEINSERTPROC)glfwGetProcAddress("glDebugMessageInsert");
|
||||
gl::DebugMessageCallback = (gl::PFNGLDEBUGMESSAGECALLBACKPROC)glfwGetProcAddress("glDebugMessageCallback");
|
||||
gl::GetDebugMessageLog = (gl::PFNGLGETDEBUGMESSAGELOGPROC)glfwGetProcAddress("glGetDebugMessageLog");
|
||||
gl::GetPointerv = (gl::PFNGLGETPOINTERVPROC)glfwGetProcAddress("glGetPointerv");
|
||||
gl::PushDebugGroup = (gl::PFNGLPUSHDEBUGGROUPPROC)glfwGetProcAddress("glPushDebugGroup");
|
||||
gl::PopDebugGroup = (gl::PFNGLPOPDEBUGGROUPPROC)glfwGetProcAddress("glPopDebugGroup");
|
||||
gl::ObjectLabel = (gl::PFNGLOBJECTLABELPROC)glfwGetProcAddress("glObjectLabel");
|
||||
gl::GetObjectLabel = (gl::PFNGLGETOBJECTLABELPROC)glfwGetProcAddress("glGetObjectLabel");
|
||||
gl::ObjectPtrLabel = (gl::PFNGLOBJECTPTRLABELPROC)glfwGetProcAddress("glObjectPtrLabel");
|
||||
gl::GetObjectPtrLabel = (gl::PFNGLGETOBJECTPTRLABELPROC)glfwGetProcAddress("glGetObjectPtrLabel");
|
||||
gl::DebugMessageControl = reinterpret_cast<gl::PFNGLDEBUGMESSAGECONTROLPROC>(glfwGetProcAddress("glDebugMessageControl"));
|
||||
gl::DebugMessageInsert = reinterpret_cast<gl::PFNGLDEBUGMESSAGEINSERTPROC>(glfwGetProcAddress("glDebugMessageInsert"));
|
||||
gl::DebugMessageCallback = reinterpret_cast<gl::PFNGLDEBUGMESSAGECALLBACKPROC>(glfwGetProcAddress("glDebugMessageCallback"));
|
||||
gl::GetDebugMessageLog = reinterpret_cast<gl::PFNGLGETDEBUGMESSAGELOGPROC>(glfwGetProcAddress("glGetDebugMessageLog"));
|
||||
gl::GetPointerv = reinterpret_cast<gl::PFNGLGETPOINTERVPROC>(glfwGetProcAddress("glGetPointerv"));
|
||||
gl::PushDebugGroup = reinterpret_cast<gl::PFNGLPUSHDEBUGGROUPPROC>(glfwGetProcAddress("glPushDebugGroup"));
|
||||
gl::PopDebugGroup = reinterpret_cast<gl::PFNGLPOPDEBUGGROUPPROC>(glfwGetProcAddress("glPopDebugGroup"));
|
||||
gl::ObjectLabel = reinterpret_cast<gl::PFNGLOBJECTLABELPROC>(glfwGetProcAddress("glObjectLabel"));
|
||||
gl::GetObjectLabel = reinterpret_cast<gl::PFNGLGETOBJECTLABELPROC>(glfwGetProcAddress("glGetObjectLabel"));
|
||||
gl::ObjectPtrLabel = reinterpret_cast<gl::PFNGLOBJECTPTRLABELPROC>(glfwGetProcAddress("glObjectPtrLabel"));
|
||||
gl::GetObjectPtrLabel = reinterpret_cast<gl::PFNGLGETOBJECTPTRLABELPROC>(glfwGetProcAddress("glGetObjectPtrLabel"));
|
||||
assert(gl::DebugMessageControl != nullptr);
|
||||
assert(gl::DebugMessageInsert != nullptr);
|
||||
assert(gl::DebugMessageCallback != nullptr);
|
||||
@@ -102,11 +102,11 @@ void GLFWView::initialize(mbgl::Map *map_) {
|
||||
assert(gl::GetObjectPtrLabel != nullptr);
|
||||
} else {
|
||||
if (extensions.find("GL_ARB_debug_output") != std::string::npos) {
|
||||
gl::DebugMessageControl = (gl::PFNGLDEBUGMESSAGECONTROLPROC)glfwGetProcAddress("glDebugMessageControlARB");
|
||||
gl::DebugMessageInsert = (gl::PFNGLDEBUGMESSAGEINSERTPROC)glfwGetProcAddress("glDebugMessageInsertARB");
|
||||
gl::DebugMessageCallback = (gl::PFNGLDEBUGMESSAGECALLBACKPROC)glfwGetProcAddress("glDebugMessageCallbackARB");
|
||||
gl::GetDebugMessageLog = (gl::PFNGLGETDEBUGMESSAGELOGPROC)glfwGetProcAddress("glGetDebugMessageLogARB");
|
||||
gl::GetPointerv = (gl::PFNGLGETPOINTERVPROC)glfwGetProcAddress("glGetPointerv");
|
||||
gl::DebugMessageControl = reinterpret_cast<gl::PFNGLDEBUGMESSAGECONTROLPROC>(glfwGetProcAddress("glDebugMessageControlARB"));
|
||||
gl::DebugMessageInsert = reinterpret_cast<gl::PFNGLDEBUGMESSAGEINSERTPROC>(glfwGetProcAddress("glDebugMessageInsertARB"));
|
||||
gl::DebugMessageCallback = reinterpret_cast<gl::PFNGLDEBUGMESSAGECALLBACKPROC>(glfwGetProcAddress("glDebugMessageCallbackARB"));
|
||||
gl::GetDebugMessageLog = reinterpret_cast<gl::PFNGLGETDEBUGMESSAGELOGPROC>(glfwGetProcAddress("glGetDebugMessageLogARB"));
|
||||
gl::GetPointerv = reinterpret_cast<gl::PFNGLGETPOINTERVPROC>(glfwGetProcAddress("glGetPointerv"));
|
||||
assert(gl::DebugMessageControl != nullptr);
|
||||
assert(gl::DebugMessageInsert != nullptr);
|
||||
assert(gl::DebugMessageCallback != nullptr);
|
||||
@@ -115,36 +115,36 @@ void GLFWView::initialize(mbgl::Map *map_) {
|
||||
}
|
||||
|
||||
if (extensions.find("GL_EXT_debug_marker") != std::string::npos) {
|
||||
gl::InsertEventMarkerEXT = (gl::PFNGLINSERTEVENTMARKEREXTPROC)glfwGetProcAddress("glInsertEventMarkerEXT");
|
||||
gl::PushGroupMarkerEXT = (gl::PFNGLPUSHGROUPMARKEREXTPROC)glfwGetProcAddress("glPushGroupMarkerEXT");
|
||||
gl::PopGroupMarkerEXT = (gl::PFNGLPOPGROUPMARKEREXTPROC)glfwGetProcAddress("glPopGroupMarkerEXT");
|
||||
gl::InsertEventMarkerEXT = reinterpret_cast<gl::PFNGLINSERTEVENTMARKEREXTPROC>(glfwGetProcAddress("glInsertEventMarkerEXT"));
|
||||
gl::PushGroupMarkerEXT = reinterpret_cast<gl::PFNGLPUSHGROUPMARKEREXTPROC>(glfwGetProcAddress("glPushGroupMarkerEXT"));
|
||||
gl::PopGroupMarkerEXT = reinterpret_cast<gl::PFNGLPOPGROUPMARKEREXTPROC>(glfwGetProcAddress("glPopGroupMarkerEXT"));
|
||||
assert(gl::InsertEventMarkerEXT != nullptr);
|
||||
assert(gl::PushGroupMarkerEXT != nullptr);
|
||||
assert(gl::PopGroupMarkerEXT != nullptr);
|
||||
}
|
||||
|
||||
if (extensions.find("GL_EXT_debug_label") != std::string::npos) {
|
||||
gl::LabelObjectEXT = (gl::PFNGLLABELOBJECTEXTPROC)glfwGetProcAddress("glLabelObjectEXT");
|
||||
gl::GetObjectLabelEXT = (gl::PFNGLGETOBJECTLABELEXTPROC)glfwGetProcAddress("glGetObjectLabelEXT");
|
||||
gl::LabelObjectEXT = reinterpret_cast<gl::PFNGLLABELOBJECTEXTPROC>(glfwGetProcAddress("glLabelObjectEXT"));
|
||||
gl::GetObjectLabelEXT = reinterpret_cast<gl::PFNGLGETOBJECTLABELEXTPROC>(glfwGetProcAddress("glGetObjectLabelEXT"));
|
||||
assert(gl::LabelObjectEXT != nullptr);
|
||||
assert(gl::GetObjectLabelEXT != nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
if (extensions.find("GL_ARB_vertex_array_object") != std::string::npos) {
|
||||
gl::BindVertexArray = (gl::PFNGLBINDVERTEXARRAYPROC)glfwGetProcAddress("glBindVertexArray");
|
||||
gl::DeleteVertexArrays = (gl::PFNGLDELETEVERTEXARRAYSPROC)glfwGetProcAddress("glDeleteVertexArrays");
|
||||
gl::GenVertexArrays = (gl::PFNGLGENVERTEXARRAYSPROC)glfwGetProcAddress("glGenVertexArrays");
|
||||
gl::IsVertexArray = (gl::PFNGLISVERTEXARRAYPROC)glfwGetProcAddress("glIsVertexArray");
|
||||
gl::BindVertexArray = reinterpret_cast<gl::PFNGLBINDVERTEXARRAYPROC>(glfwGetProcAddress("glBindVertexArray"));
|
||||
gl::DeleteVertexArrays = reinterpret_cast<gl::PFNGLDELETEVERTEXARRAYSPROC>(glfwGetProcAddress("glDeleteVertexArrays"));
|
||||
gl::GenVertexArrays = reinterpret_cast<gl::PFNGLGENVERTEXARRAYSPROC>(glfwGetProcAddress("glGenVertexArrays"));
|
||||
gl::IsVertexArray = reinterpret_cast<gl::PFNGLISVERTEXARRAYPROC>(glfwGetProcAddress("glIsVertexArray"));
|
||||
assert(gl::BindVertexArray != nullptr);
|
||||
assert(gl::DeleteVertexArrays != nullptr);
|
||||
assert(gl::GenVertexArrays != nullptr);
|
||||
assert(gl::IsVertexArray != nullptr);
|
||||
} else if (extensions.find("GL_APPLE_vertex_array_object") != std::string::npos) {
|
||||
gl::BindVertexArray = (gl::PFNGLBINDVERTEXARRAYPROC)glfwGetProcAddress("glBindVertexArrayAPPLE");
|
||||
gl::DeleteVertexArrays = (gl::PFNGLDELETEVERTEXARRAYSPROC)glfwGetProcAddress("glDeleteVertexArraysAPPLE");
|
||||
gl::GenVertexArrays = (gl::PFNGLGENVERTEXARRAYSPROC)glfwGetProcAddress("glGenVertexArraysAPPLE");
|
||||
gl::IsVertexArray = (gl::PFNGLISVERTEXARRAYPROC)glfwGetProcAddress("glIsVertexArrayAPPLE");
|
||||
gl::BindVertexArray = reinterpret_cast<gl::PFNGLBINDVERTEXARRAYPROC>(glfwGetProcAddress("glBindVertexArrayAPPLE"));
|
||||
gl::DeleteVertexArrays = reinterpret_cast<gl::PFNGLDELETEVERTEXARRAYSPROC>(glfwGetProcAddress("glDeleteVertexArraysAPPLE"));
|
||||
gl::GenVertexArrays = reinterpret_cast<gl::PFNGLGENVERTEXARRAYSPROC>(glfwGetProcAddress("glGenVertexArraysAPPLE"));
|
||||
gl::IsVertexArray = reinterpret_cast<gl::PFNGLISVERTEXARRAYPROC>(glfwGetProcAddress("glIsVertexArrayAPPLE"));
|
||||
assert(gl::BindVertexArray != nullptr);
|
||||
assert(gl::DeleteVertexArrays != nullptr);
|
||||
assert(gl::GenVertexArrays != nullptr);
|
||||
@@ -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 = reinterpret_cast<gl::PFNGLGETPROGRAMBINARYPROC>(glfwGetProcAddress("glGetProgramBinary"));
|
||||
gl::ProgramBinary = reinterpret_cast<gl::PFNGLPROGRAMBINARYPROC>(glfwGetProcAddress("glProgramBinary"));
|
||||
gl::ProgramParameteri = reinterpret_cast<gl::PFNGLPROGRAMPARAMETERIPROC>(glfwGetProcAddress("glProgramParameteri"));
|
||||
assert(gl::GetProgramBinary != nullptr);
|
||||
assert(gl::ProgramBinary != nullptr);
|
||||
assert(gl::ProgramParameteri != nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,7 +169,7 @@ void GLFWView::initialize(mbgl::Map *map_) {
|
||||
}
|
||||
|
||||
void GLFWView::key(GLFWwindow *window, int key, int /*scancode*/, int action, int mods) {
|
||||
GLFWView *view = (GLFWView *)glfwGetWindowUserPointer(window);
|
||||
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
|
||||
|
||||
if (action == GLFW_RELEASE) {
|
||||
switch (key) {
|
||||
@@ -193,17 +197,17 @@ void GLFWView::key(GLFWwindow *window, int key, int /*scancode*/, int action, in
|
||||
}
|
||||
}
|
||||
|
||||
void GLFWView::scroll(GLFWwindow *window, double /*xoffset*/, double yoffset) {
|
||||
GLFWView *view = (GLFWView *)glfwGetWindowUserPointer(window);
|
||||
double delta = yoffset * 40;
|
||||
void GLFWView::scroll(GLFWwindow *window, double /*xOffset*/, double yOffset) {
|
||||
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
|
||||
double delta = yOffset * 40;
|
||||
|
||||
bool is_wheel = delta != 0 && std::fmod(delta, 4.000244140625) == 0;
|
||||
bool isWheel = delta != 0 && std::fmod(delta, 4.000244140625) == 0;
|
||||
|
||||
double absdelta = delta < 0 ? -delta : delta;
|
||||
double scale = 2.0 / (1.0 + std::exp(-absdelta / 100.0));
|
||||
double absDelta = delta < 0 ? -delta : delta;
|
||||
double scale = 2.0 / (1.0 + std::exp(-absDelta / 100.0));
|
||||
|
||||
// Make the scroll wheel a bit slower.
|
||||
if (!is_wheel) {
|
||||
if (!isWheel) {
|
||||
scale = (scale - 1.0) / 2.0 + 1.0;
|
||||
}
|
||||
|
||||
@@ -213,22 +217,20 @@ void GLFWView::scroll(GLFWwindow *window, double /*xoffset*/, double yoffset) {
|
||||
}
|
||||
|
||||
view->map->startScaling();
|
||||
view->map->scaleBy(scale, view->last_x, view->last_y);
|
||||
view->map->scaleBy(scale, view->lastX, view->lastY);
|
||||
}
|
||||
|
||||
void GLFWView::resize(GLFWwindow *window, int, int) {
|
||||
GLFWView *view = (GLFWView *)glfwGetWindowUserPointer(window);
|
||||
void GLFWView::resize(GLFWwindow *window, int width, int height ) {
|
||||
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
|
||||
|
||||
int width, height;
|
||||
glfwGetWindowSize(window, &width, &height);
|
||||
int fb_width, fb_height;
|
||||
glfwGetFramebufferSize(window, &fb_width, &fb_height);
|
||||
int fbWidth, fbHeight;
|
||||
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
|
||||
|
||||
view->map->resize(width, height, (float)fb_width / (float)width, fb_width, fb_height);
|
||||
view->map->resize(width, height, static_cast<float>(fbWidth) / static_cast<float>(width), fbWidth, fbHeight);
|
||||
}
|
||||
|
||||
void GLFWView::mouseclick(GLFWwindow *window, int button, int action, int modifiers) {
|
||||
GLFWView *view = (GLFWView *)glfwGetWindowUserPointer(window);
|
||||
void GLFWView::mouseClick(GLFWwindow *window, int button, int action, int modifiers) {
|
||||
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
|
||||
|
||||
if (button == GLFW_MOUSE_BUTTON_RIGHT ||
|
||||
(button == GLFW_MOUSE_BUTTON_LEFT && modifiers & GLFW_MOD_CONTROL)) {
|
||||
@@ -242,33 +244,33 @@ void GLFWView::mouseclick(GLFWwindow *window, int button, int action, int modifi
|
||||
if (action == GLFW_RELEASE) {
|
||||
view->map->stopPanning();
|
||||
double now = glfwGetTime();
|
||||
if (now - view->last_click < 0.4 /* ms */) {
|
||||
if (now - view->lastClick < 0.4 /* ms */) {
|
||||
if (modifiers & GLFW_MOD_SHIFT) {
|
||||
view->map->scaleBy(0.5, view->last_x, view->last_y, 0.5);
|
||||
view->map->scaleBy(0.5, view->lastX, view->lastY, 0.5);
|
||||
} else {
|
||||
view->map->scaleBy(2.0, view->last_x, view->last_y, 0.5);
|
||||
view->map->scaleBy(2.0, view->lastX, view->lastY, 0.5);
|
||||
}
|
||||
}
|
||||
view->last_click = now;
|
||||
view->lastClick = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GLFWView::mousemove(GLFWwindow *window, double x, double y) {
|
||||
GLFWView *view = (GLFWView *)glfwGetWindowUserPointer(window);
|
||||
void GLFWView::mouseMove(GLFWwindow *window, double x, double y) {
|
||||
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
|
||||
if (view->tracking) {
|
||||
double dx = x - view->last_x;
|
||||
double dy = y - view->last_y;
|
||||
double dx = x - view->lastX;
|
||||
double dy = y - view->lastY;
|
||||
if (dx || dy) {
|
||||
view->map->startPanning();
|
||||
view->map->moveBy(dx, dy);
|
||||
}
|
||||
} else if (view->rotating) {
|
||||
view->map->startRotating();
|
||||
view->map->rotateBy(view->last_x, view->last_y, x, y);
|
||||
view->map->rotateBy(view->lastX, view->lastY, x, y);
|
||||
}
|
||||
view->last_x = x;
|
||||
view->last_y = y;
|
||||
view->lastX = x;
|
||||
view->lastY = y;
|
||||
}
|
||||
|
||||
int GLFWView::run() {
|
||||
@@ -291,11 +293,11 @@ int GLFWView::run() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void GLFWView::make_active() {
|
||||
void GLFWView::activate() {
|
||||
glfwMakeContextCurrent(window);
|
||||
}
|
||||
|
||||
void GLFWView::make_inactive() {
|
||||
void GLFWView::deactivate() {
|
||||
glfwMakeContextCurrent(nullptr);
|
||||
}
|
||||
|
||||
@@ -307,20 +309,20 @@ void GLFWView::swap() {
|
||||
glfwPostEmptyEvent();
|
||||
}
|
||||
|
||||
void GLFWView::notify_map_change(mbgl::MapChange /*change*/, mbgl::timestamp /*delay*/) {
|
||||
void GLFWView::notifyMapChange(mbgl::MapChange /*change*/, mbgl::timestamp /*delay*/) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
void GLFWView::fps() {
|
||||
static int frames = 0;
|
||||
static double time_elapsed = 0;
|
||||
static double timeElapsed = 0;
|
||||
|
||||
frames++;
|
||||
double current_time = glfwGetTime();
|
||||
double currentTime = glfwGetTime();
|
||||
|
||||
if (current_time - time_elapsed >= 1) {
|
||||
fprintf(stderr, "FPS: %4.2f\n", frames / (current_time - time_elapsed));
|
||||
time_elapsed = current_time;
|
||||
if (currentTime - timeElapsed >= 1) {
|
||||
fprintf(stderr, "FPS: %4.2f\n", frames / (currentTime - timeElapsed));
|
||||
timeElapsed = currentTime;
|
||||
frames = 0;
|
||||
}
|
||||
}
|
||||
@@ -331,71 +333,71 @@ namespace platform {
|
||||
double elapsed() { return glfwGetTime(); }
|
||||
|
||||
#ifndef GL_ES_VERSION_2_0
|
||||
void show_debug_image(std::string name, const char *data, size_t width, size_t height) {
|
||||
void showDebugImage(std::string name, const char *data, size_t width, size_t height) {
|
||||
glfwInit();
|
||||
|
||||
static GLFWwindow *debug_window = nullptr;
|
||||
if (!debug_window) {
|
||||
debug_window = glfwCreateWindow(width, height, name.c_str(), nullptr, nullptr);
|
||||
if (!debug_window) {
|
||||
static GLFWwindow *debugWindow = nullptr;
|
||||
if (!debugWindow) {
|
||||
debugWindow = glfwCreateWindow(width, height, name.c_str(), nullptr, nullptr);
|
||||
if (!debugWindow) {
|
||||
glfwTerminate();
|
||||
fprintf(stderr, "Failed to initialize window\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
GLFWwindow *current_window = glfwGetCurrentContext();
|
||||
GLFWwindow *currentWindow = glfwGetCurrentContext();
|
||||
|
||||
glfwSetWindowSize(debug_window, width, height);
|
||||
glfwMakeContextCurrent(debug_window);
|
||||
glfwSetWindowSize(debugWindow, width, height);
|
||||
glfwMakeContextCurrent(debugWindow);
|
||||
|
||||
int fb_width, fb_height;
|
||||
glfwGetFramebufferSize(debug_window, &fb_width, &fb_height);
|
||||
float scale = (float)fb_width / (float)width;
|
||||
int fbWidth, fbHeight;
|
||||
glfwGetFramebufferSize(debugWindow, &fbWidth, &fbHeight);
|
||||
float scale = static_cast<float>(fbWidth) / static_cast<float>(width);
|
||||
|
||||
MBGL_CHECK_ERROR(glPixelZoom(scale, -scale));
|
||||
MBGL_CHECK_ERROR(glRasterPos2f(-1.0f, 1.0f));
|
||||
MBGL_CHECK_ERROR(glDrawPixels(width, height, GL_LUMINANCE, GL_UNSIGNED_BYTE, data));
|
||||
glfwSwapBuffers(debug_window);
|
||||
glfwSwapBuffers(debugWindow);
|
||||
|
||||
glfwMakeContextCurrent(current_window);
|
||||
glfwMakeContextCurrent(currentWindow);
|
||||
}
|
||||
|
||||
|
||||
void show_color_debug_image(std::string name, const char *data, size_t logical_width, size_t logical_height, size_t width, size_t height) {
|
||||
void showColorDebugImage(std::string name, const char *data, size_t logicalWidth, size_t logicalHeight, size_t width, size_t height) {
|
||||
glfwInit();
|
||||
|
||||
static GLFWwindow *debug_window = nullptr;
|
||||
if (!debug_window) {
|
||||
debug_window = glfwCreateWindow(logical_width, logical_height, name.c_str(), nullptr, nullptr);
|
||||
if (!debug_window) {
|
||||
static GLFWwindow *debugWindow = nullptr;
|
||||
if (!debugWindow) {
|
||||
debugWindow = glfwCreateWindow(logicalWidth, logicalHeight, name.c_str(), nullptr, nullptr);
|
||||
if (!debugWindow) {
|
||||
glfwTerminate();
|
||||
fprintf(stderr, "Failed to initialize window\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
GLFWwindow *current_window = glfwGetCurrentContext();
|
||||
GLFWwindow *currentWindow = glfwGetCurrentContext();
|
||||
|
||||
glfwSetWindowSize(debug_window, logical_width, logical_height);
|
||||
glfwMakeContextCurrent(debug_window);
|
||||
glfwSetWindowSize(debugWindow, logicalWidth, logicalHeight);
|
||||
glfwMakeContextCurrent(debugWindow);
|
||||
|
||||
int fb_width, fb_height;
|
||||
glfwGetFramebufferSize(debug_window, &fb_width, &fb_height);
|
||||
float x_scale = (float)fb_width / (float)width;
|
||||
float y_scale = (float)fb_height / (float)height;
|
||||
int fbWidth, fbHeight;
|
||||
glfwGetFramebufferSize(debugWindow, &fbWidth, &fbHeight);
|
||||
float xScale = static_cast<float>(fbWidth) / static_cast<float>(width);
|
||||
float yScale = static_cast<float>(fbHeight) / static_cast<float>(height);
|
||||
|
||||
MBGL_CHECK_ERROR(glClearColor(0.8, 0.8, 0.8, 1));
|
||||
MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT));
|
||||
MBGL_CHECK_ERROR(glEnable(GL_BLEND));
|
||||
MBGL_CHECK_ERROR(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
|
||||
MBGL_CHECK_ERROR(glPixelZoom(x_scale, -y_scale));
|
||||
MBGL_CHECK_ERROR(glPixelZoom(xScale, -yScale));
|
||||
MBGL_CHECK_ERROR(glRasterPos2f(-1.0f, 1.0f));
|
||||
MBGL_CHECK_ERROR(glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, data));
|
||||
glfwSwapBuffers(debug_window);
|
||||
glfwSwapBuffers(debugWindow);
|
||||
|
||||
glfwMakeContextCurrent(current_window);
|
||||
glfwMakeContextCurrent(currentWindow);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ HeadlessDisplay::HeadlessDisplay() {
|
||||
// If it is, use kCGLOGLPVersion_3_2_Core and enable that extension.
|
||||
CGLPixelFormatAttribute attributes[] = {
|
||||
kCGLPFAOpenGLProfile,
|
||||
(CGLPixelFormatAttribute) kCGLOGLPVersion_Legacy,
|
||||
static_cast<CGLPixelFormatAttribute>(kCGLOGLPVersion_Legacy),
|
||||
kCGLPFAAccelerated,
|
||||
(CGLPixelFormatAttribute) 0
|
||||
static_cast<CGLPixelFormatAttribute>(0)
|
||||
};
|
||||
|
||||
GLint num;
|
||||
@@ -38,7 +38,7 @@ HeadlessDisplay::HeadlessDisplay() {
|
||||
throw std::runtime_error("Failed to open X display.");
|
||||
}
|
||||
|
||||
const char *extensions = (char *)glXQueryServerString(xDisplay, DefaultScreen(xDisplay), GLX_EXTENSIONS);
|
||||
const char *extensions = reinterpret_cast<const char *>(glXQueryServerString(xDisplay, DefaultScreen(xDisplay), GLX_EXTENSIONS));
|
||||
if (!extensions) {
|
||||
throw std::runtime_error("Cannot read GLX extensions.");
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -29,7 +24,7 @@ CGLProc CGLGetProcAddress(const char *proc) {
|
||||
}
|
||||
|
||||
CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, proc, kCFStringEncodingASCII);
|
||||
CGLProc symbol = (CGLProc)CFBundleGetFunctionPointerForName(framework, name);
|
||||
CGLProc symbol = reinterpret_cast<CGLProc>(CFBundleGetFunctionPointerForName(framework, name));
|
||||
CFRelease(name);
|
||||
return symbol;
|
||||
}
|
||||
@@ -51,89 +46,40 @@ HeadlessView::HeadlessView(std::shared_ptr<HeadlessDisplay> display)
|
||||
}
|
||||
|
||||
void HeadlessView::loadExtensions() {
|
||||
make_active();
|
||||
const std::string extensions = (char *)MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS));
|
||||
activate();
|
||||
const char *extension_ptr = reinterpret_cast<const char *>(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)));
|
||||
|
||||
if (extension_ptr) {
|
||||
const std::string extensions = extension_ptr;
|
||||
|
||||
#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 = reinterpret_cast<gl::PFNGLBINDVERTEXARRAYPROC>(CGLGetProcAddress("glBindVertexArrayAPPLE"));
|
||||
gl::DeleteVertexArrays = reinterpret_cast<gl::PFNGLDELETEVERTEXARRAYSPROC>(CGLGetProcAddress("glDeleteVertexArraysAPPLE"));
|
||||
gl::GenVertexArrays = reinterpret_cast<gl::PFNGLGENVERTEXARRAYSPROC>(CGLGetProcAddress("glGenVertexArraysAPPLE"));
|
||||
gl::IsVertexArray = reinterpret_cast<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);
|
||||
}
|
||||
#endif
|
||||
|
||||
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) {
|
||||
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.
|
||||
for (int i = 0; !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 (extensions.find("GL_ARB_vertex_array_object") != std::string::npos) {
|
||||
gl::BindVertexArray = reinterpret_cast<gl::PFNGLBINDVERTEXARRAYPROC>(glXGetProcAddress((const GLubyte *)"glBindVertexArray"));
|
||||
gl::DeleteVertexArrays = reinterpret_cast<gl::PFNGLDELETEVERTEXARRAYSPROC>(glXGetProcAddress((const GLubyte *)"glDeleteVertexArrays"));
|
||||
gl::GenVertexArrays = reinterpret_cast<gl::PFNGLGENVERTEXARRAYSPROC>(glXGetProcAddress((const GLubyte *)"glGenVertexArrays"));
|
||||
gl::IsVertexArray = reinterpret_cast<gl::PFNGLISVERTEXARRAYPROC>(glXGetProcAddress((const GLubyte *)"glIsVertexArray"));
|
||||
assert(gl::BindVertexArray != nullptr);
|
||||
assert(gl::DeleteVertexArrays != nullptr);
|
||||
assert(gl::GenVertexArrays != nullptr);
|
||||
assert(gl::IsVertexArray != nullptr);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// Restore the old error handler.
|
||||
XSetErrorHandler(previousErrorHandler);
|
||||
return ctx;
|
||||
deactivate();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void HeadlessView::createContext() {
|
||||
#if MBGL_USE_CGL
|
||||
@@ -149,27 +95,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]);
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
@@ -192,7 +126,7 @@ void HeadlessView::createContext() {
|
||||
}
|
||||
|
||||
void HeadlessView::resize(uint16_t width, uint16_t height, float pixelRatio) {
|
||||
clear_buffers();
|
||||
clearBuffers();
|
||||
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
@@ -201,7 +135,7 @@ void HeadlessView::resize(uint16_t width, uint16_t height, float pixelRatio) {
|
||||
const unsigned int w = width_ * pixelRatio_;
|
||||
const unsigned int h = height_ * pixelRatio_;
|
||||
|
||||
make_active();
|
||||
activate();
|
||||
|
||||
// Create depth/stencil buffer
|
||||
MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboDepthStencil));
|
||||
@@ -237,7 +171,7 @@ void HeadlessView::resize(uint16_t width, uint16_t height, float pixelRatio) {
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
|
||||
make_inactive();
|
||||
deactivate();
|
||||
}
|
||||
|
||||
std::unique_ptr<uint32_t[]> HeadlessView::readPixels() {
|
||||
@@ -246,9 +180,9 @@ std::unique_ptr<uint32_t[]> HeadlessView::readPixels() {
|
||||
|
||||
auto pixels = util::make_unique<uint32_t[]>(w * h);
|
||||
|
||||
make_active();
|
||||
activate();
|
||||
MBGL_CHECK_ERROR(glReadPixels(0, 0, width_, height_, GL_RGBA, GL_UNSIGNED_BYTE, pixels.get()));
|
||||
make_inactive();
|
||||
deactivate();
|
||||
|
||||
const int stride = w * 4;
|
||||
auto tmp = util::make_unique<char[]>(stride);
|
||||
@@ -262,8 +196,8 @@ std::unique_ptr<uint32_t[]> HeadlessView::readPixels() {
|
||||
return pixels;
|
||||
}
|
||||
|
||||
void HeadlessView::clear_buffers() {
|
||||
make_active();
|
||||
void HeadlessView::clearBuffers() {
|
||||
activate();
|
||||
|
||||
MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||
|
||||
@@ -282,11 +216,11 @@ void HeadlessView::clear_buffers() {
|
||||
fboDepthStencil = 0;
|
||||
}
|
||||
|
||||
make_inactive();
|
||||
deactivate();
|
||||
}
|
||||
|
||||
HeadlessView::~HeadlessView() {
|
||||
clear_buffers();
|
||||
clearBuffers();
|
||||
|
||||
#if MBGL_USE_CGL
|
||||
CGLDestroyContext(glContext);
|
||||
@@ -306,11 +240,11 @@ void HeadlessView::notify() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
void HeadlessView::notify_map_change(mbgl::MapChange /*change*/, mbgl::timestamp /*delay*/) {
|
||||
void HeadlessView::notifyMapChange(mbgl::MapChange /*change*/, mbgl::timestamp /*delay*/) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
void HeadlessView::make_active() {
|
||||
void HeadlessView::activate() {
|
||||
#if MBGL_USE_CGL
|
||||
CGLError error = CGLSetCurrentContext(glContext);
|
||||
if (error != kCGLNoError) {
|
||||
@@ -325,7 +259,7 @@ void HeadlessView::make_active() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void HeadlessView::make_inactive() {
|
||||
void HeadlessView::deactivate() {
|
||||
#if MBGL_USE_CGL
|
||||
CGLError error = CGLSetCurrentContext(nullptr);
|
||||
if (error != kCGLNoError) {
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include <uv.h>
|
||||
|
||||
// Check libuv library version.
|
||||
const static bool uv_version_check = []() {
|
||||
const static bool uvVersionCheck = []() {
|
||||
const unsigned int version = uv_version();
|
||||
const unsigned int major = (version >> 16) & 0xFF;
|
||||
const unsigned int minor = (version >> 8) & 0xFF;
|
||||
@@ -55,7 +55,7 @@ const static bool uv_version_check = []() {
|
||||
|
||||
#include <zlib.h>
|
||||
// Check zlib library version.
|
||||
const static bool zlib_version_check = []() {
|
||||
const static bool zlibVersionCheck = []() {
|
||||
const char *const version = zlibVersion();
|
||||
if (version[0] != ZLIB_VERSION[0]) {
|
||||
throw std::runtime_error(mbgl::util::sprintf<96>(
|
||||
@@ -68,7 +68,7 @@ const static bool zlib_version_check = []() {
|
||||
|
||||
#include <sqlite3.h>
|
||||
// Check sqlite3 library version.
|
||||
const static bool sqlite_version_check = []() {
|
||||
const static bool sqliteVersionCheck = []() {
|
||||
if (sqlite3_libversion_number() != SQLITE_VERSION_NUMBER) {
|
||||
throw std::runtime_error(mbgl::util::sprintf<96>(
|
||||
"sqlite3 libversion mismatch: headers report %d, but library reports %d",
|
||||
@@ -91,6 +91,7 @@ Map::Map(View& view_, FileSource& fileSource_)
|
||||
view(view_),
|
||||
#ifndef NDEBUG
|
||||
mainThread(std::this_thread::get_id()),
|
||||
mapThread(mainThread),
|
||||
#endif
|
||||
transform(view_),
|
||||
fileSource(fileSource_),
|
||||
@@ -108,7 +109,7 @@ Map::Map(View& view_, FileSource& fileSource_)
|
||||
}
|
||||
|
||||
Map::~Map() {
|
||||
if (async) {
|
||||
if (mode == Mode::Continuous) {
|
||||
stop();
|
||||
}
|
||||
|
||||
@@ -132,11 +133,11 @@ uv::worker &Map::getWorker() {
|
||||
|
||||
void Map::start() {
|
||||
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;
|
||||
@@ -200,7 +201,7 @@ void Map::start() {
|
||||
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();
|
||||
|
||||
@@ -220,15 +221,16 @@ void Map::stop(std::function<void ()> callback) {
|
||||
// already finished executing.
|
||||
thread.join();
|
||||
|
||||
async = false;
|
||||
mode = Mode::None;
|
||||
}
|
||||
|
||||
void Map::run() {
|
||||
if (mode == Mode::None) {
|
||||
#ifndef NDEBUG
|
||||
if (!async) {
|
||||
mapThread = mainThread;
|
||||
}
|
||||
#endif
|
||||
mode = Mode::Static;
|
||||
}
|
||||
assert(std::this_thread::get_id() == mapThread);
|
||||
|
||||
setup();
|
||||
@@ -240,18 +242,23 @@ 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();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
@@ -280,9 +287,9 @@ void Map::terminate() {
|
||||
void Map::setup() {
|
||||
assert(std::this_thread::get_id() == mapThread);
|
||||
assert(painter);
|
||||
view.make_active();
|
||||
view.activate();
|
||||
painter->setup();
|
||||
view.make_inactive();
|
||||
view.deactivate();
|
||||
}
|
||||
|
||||
void Map::setStyleURL(const std::string &url) {
|
||||
@@ -606,7 +613,7 @@ void Map::prepare() {
|
||||
}
|
||||
|
||||
void Map::render() {
|
||||
view.make_active();
|
||||
view.activate();
|
||||
|
||||
assert(painter);
|
||||
painter->render(*style, activeSources,
|
||||
@@ -616,5 +623,5 @@ void Map::render() {
|
||||
update();
|
||||
}
|
||||
|
||||
view.make_inactive();
|
||||
view.deactivate();
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ bool Transform::resize(const uint16_t w, const uint16_t h, const float ratio,
|
||||
if (final.width != w || final.height != h || final.pixelRatio != ratio ||
|
||||
final.framebuffer[0] != fb_w || final.framebuffer[1] != fb_h) {
|
||||
|
||||
view.notify_map_change(MapChangeRegionWillChange);
|
||||
view.notifyMapChange(MapChangeRegionWillChange);
|
||||
|
||||
current.width = final.width = w;
|
||||
current.height = final.height = h;
|
||||
@@ -38,7 +38,7 @@ bool Transform::resize(const uint16_t w, const uint16_t h, const float ratio,
|
||||
current.framebuffer[1] = final.framebuffer[1] = fb_h;
|
||||
constrain(current.scale, current.y);
|
||||
|
||||
view.notify_map_change(MapChangeRegionDidChange);
|
||||
view.notifyMapChange(MapChangeRegionDidChange);
|
||||
|
||||
return true;
|
||||
} else {
|
||||
@@ -57,7 +57,7 @@ void Transform::moveBy(const double dx, const double dy, const timestamp duratio
|
||||
void Transform::_moveBy(const double dx, const double dy, const timestamp duration) {
|
||||
// This is only called internally, so we don't need a lock here.
|
||||
|
||||
view.notify_map_change(duration ?
|
||||
view.notifyMapChange(duration ?
|
||||
MapChangeRegionWillChangeAnimated :
|
||||
MapChangeRegionWillChange);
|
||||
|
||||
@@ -78,7 +78,7 @@ void Transform::_moveBy(const double dx, const double dy, const timestamp durati
|
||||
std::make_shared<util::ease_transition<double>>(current.y, final.y, current.y, start, duration));
|
||||
}
|
||||
|
||||
view.notify_map_change(duration ?
|
||||
view.notifyMapChange(duration ?
|
||||
MapChangeRegionDidChangeAnimated :
|
||||
MapChangeRegionDidChange,
|
||||
duration);
|
||||
@@ -268,7 +268,7 @@ void Transform::_setScaleXY(const double new_scale, const double xn, const doubl
|
||||
const timestamp duration) {
|
||||
// This is only called internally, so we don't need a lock here.
|
||||
|
||||
view.notify_map_change(duration ?
|
||||
view.notifyMapChange(duration ?
|
||||
MapChangeRegionWillChangeAnimated :
|
||||
MapChangeRegionWillChange);
|
||||
|
||||
@@ -297,7 +297,7 @@ void Transform::_setScaleXY(const double new_scale, const double xn, const doubl
|
||||
Bc = s / 360;
|
||||
Cc = s / (2 * M_PI);
|
||||
|
||||
view.notify_map_change(duration ?
|
||||
view.notifyMapChange(duration ?
|
||||
MapChangeRegionDidChangeAnimated :
|
||||
MapChangeRegionDidChange,
|
||||
duration);
|
||||
@@ -376,7 +376,7 @@ void Transform::setAngle(const double new_angle, const double cx, const double c
|
||||
void Transform::_setAngle(double new_angle, const timestamp duration) {
|
||||
// This is only called internally, so we don't need a lock here.
|
||||
|
||||
view.notify_map_change(duration ?
|
||||
view.notifyMapChange(duration ?
|
||||
MapChangeRegionWillChangeAnimated :
|
||||
MapChangeRegionWillChange);
|
||||
|
||||
@@ -395,7 +395,7 @@ void Transform::_setAngle(double new_angle, const timestamp duration) {
|
||||
current.angle, final.angle, current.angle, start, duration));
|
||||
}
|
||||
|
||||
view.notify_map_change(duration ?
|
||||
view.notifyMapChange(duration ?
|
||||
MapChangeRegionDidChangeAnimated :
|
||||
MapChangeRegionDidChange,
|
||||
duration);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <mbgl/storage/caching_http_file_source.hpp>
|
||||
#include <mbgl/storage/file_request.hpp>
|
||||
#include <mbgl/storage/asset_request.hpp>
|
||||
#include <mbgl/storage/http_request.hpp>
|
||||
#include <mbgl/storage/sqlite_store.hpp>
|
||||
#include <mbgl/util/uv-messenger.h>
|
||||
@@ -17,6 +17,8 @@ CachingHTTPFileSource::~CachingHTTPFileSource() {
|
||||
}
|
||||
|
||||
void CachingHTTPFileSource::setLoop(uv_loop_t* loop_) {
|
||||
assert(!loop);
|
||||
|
||||
thread_id = std::this_thread::get_id();
|
||||
store = !path.empty() ? util::ptr<SQLiteStore>(new SQLiteStore(loop_, path)) : nullptr;
|
||||
loop = loop_;
|
||||
@@ -51,6 +53,8 @@ void CachingHTTPFileSource::clearLoop() {
|
||||
}
|
||||
|
||||
store.reset();
|
||||
|
||||
loop = nullptr;
|
||||
}
|
||||
|
||||
void CachingHTTPFileSource::setBase(std::string value) {
|
||||
@@ -91,8 +95,8 @@ std::unique_ptr<Request> CachingHTTPFileSource::request(ResourceType type, const
|
||||
}
|
||||
|
||||
if (!req) {
|
||||
if (url.substr(0, 7) == "file://") {
|
||||
req = std::make_shared<FileRequest>(url.substr(7), loop);
|
||||
if (url.substr(0, 8) == "asset://") {
|
||||
req = std::make_shared<AssetRequest>(url.substr(8), loop);
|
||||
} else {
|
||||
req = std::make_shared<HTTPRequest>(type, url, loop, store);
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
#include <mbgl/storage/file_request.hpp>
|
||||
#include <mbgl/storage/file_request_baton.hpp>
|
||||
#include <mbgl/storage/response.hpp>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
FileRequest::FileRequest(const std::string &path_, uv_loop_t *loop)
|
||||
: BaseRequest(path_), ptr(new FileRequestBaton(this, path, loop)) {
|
||||
}
|
||||
|
||||
void FileRequest::cancel() {
|
||||
assert(thread_id == std::this_thread::get_id());
|
||||
|
||||
if (ptr) {
|
||||
ptr->cancel();
|
||||
|
||||
// When deleting a FileRequest object with a uv_fs_* call is in progress, we are making sure
|
||||
// that the callback doesn't accidentally reference this object again.
|
||||
ptr->request = nullptr;
|
||||
ptr = nullptr;
|
||||
}
|
||||
|
||||
notify();
|
||||
}
|
||||
|
||||
FileRequest::~FileRequest() {
|
||||
assert(thread_id == std::this_thread::get_id());
|
||||
cancel();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#ifndef MBGL_STORAGE_FILE_REQUEST
|
||||
#define MBGL_STORAGE_FILE_REQUEST
|
||||
|
||||
#include <mbgl/storage/base_request.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
typedef struct uv_loop_s uv_loop_t;
|
||||
|
||||
struct FileRequestBaton;
|
||||
|
||||
class FileRequest : public BaseRequest {
|
||||
public:
|
||||
FileRequest(const std::string &path, uv_loop_t *loop);
|
||||
~FileRequest();
|
||||
|
||||
void cancel();
|
||||
|
||||
private:
|
||||
FileRequestBaton *ptr = nullptr;
|
||||
|
||||
friend struct FileRequestBaton;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,36 +0,0 @@
|
||||
#ifndef MBGL_STORAGE_FILE_REQUEST_BATON
|
||||
#define MBGL_STORAGE_FILE_REQUEST_BATON
|
||||
|
||||
#include <mbgl/storage/file_request.hpp>
|
||||
#include <thread>
|
||||
|
||||
#include <uv.h>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
struct FileRequestBaton {
|
||||
FileRequestBaton(FileRequest *request_, const std::string &path, uv_loop_t *loop);
|
||||
~FileRequestBaton();
|
||||
|
||||
void cancel();
|
||||
static void file_opened(uv_fs_t *req);
|
||||
static void file_stated(uv_fs_t *req);
|
||||
static void file_read(uv_fs_t *req);
|
||||
static void file_closed(uv_fs_t *req);
|
||||
static void notify_error(uv_fs_t *req);
|
||||
static void cleanup(uv_fs_t *req);
|
||||
|
||||
const std::thread::id thread_id;
|
||||
FileRequest *request = nullptr;
|
||||
uv_fs_t req;
|
||||
uv_file fd = -1;
|
||||
bool canceled = false;
|
||||
std::string body;
|
||||
uv_buf_t buffer;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user