Updating from master

This commit is contained in:
Brad Leege
2015-05-04 17:04:46 -05:00
230 changed files with 4374 additions and 4572 deletions

View File

@@ -23,7 +23,7 @@ public:
void activate() override;
void deactivate() override;
void notify() override;
void invalidate() override;
void invalidate(std::function<void()> render) override;
void notifyMapChange(mbgl::MapChange change, Duration delay = Duration::zero()) override;
@@ -39,17 +39,12 @@ public:
void createSurface(ANativeWindow *window);
void destroySurface();
void start();
void stop();
void resume();
void pause(bool waitForPause = false);
void enableFps(bool enable);
void updateFps();
void resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight);
private:
EGLConfig chooseConfig(const EGLConfig configs[], EGLint numConfigs);

View File

@@ -49,11 +49,6 @@ IB_DESIGNABLE
/** @name Managing Constraints */
/** A view controller whose top and bottom layout guides to use for proper setup of constraints in the map view internals.
*
* Certain components of the map view, such as the heading compass and the data attribution button, need to be aware of the view controller layout in order to avoid positioning content under a top navigation bar or a bottom toolbar. */
@property (nonatomic, weak) IBOutlet UIViewController *viewControllerForLayoutGuides;
#pragma mark - Accessing Map Properties
/** @name Accessing Map Properties */

View File

@@ -4,6 +4,7 @@ extern NSString *const MGLEventTypeMapLoad;
extern NSString *const MGLEventTypeMapTap;
extern NSString *const MGLEventTypeMapDragEnd;
extern NSString *const MGLEventTypeLocation;
extern NSString *const MGLEventTypeVisit;
extern NSString *const MGLEventKeyLatitude;
extern NSString *const MGLEventKeyLongitude;
@@ -16,6 +17,8 @@ extern NSString *const MGLEventKeyVerticalAccuracy;
extern NSString *const MGLEventKeyPushEnabled;
extern NSString *const MGLEventKeyEmailEnabled;
extern NSString *const MGLEventKeyGestureID;
extern NSString *const MGLEventKeyArrivalDate;
extern NSString *const MGLEventKeyDepartureDate;
extern NSString *const MGLEventGestureSingleTap;
extern NSString *const MGLEventGestureDoubleTap;
@@ -32,6 +35,7 @@ extern NSString *const MGLEventGestureRotateStart;
+ (void) setToken:(NSString *)token;
+ (void) setAppName:(NSString *)appName;
+ (void) setAppVersion:(NSString *)appVersion;
+ (void) setAppBuildNumber:(NSString *)appBuildNumber;
+ (void) pauseMetricsCollection;
+ (void) resumeMetricsCollection;

View File

@@ -5,7 +5,9 @@
// These methods can be called from any thread.
//
+ (instancetype)sharedManager;
+ (void) startUpdatingLocation;
+ (void) stopUpdatingLocation;
- (void) startUpdatingLocation;
- (void) stopUpdatingLocation;
- (void) startMonitoringVisits;
- (void) stopMonitoringVisits;
@end

View File

@@ -54,11 +54,6 @@ public:
// Only call this while the OpenGL context is exclusive to this thread.
void performCleanup();
// #############################################################################################
// Request to terminate the environment.
void terminate();
private:
unsigned id;
FileSource& fileSource;
@@ -67,9 +62,6 @@ private:
std::vector<uint32_t> abandonedVAOs;
std::vector<uint32_t> abandonedBuffers;
std::vector<uint32_t> abandonedTextures;
public:
uv_loop_t* const loop;
};
class EnvironmentScope final {

View File

@@ -1,96 +1,57 @@
#ifndef MBGL_MAP_MAP
#define MBGL_MAP_MAP
#include <mbgl/map/transform.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/map/update.hpp>
#include <mbgl/map/mode.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/projection.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/ptr.hpp>
#include <mbgl/util/vec.hpp>
#include <cstdint>
#include <atomic>
#include <thread>
#include <iosfwd>
#include <set>
#include <vector>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <string>
#include <functional>
namespace uv { class async; }
#include <vector>
#include <memory>
namespace mbgl {
class Painter;
class GlyphStore;
class LayerDescription;
class Sprite;
class Style;
class StyleLayer;
class TexturePool;
class FileSource;
class View;
class GlyphAtlas;
class SpriteAtlas;
class LineAtlas;
class Environment;
class EnvironmentScope;
class AnnotationManager;
class MapData;
class Worker;
class MapContext;
class StillImage;
namespace util {
template <class T> class Thread;
}
class Map : private util::noncopyable {
friend class View;
public:
enum class Mode : uint8_t {
None, // we're not doing any processing
Continuous, // continually updating map
Still, // a once-off still image.
};
explicit Map(View&, FileSource&);
explicit Map(View&, FileSource&,
MapMode mode = MapMode::Continuous,
bool startPaused = false);
~Map();
// Start the map render thread. It is asynchronous.
void start(bool startPaused = false, Mode mode = Mode::Continuous);
inline void start(Mode renderMode) { start(false, renderMode); }
// Stop the map render thread. This call will block until the map rendering thread stopped.
// The optional callback function will be invoked repeatedly until the map thread is stopped.
// The callback function should wait until it is woken up again by view.notify(), otherwise
// this will be a busy waiting loop.
void stop(std::function<void ()> callback = std::function<void ()>());
// Pauses the render thread. The render thread will stop running but will not be terminated and will not lose state until resumed.
void pause(bool waitForPause = false);
// Resumes a paused render thread
void resume();
// Register a callback that will get called (on the render thread) when all resources have
// been loaded and a complete render occurs.
using StillImageCallback = std::function<void(std::unique_ptr<const StillImage>)>;
void renderStill(StillImageCallback callback);
// Triggers a synchronous or asynchronous render.
void renderSync();
// Unconditionally performs a render with the current map state. May only be called from the Map
// thread.
void render();
void renderAsync();
// Notifies the Map thread that the state has changed and an update might be necessary.
void triggerUpdate(Update = Update::Nothing);
// Triggers a render. Can be called from any thread.
void triggerRender();
// Releases resources immediately
void terminate();
void update(Update update = Update::Nothing);
// Styling
void addClass(const std::string&);
@@ -134,18 +95,23 @@ public:
double getBearing() const;
void resetNorth();
// Size
void resize(uint16_t width, uint16_t height, float ratio = 1);
uint16_t getWidth() const;
uint16_t getHeight() const;
// API
void setAccessToken(const std::string &token);
std::string getAccessToken() const;
// Projection
inline void getWorldBoundsMeters(ProjectedMeters &sw, ProjectedMeters &ne) const { Projection::getWorldBoundsMeters(sw, ne); }
inline void getWorldBoundsLatLng(LatLng &sw, LatLng &ne) const { Projection::getWorldBoundsLatLng(sw, ne); }
inline double getMetersPerPixelAtLatitude(const double lat, const double zoom) const { return Projection::getMetersPerPixelAtLatitude(lat, zoom); }
inline const ProjectedMeters projectedMetersForLatLng(const LatLng latLng) const { return Projection::projectedMetersForLatLng(latLng); }
inline const LatLng latLngForProjectedMeters(const ProjectedMeters projectedMeters) const { return Projection::latLngForProjectedMeters(projectedMeters); }
inline const vec2<double> pixelForLatLng(const LatLng latLng) const { return state.pixelForLatLng(latLng); }
inline const LatLng latLngForPixel(const vec2<double> pixel) const { return state.latLngForPixel(pixel); }
void getWorldBoundsMeters(ProjectedMeters &sw, ProjectedMeters &ne) const;
void getWorldBoundsLatLng(LatLng &sw, LatLng &ne) const;
double getMetersPerPixelAtLatitude(const double lat, const double zoom) const;
const ProjectedMeters projectedMetersForLatLng(const LatLng latLng) const;
const LatLng latLngForProjectedMeters(const ProjectedMeters projectedMeters) const;
const vec2<double> pixelForLatLng(const LatLng latLng) const;
const LatLng latLngForPixel(const vec2<double> pixel) const;
// Annotations
void setDefaultPointAnnotationSymbol(const std::string&);
@@ -160,7 +126,6 @@ public:
// Memory
void setSourceTileCacheSize(size_t);
size_t getSourceTileCacheSize() const { return sourceCacheSize; }
void onLowMemory();
// Debug
@@ -168,104 +133,9 @@ public:
void toggleDebug();
bool getDebug() const;
inline const TransformState &getState() const { return state; }
TimePoint getTime() const;
inline AnnotationManager& getAnnotationManager() const { return *annotationManager; }
private:
// Runs the map event loop. ONLY run this function when you want to get render a single frame
// with this map object. It will *not* spawn a separate thread and instead block until the
// frame is completely rendered.
void run();
// This may only be called by the View object.
void resize(uint16_t width, uint16_t height, float ratio = 1);
void resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight);
util::ptr<Sprite> getSprite();
Worker& getWorker();
// Checks if render thread needs to pause
void checkForPause();
// Setup
void setup();
void updateTiles();
// Triggered by triggerUpdate();
void update();
// Loads the style set in the data object. Called by Update::StyleInfo
void reloadStyle();
void loadStyleJSON(const std::string& json, const std::string& base);
// Prepares a map render by updating the tiles we need for the current view, as well as updating
// the stylesheet.
void prepare();
// Runs the function in the map thread.
void invokeTask(std::function<void()>&&);
template <typename Fn> auto invokeSyncTask(const Fn& fn) -> decltype(fn());
void processTasks();
void updateAnnotationTiles(const std::vector<TileID>&);
size_t sourceCacheSize;
Mode mode = Mode::None;
const std::unique_ptr<Environment> env;
std::unique_ptr<EnvironmentScope> scope;
View &view;
private:
std::unique_ptr<Worker> workers;
std::thread thread;
std::unique_ptr<uv::async> asyncTerminate;
std::unique_ptr<uv::async> asyncUpdate;
std::unique_ptr<uv::async> asyncInvoke;
std::unique_ptr<uv::async> asyncRender;
bool terminating = false;
bool pausing = false;
bool isPaused = false;
std::mutex mutexRun;
std::condition_variable condRun;
std::mutex mutexPause;
std::condition_variable condPause;
// Used to signal that rendering completed.
bool rendered = false;
std::condition_variable condRendered;
std::mutex mutexRendered;
// Stores whether the map thread has been stopped already.
std::atomic_bool isStopped;
Transform transform;
TransformState state;
FileSource& fileSource;
util::ptr<Style> style;
std::unique_ptr<GlyphAtlas> glyphAtlas;
util::ptr<GlyphStore> glyphStore;
std::unique_ptr<SpriteAtlas> spriteAtlas;
util::ptr<Sprite> sprite;
std::unique_ptr<LineAtlas> lineAtlas;
util::ptr<TexturePool> texturePool;
std::unique_ptr<Painter> painter;
std::unique_ptr<AnnotationManager> annotationManager;
const std::unique_ptr<MapData> data;
std::atomic<UpdateType> updated;
std::mutex mutexTask;
std::queue<std::function<void()>> tasks;
StillImageCallback callback;
const std::unique_ptr<util::Thread<MapContext>> context;
};
}

15
include/mbgl/map/mode.hpp Normal file
View File

@@ -0,0 +1,15 @@
#ifndef MBGL_MAP_MODE
#define MBGL_MAP_MODE
#include <cstdint>
namespace mbgl {
enum class MapMode : uint8_t {
Continuous, // continually updating map
Still, // a once-off still image
};
}
#endif

View File

@@ -1,101 +0,0 @@
#ifndef MBGL_MAP_TRANSFORM
#define MBGL_MAP_TRANSFORM
#include <mbgl/map/transform_state.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/map/update.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/noncopyable.hpp>
#include <mbgl/util/vec.hpp>
#include <cstdint>
#include <cmath>
#include <forward_list>
#include <mutex>
namespace mbgl {
class View;
namespace util { class transition; }
class Transform : private util::noncopyable {
public:
Transform(View &view);
// Map view
// Note: width * ratio does not necessarily equal fb_width
bool resize(uint16_t width, uint16_t height, float ratio,
uint16_t fb_width, uint16_t fb_height);
// Position
void moveBy(double dx, double dy, Duration = Duration::zero());
void setLatLng(LatLng latLng, Duration = Duration::zero());
void setLatLngZoom(LatLng latLng, double zoom, Duration = Duration::zero());
inline const LatLng getLatLng() const { return current.getLatLng(); }
// Zoom
void scaleBy(double ds, double cx = -1, double cy = -1, Duration = Duration::zero());
void setScale(double scale, double cx = -1, double cy = -1, Duration = Duration::zero());
void setZoom(double zoom, Duration = Duration::zero());
double getZoom() const;
double getScale() const;
double getMinZoom() const;
double getMaxZoom() const;
// Angle
void rotateBy(double sx, double sy, double ex, double ey, Duration = Duration::zero());
void setAngle(double angle, Duration = Duration::zero());
void setAngle(double angle, double cx, double cy);
double getAngle() const;
// Transitions
bool needsTransition() const;
UpdateType updateTransitions(TimePoint now);
void cancelTransitions();
// Gesture
void setGestureInProgress(bool);
// Transform state
const TransformState currentState() const;
const TransformState finalState() const;
private:
// Functions prefixed with underscores will *not* perform any locks. It is the caller's
// responsibility to lock this object.
void _moveBy(double dx, double dy, Duration = Duration::zero());
void _setScale(double scale, double cx, double cy, Duration = Duration::zero());
void _setScaleXY(double new_scale, double xn, double yn, Duration = Duration::zero());
void _setAngle(double angle, Duration = Duration::zero());
void constrain(double& scale, double& y) const;
View &view;
mutable std::recursive_mutex mtx;
// This reflects the current state of the transform, representing the actual position of the
// map. After calling a transform function with a timer, this will likely remain the same until
// you render a new frame.
TransformState current;
// This reflects the final position of the transform, after all possible transition took place.
TransformState final;
// Limit the amount of zooming possible on the map.
const double min_scale = std::pow(2, 0);
const double max_scale = std::pow(2, 18);
void startTransition(std::function<Update(double)> frame,
std::function<void()> finish,
Duration);
TimePoint transitionStart;
Duration transitionDuration;
std::function<Update(TimePoint)> transitionFrameFn;
std::function<void()> transitionFinishFn;
};
}
#endif

View File

@@ -1,91 +0,0 @@
#ifndef MBGL_MAP_TRANSFORM_STATE
#define MBGL_MAP_TRANSFORM_STATE
#include <mbgl/util/mat4.hpp>
#include <mbgl/util/geo.hpp>
#include <mbgl/util/vec.hpp>
#include <cstdint>
#include <array>
#include <limits>
namespace mbgl {
class TileID;
struct box;
class TransformState {
friend class Transform;
public:
// Matrix
void matrixFor(mat4& matrix, const TileID& id) const;
box cornersToBox(uint32_t z) const;
// Dimensions
bool hasSize() const;
uint16_t getWidth() const;
uint16_t getHeight() const;
uint16_t getFramebufferWidth() const;
uint16_t getFramebufferHeight() const;
const std::array<uint16_t, 2> getFramebufferDimensions() const;
float getPixelRatio() const;
float worldSize() const;
float lngX(float lon) const;
float latY(float lat) const;
std::array<float, 2> locationCoordinate(float lon, float lat) const;
void getLonLat(double &lon, double &lat) const;
// Position
const LatLng getLatLng() const;
// Zoom
float getNormalizedZoom() const;
double getZoom() const;
int32_t getIntegerZoom() const;
double getZoomFraction() const;
double getScale() const;
// Rotation
float getAngle() const;
// Projection
const vec2<double> pixelForLatLng(const LatLng latLng) const;
const LatLng latLngForPixel(const vec2<double> pixel) const;
// Changing
bool isChanging() const;
private:
double pixel_x() const;
double pixel_y() const;
private:
// logical dimensions
uint16_t width = 0, height = 0;
// physical (framebuffer) dimensions
std::array<uint16_t, 2> framebuffer = {{ 0, 0 }};
// map scale factor
float pixelRatio = 0;
// cache values for spherical mercator math
double Bc, Cc;
// animation state
bool rotating = false;
bool scaling = false;
bool panning = false;
bool gestureInProgress = false;
// map position
double x = 0, y = 0;
double angle = 0;
double scale = 1;
};
}
#endif

View File

@@ -9,7 +9,6 @@ using UpdateType = uint32_t;
enum class Update : UpdateType {
Nothing = 0,
StyleInfo = 1 << 0,
Debug = 1 << 1,
DefaultTransitionDuration = 1 << 2,
Classes = 1 << 3,

View File

@@ -2,6 +2,7 @@
#define MBGL_MAP_VIEW
#include <mbgl/util/chrono.hpp>
#include <functional>
#include <memory>
@@ -39,13 +40,13 @@ public:
virtual void notify() = 0;
// Called from the render thread. The implementation must trigger a rerender.
// (i.e. map->renderSync() or map->renderAsync() must be called as a result of this)
virtual void invalidate() = 0;
// Called from the render thread. The implementation should resize the framebuffer.
virtual void resize(uint16_t width, uint16_t height, float pixelRatio);
// Called from the render (=GL) thread. Signals that the contents of the contents
// may be discarded. The default is a no-op.
virtual void discard();
// Called from the render thread. The implementation must trigger a rerender.
// (i.e. either the passed render() function for rendering immediately on the map thread,
// or map->renderSync() from the main thread must be called as a result of this)
virtual void invalidate(std::function<void()> render) = 0;
// Reads the pixel data from the current framebuffer. If your View implementation
// doesn't support reading from the framebuffer, return a null pointer.
@@ -58,10 +59,6 @@ public:
MapChange change,
Duration delay = Duration::zero());
protected:
// Resizes the view
void resize(uint16_t width, uint16_t height, float ratio, uint16_t fbWidth, uint16_t fbHeight);
protected:
mbgl::Map *map = nullptr;
};

View File

@@ -17,7 +17,7 @@ public:
void activate() override;
void deactivate() override;
void notify() override;
void invalidate() override;
void invalidate(std::function<void()> render) override;
static void onKey(GLFWwindow *window, int key, int scancode, int action, int mods);
static void onScroll(GLFWwindow *window, double xoffset, double yoffset);
@@ -25,7 +25,7 @@ public:
static void onMouseClick(GLFWwindow *window, int button, int action, int modifiers);
static void onMouseMove(GLFWwindow *window, double x, double y);
int run();
void run();
void fps();
public:

View File

@@ -17,6 +17,7 @@ typedef XID GLXPbuffer;
#include <mbgl/platform/gl.hpp>
#include <memory>
#include <thread>
namespace mbgl {
@@ -28,13 +29,11 @@ public:
HeadlessView(std::shared_ptr<HeadlessDisplay> display, uint16_t width = 256, uint16_t height = 256, float pixelRatio = 1);
~HeadlessView();
void resize(uint16_t width, uint16_t height, float pixelRatio);
void activate() override;
void deactivate() override;
void notify() override;
void invalidate() override;
void discard() override;
void resize(uint16_t width, uint16_t height, float pixelRatio) override;
void invalidate(std::function<void()> render) override;
std::unique_ptr<StillImage> readStillImage() override;
private:
@@ -56,12 +55,7 @@ private:
float pixelRatio = 0;
};
// These are the values that represent the state of the current framebuffer.
Dimensions current;
// These are the values that will be used after the next discard() event.
std::mutex prospectiveMutex;
Dimensions prospective;
Dimensions dimensions;
#if MBGL_USE_CGL
CGLContextObj glContext = nullptr;

View File

@@ -10,10 +10,9 @@ extern "C"
}
#pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wshadow"
#endif
#include <boost/iostreams/stream.hpp>
#pragma GCC diagnostic pop

View File

@@ -12,10 +12,9 @@ extern "C"
#include <memory>
#pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#pragma GCC diagnostic ignored "-Wshadow"
#endif
#include <boost/iostreams/stream.hpp>
#pragma GCC diagnostic pop

View File

@@ -159,7 +159,7 @@ inline void start_group(const std::string &str) {
if (gl::PushDebugGroup != nullptr) {
MBGL_CHECK_ERROR(gl::PushDebugGroup(GL_DEBUG_SOURCE_APPLICATION, 0, GLsizei(str.size()), str.c_str()));
} else if (gl::PushGroupMarkerEXT != nullptr) {
MBGL_CHECK_ERROR(gl::PushGroupMarkerEXT(GLsizei(str.size()), str.c_str()));
MBGL_CHECK_ERROR(gl::PushGroupMarkerEXT(GLsizei(str.size() + 1), str.c_str()));
}
// fprintf(stderr, "%s%s\n", std::string(indent * 4, ' ').c_str(), str.c_str());
// indent++;

View File

@@ -21,6 +21,9 @@ const std::string &applicationRoot();
// Returns the path to the asset location.
const std::string &assetRoot();
// Makes the current thread low priority.
void makeThreadLowPriority();
// Shows an alpha image with the specified dimensions in a named window.
void showDebugImage(std::string name, const char *data, size_t width, size_t height);

View File

@@ -16,12 +16,9 @@ public:
~DefaultFileSource() override;
// FileSource API
Request *request(const Resource &resource, uv_loop_t *loop, const Environment &env,
Callback callback) override;
void cancel(Request *request) override;
void request(const Resource &resource, const Environment &env, Callback callback) override;
void abort(const Environment &env) override;
Request* request(const Resource&, uv_loop_t*, Callback) override;
void cancel(Request*) override;
void request(const Resource&, Callback) override;
public:
class Impl;

View File

@@ -15,7 +15,6 @@ typedef struct uv_loop_s uv_loop_t;
namespace mbgl {
class Request;
class Environment;
class FileSource : private util::noncopyable {
protected:
@@ -28,19 +27,12 @@ public:
// These can be called from any thread. The callback will be invoked in the loop.
// You can only cancel a request from the same thread it was created in.
virtual Request *request(const Resource &resource, uv_loop_t *loop, const Environment &env,
Callback callback) = 0;
virtual void cancel(Request *request) = 0;
virtual Request* request(const Resource&, uv_loop_t*, Callback) = 0;
virtual void cancel(Request*) = 0;
// These can be called from any thread. The callback will be invoked in an arbitrary other thread.
// You cannot cancel these requests.
virtual void request(const Resource &resource, const Environment &env, Callback callback) = 0;
// This can be called from any thread. All requests with the environment pointer env should be
// notified as errored. Note that this is /different/ from canceling requests; a canceled
// request's callback is never called, while an aborted request's callback is called with
// a error message.
virtual void abort(const Environment &env) = 0;
virtual void request(const Resource&, Callback) = 0;
};
}

View File

@@ -17,14 +17,13 @@ typedef struct uv_loop_s uv_loop_t;
namespace mbgl {
class Response;
class Environment;
class Request : private util::noncopyable {
MBGL_STORE_THREAD(tid)
public:
using Callback = std::function<void(const Response &)>;
Request(const Resource &resource, uv_loop_t *loop, const Environment &env, Callback callback);
Request(const Resource &resource, uv_loop_t *loop, Callback callback);
public:
// May be called from any thread.
@@ -48,11 +47,6 @@ private:
public:
const Resource resource;
// The environment ref is used to associate requests with a particular environment. This allows
// us to only terminate requests associated with that environment, e.g. when the map the env
// belongs to is discarded.
const Environment &env;
};
}

View File

@@ -20,8 +20,9 @@ public:
void get(const Resource &resource, Callback callback) override;
void put(const Resource &resource, std::shared_ptr<const Response> response, Hint hint) override;
private:
class Impl;
private:
const std::unique_ptr<util::Thread<Impl>> thread;
};

View File

@@ -1,95 +0,0 @@
#ifndef MBGL_UTIL_ASYNC_QUEUE
#define MBGL_UTIL_ASYNC_QUEUE
#include "std.hpp"
#include <uv.h>
#include <thread>
#include <mutex>
#include <functional>
#include <queue>
#include <string>
#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10
#define UV_ASYNC_PARAMS(handle) uv_async_t *handle, int
#else
#define UV_ASYNC_PARAMS(handle) uv_async_t *handle
#endif
namespace mbgl {
namespace util {
template <typename T>
class AsyncQueue {
public:
AsyncQueue(uv_loop_t *loop, std::function<void(T &)> fn) :
callback(fn) {
async.data = this;
uv_async_init(loop, &async, [](UV_ASYNC_PARAMS(handle)) {
auto q = reinterpret_cast<AsyncQueue *>(handle->data);
q->process();
});
}
void send(T &&data) {
{
std::lock_guard<std::mutex> lock(mutex);
queue.push(util::make_unique<T>(std::move(data)));
}
uv_async_send(&async);
}
void send(std::unique_ptr<T> data) {
{
std::lock_guard<std::mutex> lock(mutex);
queue.push(std::move(data));
}
uv_async_send(&async);
}
void stop() {
uv_close((uv_handle_t *)&async, [](uv_handle_t *handle) {
delete reinterpret_cast<AsyncQueue *>(handle->data);
});
}
void ref() {
uv_ref((uv_handle_t *)&async);
}
void unref() {
uv_unref((uv_handle_t *)&async);
}
private:
~AsyncQueue() {
}
void process() {
std::unique_ptr<T> item;
while (true) {
mutex.lock();
if (queue.empty()) {
mutex.unlock();
break;
}
item = std::move(queue.front());
queue.pop();
mutex.unlock();
callback(*item);
}
}
private:
std::mutex mutex;
uv_async_t async;
std::queue<std::unique_ptr<T>> queue;
std::function<void(T &)> callback;
};
}
}
#endif

View File

@@ -0,0 +1,87 @@
#ifndef MBGL_UTIL_GL_HELPER
#define MBGL_UTIL_GL_HELPER
#include <mbgl/platform/gl.hpp>
#include <array>
namespace {
template <typename T, T (*Create)(), void (*Destroy)(const T&)>
class Preserve {
public:
Preserve() : data(Create()) {}
~Preserve() { Destroy(data); }
private:
const T data;
};
inline bool getBlend() {
return glIsEnabled(GL_BLEND);
}
inline void setBlend(const bool& enabled) {
enabled ? MBGL_CHECK_ERROR(glEnable(GL_BLEND)) : MBGL_CHECK_ERROR(glDisable(GL_BLEND));
}
inline std::array<double, 4> getClearColor() {
std::array<double, 4> color;
MBGL_CHECK_ERROR(glGetDoublev(GL_COLOR_CLEAR_VALUE, color.data()));
return color;
}
inline void setClearColor(const std::array<double, 4>& color) {
MBGL_CHECK_ERROR(glClearColor(color[0], color[1], color[2], color[3]));
}
inline std::array<GLenum, 2> getBlendFunc() {
GLint func[2];
glGetIntegerv(GL_BLEND_SRC, &func[0]);
glGetIntegerv(GL_BLEND_DST, &func[1]);
return {{ static_cast<GLenum>(func[0]), static_cast<GLenum>(func[1]) }};
}
inline void setBlendFunc(const std::array<GLenum, 2>& func) {
MBGL_CHECK_ERROR(glBlendFunc(func[0], func[1]));
}
inline std::array<double, 2> getPixelZoom() {
std::array<double, 2> zoom;
glGetDoublev(GL_ZOOM_X, &zoom[0]);
glGetDoublev(GL_ZOOM_Y, &zoom[1]);
return zoom;
}
inline void setPixelZoom(const std::array<double, 2>& func) {
MBGL_CHECK_ERROR(glPixelZoom(func[0], func[1]));
}
inline std::array<double, 4> getRasterPos() {
std::array<double, 4> pos;
MBGL_CHECK_ERROR(glGetDoublev(GL_CURRENT_RASTER_POSITION, pos.data()));
return pos;
}
inline void setRasterPos(const std::array<double, 4>& pos) {
MBGL_CHECK_ERROR(glRasterPos4d(pos[0], pos[1], pos[2], pos[3]));
}
} // end anonymous namespace
namespace mbgl {
namespace gl {
using PreserveBlend = Preserve<bool, getBlend, setBlend>;
using PreserveClearColor = Preserve<std::array<double, 4>, getClearColor, setClearColor>;
using PreserveBlendFunc = Preserve<std::array<GLenum, 2>, getBlendFunc, setBlendFunc>;
using PreservePixelZoom = Preserve<std::array<double, 2>, getPixelZoom, setPixelZoom>;
using PreserveRasterPos = Preserve<std::array<double, 4>, getRasterPos, setRasterPos>;
}
}
#endif

View File

@@ -74,6 +74,11 @@ inline vec2<T> normal(const S1& a, const S2& b) {
return { dx / c, dy / c };
}
template <typename T>
inline T perp(const T& a) {
return T(-a.y, a.x);
}
template <typename T, typename S1, typename S2>
inline T dist(const S1& a, const S2& b) {
T dx = b.x - a.x;
@@ -93,6 +98,11 @@ inline T mag(const S& a) {
return std::sqrt(a.x * a.x + a.y * a.y);
}
template <typename S>
inline S unit(const S& a) {
return a * (1 / mag(a));
}
template <typename T>
T clamp(T value, T min, T max) {
return value < min ? min : (value > max ? max : value);

View File

@@ -4,9 +4,8 @@
#include <string>
#pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wunused-local-typedefs"
#endif
#include <boost/lexical_cast.hpp>
#pragma GCC diagnostic pop

View File

@@ -61,7 +61,13 @@ struct vec2 {
template <typename O>
inline typename std::enable_if<!std::is_arithmetic<O>::value, vec2>::type
operator-(const O &o) const {
return {x - o.x, y - o.y};
return vec2<T>(x - o.x, y - o.y);
}
template <typename O>
inline typename std::enable_if<!std::is_arithmetic<O>::value, vec2>::type
operator+(const O &o) const {
return vec2<T>(x + o.x, y + o.y);
}
template <typename M>