[core] separate Backend from View for headless rendering
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <mbgl/benchmark/util.hpp>
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/thread_pool.hpp>
|
||||
#include <mbgl/sprite/sprite_image.hpp>
|
||||
@@ -35,11 +35,11 @@ public:
|
||||
}
|
||||
|
||||
util::RunLoop loop;
|
||||
std::shared_ptr<HeadlessDisplay> display{ std::make_shared<HeadlessDisplay>() };
|
||||
HeadlessView view{ display, 1 };
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view;
|
||||
DefaultFileSource fileSource{ "benchmark/fixtures/api/cache.db", "." };
|
||||
ThreadPool threadPool{ 4 };
|
||||
Map map{ view, fileSource, threadPool, MapMode::Still };
|
||||
Map map{ backend, view, view.getPixelRatio(), fileSource, threadPool, MapMode::Still };
|
||||
ScreenBox box{{ 0, 0 }, { 1000, 1000 }};
|
||||
};
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
namespace {
|
||||
|
||||
std::unique_ptr<GLFWView> view;
|
||||
GLFWView* view = nullptr;
|
||||
|
||||
}
|
||||
|
||||
@@ -104,7 +104,8 @@ int main(int argc, char *argv[]) {
|
||||
mbgl::Log::Info(mbgl::Event::General, "BENCHMARK MODE: Some optimizations are disabled.");
|
||||
}
|
||||
|
||||
view = std::make_unique<GLFWView>(fullscreen, benchmark);
|
||||
GLFWView backend(fullscreen, benchmark);
|
||||
view = &backend;
|
||||
|
||||
mbgl::DefaultFileSource fileSource("/tmp/mbgl-cache.db", ".");
|
||||
|
||||
@@ -118,7 +119,7 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
mbgl::ThreadPool threadPool(4);
|
||||
|
||||
mbgl::Map map(*view, fileSource, threadPool);
|
||||
mbgl::Map map(backend, backend, backend.getPixelRatio(), fileSource, threadPool);
|
||||
|
||||
// Load settings
|
||||
mbgl::Settings_JSON settings;
|
||||
@@ -181,5 +182,6 @@ int main(int argc, char *argv[]) {
|
||||
"Exit location: --lat=\"%f\" --lon=\"%f\" --zoom=\"%f\" --bearing \"%f\"",
|
||||
settings.latitude, settings.longitude, settings.zoom, settings.bearing);
|
||||
|
||||
view = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <mbgl/util/io.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/thread_pool.hpp>
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
@@ -84,9 +84,10 @@ int main(int argc, char *argv[]) {
|
||||
fileSource.setAccessToken(std::string(token));
|
||||
}
|
||||
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view(pixelRatio, width, height);
|
||||
ThreadPool threadPool(4);
|
||||
Map map(view, fileSource, threadPool, MapMode::Still);
|
||||
Map map(backend, view, view.getPixelRatio(), fileSource, threadPool, MapMode::Still);
|
||||
|
||||
map.setStyleJSON(style);
|
||||
map.setClasses(classes);
|
||||
|
||||
@@ -54,6 +54,7 @@ set(MBGL_CORE_FILES
|
||||
|
||||
# gl
|
||||
include/mbgl/gl/gl.hpp
|
||||
include/mbgl/gl/implementation.hpp
|
||||
src/mbgl/gl/attribute.hpp
|
||||
src/mbgl/gl/context.cpp
|
||||
src/mbgl/gl/context.hpp
|
||||
@@ -92,11 +93,13 @@ set(MBGL_CORE_FILES
|
||||
src/mbgl/layout/symbol_layout.hpp
|
||||
|
||||
# map
|
||||
include/mbgl/map/backend.hpp
|
||||
include/mbgl/map/camera.hpp
|
||||
include/mbgl/map/map.hpp
|
||||
include/mbgl/map/mode.hpp
|
||||
include/mbgl/map/update.hpp
|
||||
include/mbgl/map/view.hpp
|
||||
src/mbgl/map/backend.cpp
|
||||
src/mbgl/map/change.hpp
|
||||
src/mbgl/map/map.cpp
|
||||
src/mbgl/map/transform.cpp
|
||||
@@ -130,6 +133,7 @@ set(MBGL_CORE_FILES
|
||||
|
||||
# platform/default
|
||||
include/mbgl/platform/default/glfw_view.hpp
|
||||
include/mbgl/platform/default/headless_backend.hpp
|
||||
include/mbgl/platform/default/headless_display.hpp
|
||||
include/mbgl/platform/default/headless_view.hpp
|
||||
include/mbgl/platform/default/settings_json.hpp
|
||||
|
||||
14
include/mbgl/gl/implementation.hpp
Normal file
14
include/mbgl/gl/implementation.hpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__QT__)
|
||||
#define MBGL_USE_QT 1
|
||||
#elif defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_IOS
|
||||
#define MBGL_USE_EAGL 1
|
||||
#else
|
||||
#define MBGL_USE_CGL 1
|
||||
#endif
|
||||
#else
|
||||
#define MBGL_USE_GLX 1
|
||||
#endif
|
||||
34
include/mbgl/map/backend.hpp
Normal file
34
include/mbgl/map/backend.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/map/change.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class Map;
|
||||
|
||||
class Backend {
|
||||
public:
|
||||
virtual ~Backend() = default;
|
||||
|
||||
// Called when the backend's GL context needs to be made active or inactive. These are called,
|
||||
// as a matched pair, in four situations:
|
||||
//
|
||||
// 1. When releasing GL resources during Map destruction
|
||||
// 2. When calling a CustomLayerInitializeFunction, during Map::addLayer
|
||||
// 3. When calling a CustomLayerDeinitializeFunction, during Map::removeLayer
|
||||
// 4. When rendering for Map::renderStill
|
||||
//
|
||||
// They are *not* called for Map::render; it is assumed that the correct context is already
|
||||
// activated prior to calling Map::render.
|
||||
virtual void activate() = 0;
|
||||
virtual void deactivate() = 0;
|
||||
|
||||
// Called when the map needs to be rendered; the backend should call Map::render() at some point
|
||||
// in the near future. (Not called for Map::renderStill() mode.)
|
||||
virtual void invalidate() = 0;
|
||||
|
||||
// Notifies a watcher of map x/y/scale/rotation changes.
|
||||
virtual void notifyMapChange(MapChange change);
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class Backend;
|
||||
class View;
|
||||
class FileSource;
|
||||
class Scheduler;
|
||||
@@ -33,7 +34,11 @@ class Layer;
|
||||
|
||||
class Map : private util::noncopyable {
|
||||
public:
|
||||
explicit Map(View&, FileSource&, Scheduler&,
|
||||
explicit Map(Backend&,
|
||||
View&,
|
||||
float pixelRatio,
|
||||
FileSource&,
|
||||
Scheduler&,
|
||||
MapMode mapMode = MapMode::Continuous,
|
||||
GLContextMode contextMode = GLContextMode::Unique,
|
||||
ConstrainMode constrainMode = ConstrainMode::HeightOnly,
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/map/change.hpp>
|
||||
#include <mbgl/util/chrono.hpp>
|
||||
#include <mbgl/util/image.hpp>
|
||||
|
||||
#include <array>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class Map;
|
||||
|
||||
class View {
|
||||
class View : private util::noncopyable {
|
||||
public:
|
||||
virtual ~View() = default;
|
||||
|
||||
// Called directly after initialization. Must always return the same value, i.e. it may
|
||||
// not change over time.
|
||||
virtual float getPixelRatio() const = 0;
|
||||
// Called when this View is associated with a Map object.
|
||||
virtual void initialize(Map*);
|
||||
|
||||
// Called when this View is used for rendering. Implementations should ensure that a renderable
|
||||
// object is bound and glClear/glDraw* calls can be done.
|
||||
virtual void bind() = 0;
|
||||
|
||||
// Called when the View signaled a dimension change. Must return the logical dimension
|
||||
// of this map in pixels.
|
||||
@@ -30,34 +29,12 @@ public:
|
||||
// different from that rule.
|
||||
virtual std::array<uint16_t, 2> getFramebufferSize() const = 0;
|
||||
|
||||
// Called when this View is associated with a Map object.
|
||||
virtual void initialize(Map*);
|
||||
|
||||
// Called when the view's GL context needs to be made active or inactive. These are called,
|
||||
// as a matched pair, in four situations:
|
||||
//
|
||||
// 1. When releasing GL resources during Map destruction
|
||||
// 2. When calling a CustomLayerInitializeFunction, during Map::addLayer
|
||||
// 3. When calling a CustomLayerDeinitializeFunction, during Map::removeLayer
|
||||
// 4. When rendering for Map::renderStill
|
||||
//
|
||||
// They are *not* called for Map::render; it is assumed that the correct context is already
|
||||
// activated prior to calling Map::render.
|
||||
virtual void activate() = 0;
|
||||
virtual void deactivate() = 0;
|
||||
|
||||
// Called when the map needs to be rendered; the view should call Map::render() at some point
|
||||
// in the near future. (Not called for Map::renderStill() mode.)
|
||||
virtual void invalidate() = 0;
|
||||
|
||||
// Reads the pixel data from the current framebuffer. If your View implementation
|
||||
// doesn't support reading from the framebuffer, return a null pointer.
|
||||
virtual PremultipliedImage readStillImage(std::array<uint16_t, 2> size = {{ 0, 0 }});
|
||||
|
||||
// Notifies a watcher of map x/y/scale/rotation changes.
|
||||
virtual void notifyMapChange(MapChange change);
|
||||
|
||||
protected:
|
||||
mbgl::Map *map = nullptr;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/mbgl.hpp>
|
||||
#include <mbgl/map/backend.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/util/timer.hpp>
|
||||
#include <mbgl/util/geometry.hpp>
|
||||
@@ -11,26 +12,12 @@
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
class GLFWView : public mbgl::View {
|
||||
class GLFWView : public mbgl::View, public mbgl::Backend {
|
||||
public:
|
||||
GLFWView(bool fullscreen = false, bool benchmark = false);
|
||||
~GLFWView() override;
|
||||
|
||||
float getPixelRatio() const override;
|
||||
std::array<uint16_t, 2> getSize() const override;
|
||||
std::array<uint16_t, 2> getFramebufferSize() const override;
|
||||
|
||||
void initialize(mbgl::Map*) override;
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
void invalidate() override;
|
||||
|
||||
static void onKey(GLFWwindow *window, int key, int scancode, int action, int mods);
|
||||
static void onScroll(GLFWwindow *window, double xoffset, double yoffset);
|
||||
static void onWindowResize(GLFWwindow *window, int width, int height);
|
||||
static void onFramebufferResize(GLFWwindow *window, int width, int height);
|
||||
static void onMouseClick(GLFWwindow *window, int button, int action, int modifiers);
|
||||
static void onMouseMove(GLFWwindow *window, double x, double y);
|
||||
float getPixelRatio() const;
|
||||
|
||||
// Callback called when the user presses the key mapped to style change.
|
||||
// The expected action is to set a new style, different to the current one.
|
||||
@@ -41,12 +28,33 @@ public:
|
||||
void setWindowTitle(const std::string&);
|
||||
|
||||
void run();
|
||||
|
||||
private:
|
||||
// mbgl::View implementation
|
||||
void initialize(mbgl::Map*) override;
|
||||
void bind() override;
|
||||
std::array<uint16_t, 2> getSize() const override;
|
||||
std::array<uint16_t, 2> getFramebufferSize() const override;
|
||||
|
||||
// mbgl::Backend implementation
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
void invalidate() override;
|
||||
|
||||
// Window callbacks
|
||||
static void onKey(GLFWwindow *window, int key, int scancode, int action, int mods);
|
||||
static void onScroll(GLFWwindow *window, double xoffset, double yoffset);
|
||||
static void onWindowResize(GLFWwindow *window, int width, int height);
|
||||
static void onFramebufferResize(GLFWwindow *window, int width, int height);
|
||||
static void onMouseClick(GLFWwindow *window, int button, int action, int modifiers);
|
||||
static void onMouseMove(GLFWwindow *window, double x, double y);
|
||||
|
||||
// Internal
|
||||
void report(float duration);
|
||||
|
||||
void setMapChangeCallback(std::function<void(mbgl::MapChange)> callback);
|
||||
void notifyMapChange(mbgl::MapChange change) override;
|
||||
|
||||
private:
|
||||
mbgl::Color makeRandomColor() const;
|
||||
mbgl::Point<double> makeRandomPoint() const;
|
||||
static std::shared_ptr<const mbgl::SpriteImage>
|
||||
|
||||
78
include/mbgl/platform/default/headless_backend.hpp
Normal file
78
include/mbgl/platform/default/headless_backend.hpp
Normal file
@@ -0,0 +1,78 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/gl/implementation.hpp>
|
||||
|
||||
#if MBGL_USE_QT
|
||||
class QGLWidget;
|
||||
#elif MBGL_USE_CGL
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#elif MBGL_USE_GLX
|
||||
typedef struct _XDisplay Display;
|
||||
typedef struct __GLXcontextRec* GLXContext;
|
||||
typedef struct __GLXFBConfigRec* GLXFBConfig;
|
||||
typedef long unsigned int XID;
|
||||
typedef XID GLXPbuffer;
|
||||
#endif
|
||||
|
||||
#include <mbgl/map/backend.hpp>
|
||||
#include <mbgl/gl/extension.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <functional>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class HeadlessDisplay;
|
||||
|
||||
class HeadlessBackend : public Backend {
|
||||
public:
|
||||
HeadlessBackend();
|
||||
HeadlessBackend(std::shared_ptr<HeadlessDisplay>);
|
||||
~HeadlessBackend() override;
|
||||
|
||||
void invalidate() override;
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
void notifyMapChange(MapChange) override;
|
||||
|
||||
void setMapChangeCallback(std::function<void(MapChange)>&& cb) { mapChangeCallback = std::move(cb); }
|
||||
|
||||
private:
|
||||
void activateContext();
|
||||
void deactivateContext();
|
||||
|
||||
private:
|
||||
// Implementation specific functions
|
||||
static gl::glProc initializeExtension(const char*);
|
||||
void createContext();
|
||||
void destroyContext();
|
||||
|
||||
std::shared_ptr<HeadlessDisplay> display;
|
||||
|
||||
bool extensionsLoaded = false;
|
||||
bool active = false;
|
||||
|
||||
#if MBGL_USE_QT
|
||||
QGLWidget* glContext = nullptr;
|
||||
#endif
|
||||
|
||||
#if MBGL_USE_CGL
|
||||
CGLContextObj glContext = nullptr;
|
||||
#endif
|
||||
|
||||
#if MBGL_USE_EAGL
|
||||
void *glContext = nullptr;
|
||||
#endif
|
||||
|
||||
#if MBGL_USE_GLX
|
||||
Display *xDisplay = nullptr;
|
||||
GLXFBConfig *fbConfigs = nullptr;
|
||||
GLXContext glContext = nullptr;
|
||||
GLXPbuffer glxPbuffer = 0;
|
||||
#endif
|
||||
|
||||
std::function<void(MapChange)> mapChangeCallback;
|
||||
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -1,6 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/gl/implementation.hpp>
|
||||
|
||||
#if MBGL_USE_CGL
|
||||
#include <OpenGL/OpenGL.h>
|
||||
#elif MBGL_USE_GLX
|
||||
typedef struct _XDisplay Display;
|
||||
typedef struct __GLXFBConfigRec* GLXFBConfig;
|
||||
#endif
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
|
||||
@@ -1,95 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(__QT__)
|
||||
#define MBGL_USE_QT 1
|
||||
class QGLWidget;
|
||||
#elif defined(__APPLE__)
|
||||
#include <TargetConditionals.h>
|
||||
#if TARGET_OS_IOS
|
||||
#define MBGL_USE_EAGL 1
|
||||
#else
|
||||
#define MBGL_USE_CGL 1
|
||||
#endif
|
||||
#else
|
||||
#define GL_GLEXT_PROTOTYPES
|
||||
#define MBGL_USE_GLX 1
|
||||
typedef struct _XDisplay Display;
|
||||
typedef struct __GLXcontextRec* GLXContext;
|
||||
typedef struct __GLXFBConfigRec* GLXFBConfig;
|
||||
typedef long unsigned int XID;
|
||||
typedef XID GLXPbuffer;
|
||||
#endif
|
||||
|
||||
#include <mbgl/mbgl.hpp>
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
#include <mbgl/map/view.hpp>
|
||||
#include <mbgl/gl/types.hpp>
|
||||
#include <mbgl/gl/extension.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class HeadlessDisplay;
|
||||
|
||||
class HeadlessView : public View {
|
||||
public:
|
||||
HeadlessView(float pixelRatio, uint16_t width = 256, uint16_t height = 256);
|
||||
HeadlessView(std::shared_ptr<HeadlessDisplay> display, float pixelRatio, uint16_t width = 256, uint16_t height = 256);
|
||||
HeadlessView(float pixelRatio = 1, uint16_t width = 256, uint16_t height = 256);
|
||||
~HeadlessView() override;
|
||||
|
||||
float getPixelRatio() const override;
|
||||
void bind() override;
|
||||
|
||||
std::array<uint16_t, 2> getSize() const override;
|
||||
std::array<uint16_t, 2> getFramebufferSize() const override;
|
||||
|
||||
void invalidate() override;
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
void notifyMapChange(MapChange) override;
|
||||
|
||||
PremultipliedImage readStillImage(std::array<uint16_t, 2> size = {{ 0, 0 }}) override;
|
||||
|
||||
float getPixelRatio() const;
|
||||
|
||||
void resize(uint16_t width, uint16_t height);
|
||||
void setMapChangeCallback(std::function<void(MapChange)>&& cb) { mapChangeCallback = std::move(cb); }
|
||||
|
||||
private:
|
||||
// Implementation specific functions
|
||||
static gl::glProc initializeExtension(const char*);
|
||||
void createContext();
|
||||
void destroyContext();
|
||||
void clearBuffers();
|
||||
void resizeFramebuffer();
|
||||
void activateContext();
|
||||
void deactivateContext();
|
||||
void bindFramebuffer();
|
||||
|
||||
std::shared_ptr<HeadlessDisplay> display;
|
||||
private:
|
||||
const float pixelRatio;
|
||||
std::array<uint16_t, 2> dimensions;
|
||||
|
||||
bool needsResize = false;
|
||||
bool extensionsLoaded = false;
|
||||
bool active = false;
|
||||
|
||||
#if MBGL_USE_QT
|
||||
QGLWidget* glContext = nullptr;
|
||||
#endif
|
||||
|
||||
#if MBGL_USE_CGL
|
||||
CGLContextObj glContext = nullptr;
|
||||
#endif
|
||||
|
||||
#if MBGL_USE_EAGL
|
||||
void *glContext = nullptr;
|
||||
#endif
|
||||
|
||||
#if MBGL_USE_GLX
|
||||
Display *xDisplay = nullptr;
|
||||
GLXFBConfig *fbConfigs = nullptr;
|
||||
GLXContext glContext = nullptr;
|
||||
GLXPbuffer glxPbuffer = 0;
|
||||
#endif
|
||||
|
||||
std::function<void(MapChange)> mapChangeCallback;
|
||||
|
||||
gl::FramebufferID fbo = 0;
|
||||
gl::RenderbufferID fboDepthStencil = 0;
|
||||
|
||||
@@ -55,10 +55,8 @@ void log_gl_string(GLenum name, const char *label) {
|
||||
}
|
||||
}
|
||||
|
||||
NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float pixelRatio_, int availableProcessors_, size_t totalMemory_)
|
||||
: mbgl::View(*this),
|
||||
env(env_),
|
||||
pixelRatio(pixelRatio_),
|
||||
NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float pixelRatio, int availableProcessors_, size_t totalMemory_)
|
||||
: env(env_),
|
||||
availableProcessors(availableProcessors_),
|
||||
totalMemory(totalMemory_),
|
||||
threadPool(4) {
|
||||
@@ -82,7 +80,7 @@ NativeMapView::NativeMapView(JNIEnv *env_, jobject obj_, float pixelRatio_, int
|
||||
mbgl::android::cachePath + "/mbgl-offline.db",
|
||||
mbgl::android::apkPath);
|
||||
|
||||
map = std::make_unique<mbgl::Map>(*this, *fileSource, threadPool, MapMode::Continuous);
|
||||
map = std::make_unique<mbgl::Map>(*this, *this, pixelRatio, *fileSource, threadPool, MapMode::Continuous);
|
||||
|
||||
float zoomFactor = map->getMaxZoom() - map->getMinZoom() + 1;
|
||||
float cpuFactor = availableProcessors;
|
||||
@@ -114,8 +112,8 @@ NativeMapView::~NativeMapView() {
|
||||
vm = nullptr;
|
||||
}
|
||||
|
||||
float NativeMapView::getPixelRatio() const {
|
||||
return pixelRatio;
|
||||
void NativeMapView::bind() {
|
||||
MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||
}
|
||||
|
||||
std::array<uint16_t, 2> NativeMapView::getSize() const {
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/map/view.hpp>
|
||||
#include <mbgl/map/backend.hpp>
|
||||
#include <mbgl/util/noncopyable.hpp>
|
||||
#include <mbgl/platform/default/thread_pool.hpp>
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
@@ -14,12 +15,13 @@
|
||||
namespace mbgl {
|
||||
namespace android {
|
||||
|
||||
class NativeMapView : public mbgl::View, private mbgl::util::noncopyable {
|
||||
class NativeMapView : public mbgl::View, public mbgl::Backend {
|
||||
public:
|
||||
NativeMapView(JNIEnv *env, jobject obj, float pixelRatio, int availableProcessors, size_t totalMemory);
|
||||
virtual ~NativeMapView();
|
||||
|
||||
float getPixelRatio() const override;
|
||||
void bind() override;
|
||||
|
||||
std::array<uint16_t, 2> getSize() const override;
|
||||
std::array<uint16_t, 2> getFramebufferSize() const override;
|
||||
void activate() override;
|
||||
@@ -89,7 +91,6 @@ private:
|
||||
int height = 0;
|
||||
int fbWidth = 0;
|
||||
int fbHeight = 0;
|
||||
const float pixelRatio;
|
||||
|
||||
int availableProcessors = 0;
|
||||
size_t totalMemory = 0;
|
||||
|
||||
58
platform/darwin/src/headless_backend_cgl.cpp
Normal file
58
platform/darwin/src/headless_backend_cgl.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
|
||||
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
|
||||
if (!framework) {
|
||||
throw std::runtime_error("Failed to load OpenGL framework.");
|
||||
}
|
||||
|
||||
CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
|
||||
void* symbol = CFBundleGetFunctionPointerForName(framework, str);
|
||||
CFRelease(str);
|
||||
|
||||
return reinterpret_cast<gl::glProc>(symbol);
|
||||
}
|
||||
|
||||
void HeadlessBackend::createContext() {
|
||||
CGLError error = CGLCreateContext(display->pixelFormat, nullptr, &glContext);
|
||||
if (error != kCGLNoError) {
|
||||
throw std::runtime_error(std::string("Error creating GL context object:") +
|
||||
CGLErrorString(error) + "\n");
|
||||
}
|
||||
|
||||
error = CGLEnable(glContext, kCGLCEMPEngine);
|
||||
if (error != kCGLNoError) {
|
||||
throw std::runtime_error(std::string("Error enabling OpenGL multithreading:") +
|
||||
CGLErrorString(error) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessBackend::destroyContext() {
|
||||
CGLDestroyContext(glContext);
|
||||
}
|
||||
|
||||
void HeadlessBackend::activateContext() {
|
||||
CGLError error = CGLSetCurrentContext(glContext);
|
||||
if (error != kCGLNoError) {
|
||||
throw std::runtime_error(std::string("Switching OpenGL context failed:") +
|
||||
CGLErrorString(error) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessBackend::deactivateContext() {
|
||||
CGLError error = CGLSetCurrentContext(nullptr);
|
||||
if (error != kCGLNoError) {
|
||||
throw std::runtime_error(std::string("Removing OpenGL context failed:") +
|
||||
CGLErrorString(error) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
46
platform/darwin/src/headless_backend_eagl.mm
Normal file
46
platform/darwin/src/headless_backend_eagl.mm
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
|
||||
#include <mbgl/gl/extension.hpp>
|
||||
|
||||
#include <OpenGLES/EAGL.h>
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
|
||||
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
|
||||
if (!framework) {
|
||||
throw std::runtime_error("Failed to load OpenGL framework.");
|
||||
}
|
||||
|
||||
CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
|
||||
void* symbol = CFBundleGetFunctionPointerForName(framework, str);
|
||||
CFRelease(str);
|
||||
|
||||
return reinterpret_cast<gl::glProc>(symbol);
|
||||
}
|
||||
|
||||
void HeadlessBackend::createContext() {
|
||||
glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
if (glContext == nil) {
|
||||
throw std::runtime_error("Error creating GL context object");
|
||||
}
|
||||
[reinterpret_cast<EAGLContext*>(glContext) retain];
|
||||
reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES;
|
||||
}
|
||||
|
||||
void HeadlessBackend::destroyContext() {
|
||||
[reinterpret_cast<EAGLContext*>(glContext) release];
|
||||
glContext = nil;
|
||||
}
|
||||
|
||||
void HeadlessBackend::activateContext() {
|
||||
[EAGLContext setCurrentContext:reinterpret_cast<EAGLContext*>(glContext)];
|
||||
}
|
||||
|
||||
void HeadlessBackend::deactivateContext() {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -1,37 +1,14 @@
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
|
||||
#include <CoreFoundation/CoreFoundation.h>
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
gl::glProc HeadlessView::initializeExtension(const char* name) {
|
||||
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
|
||||
if (!framework) {
|
||||
throw std::runtime_error("Failed to load OpenGL framework.");
|
||||
}
|
||||
|
||||
CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
|
||||
void* symbol = CFBundleGetFunctionPointerForName(framework, str);
|
||||
CFRelease(str);
|
||||
|
||||
return reinterpret_cast<gl::glProc>(symbol);
|
||||
}
|
||||
|
||||
void HeadlessView::createContext() {
|
||||
CGLError error = CGLCreateContext(display->pixelFormat, nullptr, &glContext);
|
||||
if (error != kCGLNoError) {
|
||||
throw std::runtime_error(std::string("Error creating GL context object:") + CGLErrorString(error) + "\n");
|
||||
}
|
||||
|
||||
error = CGLEnable(glContext, kCGLCEMPEngine);
|
||||
if (error != kCGLNoError) {
|
||||
throw std::runtime_error(std::string("Error enabling OpenGL multithreading:") + CGLErrorString(error) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessView::destroyContext() {
|
||||
CGLDestroyContext(glContext);
|
||||
void HeadlessView::bindFramebuffer() {
|
||||
assert(fbo);
|
||||
MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo));
|
||||
}
|
||||
|
||||
void HeadlessView::resizeFramebuffer() {
|
||||
@@ -76,8 +53,6 @@ void HeadlessView::resizeFramebuffer() {
|
||||
}
|
||||
|
||||
void HeadlessView::clearBuffers() {
|
||||
assert(active);
|
||||
|
||||
MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||
|
||||
if (fbo) {
|
||||
@@ -96,18 +71,4 @@ void HeadlessView::clearBuffers() {
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessView::activateContext() {
|
||||
CGLError error = CGLSetCurrentContext(glContext);
|
||||
if (error != kCGLNoError) {
|
||||
throw std::runtime_error(std::string("Switching OpenGL context failed:") + CGLErrorString(error) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessView::deactivateContext() {
|
||||
CGLError error = CGLSetCurrentContext(nullptr);
|
||||
if (error != kCGLNoError) {
|
||||
throw std::runtime_error(std::string("Removing OpenGL context failed:") + CGLErrorString(error) + "\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,35 +1,14 @@
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
|
||||
#include <OpenGLES/EAGL.h>
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
gl::glProc HeadlessView::initializeExtension(const char* name) {
|
||||
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
|
||||
if (!framework) {
|
||||
throw std::runtime_error("Failed to load OpenGL framework.");
|
||||
}
|
||||
|
||||
CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
|
||||
void* symbol = CFBundleGetFunctionPointerForName(framework, str);
|
||||
CFRelease(str);
|
||||
|
||||
return reinterpret_cast<gl::glProc>(symbol);
|
||||
}
|
||||
|
||||
void HeadlessView::createContext() {
|
||||
glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
if (glContext == nil) {
|
||||
throw std::runtime_error("Error creating GL context object");
|
||||
}
|
||||
[reinterpret_cast<EAGLContext*>(glContext) retain];
|
||||
reinterpret_cast<EAGLContext*>(glContext).multiThreaded = YES;
|
||||
}
|
||||
|
||||
void HeadlessView::destroyContext() {
|
||||
[reinterpret_cast<EAGLContext*>(glContext) release];
|
||||
glContext = nil;
|
||||
void HeadlessView::bindFramebuffer() {
|
||||
assert(fbo);
|
||||
MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo));
|
||||
}
|
||||
|
||||
void HeadlessView::resizeFramebuffer() {
|
||||
@@ -72,8 +51,6 @@ void HeadlessView::resizeFramebuffer() {
|
||||
}
|
||||
|
||||
void HeadlessView::clearBuffers() {
|
||||
assert(active);
|
||||
|
||||
MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||
|
||||
if (fbo) {
|
||||
@@ -92,12 +69,4 @@ void HeadlessView::clearBuffers() {
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessView::activateContext() {
|
||||
[EAGLContext setCurrentContext:reinterpret_cast<EAGLContext*>(glContext)];
|
||||
}
|
||||
|
||||
void HeadlessView::deactivateContext() {
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -129,6 +129,10 @@ void GLFWView::initialize(mbgl::Map *map_) {
|
||||
map->addAnnotationIcon("default_marker", makeSpriteImage(22, 22, 1));
|
||||
}
|
||||
|
||||
void GLFWView::bind() {
|
||||
MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||
}
|
||||
|
||||
void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, int mods) {
|
||||
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
|
||||
|
||||
|
||||
56
platform/default/headless_backend.cpp
Normal file
56
platform/default/headless_backend.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
HeadlessBackend::HeadlessBackend() : display(std::make_shared<HeadlessDisplay>()) {
|
||||
activate();
|
||||
}
|
||||
|
||||
HeadlessBackend::HeadlessBackend(std::shared_ptr<HeadlessDisplay> display_)
|
||||
: display(std::move(display_)) {
|
||||
activate();
|
||||
}
|
||||
|
||||
HeadlessBackend::~HeadlessBackend() {
|
||||
deactivate();
|
||||
destroyContext();
|
||||
}
|
||||
|
||||
void HeadlessBackend::activate() {
|
||||
active = true;
|
||||
|
||||
if (!glContext) {
|
||||
if (!display) {
|
||||
throw std::runtime_error("Display is not set");
|
||||
}
|
||||
createContext();
|
||||
}
|
||||
|
||||
activateContext();
|
||||
|
||||
if (!extensionsLoaded) {
|
||||
gl::InitializeExtensions(initializeExtension);
|
||||
extensionsLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessBackend::deactivate() {
|
||||
deactivateContext();
|
||||
active = false;
|
||||
}
|
||||
|
||||
void HeadlessBackend::invalidate() {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void HeadlessBackend::notifyMapChange(MapChange change) {
|
||||
if (mapChangeCallback) {
|
||||
mapChangeCallback(change);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
67
platform/default/headless_backend_glx.cpp
Normal file
67
platform/default/headless_backend_glx.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
// #include <cassert>
|
||||
|
||||
#include <GL/glx.h>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
|
||||
return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
|
||||
}
|
||||
|
||||
void HeadlessBackend::createContext() {
|
||||
xDisplay = display->xDisplay;
|
||||
fbConfigs = display->fbConfigs;
|
||||
|
||||
if (!glContext) {
|
||||
// Try to create a legacy context
|
||||
glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, None, True);
|
||||
if (glContext) {
|
||||
if (!glXIsDirect(xDisplay, glContext)) {
|
||||
Log::Error(Event::OpenGL, "failed to create direct OpenGL Legacy context");
|
||||
glXDestroyContext(xDisplay, glContext);
|
||||
glContext = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (glContext == nullptr) {
|
||||
throw std::runtime_error("Error creating GL context object.");
|
||||
}
|
||||
|
||||
// Create a dummy pbuffer. We will render to framebuffers anyway, but we need a pbuffer to
|
||||
// activate the context.
|
||||
int pbufferAttributes[] = {
|
||||
GLX_PBUFFER_WIDTH, 8,
|
||||
GLX_PBUFFER_HEIGHT, 8,
|
||||
None
|
||||
};
|
||||
glxPbuffer = glXCreatePbuffer(xDisplay, fbConfigs[0], pbufferAttributes);
|
||||
}
|
||||
|
||||
void HeadlessBackend::destroyContext() {
|
||||
if (glxPbuffer) {
|
||||
glXDestroyPbuffer(xDisplay, glxPbuffer);
|
||||
glxPbuffer = 0;
|
||||
}
|
||||
|
||||
glXDestroyContext(xDisplay, glContext);
|
||||
}
|
||||
|
||||
void HeadlessBackend::activateContext() {
|
||||
if (!glXMakeContextCurrent(xDisplay, glxPbuffer, glxPbuffer, glContext)) {
|
||||
throw std::runtime_error("Switching OpenGL context failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessBackend::deactivateContext() {
|
||||
if (!glXMakeContextCurrent(xDisplay, 0, 0, nullptr)) {
|
||||
throw std::runtime_error("Removing OpenGL context failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -1,12 +1,13 @@
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
|
||||
#if MBGL_USE_GLX
|
||||
#include <GL/glx.h>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
HeadlessDisplay::HeadlessDisplay() {
|
||||
|
||||
@@ -1,34 +1,27 @@
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
|
||||
#include <cassert>
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
HeadlessView::HeadlessView(float pixelRatio_, uint16_t width, uint16_t height)
|
||||
: display(std::make_shared<HeadlessDisplay>())
|
||||
, pixelRatio(pixelRatio_)
|
||||
, dimensions({{ width, height }})
|
||||
, needsResize(true) {
|
||||
}
|
||||
|
||||
HeadlessView::HeadlessView(std::shared_ptr<HeadlessDisplay> display_,
|
||||
float pixelRatio_,
|
||||
uint16_t width,
|
||||
uint16_t height)
|
||||
: display(std::move(display_))
|
||||
, pixelRatio(pixelRatio_)
|
||||
, dimensions({{ width, height }})
|
||||
, needsResize(true) {
|
||||
: pixelRatio(pixelRatio_), dimensions({ { width, height } }), needsResize(true) {
|
||||
}
|
||||
|
||||
HeadlessView::~HeadlessView() {
|
||||
activate();
|
||||
clearBuffers();
|
||||
deactivate();
|
||||
}
|
||||
|
||||
destroyContext();
|
||||
void HeadlessView::bind() {
|
||||
if (needsResize) {
|
||||
clearBuffers();
|
||||
resizeFramebuffer();
|
||||
needsResize = false;
|
||||
} else {
|
||||
bindFramebuffer();
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessView::resize(const uint16_t width, const uint16_t height) {
|
||||
@@ -41,8 +34,6 @@ void HeadlessView::resize(const uint16_t width, const uint16_t height) {
|
||||
}
|
||||
|
||||
PremultipliedImage HeadlessView::readStillImage(std::array<uint16_t, 2> size) {
|
||||
assert(active);
|
||||
|
||||
if (!size[0] || !size[1]) {
|
||||
size[0] = dimensions[0] * pixelRatio;
|
||||
size[1] = dimensions[1] * pixelRatio;
|
||||
@@ -76,43 +67,4 @@ std::array<uint16_t, 2> HeadlessView::getFramebufferSize() const {
|
||||
static_cast<uint16_t>(dimensions[1] * pixelRatio) }};
|
||||
}
|
||||
|
||||
void HeadlessView::activate() {
|
||||
active = true;
|
||||
|
||||
if (!glContext) {
|
||||
if (!display) {
|
||||
throw std::runtime_error("Display is not set");
|
||||
}
|
||||
createContext();
|
||||
}
|
||||
|
||||
activateContext();
|
||||
|
||||
if (!extensionsLoaded) {
|
||||
gl::InitializeExtensions(initializeExtension);
|
||||
extensionsLoaded = true;
|
||||
}
|
||||
|
||||
if (needsResize) {
|
||||
clearBuffers();
|
||||
resizeFramebuffer();
|
||||
needsResize = false;
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessView::deactivate() {
|
||||
deactivateContext();
|
||||
active = false;
|
||||
}
|
||||
|
||||
void HeadlessView::invalidate() {
|
||||
assert(false);
|
||||
}
|
||||
|
||||
void HeadlessView::notifyMapChange(MapChange change) {
|
||||
if (mapChangeCallback) {
|
||||
mapChangeCallback(change);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,54 +1,14 @@
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/log.hpp>
|
||||
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include <GL/glx.h>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
gl::glProc HeadlessView::initializeExtension(const char* name) {
|
||||
return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
|
||||
}
|
||||
|
||||
void HeadlessView::createContext() {
|
||||
xDisplay = display->xDisplay;
|
||||
fbConfigs = display->fbConfigs;
|
||||
|
||||
if (!glContext) {
|
||||
// Try to create a legacy context
|
||||
glContext = glXCreateNewContext(xDisplay, fbConfigs[0], GLX_RGBA_TYPE, None, True);
|
||||
if (glContext) {
|
||||
if (!glXIsDirect(xDisplay, glContext)) {
|
||||
Log::Error(Event::OpenGL, "failed to create direct OpenGL Legacy context");
|
||||
glXDestroyContext(xDisplay, glContext);
|
||||
glContext = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (glContext == nullptr) {
|
||||
throw std::runtime_error("Error creating GL context object.");
|
||||
}
|
||||
|
||||
// Create a dummy pbuffer. We will render to framebuffers anyway, but we need a pbuffer to
|
||||
// activate the context.
|
||||
int pbufferAttributes[] = {
|
||||
GLX_PBUFFER_WIDTH, 8,
|
||||
GLX_PBUFFER_HEIGHT, 8,
|
||||
None
|
||||
};
|
||||
glxPbuffer = glXCreatePbuffer(xDisplay, fbConfigs[0], pbufferAttributes);
|
||||
}
|
||||
|
||||
void HeadlessView::destroyContext() {
|
||||
if (glxPbuffer) {
|
||||
glXDestroyPbuffer(xDisplay, glxPbuffer);
|
||||
glxPbuffer = 0;
|
||||
}
|
||||
|
||||
glXDestroyContext(xDisplay, glContext);
|
||||
void HeadlessView::bindFramebuffer() {
|
||||
assert(fbo);
|
||||
MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo));
|
||||
}
|
||||
|
||||
void HeadlessView::resizeFramebuffer() {
|
||||
@@ -93,8 +53,6 @@ void HeadlessView::resizeFramebuffer() {
|
||||
}
|
||||
|
||||
void HeadlessView::clearBuffers() {
|
||||
assert(active);
|
||||
|
||||
MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0));
|
||||
|
||||
if (fbo) {
|
||||
@@ -113,16 +71,4 @@ void HeadlessView::clearBuffers() {
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessView::activateContext() {
|
||||
if (!glXMakeContextCurrent(xDisplay, glxPbuffer, glxPbuffer, glContext)) {
|
||||
throw std::runtime_error("Switching OpenGL context failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessView::deactivateContext() {
|
||||
if (!glXMakeContextCurrent(xDisplay, 0, 0, nullptr)) {
|
||||
throw std::runtime_error("Removing OpenGL context failed.\n");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -37,7 +37,9 @@ macro(mbgl_platform_core)
|
||||
PRIVATE platform/darwin/src/image.mm
|
||||
|
||||
# Headless view
|
||||
PRIVATE platform/darwin/src/headless_view_eagl.mm
|
||||
PRIVATE platform/darwin/src/headless_backend_eagl.mm
|
||||
PRIVATE platform/darwin/src/headless_view_eagl.cpp
|
||||
PRIVATE platform/default/headless_backend.cpp
|
||||
PRIVATE platform/default/headless_display.cpp
|
||||
PRIVATE platform/default/headless_view.cpp
|
||||
|
||||
@@ -53,7 +55,7 @@ macro(mbgl_platform_core)
|
||||
|
||||
# TODO: Remove this by converting to ARC
|
||||
set_source_files_properties(
|
||||
platform/darwin/src/headless_view_eagl.mm
|
||||
platform/darwin/src/headless_backend_eagl.mm
|
||||
PROPERTIES
|
||||
COMPILE_FLAGS -fno-objc-arc
|
||||
)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <mbgl/storage/network_status.hpp>
|
||||
#include <mbgl/style/transition_options.hpp>
|
||||
#include <mbgl/style/layers/custom_layer.hpp>
|
||||
#include <mbgl/map/backend.hpp>
|
||||
#include <mbgl/math/wrap.hpp>
|
||||
#include <mbgl/util/geo.hpp>
|
||||
#include <mbgl/util/constants.hpp>
|
||||
@@ -389,8 +390,7 @@ public:
|
||||
self.clipsToBounds = YES;
|
||||
|
||||
// setup mbgl view
|
||||
const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
|
||||
_mbglView = new MBGLView(self, scaleFactor);
|
||||
_mbglView = new MBGLView(self);
|
||||
|
||||
// Delete the pre-offline ambient cache at ~/Library/Caches/cache.db.
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
@@ -398,9 +398,10 @@ public:
|
||||
[[NSFileManager defaultManager] removeItemAtPath:fileCachePath error:NULL];
|
||||
|
||||
// setup mbgl map
|
||||
const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
|
||||
mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
|
||||
_mbglThreadPool = new mbgl::ThreadPool(4);
|
||||
_mbglMap = new mbgl::Map(*_mbglView, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
|
||||
_mbglMap = new mbgl::Map(*_mbglView, *_mbglView, scaleFactor, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
|
||||
[self validateTileCacheSize];
|
||||
|
||||
// start paused if in IB
|
||||
@@ -4938,15 +4939,11 @@ public:
|
||||
return _annotationViewReuseQueueByIdentifier[identifier];
|
||||
}
|
||||
|
||||
class MBGLView : public mbgl::View
|
||||
class MBGLView : public mbgl::View, public mbgl::Backend
|
||||
{
|
||||
public:
|
||||
MBGLView(MGLMapView* nativeView_, const float scaleFactor_)
|
||||
: nativeView(nativeView_), scaleFactor(scaleFactor_) {
|
||||
}
|
||||
|
||||
float getPixelRatio() const override {
|
||||
return scaleFactor;
|
||||
MBGLView(MGLMapView* nativeView_)
|
||||
: nativeView(nativeView_) {
|
||||
}
|
||||
|
||||
std::array<uint16_t, 2> getSize() const override {
|
||||
@@ -4959,6 +4956,10 @@ public:
|
||||
static_cast<uint16_t>([[nativeView glView] drawableHeight]) }};
|
||||
}
|
||||
|
||||
void bind() override {
|
||||
[nativeView.glView bindDrawable];
|
||||
}
|
||||
|
||||
void notifyMapChange(mbgl::MapChange change) override
|
||||
{
|
||||
[nativeView notifyMapChange:change];
|
||||
@@ -4981,7 +4982,6 @@ public:
|
||||
|
||||
private:
|
||||
__weak MGLMapView *nativeView = nullptr;
|
||||
const float scaleFactor;
|
||||
};
|
||||
|
||||
@end
|
||||
|
||||
@@ -41,9 +41,11 @@ macro(mbgl_platform_core)
|
||||
PRIVATE platform/default/webp_reader.cpp
|
||||
|
||||
# Headless view
|
||||
PRIVATE platform/default/headless_backend_glx.cpp
|
||||
PRIVATE platform/default/headless_view_glx.cpp
|
||||
PRIVATE platform/default/headless_backend.cpp
|
||||
PRIVATE platform/default/headless_display.cpp
|
||||
PRIVATE platform/default/headless_view.cpp
|
||||
PRIVATE platform/default/headless_view_glx.cpp
|
||||
|
||||
# Thread pool
|
||||
PRIVATE platform/default/thread_pool.cpp
|
||||
|
||||
@@ -35,7 +35,9 @@ macro(mbgl_platform_core)
|
||||
PRIVATE platform/darwin/src/image.mm
|
||||
|
||||
# Headless view
|
||||
PRIVATE platform/darwin/src/headless_backend_cgl.cpp
|
||||
PRIVATE platform/darwin/src/headless_view_cgl.cpp
|
||||
PRIVATE platform/default/headless_backend.cpp
|
||||
PRIVATE platform/default/headless_display.cpp
|
||||
PRIVATE platform/default/headless_view.cpp
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#import <mbgl/platform/default/thread_pool.hpp>
|
||||
#import <mbgl/gl/extension.hpp>
|
||||
#import <mbgl/gl/gl.hpp>
|
||||
#import <mbgl/map/backend.hpp>
|
||||
#import <mbgl/sprite/sprite_image.hpp>
|
||||
#import <mbgl/storage/default_file_source.hpp>
|
||||
#import <mbgl/storage/network_status.hpp>
|
||||
@@ -248,7 +249,7 @@ public:
|
||||
_isTargetingInterfaceBuilder = NSProcessInfo.processInfo.mgl_isInterfaceBuilderDesignablesAgent;
|
||||
|
||||
// Set up cross-platform controllers and resources.
|
||||
_mbglView = new MGLMapViewImpl(self, [NSScreen mainScreen].backingScaleFactor);
|
||||
_mbglView = new MGLMapViewImpl(self);
|
||||
|
||||
// Delete the pre-offline ambient cache at
|
||||
// ~/Library/Caches/com.mapbox.sdk.ios/cache.db.
|
||||
@@ -264,7 +265,7 @@ public:
|
||||
|
||||
mbgl::DefaultFileSource *mbglFileSource = [MGLOfflineStorage sharedOfflineStorage].mbglFileSource;
|
||||
_mbglThreadPool = new mbgl::ThreadPool(4);
|
||||
_mbglMap = new mbgl::Map(*_mbglView, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
|
||||
_mbglMap = new mbgl::Map(*_mbglView, *_mbglView, [NSScreen mainScreen].backingScaleFactor, *mbglFileSource, *_mbglThreadPool, mbgl::MapMode::Continuous, mbgl::GLContextMode::Unique, mbgl::ConstrainMode::None, mbgl::ViewportMode::Default);
|
||||
[self validateTileCacheSize];
|
||||
|
||||
// Install the OpenGL layer. Interface Builder’s synchronous drawing means
|
||||
@@ -745,6 +746,8 @@ public:
|
||||
return reinterpret_cast<mbgl::gl::glProc>(symbol);
|
||||
});
|
||||
|
||||
_mbglView->updateFramebufferBinding();
|
||||
|
||||
_mbglMap->render();
|
||||
|
||||
if (_isPrinting) {
|
||||
@@ -2531,14 +2534,10 @@ public:
|
||||
}
|
||||
|
||||
/// Adapter responsible for bridging calls from mbgl to MGLMapView and Cocoa.
|
||||
class MGLMapViewImpl : public mbgl::View {
|
||||
class MGLMapViewImpl : public mbgl::View, public mbgl::Backend {
|
||||
public:
|
||||
MGLMapViewImpl(MGLMapView *nativeView_, const float scaleFactor_)
|
||||
: nativeView(nativeView_), scaleFactor(scaleFactor_) {}
|
||||
|
||||
float getPixelRatio() const override {
|
||||
return scaleFactor;
|
||||
}
|
||||
MGLMapViewImpl(MGLMapView *nativeView_)
|
||||
: nativeView(nativeView_) {}
|
||||
|
||||
std::array<uint16_t, 2> getSize() const override {
|
||||
return {{ static_cast<uint16_t>(nativeView.bounds.size.width),
|
||||
@@ -2568,6 +2567,14 @@ public:
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
}
|
||||
|
||||
void updateFramebufferBinding() {
|
||||
MBGL_CHECK_ERROR(glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo));
|
||||
}
|
||||
|
||||
void bind() override {
|
||||
MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, fbo));
|
||||
}
|
||||
|
||||
mbgl::PremultipliedImage readStillImage(std::array<uint16_t, 2> size = {{ 0, 0 }}) override {
|
||||
if (!size[0] || !size[1]) {
|
||||
size = getFramebufferSize();
|
||||
@@ -2592,8 +2599,8 @@ private:
|
||||
/// Cocoa map view that this adapter bridges to.
|
||||
__weak MGLMapView *nativeView = nullptr;
|
||||
|
||||
/// Backing scale factor of the view.
|
||||
const float scaleFactor;
|
||||
/// The current framebuffer of the NSOpenGLLayer we are painting to.
|
||||
GLint fbo = 0;
|
||||
};
|
||||
|
||||
@end
|
||||
|
||||
@@ -773,15 +773,16 @@ void NodeMap::QueryRenderedFeatures(const Nan::FunctionCallbackInfo<v8::Value>&
|
||||
}
|
||||
|
||||
NodeMap::NodeMap(v8::Local<v8::Object> options) :
|
||||
view(sharedDisplay(), [&] {
|
||||
backend(sharedDisplay()),
|
||||
view([&] {
|
||||
Nan::HandleScope scope;
|
||||
return Nan::Has(options, Nan::New("ratio").ToLocalChecked()).FromJust() ? Nan::Get(options, Nan::New("ratio").ToLocalChecked()).ToLocalChecked()->NumberValue() : 1.0;
|
||||
}()),
|
||||
threadpool(),
|
||||
map(std::make_unique<mbgl::Map>(view, *this, threadpool, mbgl::MapMode::Still)),
|
||||
map(std::make_unique<mbgl::Map>(backend, view, view.getPixelRatio(), *this, threadpool, mbgl::MapMode::Still)),
|
||||
async(new uv_async_t) {
|
||||
|
||||
view.setMapChangeCallback([&](mbgl::MapChange change) {
|
||||
backend.setMapChangeCallback([&](mbgl::MapChange change) {
|
||||
if (change == mbgl::MapChangeDidFailLoadingMap) {
|
||||
throw std::runtime_error("Requires a map style to be a valid style JSON");
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
@@ -53,6 +54,7 @@ public:
|
||||
|
||||
std::unique_ptr<mbgl::AsyncRequest> request(const mbgl::Resource&, mbgl::FileSource::Callback);
|
||||
|
||||
mbgl::HeadlessBackend backend;
|
||||
mbgl::HeadlessView view;
|
||||
NodeThreadPool threadpool;
|
||||
std::unique_ptr<mbgl::Map> map;
|
||||
|
||||
@@ -43,8 +43,10 @@ endmacro()
|
||||
macro(mbgl_platform_test)
|
||||
target_sources(mbgl-test
|
||||
PRIVATE test/src/main.cpp
|
||||
PRIVATE platform/qt/test/headless_backend_qt.cpp
|
||||
PRIVATE platform/qt/test/headless_view_qt.cpp
|
||||
PRIVATE platform/qt/test/qmapboxgl.cpp
|
||||
PRIVATE platform/default/headless_backend.cpp
|
||||
PRIVATE platform/default/headless_display.cpp
|
||||
PRIVATE platform/default/headless_view.cpp
|
||||
)
|
||||
|
||||
@@ -813,7 +813,7 @@ QMapboxGLPrivate::QMapboxGLPrivate(QMapboxGL *q, const QMapboxGLSettings &settin
|
||||
settings.cacheDatabaseMaximumSize()))
|
||||
, threadPool(4)
|
||||
, mapObj(std::make_unique<mbgl::Map>(
|
||||
*this, *fileSourceObj, threadPool,
|
||||
*this, *this, getPixelRatio(), *fileSourceObj, threadPool,
|
||||
static_cast<mbgl::MapMode>(settings.mapMode()),
|
||||
static_cast<mbgl::GLContextMode>(settings.contextMode()),
|
||||
static_cast<mbgl::ConstrainMode>(settings.constrainMode()),
|
||||
@@ -845,6 +845,11 @@ float QMapboxGLPrivate::getPixelRatio() const
|
||||
return pixelRatio;
|
||||
}
|
||||
|
||||
void QMapboxGLPrivate::bind()
|
||||
{
|
||||
MBGL_CHECK_ERROR(glBindFramebuffer(GL_FRAMEBUFFER, 0));
|
||||
}
|
||||
|
||||
std::array<uint16_t, 2> QMapboxGLPrivate::getSize() const
|
||||
{
|
||||
return {{ static_cast<uint16_t>(size.width()), static_cast<uint16_t>(size.height()) }};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "qmapboxgl.hpp"
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/map/backend.hpp>
|
||||
#include <mbgl/map/view.hpp>
|
||||
#include <mbgl/platform/default/thread_pool.hpp>
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
@@ -11,7 +12,7 @@
|
||||
#include <QObject>
|
||||
#include <QSize>
|
||||
|
||||
class QMapboxGLPrivate : public QObject, public mbgl::View
|
||||
class QMapboxGLPrivate : public QObject, public mbgl::View, public mbgl::Backend
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -20,7 +21,8 @@ public:
|
||||
virtual ~QMapboxGLPrivate();
|
||||
|
||||
// mbgl::View implementation.
|
||||
float getPixelRatio() const final;
|
||||
float getPixelRatio() const;
|
||||
void bind() final;
|
||||
std::array<uint16_t, 2> getSize() const final;
|
||||
std::array<uint16_t, 2> getFramebufferSize() const final;
|
||||
|
||||
|
||||
46
platform/qt/test/headless_backend_qt.cpp
Normal file
46
platform/qt/test/headless_backend_qt.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QGLContext>
|
||||
#include <QGLWidget>
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QOpenGLContext>
|
||||
#endif
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
|
||||
#if QT_VERSION >= 0x050000
|
||||
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
|
||||
return thisContext->getProcAddress(name);
|
||||
#else
|
||||
const QGLContext* thisContext = QGLContext::currentContext();
|
||||
return reinterpret_cast<mbgl::gl::glProc>(thisContext->getProcAddress(name));
|
||||
#endif
|
||||
}
|
||||
|
||||
void HeadlessBackend::createContext() {
|
||||
static const char* argv[] = { "mbgl" };
|
||||
static int argc = 1;
|
||||
static auto* app = new QApplication(argc, const_cast<char**>(argv));
|
||||
|
||||
Q_UNUSED(app);
|
||||
|
||||
glContext = new QGLWidget;
|
||||
}
|
||||
|
||||
void HeadlessBackend::destroyContext() {
|
||||
delete glContext;
|
||||
}
|
||||
|
||||
void HeadlessBackend::activateContext() {
|
||||
glContext->makeCurrent();
|
||||
}
|
||||
|
||||
void HeadlessBackend::deactivateContext() {
|
||||
glContext->doneCurrent();
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QGLContext>
|
||||
#include <QGLWidget>
|
||||
@@ -9,30 +10,13 @@
|
||||
#include <QOpenGLContext>
|
||||
#endif
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
gl::glProc HeadlessView::initializeExtension(const char* name) {
|
||||
#if QT_VERSION >= 0x050000
|
||||
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
|
||||
return thisContext->getProcAddress(name);
|
||||
#else
|
||||
const QGLContext* thisContext = QGLContext::currentContext();
|
||||
return reinterpret_cast<mbgl::gl::glProc>(thisContext->getProcAddress(name));
|
||||
#endif
|
||||
}
|
||||
|
||||
void HeadlessView::createContext() {
|
||||
static const char* argv[] = { "mbgl" };
|
||||
static int argc = 1;
|
||||
static auto* app = new QApplication(argc, const_cast<char**>(argv));
|
||||
|
||||
Q_UNUSED(app);
|
||||
|
||||
glContext = new QGLWidget;
|
||||
}
|
||||
|
||||
void HeadlessView::destroyContext() {
|
||||
delete glContext;
|
||||
void HeadlessView::bindFramebuffer() {
|
||||
assert(fbo);
|
||||
MBGL_CHECK_ERROR(glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo));
|
||||
}
|
||||
|
||||
void HeadlessView::resizeFramebuffer() {
|
||||
@@ -95,12 +79,4 @@ void HeadlessView::clearBuffers() {
|
||||
}
|
||||
}
|
||||
|
||||
void HeadlessView::activateContext() {
|
||||
glContext->makeCurrent();
|
||||
}
|
||||
|
||||
void HeadlessView::deactivateContext() {
|
||||
glContext->doneCurrent();
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
12
src/mbgl/map/backend.cpp
Normal file
12
src/mbgl/map/backend.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include <mbgl/map/backend.hpp>
|
||||
|
||||
#include <cassert>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
void Backend::notifyMapChange(MapChange) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/map/camera.hpp>
|
||||
#include <mbgl/map/view.hpp>
|
||||
#include <mbgl/map/backend.hpp>
|
||||
#include <mbgl/map/transform.hpp>
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
#include <mbgl/annotation/annotation_manager.hpp>
|
||||
@@ -36,7 +37,15 @@ enum class RenderState : uint8_t {
|
||||
|
||||
class Map::Impl : public style::Observer {
|
||||
public:
|
||||
Impl(View&, FileSource&, Scheduler&, MapMode, GLContextMode, ConstrainMode, ViewportMode);
|
||||
Impl(Backend&,
|
||||
View&,
|
||||
float pixelRatio,
|
||||
FileSource&,
|
||||
Scheduler&,
|
||||
MapMode,
|
||||
GLContextMode,
|
||||
ConstrainMode,
|
||||
ViewportMode);
|
||||
|
||||
void onSourceAttributionChanged(style::Source&, const std::string&) override;
|
||||
void onUpdate(Update) override;
|
||||
@@ -49,6 +58,7 @@ public:
|
||||
|
||||
void loadStyleJSON(const std::string&);
|
||||
|
||||
Backend& backend;
|
||||
View& view;
|
||||
FileSource& fileSource;
|
||||
Scheduler& scheduler;
|
||||
@@ -81,34 +91,53 @@ public:
|
||||
bool loading = false;
|
||||
};
|
||||
|
||||
Map::Map(View& view, FileSource& fileSource, Scheduler& scheduler, MapMode mapMode, GLContextMode contextMode, ConstrainMode constrainMode, ViewportMode viewportMode)
|
||||
: impl(std::make_unique<Impl>(view, fileSource, scheduler, mapMode, contextMode, constrainMode, viewportMode)) {
|
||||
Map::Map(Backend& backend,
|
||||
View& view,
|
||||
const float pixelRatio,
|
||||
FileSource& fileSource,
|
||||
Scheduler& scheduler,
|
||||
MapMode mapMode,
|
||||
GLContextMode contextMode,
|
||||
ConstrainMode constrainMode,
|
||||
ViewportMode viewportMode)
|
||||
: impl(std::make_unique<Impl>(backend,
|
||||
view,
|
||||
pixelRatio,
|
||||
fileSource,
|
||||
scheduler,
|
||||
mapMode,
|
||||
contextMode,
|
||||
constrainMode,
|
||||
viewportMode)) {
|
||||
view.initialize(this);
|
||||
update(Update::Dimensions);
|
||||
}
|
||||
|
||||
Map::Impl::Impl(View& view_,
|
||||
Map::Impl::Impl(Backend& backend_,
|
||||
View& view_,
|
||||
float pixelRatio_,
|
||||
FileSource& fileSource_,
|
||||
Scheduler& scheduler_,
|
||||
MapMode mode_,
|
||||
GLContextMode contextMode_,
|
||||
ConstrainMode constrainMode_,
|
||||
ViewportMode viewportMode_)
|
||||
: view(view_),
|
||||
: backend(backend_),
|
||||
view(view_),
|
||||
fileSource(fileSource_),
|
||||
scheduler(scheduler_),
|
||||
transform([this](MapChange change) { view.notifyMapChange(change); },
|
||||
transform([this](MapChange change) { backend.notifyMapChange(change); },
|
||||
constrainMode_,
|
||||
viewportMode_),
|
||||
mode(mode_),
|
||||
contextMode(contextMode_),
|
||||
pixelRatio(view.getPixelRatio()),
|
||||
pixelRatio(pixelRatio_),
|
||||
asyncUpdate([this] { update(); }),
|
||||
annotationManager(std::make_unique<AnnotationManager>(pixelRatio)) {
|
||||
}
|
||||
|
||||
Map::~Map() {
|
||||
impl->view.activate();
|
||||
impl->backend.activate();
|
||||
|
||||
impl->styleRequest = nullptr;
|
||||
|
||||
@@ -118,7 +147,7 @@ Map::~Map() {
|
||||
impl->annotationManager.reset();
|
||||
impl->painter.reset();
|
||||
|
||||
impl->view.deactivate();
|
||||
impl->backend.deactivate();
|
||||
}
|
||||
|
||||
void Map::renderStill(StillImageCallback callback) {
|
||||
@@ -162,16 +191,16 @@ void Map::render() {
|
||||
}
|
||||
|
||||
if (impl->renderState == RenderState::Never) {
|
||||
impl->view.notifyMapChange(MapChangeWillStartRenderingMap);
|
||||
impl->backend.notifyMapChange(MapChangeWillStartRenderingMap);
|
||||
}
|
||||
|
||||
impl->view.notifyMapChange(MapChangeWillStartRenderingFrame);
|
||||
impl->backend.notifyMapChange(MapChangeWillStartRenderingFrame);
|
||||
|
||||
const Update flags = impl->transform.updateTransitions(Clock::now());
|
||||
|
||||
impl->render();
|
||||
|
||||
impl->view.notifyMapChange(isFullyLoaded() ?
|
||||
impl->backend.notifyMapChange(isFullyLoaded() ?
|
||||
MapChangeDidFinishRenderingFrameFullyRendered :
|
||||
MapChangeDidFinishRenderingFrame);
|
||||
|
||||
@@ -179,10 +208,10 @@ void Map::render() {
|
||||
impl->renderState = RenderState::Partial;
|
||||
} else if (impl->renderState != RenderState::Fully) {
|
||||
impl->renderState = RenderState::Fully;
|
||||
impl->view.notifyMapChange(MapChangeDidFinishRenderingMapFullyRendered);
|
||||
impl->backend.notifyMapChange(MapChangeDidFinishRenderingMapFullyRendered);
|
||||
if (impl->loading) {
|
||||
impl->loading = false;
|
||||
impl->view.notifyMapChange(MapChangeDidFinishLoadingMap);
|
||||
impl->backend.notifyMapChange(MapChangeDidFinishLoadingMap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -240,11 +269,11 @@ void Map::Impl::update() {
|
||||
style->updateTiles(parameters);
|
||||
|
||||
if (mode == MapMode::Continuous) {
|
||||
view.invalidate();
|
||||
backend.invalidate();
|
||||
} else if (callback && style->isLoaded()) {
|
||||
view.activate();
|
||||
backend.activate();
|
||||
render();
|
||||
view.deactivate();
|
||||
backend.deactivate();
|
||||
}
|
||||
|
||||
updateFlags = Update::Nothing;
|
||||
@@ -255,8 +284,7 @@ void Map::Impl::render() {
|
||||
painter = std::make_unique<Painter>(transform.getState());
|
||||
}
|
||||
|
||||
FrameData frameData { view.getFramebufferSize(),
|
||||
timePoint,
|
||||
FrameData frameData { timePoint,
|
||||
pixelRatio,
|
||||
mode,
|
||||
contextMode,
|
||||
@@ -264,6 +292,7 @@ void Map::Impl::render() {
|
||||
|
||||
painter->render(*style,
|
||||
frameData,
|
||||
view,
|
||||
annotationManager->getSpriteAtlas());
|
||||
|
||||
if (mode == MapMode::Still) {
|
||||
@@ -291,7 +320,7 @@ void Map::setStyleURL(const std::string& url) {
|
||||
|
||||
impl->loading = true;
|
||||
|
||||
impl->view.notifyMapChange(MapChangeWillStartLoadingMap);
|
||||
impl->backend.notifyMapChange(MapChangeWillStartLoadingMap);
|
||||
|
||||
impl->styleRequest = nullptr;
|
||||
impl->styleURL = url;
|
||||
@@ -335,7 +364,7 @@ void Map::setStyleJSON(const std::string& json) {
|
||||
|
||||
impl->loading = true;
|
||||
|
||||
impl->view.notifyMapChange(MapChangeWillStartLoadingMap);
|
||||
impl->backend.notifyMapChange(MapChangeWillStartLoadingMap);
|
||||
|
||||
impl->styleURL.clear();
|
||||
impl->styleJSON.clear();
|
||||
@@ -801,12 +830,12 @@ void Map::addLayer(std::unique_ptr<Layer> layer, const optional<std::string>& be
|
||||
}
|
||||
|
||||
impl->styleMutated = true;
|
||||
impl->view.activate();
|
||||
impl->backend.activate();
|
||||
|
||||
impl->style->addLayer(std::move(layer), before);
|
||||
update(Update::Classes);
|
||||
|
||||
impl->view.deactivate();
|
||||
impl->backend.deactivate();
|
||||
}
|
||||
|
||||
void Map::removeLayer(const std::string& id) {
|
||||
@@ -815,12 +844,12 @@ void Map::removeLayer(const std::string& id) {
|
||||
}
|
||||
|
||||
impl->styleMutated = true;
|
||||
impl->view.activate();
|
||||
impl->backend.activate();
|
||||
|
||||
impl->style->removeLayer(id);
|
||||
update(Update::Classes);
|
||||
|
||||
impl->view.deactivate();
|
||||
impl->backend.deactivate();
|
||||
}
|
||||
|
||||
void Map::addImage(const std::string& name, std::unique_ptr<const SpriteImage> image) {
|
||||
@@ -971,7 +1000,7 @@ void Map::setSourceTileCacheSize(size_t size) {
|
||||
impl->sourceCacheSize = size;
|
||||
if (!impl->style) return;
|
||||
impl->style->setSourceTileCacheSize(size);
|
||||
impl->view.invalidate();
|
||||
impl->backend.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -981,12 +1010,12 @@ void Map::onLowMemory() {
|
||||
}
|
||||
if (impl->style) {
|
||||
impl->style->onLowMemory();
|
||||
impl->view.invalidate();
|
||||
impl->backend.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void Map::Impl::onSourceAttributionChanged(style::Source&, const std::string&) {
|
||||
view.notifyMapChange(MapChangeSourceDidChange);
|
||||
backend.notifyMapChange(MapChangeSourceDidChange);
|
||||
}
|
||||
|
||||
void Map::Impl::onUpdate(Update flags) {
|
||||
@@ -999,11 +1028,11 @@ void Map::Impl::onUpdate(Update flags) {
|
||||
}
|
||||
|
||||
void Map::Impl::onStyleLoaded() {
|
||||
view.notifyMapChange(MapChangeDidFinishLoadingStyle);
|
||||
backend.notifyMapChange(MapChangeDidFinishLoadingStyle);
|
||||
}
|
||||
|
||||
void Map::Impl::onStyleError() {
|
||||
view.notifyMapChange(MapChangeDidFailLoadingMap);
|
||||
backend.notifyMapChange(MapChangeDidFailLoadingMap);
|
||||
}
|
||||
|
||||
void Map::Impl::onResourceError(std::exception_ptr error) {
|
||||
|
||||
@@ -5,18 +5,13 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
PremultipliedImage View::readStillImage(std::array<uint16_t, 2>) {
|
||||
return {};
|
||||
}
|
||||
|
||||
void View::initialize(Map *map_) {
|
||||
assert(map_);
|
||||
map = map_;
|
||||
}
|
||||
|
||||
PremultipliedImage View::readStillImage(std::array<uint16_t, 2>) {
|
||||
return {};
|
||||
}
|
||||
|
||||
void View::notifyMapChange(MapChange) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
namespace mbgl {
|
||||
|
||||
class Shaders;
|
||||
class View;
|
||||
|
||||
class PaintParameters {
|
||||
public:
|
||||
Shaders& shaders;
|
||||
View& view;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <mbgl/style/source.hpp>
|
||||
#include <mbgl/style/source_impl.hpp>
|
||||
|
||||
#include <mbgl/map/view.hpp>
|
||||
|
||||
#include <mbgl/platform/log.hpp>
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
#include <mbgl/gl/debugging.hpp>
|
||||
@@ -90,19 +92,18 @@ void Painter::cleanup() {
|
||||
context.performCleanup();
|
||||
}
|
||||
|
||||
void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& annotationSpriteAtlas) {
|
||||
if (frame.framebufferSize != frame_.framebufferSize) {
|
||||
context.viewport.setDefaultValue(
|
||||
{ 0, 0, frame_.framebufferSize[0], frame_.framebufferSize[1] });
|
||||
}
|
||||
void Painter::render(const Style& style, const FrameData& frame_, View& view, SpriteAtlas& annotationSpriteAtlas) {
|
||||
context.viewport.setDefaultValue(
|
||||
{ 0, 0, view.getFramebufferSize()[0], view.getFramebufferSize()[1] });
|
||||
frame = frame_;
|
||||
|
||||
PaintParameters parameters {
|
||||
#ifndef NDEBUG
|
||||
paintMode() == PaintMode::Overdraw ? *overdrawShaders : *shaders
|
||||
paintMode() == PaintMode::Overdraw ? *overdrawShaders : *shaders,
|
||||
#else
|
||||
*shaders
|
||||
*shaders,
|
||||
#endif
|
||||
view
|
||||
};
|
||||
|
||||
glyphAtlas = style.glyphAtlas.get();
|
||||
@@ -148,7 +149,8 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
|
||||
// tiles whatsoever.
|
||||
{
|
||||
MBGL_DEBUG_GROUP("clear");
|
||||
context.bindFramebuffer.reset();
|
||||
context.bindFramebuffer.setDirty();
|
||||
view.bind();
|
||||
context.viewport.reset();
|
||||
context.stencilFunc.reset();
|
||||
context.stencilTest = true;
|
||||
@@ -188,7 +190,7 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
|
||||
|
||||
#if not MBGL_USE_GLES2 and not defined(NDEBUG)
|
||||
if (frame.debugOptions & MapDebugOptions::StencilClip) {
|
||||
renderClipMasks();
|
||||
renderClipMasks(parameters);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
@@ -231,7 +233,7 @@ void Painter::render(const Style& style, const FrameData& frame_, SpriteAtlas& a
|
||||
|
||||
#if not MBGL_USE_GLES2 and not defined(NDEBUG)
|
||||
if (frame.debugOptions & MapDebugOptions::DepthBuffer) {
|
||||
renderDepthBuffer();
|
||||
renderDepthBuffer(parameters);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -302,7 +304,8 @@ void Painter::renderPass(PaintParameters& parameters,
|
||||
setDepthSublayer(0);
|
||||
layer.as<CustomLayer>()->impl->render(state);
|
||||
context.setDirtyState();
|
||||
context.bindFramebuffer.reset();
|
||||
context.bindFramebuffer.setDirty();
|
||||
parameters.view.bind();
|
||||
context.viewport.reset();
|
||||
} else {
|
||||
MBGL_DEBUG_GROUP(layer.baseImpl->id + " - " + util::toString(item.tile->id));
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace mbgl {
|
||||
|
||||
class RenderTile;
|
||||
class SpriteAtlas;
|
||||
class View;
|
||||
class GlyphAtlas;
|
||||
class LineAtlas;
|
||||
struct FrameData;
|
||||
@@ -58,7 +59,6 @@ class BackgroundLayer;
|
||||
} // namespace style
|
||||
|
||||
struct FrameData {
|
||||
std::array<uint16_t, 2> framebufferSize = {{ 0, 0 }};
|
||||
TimePoint timePoint;
|
||||
float pixelRatio;
|
||||
MapMode mapMode;
|
||||
@@ -73,6 +73,7 @@ public:
|
||||
|
||||
void render(const style::Style&,
|
||||
const FrameData&,
|
||||
View&,
|
||||
SpriteAtlas& annotationSpriteAtlas);
|
||||
|
||||
void cleanup();
|
||||
@@ -85,9 +86,9 @@ public:
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Renders tile clip boundaries, using stencil buffer to calculate fill color.
|
||||
void renderClipMasks();
|
||||
void renderClipMasks(PaintParameters&);
|
||||
// Renders the depth buffer.
|
||||
void renderDepthBuffer();
|
||||
void renderDepthBuffer(PaintParameters&);
|
||||
#endif
|
||||
|
||||
void renderDebugText(Tile&, const mat4&);
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include <mbgl/renderer/painter.hpp>
|
||||
#include <mbgl/renderer/debug_bucket.hpp>
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/map/view.hpp>
|
||||
#include <mbgl/tile/tile.hpp>
|
||||
#include <mbgl/shader/shaders.hpp>
|
||||
#include <mbgl/util/string.hpp>
|
||||
@@ -87,7 +89,7 @@ void Painter::renderDebugFrame(const mat4 &matrix) {
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
void Painter::renderClipMasks() {
|
||||
void Painter::renderClipMasks(PaintParameters& parameters) {
|
||||
context.stencilTest = false;
|
||||
context.depthTest = false;
|
||||
context.program = 0;
|
||||
@@ -98,7 +100,7 @@ void Painter::renderClipMasks() {
|
||||
context.rasterPos = { -1, -1, 0, 0 };
|
||||
|
||||
// Read the stencil buffer
|
||||
const auto& fbSize = frame.framebufferSize;
|
||||
const auto& fbSize = parameters.view.getFramebufferSize();
|
||||
auto pixels = std::make_unique<uint8_t[]>(fbSize[0] * fbSize[1]);
|
||||
MBGL_CHECK_ERROR(glReadPixels(
|
||||
0, // GLint x
|
||||
@@ -120,12 +122,14 @@ void Painter::renderClipMasks() {
|
||||
|
||||
MBGL_CHECK_ERROR(glWindowPos2i(0, 0));
|
||||
MBGL_CHECK_ERROR(glDrawPixels(fbSize[0], fbSize[1], GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels.get()));
|
||||
#else
|
||||
(void)parameters;
|
||||
#endif // MBGL_USE_GLES2
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
#ifndef NDEBUG
|
||||
void Painter::renderDepthBuffer() {
|
||||
void Painter::renderDepthBuffer(PaintParameters& parameters) {
|
||||
context.stencilTest = false;
|
||||
context.depthTest = false;
|
||||
context.program = 0;
|
||||
@@ -136,7 +140,7 @@ void Painter::renderDepthBuffer() {
|
||||
context.rasterPos = { -1, -1, 0, 0 };
|
||||
|
||||
// Read the stencil buffer
|
||||
const auto& fbSize = frame.framebufferSize;
|
||||
const auto& fbSize = parameters.view.getFramebufferSize();
|
||||
auto pixels = std::make_unique<GLubyte[]>(fbSize[0] * fbSize[1]);
|
||||
|
||||
const double base = 1.0 / (1.0 - depthRangeSize);
|
||||
@@ -155,6 +159,8 @@ void Painter::renderDepthBuffer() {
|
||||
|
||||
MBGL_CHECK_ERROR(glWindowPos2i(0, 0));
|
||||
MBGL_CHECK_ERROR(glDrawPixels(fbSize[0], fbSize[1], GL_LUMINANCE, GL_UNSIGNED_BYTE, pixels.get()));
|
||||
#else
|
||||
(void)parameters;
|
||||
#endif // MBGL_USE_GLES2
|
||||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <mbgl/renderer/painter.hpp>
|
||||
#include <mbgl/renderer/paint_parameters.hpp>
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
#include <mbgl/map/view.hpp>
|
||||
|
||||
#include <mbgl/renderer/fill_bucket.hpp>
|
||||
#include <mbgl/renderer/render_tile.hpp>
|
||||
@@ -29,7 +30,7 @@ void Painter::renderFill(PaintParameters& parameters,
|
||||
const bool isOutlineColorDefined = !properties.fillOutlineColor.isUndefined();
|
||||
Color strokeColor = isOutlineColorDefined? properties.fillOutlineColor : fillColor;
|
||||
|
||||
auto worldSize = util::convert<GLfloat>(frame.framebufferSize);
|
||||
auto worldSize = util::convert<GLfloat>(parameters.view.getFramebufferSize());
|
||||
|
||||
bool pattern = !properties.fillPattern.value.from.empty();
|
||||
bool outline = properties.fillAntialias && !pattern && isOutlineColorDefined;
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include <mbgl/annotation/annotation.hpp>
|
||||
#include <mbgl/sprite/sprite_image.hpp>
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/util/io.hpp>
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
@@ -23,11 +23,11 @@ std::shared_ptr<SpriteImage> namedMarker(const std::string &name) {
|
||||
class AnnotationTest {
|
||||
public:
|
||||
util::RunLoop loop;
|
||||
std::shared_ptr<HeadlessDisplay> display { std::make_shared<HeadlessDisplay>() };
|
||||
HeadlessView view { display, 1 };
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view;
|
||||
StubFileSource fileSource;
|
||||
ThreadPool threadPool { 4 };
|
||||
Map map { view, fileSource, threadPool, MapMode::Still };
|
||||
Map map { backend, view, view.getPixelRatio(), fileSource, threadPool, MapMode::Still };
|
||||
|
||||
void checkRendering(const char * name) {
|
||||
test::checkImage(std::string("test/fixtures/annotations/") + name,
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
#include <mbgl/test/fixture_log_observer.hpp>
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/storage/online_file_source.hpp>
|
||||
#include <mbgl/platform/default/thread_pool.hpp>
|
||||
#include <mbgl/util/exception.hpp>
|
||||
@@ -19,13 +20,14 @@ TEST(API, RenderWithoutCallback) {
|
||||
|
||||
util::RunLoop loop;
|
||||
|
||||
auto display = std::make_shared<mbgl::HeadlessDisplay>();
|
||||
HeadlessView view(display, 1);
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view;
|
||||
view.resize(128, 512);
|
||||
StubFileSource fileSource;
|
||||
ThreadPool threadPool(4);
|
||||
|
||||
std::unique_ptr<Map> map = std::make_unique<Map>(view, fileSource, threadPool, MapMode::Still);
|
||||
std::unique_ptr<Map> map = std::make_unique<Map>(backend, view, view.getPixelRatio(),
|
||||
fileSource, threadPool, MapMode::Still);
|
||||
map->renderStill(nullptr);
|
||||
|
||||
// Force Map thread to join.
|
||||
@@ -44,13 +46,13 @@ TEST(API, RenderWithoutCallback) {
|
||||
TEST(API, RenderWithoutStyle) {
|
||||
util::RunLoop loop;
|
||||
|
||||
auto display = std::make_shared<mbgl::HeadlessDisplay>();
|
||||
HeadlessView view(display, 1);
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view;
|
||||
view.resize(128, 512);
|
||||
StubFileSource fileSource;
|
||||
ThreadPool threadPool(4);
|
||||
|
||||
Map map(view, fileSource, threadPool, MapMode::Still);
|
||||
Map map(backend, view, view.getPixelRatio(), fileSource, threadPool, MapMode::Still);
|
||||
|
||||
std::exception_ptr error;
|
||||
map.renderStill([&](std::exception_ptr error_, PremultipliedImage&&) {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/thread_pool.hpp>
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
@@ -85,8 +85,8 @@ public:
|
||||
TEST(CustomLayer, Basic) {
|
||||
util::RunLoop loop;
|
||||
|
||||
auto display = std::make_shared<mbgl::HeadlessDisplay>();
|
||||
HeadlessView view(display, 1);
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view;
|
||||
|
||||
#ifdef MBGL_ASSET_ZIP
|
||||
// Regenerate with `cd test/fixtures/api/ && zip -r assets.zip assets/`
|
||||
@@ -97,7 +97,7 @@ TEST(CustomLayer, Basic) {
|
||||
|
||||
ThreadPool threadPool(4);
|
||||
|
||||
Map map(view, fileSource, threadPool, MapMode::Still);
|
||||
Map map(backend, view, view.getPixelRatio(), fileSource, threadPool, MapMode::Still);
|
||||
map.setStyleJSON(util::read_file("test/fixtures/api/water.json"));
|
||||
map.setLatLngZoom({ 37.8, -122.5 }, 10);
|
||||
map.addLayer(std::make_unique<CustomLayer>(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/thread_pool.hpp>
|
||||
#include <mbgl/sprite/sprite_image.hpp>
|
||||
@@ -26,11 +26,11 @@ public:
|
||||
}
|
||||
|
||||
util::RunLoop loop;
|
||||
std::shared_ptr<HeadlessDisplay> display { std::make_shared<HeadlessDisplay>() };
|
||||
HeadlessView view { display, 1 };
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view;
|
||||
StubFileSource fileSource;
|
||||
ThreadPool threadPool { 4 };
|
||||
Map map { view, fileSource, threadPool, MapMode::Still };
|
||||
Map map { backend, view, view.getPixelRatio(), fileSource, threadPool, MapMode::Still };
|
||||
};
|
||||
|
||||
} // end namespace
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <mbgl/test/fixture_log_observer.hpp>
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/thread_pool.hpp>
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
@@ -25,8 +25,8 @@ TEST(API, TEST_REQUIRES_SERVER(RenderMissingTile)) {
|
||||
|
||||
const auto style = util::read_file("test/fixtures/api/water_missing_tiles.json");
|
||||
|
||||
auto display = std::make_shared<mbgl::HeadlessDisplay>();
|
||||
HeadlessView view(display, 1, 256, 512);
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view(1, 256, 512);
|
||||
#ifdef MBGL_ASSET_ZIP
|
||||
// Regenerate with `cd test/fixtures/api/ && zip -r assets.zip assets/`
|
||||
DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets.zip");
|
||||
@@ -38,7 +38,7 @@ TEST(API, TEST_REQUIRES_SERVER(RenderMissingTile)) {
|
||||
|
||||
Log::setObserver(std::make_unique<FixtureLogObserver>());
|
||||
|
||||
Map map(view, fileSource, threadPool, MapMode::Still);
|
||||
Map map(backend, view, view.getPixelRatio(), fileSource, threadPool, MapMode::Still);
|
||||
|
||||
std::string message;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <mbgl/test/fixture_log_observer.hpp>
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/thread_pool.hpp>
|
||||
#include <mbgl/storage/default_file_source.hpp>
|
||||
@@ -19,9 +19,8 @@ TEST(API, RepeatedRender) {
|
||||
|
||||
const auto style = util::read_file("test/fixtures/api/water.json");
|
||||
|
||||
auto display = std::make_shared<mbgl::HeadlessDisplay>();
|
||||
HeadlessView view(display, 1, 256, 512);
|
||||
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view(1, 256, 512);
|
||||
#ifdef MBGL_ASSET_ZIP
|
||||
// Regenerate with `cd test/fixtures/api/ && zip -r assets.zip assets/`
|
||||
DefaultFileSource fileSource(":memory:", "test/fixtures/api/assets.zip");
|
||||
@@ -33,7 +32,7 @@ TEST(API, RepeatedRender) {
|
||||
|
||||
Log::setObserver(std::make_unique<FixtureLogObserver>());
|
||||
|
||||
Map map(view, fileSource, threadPool, MapMode::Still);
|
||||
Map map(backend, view, view.getPixelRatio(), fileSource, threadPool, MapMode::Still);
|
||||
|
||||
{
|
||||
map.setStyleJSON(style);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include <mbgl/test/util.hpp>
|
||||
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
@@ -67,8 +67,8 @@ TEST(GLObject, Value) {
|
||||
}
|
||||
|
||||
TEST(GLObject, Store) {
|
||||
mbgl::HeadlessView view(std::make_shared<mbgl::HeadlessDisplay>(), 1);
|
||||
view.activate();
|
||||
mbgl::HeadlessBackend backend;
|
||||
mbgl::HeadlessView view;
|
||||
|
||||
mbgl::gl::Context context;
|
||||
EXPECT_TRUE(context.empty());
|
||||
@@ -106,5 +106,5 @@ TEST(GLObject, Store) {
|
||||
context.reset();
|
||||
EXPECT_TRUE(context.empty());
|
||||
|
||||
view.deactivate();
|
||||
backend.deactivate();
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <mbgl/test/fixture_log_observer.hpp>
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/thread_pool.hpp>
|
||||
#include <mbgl/sprite/sprite_image.hpp>
|
||||
@@ -22,15 +22,16 @@ using namespace std::literals::string_literals;
|
||||
|
||||
struct MapTest {
|
||||
util::RunLoop runLoop;
|
||||
std::shared_ptr<HeadlessDisplay> display { std::make_shared<mbgl::HeadlessDisplay>() };
|
||||
HeadlessView view { display, 1 };
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view;
|
||||
StubFileSource fileSource;
|
||||
ThreadPool threadPool { 4 };
|
||||
};
|
||||
|
||||
TEST(Map, LatLngBehavior) {
|
||||
MapTest test;
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
|
||||
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
|
||||
|
||||
@@ -64,7 +65,8 @@ TEST(Map, Offline) {
|
||||
fileSource.put(Resource::glyphs(prefix + "{fontstack}/{range}.pbf", {{"Helvetica"}}, {0, 255}), expiredItem("glyph.pbf"));
|
||||
NetworkStatus::Set(NetworkStatus::Status::Offline);
|
||||
|
||||
Map map(test.view, fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setStyleURL(prefix + "style.json");
|
||||
|
||||
test::checkImage("test/fixtures/map/offline",
|
||||
@@ -81,14 +83,15 @@ TEST(Map, SetStyleInvalidJSON) {
|
||||
Log::setObserver(std::make_unique<FixtureLogObserver>());
|
||||
|
||||
bool fail = false;
|
||||
test.view.setMapChangeCallback([&](MapChange change) {
|
||||
test.backend.setMapChangeCallback([&](MapChange change) {
|
||||
if (change == mbgl::MapChangeDidFailLoadingMap) {
|
||||
fail = true;
|
||||
}
|
||||
});
|
||||
|
||||
{
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource,
|
||||
test.threadPool, MapMode::Still);
|
||||
map.setStyleJSON("invalid");
|
||||
}
|
||||
|
||||
@@ -113,13 +116,14 @@ TEST(Map, SetStyleInvalidURL) {
|
||||
return response;
|
||||
};
|
||||
|
||||
test.view.setMapChangeCallback([&](MapChange change) {
|
||||
test.backend.setMapChangeCallback([&](MapChange change) {
|
||||
if (change == mbgl::MapChangeDidFailLoadingMap) {
|
||||
test.runLoop.stop();
|
||||
}
|
||||
});
|
||||
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setStyleURL("mapbox://bar");
|
||||
|
||||
test.runLoop.run();
|
||||
@@ -128,7 +132,8 @@ TEST(Map, SetStyleInvalidURL) {
|
||||
TEST(Map, DoubleStyleLoad) {
|
||||
MapTest test;
|
||||
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setStyleJSON("");
|
||||
map.setStyleJSON("");
|
||||
}
|
||||
@@ -139,7 +144,8 @@ TEST(Map, StyleFresh) {
|
||||
MapTest test;
|
||||
FakeFileSource fileSource;
|
||||
|
||||
Map map(test.view, fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setStyleURL("mapbox://styles/test");
|
||||
EXPECT_EQ(1u, fileSource.requests.size());
|
||||
|
||||
@@ -159,7 +165,8 @@ TEST(Map, StyleExpired) {
|
||||
MapTest test;
|
||||
FakeFileSource fileSource;
|
||||
|
||||
Map map(test.view, fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setStyleURL("mapbox://styles/test");
|
||||
EXPECT_EQ(1u, fileSource.requests.size());
|
||||
|
||||
@@ -186,7 +193,8 @@ TEST(Map, StyleExpiredWithAnnotations) {
|
||||
MapTest test;
|
||||
FakeFileSource fileSource;
|
||||
|
||||
Map map(test.view, fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setStyleURL("mapbox://styles/test");
|
||||
EXPECT_EQ(1u, fileSource.requests.size());
|
||||
|
||||
@@ -210,7 +218,8 @@ TEST(Map, StyleEarlyMutation) {
|
||||
MapTest test;
|
||||
FakeFileSource fileSource;
|
||||
|
||||
Map map(test.view, fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setStyleURL("mapbox://styles/test");
|
||||
map.addLayer(std::make_unique<style::BackgroundLayer>("bg"));
|
||||
|
||||
@@ -224,11 +233,12 @@ TEST(Map, StyleEarlyMutation) {
|
||||
|
||||
TEST(Map, StyleLoadedSignal) {
|
||||
MapTest test;
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
|
||||
// The map should emit a signal on style loaded
|
||||
bool emitted = false;
|
||||
test.view.setMapChangeCallback([&](MapChange change) {
|
||||
test.backend.setMapChangeCallback([&](MapChange change) {
|
||||
if (change == mbgl::MapChangeDidFinishLoadingStyle) {
|
||||
emitted = true;
|
||||
}
|
||||
@@ -245,7 +255,8 @@ TEST(Map, StyleLoadedSignal) {
|
||||
TEST(Map, AddLayer) {
|
||||
MapTest test;
|
||||
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
|
||||
|
||||
auto layer = std::make_unique<BackgroundLayer>("background");
|
||||
@@ -258,7 +269,8 @@ TEST(Map, AddLayer) {
|
||||
TEST(Map, RemoveLayer) {
|
||||
MapTest test;
|
||||
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
|
||||
|
||||
auto layer = std::make_unique<BackgroundLayer>("background");
|
||||
@@ -283,7 +295,8 @@ TEST(Map, DisabledSources) {
|
||||
return {};
|
||||
};
|
||||
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setZoom(1);
|
||||
|
||||
// This stylesheet has two raster layers, one that starts at zoom 1, the other at zoom 0.
|
||||
@@ -333,7 +346,8 @@ TEST(Map, DisabledSources) {
|
||||
TEST(Map, Classes) {
|
||||
MapTest test;
|
||||
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setStyleJSON(util::read_file("test/fixtures/api/empty.json"));
|
||||
|
||||
EXPECT_FALSE(map.getTransitionOptions().duration);
|
||||
@@ -367,7 +381,8 @@ TEST(Map, Classes) {
|
||||
TEST(Map, AddImage) {
|
||||
MapTest test;
|
||||
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
auto decoded1 = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png"));
|
||||
auto decoded2 = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png"));
|
||||
auto image1 = std::make_unique<SpriteImage>(std::move(decoded1), 1.0);
|
||||
@@ -384,7 +399,8 @@ TEST(Map, AddImage) {
|
||||
TEST(Map, RemoveImage) {
|
||||
MapTest test;
|
||||
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
auto decoded = decodeImage(util::read_file("test/fixtures/sprites/default_marker.png"));
|
||||
auto image = std::make_unique<SpriteImage>(std::move(decoded), 1.0);
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <mbgl/test/util.hpp>
|
||||
|
||||
#include <mbgl/map/map.hpp>
|
||||
#include <mbgl/platform/default/headless_display.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/platform/default/thread_pool.hpp>
|
||||
#include <mbgl/util/io.hpp>
|
||||
@@ -56,8 +56,8 @@ public:
|
||||
}
|
||||
|
||||
util::RunLoop runLoop;
|
||||
std::shared_ptr<HeadlessDisplay> display { std::make_shared<mbgl::HeadlessDisplay>() };
|
||||
HeadlessView view { display, 2 };
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view{ 2 };
|
||||
StubFileSource fileSource;
|
||||
ThreadPool threadPool { 4 };
|
||||
|
||||
@@ -93,7 +93,8 @@ private:
|
||||
TEST(Memory, Vector) {
|
||||
MemoryTest test;
|
||||
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setZoom(16); // more map features
|
||||
map.setStyleURL("mapbox://streets");
|
||||
|
||||
@@ -103,7 +104,8 @@ TEST(Memory, Vector) {
|
||||
TEST(Memory, Raster) {
|
||||
MemoryTest test;
|
||||
|
||||
Map map(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource, test.threadPool,
|
||||
MapMode::Still);
|
||||
map.setStyleURL("mapbox://satellite");
|
||||
|
||||
test::render(map);
|
||||
@@ -130,7 +132,8 @@ TEST(Memory, Footprint) {
|
||||
|
||||
// Warm up buffers and cache.
|
||||
for (unsigned i = 0; i < 10; ++i) {
|
||||
Map map(test.view, test.fileSource,test.threadPool, MapMode::Still);
|
||||
Map map(test.backend, test.view, test.view.getPixelRatio(), test.fileSource,
|
||||
test.threadPool, MapMode::Still);
|
||||
renderMap(&map, "mapbox://streets");
|
||||
renderMap(&map, "mapbox://satellite");
|
||||
};
|
||||
@@ -144,7 +147,8 @@ TEST(Memory, Footprint) {
|
||||
|
||||
long vectorInitialRSS = getRSS();
|
||||
for (unsigned i = 0; i < runs; ++i) {
|
||||
auto vector = std::make_unique<Map>(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
auto vector = std::make_unique<Map>(test.backend, test.view, test.view.getPixelRatio(),
|
||||
test.fileSource, test.threadPool, MapMode::Still);
|
||||
renderMap(vector.get(), "mapbox://streets");
|
||||
maps.push_back(std::move(vector));
|
||||
};
|
||||
@@ -153,7 +157,8 @@ TEST(Memory, Footprint) {
|
||||
|
||||
long rasterInitialRSS = getRSS();
|
||||
for (unsigned i = 0; i < runs; ++i) {
|
||||
auto raster = std::make_unique<Map>(test.view, test.fileSource, test.threadPool, MapMode::Still);
|
||||
auto raster = std::make_unique<Map>(test.backend, test.view, test.view.getPixelRatio(),
|
||||
test.fileSource, test.threadPool, MapMode::Still);
|
||||
renderMap(raster.get(), "mapbox://satellite");
|
||||
maps.push_back(std::move(raster));
|
||||
};
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
#include <mbgl/test/util.hpp>
|
||||
|
||||
#include <mbgl/gl/context.hpp>
|
||||
#include <mbgl/platform/default/headless_backend.hpp>
|
||||
#include <mbgl/platform/default/headless_view.hpp>
|
||||
#include <mbgl/gl/gl.hpp>
|
||||
|
||||
#include <mbgl/util/offscreen_texture.hpp>
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
TEST(OffscreenTexture, EmptyRed) {
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view(1.0f, 512, 256);
|
||||
view.activate();
|
||||
view.bind();
|
||||
|
||||
MBGL_CHECK_ERROR(glClearColor(1.0f, 0.0f, 0.0f, 1.0f));
|
||||
MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT));
|
||||
@@ -64,11 +67,11 @@ struct Buffer {
|
||||
|
||||
|
||||
TEST(OffscreenTexture, RenderToTexture) {
|
||||
HeadlessBackend backend;
|
||||
HeadlessView view(1.0f, 512, 256);
|
||||
view.activate();
|
||||
view.bind();
|
||||
gl::Context context;
|
||||
context.viewport.setDefaultValue(gl::value::Viewport::Get());
|
||||
context.bindFramebuffer.setDefaultValue(gl::value::BindFramebuffer::Get());
|
||||
|
||||
MBGL_CHECK_ERROR(glEnable(GL_BLEND));
|
||||
MBGL_CHECK_ERROR(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
|
||||
@@ -130,6 +133,8 @@ void main() {
|
||||
|
||||
// Now reset the FBO back to normal and retrieve the original (restored) framebuffer.
|
||||
context.resetState();
|
||||
context.bindFramebuffer.setDirty();
|
||||
view.bind();
|
||||
|
||||
image = view.readStillImage();
|
||||
test::checkImage("test/fixtures/offscreen_texture/render-to-fbo", image, 0, 0);
|
||||
|
||||
Reference in New Issue
Block a user