Make pixelRatio constant across a Map object lifetime

also moves framebuffer size out of TransformState into its own object
This commit is contained in:
Konstantin Käfer
2015-07-01 12:39:21 +02:00
parent 3a07cb2f1e
commit 675ddddee7
40 changed files with 308 additions and 214 deletions

View File

@@ -180,12 +180,12 @@ namespace {
using namespace mbgl::android;
jlong JNICALL
nativeCreate(JNIEnv *env, jobject obj, jstring cachePath_, jstring dataPath_, jstring apkPath_) {
nativeCreate(JNIEnv *env, jobject obj, jstring cachePath_, jstring dataPath_, jstring apkPath_, jfloat pixelRatio) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeCreate");
cachePath = std_string_from_jstring(env, cachePath_);
dataPath = std_string_from_jstring(env, dataPath_);
apkPath = std_string_from_jstring(env, apkPath_);
NativeMapView *nativeMapView = new NativeMapView(env, obj);
NativeMapView *nativeMapView = new NativeMapView(env, obj, pixelRatio);
jlong mapViewPtr = reinterpret_cast<jlong>(nativeMapView);
return mapViewPtr;
}
@@ -285,20 +285,26 @@ void JNICALL nativeOnInvalidate(JNIEnv *env, jobject obj, jlong nativeMapViewPtr
nativeMapView->onInvalidate();
}
void JNICALL nativeResize(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jint width, jint height,
jfloat ratio, jint fbWidth, jint fbHeight) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeResize");
void JNICALL nativeViewResize(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jint width, jint height) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeViewResize");
assert(nativeMapViewPtr != 0);
assert(width >= 0);
assert(height >= 0);
assert(width <= UINT16_MAX);
assert(height <= UINT16_MAX);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->resizeView(width, height);
}
void JNICALL nativeFramebufferResize(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jint fbWidth, jint fbHeight) {
mbgl::Log::Debug(mbgl::Event::JNI, "nativeFramebufferResize");
assert(nativeMapViewPtr != 0);
assert(fbWidth >= 0);
assert(fbHeight >= 0);
assert(fbWidth <= UINT16_MAX);
assert(fbHeight <= UINT16_MAX);
NativeMapView *nativeMapView = reinterpret_cast<NativeMapView *>(nativeMapViewPtr);
nativeMapView->getMap().resize(width, height, ratio);
nativeMapView->resizeFramebuffer(fbWidth, fbHeight);
}
void JNICALL nativeRemoveClass(JNIEnv *env, jobject obj, jlong nativeMapViewPtr, jstring clazz) {
@@ -922,7 +928,7 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
}
const std::vector<JNINativeMethod> methods = {
{"nativeCreate", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J",
{"nativeCreate", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;F)J",
reinterpret_cast<void *>(&nativeCreate)},
{"nativeDestroy", "(J)V", reinterpret_cast<void *>(&nativeDestroy)},
{"nativeInitializeDisplay", "(J)V", reinterpret_cast<void *>(&nativeInitializeDisplay)},
@@ -936,9 +942,12 @@ extern "C" JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
{"nativeResume", "(J)V", reinterpret_cast<void *>(&nativeResume)},
{"nativeUpdate", "(J)V", reinterpret_cast<void *>(&nativeUpdate)},
{"nativeOnInvalidate", "(J)V", reinterpret_cast<void *>(&nativeOnInvalidate)},
{"nativeResize", "(JIIFII)V",
{"nativeViewResize", "(JII)V",
reinterpret_cast<void *>(static_cast<void JNICALL (
*)(JNIEnv *, jobject, jlong, jint, jint, jfloat, jint, jint)>(&nativeResize))},
*)(JNIEnv *, jobject, jlong, jint, jint)>(&nativeViewResize))},
{"nativeFramebufferResize", "(JII)V",
reinterpret_cast<void *>(static_cast<void JNICALL (
*)(JNIEnv *, jobject, jlong, jint, jint)>(&nativeFramebufferResize))},
{"nativeAddClass", "(JLjava/lang/String;)V",
reinterpret_cast<void *>(&nativeAddClass)},
{"nativeRemoveClass", "(JLjava/lang/String;)V",

View File

@@ -52,8 +52,9 @@ void log_gl_string(GLenum name, const char *label) {
}
}
NativeMapView::NativeMapView(JNIEnv *env, jobject obj_)
NativeMapView::NativeMapView(JNIEnv *env, jobject obj_, float pixelRatio_)
: mbgl::View(*this),
pixelRatio(pixelRatio_),
fileCache(mbgl::android::cachePath + "/mbgl-cache.db"),
fileSource(&fileCache),
map(*this, fileSource, MapMode::Continuous) {
@@ -98,6 +99,18 @@ NativeMapView::~NativeMapView() {
vm = nullptr;
}
float NativeMapView::getPixelRatio() const {
return pixelRatio;
}
std::array<uint16_t, 2> NativeMapView::getSize() const {
return {{ static_cast<uint16_t>(width), static_cast<uint16_t>(height) }};
}
std::array<uint16_t, 2> NativeMapView::getFramebufferSize() const {
return {{ static_cast<uint16_t>(fbWidth), static_cast<uint16_t>(fbHeight) }};
}
void NativeMapView::activate() {
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::activate");
if ((display != EGL_NO_DISPLAY) && (surface != EGL_NO_SURFACE) && (context != EGL_NO_CONTEXT)) {
@@ -754,5 +767,16 @@ void NativeMapView::onInvalidate() {
}
}
void NativeMapView::resizeView(int w, int h) {
width = w;
height = h;
map.update(mbgl::Update::Dimensions);
}
void NativeMapView::resizeFramebuffer(int w, int h) {
fbWidth = w;
fbHeight = h;
}
}
}

View File

@@ -145,7 +145,7 @@ public class MapView extends SurfaceView {
String apkPath = context.getPackageCodePath();
// Create the NativeMapView
mNativeMapView = new NativeMapView(this, cachePath, dataPath, apkPath);
mNativeMapView = new NativeMapView(this, cachePath, dataPath, apkPath, mScreenDensity);
// Load the attributes
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MapView, 0, 0);
@@ -477,6 +477,10 @@ public class MapView extends SurfaceView {
mNativeMapView.resume();
}
public void onSizeChanged(int width, int height, int oldw, int oldh) {
mNativeMapView.resizeView((int)(width / mScreenDensity), (int)(height / mScreenDensity));
}
// This class handles SurfaceHolder callbacks
private class Callbacks implements SurfaceHolder.Callback {
@@ -498,9 +502,8 @@ public class MapView extends SurfaceView {
// changed
// Must handle window resizing here.
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
mNativeMapView.resize((int) (width / mScreenDensity), (int) (height / mScreenDensity), mScreenDensity, width, height);
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mNativeMapView.resizeFramebuffer(width, height);
}
}

View File

@@ -39,11 +39,11 @@ class NativeMapView {
// Constructors
//
public NativeMapView(MapView mapView, String cachePath, String dataPath, String apkPath) {
public NativeMapView(MapView mapView, String cachePath, String dataPath, String apkPath, float pixelRatio) {
mMapView = mapView;
// Create the NativeMapView
mNativeMapViewPtr = nativeCreate(cachePath, dataPath, apkPath);
mNativeMapViewPtr = nativeCreate(cachePath, dataPath, apkPath, pixelRatio);
}
//
@@ -90,8 +90,7 @@ class NativeMapView {
nativeOnInvalidate(mNativeMapViewPtr);
}
public void resize(int width, int height, float ratio, int fbWidth,
int fbHeight) {
public void resizeView(int width, int height) {
if (width < 0) {
throw new IllegalArgumentException("width cannot be negative.");
}
@@ -100,6 +99,19 @@ class NativeMapView {
throw new IllegalArgumentException("height cannot be negative.");
}
if (width > 65535) {
throw new IllegalArgumentException(
"width cannot be greater than 65535.");
}
if (height > 65535) {
throw new IllegalArgumentException(
"height cannot be greater than 65535.");
}
nativeViewResize(mNativeMapViewPtr, width, height);
}
public void resizeFramebuffer(int fbWidth, int fbHeight) {
if (fbWidth < 0) {
throw new IllegalArgumentException("fbWidth cannot be negative.");
}
@@ -117,7 +129,7 @@ class NativeMapView {
throw new IllegalArgumentException(
"fbHeight cannot be greater than 65535.");
}
nativeResize(mNativeMapViewPtr, width, height, ratio, fbWidth, fbHeight);
nativeFramebufferResize(mNativeMapViewPtr, fbWidth, fbHeight);
}
public void addClass(String clazz) {
@@ -370,7 +382,7 @@ class NativeMapView {
super.finalize();
}
private native long nativeCreate(String cachePath, String dataPath, String apkPath);
private native long nativeCreate(String cachePath, String dataPath, String apkPath, float pixelRatio);
private native void nativeDestroy(long nativeMapViewPtr);
@@ -395,8 +407,9 @@ class NativeMapView {
private native void nativeOnInvalidate(long nativeMapViewPtr);
private native void nativeResize(long nativeMapViewPtr, int width,
int height, float ratio, int fbWidth, int fbHeight);
private native void nativeViewResize(long nativeMapViewPtr, int width, int height);
private native void nativeFramebufferResize(long nativeMapViewPtr, int fbWidth, int fbHeight);
private native void nativeAddClass(long nativeMapViewPtr, String clazz);

View File

@@ -85,13 +85,12 @@ int main(int argc, char *argv[]) {
fileSource.setAccessToken(std::string(token));
}
HeadlessView view;
HeadlessView view(pixelRatio, width, height);
Map map(view, fileSource, MapMode::Still);
map.setStyleJSON(style, ".");
map.setClasses(classes);
map.resize(width, height, pixelRatio);
map.setLatLngZoom({ lat, lon }, zoom);
map.setBearing(bearing);

View File

@@ -17,9 +17,12 @@ namespace android {
class NativeMapView : public mbgl::View, private mbgl::util::noncopyable {
public:
NativeMapView(JNIEnv *env, jobject obj);
NativeMapView(JNIEnv *env, jobject obj, float pixelRatio);
virtual ~NativeMapView();
float getPixelRatio() const override;
std::array<uint16_t, 2> getSize() const override;
std::array<uint16_t, 2> getFramebufferSize() const override;
void activate() override;
void deactivate() override;
void notify() override;
@@ -48,6 +51,9 @@ public:
void onInvalidate();
void resizeView(int width, int height);
void resizeFramebuffer(int width, int height);
private:
EGLConfig chooseConfig(const EGLConfig configs[], EGLint numConfigs);
@@ -73,6 +79,12 @@ private:
bool fpsEnabled = false;
double fps = 0.0;
int width = 0;
int height = 0;
int fbWidth = 0;
int fbHeight = 0;
const float pixelRatio;
// Ensure these are initialised last
mbgl::SQLiteCache fileCache;
mbgl::DefaultFileSource fileSource;

View File

@@ -113,7 +113,6 @@ public:
void resetNorth();
// Size
void resize(uint16_t width, uint16_t height, float ratio = 1);
uint16_t getWidth() const;
uint16_t getHeight() const;

View File

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

View File

@@ -30,6 +30,21 @@ enum MapChange : uint8_t {
class View {
public:
// Called from the main thread directly after initialization. Must always return the same value,
// i.e. it may not change over time.
virtual float getPixelRatio() const = 0;
// Called from the main thread when the View signaled a dimension change. Must return the
// logical dimension of this map in pixels.
virtual std::array<uint16_t, 2> getSize() const = 0;
// Called from the main thread for every frame that is being rendered. Must return the absolute
// dimensions of the current framebuffer. Typically, this is the logical width scaled by the
// pixel ratio, but in case the view was moved to display with a different pixel ratio, it can
// also be different from that rule.
virtual std::array<uint16_t, 2> getFramebufferSize() const = 0;
// Called from the main thread when this View is associated with a Map object.
virtual void initialize(Map *map_);
// Called from the render thread. Makes the GL context active in the current
@@ -43,9 +58,6 @@ public:
virtual void notify() = 0;
// Called from the render thread. The implementation should resize the framebuffer.
virtual void resize(uint16_t width, uint16_t height, float pixelRatio);
// Called from the render thread. The implementation must trigger a rerender.
// (map->renderSync() from the main thread must be called as a result of this)
virtual void invalidate() = 0;

View File

@@ -15,6 +15,10 @@ public:
GLFWView(bool fullscreen = false);
~GLFWView();
float getPixelRatio() const override;
std::array<uint16_t, 2> getSize() const override;
std::array<uint16_t, 2> getFramebufferSize() const override;
void initialize(mbgl::Map *map) override;
void activate() override;
void deactivate() override;
@@ -24,7 +28,8 @@ public:
static void onKey(GLFWwindow *window, int key, int scancode, int action, int mods);
static void onScroll(GLFWwindow *window, double xoffset, double yoffset);
static void onResize(GLFWwindow *window, int width, int height);
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);
@@ -57,6 +62,9 @@ private:
int width = 1024;
int height = 768;
int fbWidth;
int fbHeight;
float pixelRatio;
double lastX = 0, lastY = 0;

View File

@@ -25,18 +25,23 @@ class HeadlessDisplay;
class HeadlessView : public View {
public:
HeadlessView(uint16_t width = 256, uint16_t height = 256, float pixelRatio = 1);
HeadlessView(std::shared_ptr<HeadlessDisplay> display, uint16_t width = 256, uint16_t height = 256, float pixelRatio = 1);
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 getPixelRatio() const override;
std::array<uint16_t, 2> getSize() const override;
std::array<uint16_t, 2> getFramebufferSize() const override;
void activate() override;
void deactivate() override;
void notify() override;
void resize(uint16_t width, uint16_t height, float pixelRatio) override;
void invalidate() override;
void swap() override;
std::unique_ptr<StillImage> readStillImage() override;
void resize(uint16_t width, uint16_t height);
private:
void createContext();
void loadExtensions();
@@ -45,18 +50,8 @@ private:
private:
std::shared_ptr<HeadlessDisplay> display;
struct Dimensions {
inline Dimensions(uint16_t width = 0, uint16_t height = 0, float pixelRatio = 0);
inline uint16_t pixelWidth() const { return width * pixelRatio; }
inline uint16_t pixelHeight() const { return height * pixelRatio; }
uint16_t width = 0;
uint16_t height = 0;
float pixelRatio = 0;
};
Dimensions dimensions;
const float pixelRatio;
std::array<uint16_t, 2> dimensions;
#if MBGL_USE_CGL
CGLContextObj glContext = nullptr;

View File

@@ -58,13 +58,17 @@ GLFWView::GLFWView(bool fullscreen_) : fullscreen(fullscreen_) {
glfwSetCursorPosCallback(window, onMouseMove);
glfwSetMouseButtonCallback(window, onMouseClick);
glfwSetWindowSizeCallback(window, onResize);
glfwSetFramebufferSizeCallback(window, onResize);
glfwSetWindowSizeCallback(window, onWindowResize);
glfwSetFramebufferSizeCallback(window, onFramebufferResize);
glfwSetScrollCallback(window, onScroll);
glfwSetKeyCallback(window, onKey);
mbgl::gl::InitializeExtensions(glfwGetProcAddress);
glfwGetWindowSize(window, &width, &height);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
pixelRatio = static_cast<float>(fbWidth) / width;
glfwMakeContextCurrent(nullptr);
}
@@ -75,9 +79,6 @@ GLFWView::~GLFWView() {
void GLFWView::initialize(mbgl::Map *map_) {
View::initialize(map_);
glfwGetWindowSize(window, &width, &height);
onResize(window, width, height);
}
void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, int mods) {
@@ -226,15 +227,20 @@ void GLFWView::onScroll(GLFWwindow *window, double /*xOffset*/, double yOffset)
view->map->scaleBy(scale, view->lastX, view->lastY);
}
void GLFWView::onResize(GLFWwindow *window, int width, int height ) {
void GLFWView::onWindowResize(GLFWwindow *window, int width, int height) {
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
view->width = width;
view->height = height;
int fbWidth, fbHeight;
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
view->map->update(mbgl::Update::Dimensions);
}
view->map->resize(width, height, static_cast<float>(fbWidth) / static_cast<float>(width));
void GLFWView::onFramebufferResize(GLFWwindow *window, int width, int height) {
GLFWView *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
view->fbWidth = width;
view->fbHeight = height;
view->map->update();
}
void GLFWView::onMouseClick(GLFWwindow *window, int button, int action, int modifiers) {
@@ -287,6 +293,18 @@ void GLFWView::run() {
}
}
float GLFWView::getPixelRatio() const {
return pixelRatio;
}
std::array<uint16_t, 2> GLFWView::getSize() const {
return {{ static_cast<uint16_t>(width), static_cast<uint16_t>(height) }};
}
std::array<uint16_t, 2> GLFWView::getFramebufferSize() const {
return {{ static_cast<uint16_t>(fbWidth), static_cast<uint16_t>(fbHeight) }};
}
void GLFWView::activate() {
glfwMakeContextCurrent(window);
}

View File

@@ -20,21 +20,17 @@
namespace mbgl {
HeadlessView::HeadlessView(uint16_t width, uint16_t height, float pixelRatio)
: display(std::make_shared<HeadlessDisplay>()) {
activate();
resize(width, height, pixelRatio);
deactivate();
HeadlessView::HeadlessView(float pixelRatio_, uint16_t width, uint16_t height)
: display(std::make_shared<HeadlessDisplay>()), pixelRatio(pixelRatio_) {
resize(width, height);
}
HeadlessView::HeadlessView(std::shared_ptr<HeadlessDisplay> display_,
float pixelRatio_,
uint16_t width,
uint16_t height,
float pixelRatio)
: display(display_) {
activate();
resize(width, height, pixelRatio);
deactivate();
uint16_t height)
: display(display_), pixelRatio(pixelRatio_) {
resize(width, height);
}
void HeadlessView::loadExtensions() {
@@ -118,17 +114,15 @@ bool HeadlessView::isActive() {
return std::this_thread::get_id() == thread;
}
HeadlessView::Dimensions::Dimensions(uint16_t width_, uint16_t height_, float pixelRatio_)
: width(width_), height(height_), pixelRatio(pixelRatio_) {
}
void HeadlessView::resize(const uint16_t width, const uint16_t height) {
activate();
void HeadlessView::resize(const uint16_t width, const uint16_t height, const float pixelRatio) {
dimensions = { width, height, pixelRatio };
dimensions = {{ width, height }};
clearBuffers();
const unsigned int w = dimensions.width * dimensions.pixelRatio;
const unsigned int h = dimensions.height * dimensions.pixelRatio;
const unsigned int w = dimensions[0] * pixelRatio;
const unsigned int h = dimensions[1] * pixelRatio;
// Create depth/stencil buffer
MBGL_CHECK_ERROR(glGenRenderbuffersEXT(1, &fboDepthStencil));
@@ -150,26 +144,28 @@ void HeadlessView::resize(const uint16_t width, const uint16_t height, const flo
GLenum status = MBGL_CHECK_ERROR(glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
if (status != GL_FRAMEBUFFER_COMPLETE_EXT) {
std::stringstream error("Couldn't create framebuffer: ");
std::string error("Couldn't create framebuffer: ");
switch (status) {
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: (error << "incomplete attachment.\n"); break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: error << "incomplete missing attachment.\n"; break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: error << "incomplete dimensions.\n"; break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: error << "incomplete formats.\n"; break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: error << "incomplete draw buffer.\n"; break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: error << "incomplete read buffer.\n"; break;
case GL_FRAMEBUFFER_UNSUPPORTED: error << "unsupported.\n"; break;
default: error << "other\n"; break;
case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT: (error += "incomplete attachment"); break;
case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT: error += "incomplete missing attachment"; break;
case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT: error += "incomplete dimensions"; break;
case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT: error += "incomplete formats"; break;
case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT: error += "incomplete draw buffer"; break;
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT: error += "incomplete read buffer"; break;
case GL_FRAMEBUFFER_UNSUPPORTED: error += "unsupported"; break;
default: error += "other"; break;
}
throw std::runtime_error(error.str());
throw std::runtime_error(error);
}
deactivate();
}
std::unique_ptr<StillImage> HeadlessView::readStillImage() {
assert(isActive());
const unsigned int w = dimensions.pixelWidth();
const unsigned int h = dimensions.pixelHeight();
const unsigned int w = dimensions[0] * pixelRatio;
const unsigned int h = dimensions[1] * pixelRatio;
auto image = std::make_unique<StillImage>();
image->width = w;
@@ -234,6 +230,19 @@ void HeadlessView::notify() {
// no-op
}
float HeadlessView::getPixelRatio() const {
return pixelRatio;
}
std::array<uint16_t, 2> HeadlessView::getSize() const {
return dimensions;
}
std::array<uint16_t, 2> HeadlessView::getFramebufferSize() const {
return {{ static_cast<uint16_t>(dimensions[0] * pixelRatio),
static_cast<uint16_t>(dimensions[1] * pixelRatio) }};
}
void HeadlessView::activate() {
if (thread != std::thread::id()) {
throw std::runtime_error("OpenGL context was already current");

View File

@@ -218,9 +218,9 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
_glView.enableSetNeedsDisplay = YES;
_glView.drawableStencilFormat = GLKViewDrawableStencilFormat8;
_glView.drawableDepthFormat = GLKViewDrawableDepthFormat16;
if ([UIScreen instancesRespondToSelector:@selector(nativeScale)]) {
_glView.contentScaleFactor = [[UIScreen mainScreen] nativeScale];
}
const float scaleFactor = [UIScreen instancesRespondToSelector:@selector(nativeScale)] ? [[UIScreen mainScreen] nativeScale] : [[UIScreen mainScreen] scale];
_glView.contentScaleFactor = scaleFactor;
_glView.delegate = self;
[_glView bindDrawable];
[self insertSubview:_glView atIndex:0];
@@ -247,7 +247,7 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
// setup mbgl map
//
_mbglView = new MBGLView(self);
_mbglView = new MBGLView(self, scaleFactor);
_mbglFileSource = new mbgl::DefaultFileSource([MGLFileCache obtainSharedCacheWithObject:self]);
// Start paused on the IB canvas
@@ -255,7 +255,6 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
if (_isTargetingInterfaceBuilder) {
_mbglMap->pause();
}
_mbglMap->resize(self.bounds.size.width, self.bounds.size.height, _glView.contentScaleFactor);
// Observe for changes to the global access token (and find out the current one).
[[MGLAccountManager sharedManager] addObserver:self
@@ -666,12 +665,10 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
}
// This is the delegate of the GLKView object's display call.
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
- (void)glkView:(__unused GLKView *)view drawInRect:(__unused CGRect)rect
{
if ( ! self.isDormant)
{
_mbglMap->resize(rect.size.width, rect.size.height, view.contentScaleFactor);
CGFloat zoomFactor = _mbglMap->getMaxZoom() - _mbglMap->getMinZoom() + 1;
CGFloat cpuFactor = (CGFloat)[[NSProcessInfo processInfo] processorCount];
CGFloat memoryFactor = (CGFloat)[[NSProcessInfo processInfo] physicalMemory] / 1000 / 1000 / 1000;
@@ -693,7 +690,7 @@ std::chrono::steady_clock::duration secondsAsDuration(float duration)
if ( ! _isTargetingInterfaceBuilder)
{
_mbglMap->update();
_mbglMap->update(mbgl::Update::Dimensions);
}
if (self.attributionSheet.visible)
@@ -2449,6 +2446,11 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng)
- (void)notifyMapChange:(mbgl::MapChange)change
{
// Ignore map updates when the Map object isn't set.
if (!_mbglMap) {
return;
}
switch (change)
{
case mbgl::MapChangeRegionWillChange:
@@ -2778,10 +2780,26 @@ CLLocationCoordinate2D MGLLocationCoordinate2DFromLatLng(mbgl::LatLng latLng)
class MBGLView : public mbgl::View
{
public:
MBGLView(MGLMapView *nativeView_) : nativeView(nativeView_) {}
MBGLView(MGLMapView* nativeView_, const float scaleFactor_)
: nativeView(nativeView_), scaleFactor(scaleFactor_) {
}
virtual ~MBGLView() {}
float getPixelRatio() const override {
return scaleFactor;
}
std::array<uint16_t, 2> getSize() const override {
return {{ static_cast<uint16_t>([nativeView bounds].size.width),
static_cast<uint16_t>([nativeView bounds].size.height) }};
}
std::array<uint16_t, 2> getFramebufferSize() const override {
return {{ static_cast<uint16_t>([[nativeView glView] drawableWidth]),
static_cast<uint16_t>([[nativeView glView] drawableHeight]) }};
}
void notify() override
{
// no-op
@@ -2817,6 +2835,7 @@ class MBGLView : public mbgl::View
private:
__weak MGLMapView *nativeView = nullptr;
const float scaleFactor;
};
@end

View File

@@ -15,10 +15,11 @@ namespace mbgl {
Map::Map(View& view_, FileSource& fileSource, MapMode mode)
: view(view_),
transform(std::make_unique<Transform>(view)),
data(std::make_unique<MapData>(mode)),
data(std::make_unique<MapData>(mode, view.getPixelRatio())),
context(std::make_unique<util::Thread<MapContext>>(util::ThreadContext{"Map", util::ThreadType::Map, util::ThreadPriority::Regular}, view, fileSource, *data))
{
view.initialize(this);
update(Update::Dimensions);
}
Map::~Map() {
@@ -43,7 +44,8 @@ void Map::resume() {
}
void Map::renderStill(StillImageCallback callback) {
context->invoke(&MapContext::renderStill, transform->getState(), callback);
context->invoke(&MapContext::renderStill, transform->getState(),
FrameData{ view.getFramebufferSize() }, callback);
}
void Map::renderSync() {
@@ -53,8 +55,8 @@ void Map::renderSync() {
view.notifyMapChange(MapChangeWillStartRenderingFrame);
MapContext::RenderResult result =
context->invokeSync<MapContext::RenderResult>(&MapContext::renderSync, transform->getState());
MapContext::RenderResult result = context->invokeSync<MapContext::RenderResult>(
&MapContext::renderSync, transform->getState(), FrameData{ view.getFramebufferSize() });
view.notifyMapChange(result.fullyLoaded ?
MapChangeDidFinishRenderingFrameFullyRendered :
@@ -75,6 +77,10 @@ void Map::renderSync() {
}
void Map::update(Update update_) {
if (update_ == Update::Dimensions) {
transform->resize(view.getSize());
}
context->invoke(&MapContext::triggerUpdate, transform->getState(), update_);
}
@@ -96,15 +102,6 @@ std::string Map::getStyleJSON() const {
return context->invokeSync<std::string>(&MapContext::getStyleJSON);
}
#pragma mark - Size
void Map::resize(uint16_t width, uint16_t height, float ratio) {
if (transform->resize(width, height, ratio, width * ratio, height * ratio)) {
context->invoke(&MapContext::resize, width, height, ratio);
update();
}
}
#pragma mark - Transitions
void Map::cancelTransitions() {
@@ -185,7 +182,7 @@ void Map::fitBounds(AnnotationSegment segment, EdgeInsets padding, Duration dura
if (segment.empty()) {
return;
}
// Calculate the bounds of the possibly rotated shape with respect to the viewport.
vec2<> nePixel = {-INFINITY, -INFINITY};
vec2<> swPixel = {INFINITY, INFINITY};

View File

@@ -79,10 +79,6 @@ void MapContext::pause() {
view.activate();
}
void MapContext::resize(uint16_t width, uint16_t height, float ratio) {
view.resize(width, height, ratio);
}
void MapContext::triggerUpdate(const TransformState& state, const Update u) {
transformState = state;
updated |= static_cast<UpdateType>(u);
@@ -266,14 +262,14 @@ void MapContext::update() {
if (data.mode == MapMode::Continuous) {
view.invalidate();
} else if (callback && style->isLoaded()) {
renderSync(transformState);
renderSync(transformState, frameData);
}
}
updated = static_cast<UpdateType>(Update::Nothing);
}
void MapContext::renderStill(const TransformState& state, StillImageCallback fn) {
void MapContext::renderStill(const TransformState& state, const FrameData& frame, StillImageCallback fn) {
if (!fn) {
Log::Error(Event::General, "StillImageCallback not set");
return;
@@ -301,12 +297,13 @@ void MapContext::renderStill(const TransformState& state, StillImageCallback fn)
callback = fn;
transformState = state;
frameData = frame;
updated |= static_cast<UpdateType>(Update::RenderStill);
asyncUpdate->send();
}
MapContext::RenderResult MapContext::renderSync(const TransformState& state) {
MapContext::RenderResult MapContext::renderSync(const TransformState& state, const FrameData& frame) {
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
// Style was not loaded yet.
@@ -320,12 +317,12 @@ MapContext::RenderResult MapContext::renderSync(const TransformState& state) {
glObjectStore.performCleanup();
if (!painter) {
painter = std::make_unique<Painter>();
painter = std::make_unique<Painter>(data.pixelRatio);
painter->setup();
}
painter->setDebug(data.getDebug());
painter->render(*style, transformState, data.getAnimationTime());
painter->render(*style, transformState, frame, data.getAnimationTime());
if (data.mode == MapMode::Still) {
callback(nullptr, view.readStillImage());

View File

@@ -26,6 +26,11 @@ class StillImage;
struct LatLng;
struct LatLngBounds;
struct FrameData {
std::array<uint16_t, 2> framebufferSize;
};
class MapContext : public Style::Observer {
public:
MapContext(View&, FileSource&, MapData&);
@@ -38,13 +43,11 @@ public:
void pause();
void resize(uint16_t width, uint16_t height, float ratio);
using StillImageCallback = std::function<void(std::exception_ptr, std::unique_ptr<const StillImage>)>;
void triggerUpdate(const TransformState&, Update = Update::Nothing);
void renderStill(const TransformState&, StillImageCallback callback);
RenderResult renderSync(const TransformState&);
void renderStill(const TransformState&, const FrameData&, StillImageCallback callback);
RenderResult renderSync(const TransformState&, const FrameData&);
void setStyleURL(const std::string&);
void setStyleJSON(const std::string& json, const std::string& base);
@@ -95,6 +98,7 @@ private:
StillImageCallback callback;
size_t sourceCacheSize;
TransformState transformState;
FrameData frameData;
};
}

View File

@@ -20,7 +20,8 @@ class MapData {
using Lock = std::lock_guard<std::mutex>;
public:
inline MapData(MapMode mode_) : mode(mode_) {
inline MapData(MapMode mode_, const float pixelRatio_) : mode(mode_), pixelRatio(pixelRatio_) {
assert(pixelRatio > 0);
setAnimationTime(TimePoint::min());
setDefaultTransitionDuration(Duration::zero());
}
@@ -77,7 +78,7 @@ public:
}
inline void setDefaultTransitionDuration(Duration duration) {
defaultTransitionDuration = duration;
};
}
util::exclusive<AnnotationManager> getAnnotationManager() {
return util::exclusive<AnnotationManager>(
@@ -87,6 +88,7 @@ public:
public:
const MapMode mode;
const float pixelRatio;
private:
mutable std::mutex annotationManagerMutex;

View File

@@ -292,11 +292,11 @@ TileData::State Source::addTile(MapData& data,
if (info.type == SourceType::Vector) {
auto tileData = std::make_shared<VectorTileData>(normalized_id, style, info,
transformState.getAngle(), data.getCollisionDebug());
tileData->request(transformState.getPixelRatio(), callback);
tileData->request(data.pixelRatio, callback);
new_tile.data = tileData;
} else if (info.type == SourceType::Raster) {
auto tileData = std::make_shared<RasterTileData>(normalized_id, texturePool, info, style.workers);
tileData->request(transformState.getPixelRatio(), callback);
tileData->request(data.pixelRatio, callback);
new_tile.data = tileData;
} else if (info.type == SourceType::Annotations) {
new_tile.data = std::make_shared<LiveTileData>(normalized_id,

View File

@@ -34,18 +34,13 @@ Transform::Transform(View &view_)
#pragma mark - Map View
bool Transform::resize(const uint16_t w, const uint16_t h, const float ratio,
const uint16_t fb_w, const uint16_t fb_h) {
if (state.width != w || state.height != h || state.pixelRatio != ratio ||
state.framebuffer[0] != fb_w || state.framebuffer[1] != fb_h) {
bool Transform::resize(const std::array<uint16_t, 2> size) {
if (state.width != size[0] || state.height != size[1]) {
view.notifyMapChange(MapChangeRegionWillChange);
state.width = w;
state.height = h;
state.pixelRatio = ratio;
state.framebuffer[0] = fb_w;
state.framebuffer[1] = fb_h;
state.width = size[0];
state.height = size[1];
state.constrain(state.scale, state.y);
view.notifyMapChange(MapChangeRegionDidChange);

View File

@@ -20,9 +20,7 @@ public:
Transform(View&);
// Map view
// Note: width * ratio does not necessarily equal fb_width
bool resize(uint16_t width, uint16_t height, float ratio,
uint16_t fb_width, uint16_t fb_height);
bool resize(std::array<uint16_t, 2> size);
// Position
void moveBy(double dx, double dy, Duration = Duration::zero());

View File

@@ -74,23 +74,6 @@ uint16_t TransformState::getHeight() const {
return height;
}
uint16_t TransformState::getFramebufferWidth() const {
return framebuffer[0];
}
uint16_t TransformState::getFramebufferHeight() const {
return framebuffer[1];
}
const std::array<uint16_t, 2> TransformState::getFramebufferDimensions() const {
return framebuffer;
}
float TransformState::getPixelRatio() const {
return pixelRatio;
}
#pragma mark - Position
const LatLng TransformState::getLatLng() const {

View File

@@ -27,10 +27,6 @@ public:
bool hasSize() const;
uint16_t getWidth() const;
uint16_t getHeight() const;
uint16_t getFramebufferWidth() const;
uint16_t getFramebufferHeight() const;
const std::array<uint16_t, 2> getFramebufferDimensions() const;
float getPixelRatio() const;
float worldSize() const;
float lngX(float lon) const;
@@ -73,12 +69,7 @@ private:
// logical dimensions
uint16_t width = 0, height = 0;
// physical (framebuffer) dimensions
std::array<uint16_t, 2> framebuffer = {{ 0, 0 }};
// map scale factor
float pixelRatio = 0;
private:
// animation state
bool rotating = false;
bool scaling = false;

View File

@@ -11,10 +11,6 @@ void View::initialize(Map *map_) {
map = map_;
}
void View::resize(uint16_t, uint16_t, float) {
// no-op
}
std::unique_ptr<StillImage> View::readStillImage() {
return nullptr;
}

View File

@@ -2,6 +2,7 @@
#include <mbgl/map/source.hpp>
#include <mbgl/map/tile.hpp>
#include <mbgl/map/map_context.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/gl/debugging.hpp>
@@ -40,7 +41,7 @@
using namespace mbgl;
Painter::Painter() {
Painter::Painter(const float pixelRatio_) : pixelRatio(pixelRatio_) {
}
Painter::~Painter() {
@@ -104,8 +105,8 @@ void Painter::setupShaders() {
}
void Painter::resize() {
if (gl_viewport != state.getFramebufferDimensions()) {
gl_viewport = state.getFramebufferDimensions();
if (gl_viewport != frame.framebufferSize) {
gl_viewport = frame.framebufferSize;
assert(gl_viewport[0] > 0 && gl_viewport[1] > 0);
MBGL_CHECK_ERROR(glViewport(0, 0, gl_viewport[0], gl_viewport[1]));
}
@@ -164,8 +165,9 @@ void Painter::prepareTile(const Tile& tile) {
config.stencilFunc = { GL_EQUAL, ref, mask };
}
void Painter::render(const Style& style, TransformState state_, TimePoint time) {
void Painter::render(const Style& style, TransformState state_, const FrameData& frame_, TimePoint time) {
state = state_;
frame = frame_;
glyphAtlas = style.glyphAtlas.get();
spriteAtlas = style.spriteAtlas.get();

View File

@@ -2,6 +2,7 @@
#define MBGL_RENDERER_PAINTER
#include <mbgl/map/transform_state.hpp>
#include <mbgl/map/map_context.hpp>
#include <mbgl/renderer/frame_history.hpp>
#include <mbgl/renderer/bucket.hpp>
@@ -31,6 +32,7 @@ class SpriteAtlas;
class GlyphAtlas;
class LineAtlas;
class Source;
struct FrameData;
class DebugBucket;
@@ -79,7 +81,7 @@ struct RenderItem {
class Painter : private util::noncopyable {
public:
Painter();
Painter(float pixelRatio);
~Painter();
void setup();
@@ -93,6 +95,7 @@ public:
void render(const Style& style,
TransformState state,
const FrameData& frame,
TimePoint time);
// Renders debug information for a tile.
@@ -118,6 +121,7 @@ public:
void createPrerendered(RasterBucket& bucket, const StyleLayer &layer_desc, const TileID& id);
// Adjusts the dimensions of the OpenGL viewport
void resize();
// Changes whether debug information is drawn onto the map
@@ -187,7 +191,10 @@ public:
}();
private:
const float pixelRatio;
TransformState state;
FrameData frame;
bool debug = false;
int indent = 0;

View File

@@ -28,7 +28,7 @@ void Painter::renderDebugText(DebugBucket& bucket, const mat4 &matrix) {
// Draw white outline
plainShader->u_color = {{ 1.0f, 1.0f, 1.0f, 1.0f }};
lineWidth(4.0f * state.getPixelRatio());
lineWidth(4.0f * pixelRatio);
bucket.drawLines(*plainShader);
#ifndef GL_ES_VERSION_2_0
@@ -39,7 +39,7 @@ void Painter::renderDebugText(DebugBucket& bucket, const mat4 &matrix) {
// Draw black text.
plainShader->u_color = {{ 0.0f, 0.0f, 0.0f, 1.0f }};
lineWidth(2.0f * state.getPixelRatio());
lineWidth(2.0f * pixelRatio);
bucket.drawLines(*plainShader);
config.depthTest = true;
@@ -60,6 +60,6 @@ void Painter::renderDebugFrame(const mat4 &matrix) {
// draw tile outline
tileBorderArray.bind(*plainShader, tileBorderBuffer, BUFFER_OFFSET(0));
plainShader->u_color = {{ 1.0f, 0.0f, 0.0f, 1.0f }};
lineWidth(4.0f * state.getPixelRatio());
lineWidth(4.0f * pixelRatio);
MBGL_CHECK_ERROR(glDrawArrays(GL_LINE_STRIP, 0, (GLsizei)tileBorderBuffer.index()));
}

View File

@@ -52,8 +52,8 @@ void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const
// Draw the entire line
outlineShader->u_world = {{
static_cast<float>(state.getFramebufferWidth()),
static_cast<float>(state.getFramebufferHeight())
static_cast<float>(frame.framebufferSize[0]),
static_cast<float>(frame.framebufferSize[1])
}};
config.depthRange = { strata, 1.0f };
bucket.drawVertices(*outlineShader);
@@ -128,8 +128,8 @@ void Painter::renderFill(FillBucket& bucket, const StyleLayer &layer_desc, const
// Draw the entire line
outlineShader->u_world = {{
static_cast<float>(state.getFramebufferWidth()),
static_cast<float>(state.getFramebufferHeight())
static_cast<float>(frame.framebufferSize[0]),
static_cast<float>(frame.framebufferSize[1])
}};
config.depthRange = { strata + strata_epsilon + strata_epsilon, 1.0f };

View File

@@ -26,7 +26,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const
// the distance over which the line edge fades out.
// Retina devices need a smaller distance to avoid aliasing.
float antialiasing = 1 / state.getPixelRatio();
float antialiasing = 1.0 / pixelRatio;
float blur = properties.blur + antialiasing;
float edgeWidth = properties.width / 2.0;
@@ -50,7 +50,6 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const
color[2] *= properties.opacity;
color[3] *= properties.opacity;
float ratio = state.getPixelRatio();
mat4 vtxMatrix = translatedMatrix(matrix, properties.translate, id, properties.translateAnchor);
config.depthRange = { strata, 1.0f };
@@ -62,7 +61,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const
linesdfShader->u_matrix = vtxMatrix;
linesdfShader->u_exmatrix = extrudeMatrix;
linesdfShader->u_linewidth = {{ outset, inset }};
linesdfShader->u_ratio = ratio;
linesdfShader->u_ratio = pixelRatio;
linesdfShader->u_blur = blur;
linesdfShader->u_color = color;
@@ -81,7 +80,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const
linesdfShader->u_patternscale_b = {{ scaleXB, scaleYB }};
linesdfShader->u_tex_y_b = posB.y;
linesdfShader->u_image = 0;
linesdfShader->u_sdfgamma = lineAtlas->width / (properties.dash_line_width * std::min(posA.width, posB.width) * 256.0 * state.getPixelRatio()) / 2;
linesdfShader->u_sdfgamma = lineAtlas->width / (properties.dash_line_width * std::min(posA.width, posB.width) * 256.0 * pixelRatio) / 2;
linesdfShader->u_mix = properties.dash_array.t;
bucket.drawLineSDF(*linesdfShader);
@@ -97,7 +96,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const
linepatternShader->u_matrix = vtxMatrix;
linepatternShader->u_exmatrix = extrudeMatrix;
linepatternShader->u_linewidth = {{ outset, inset }};
linepatternShader->u_ratio = ratio;
linepatternShader->u_ratio = pixelRatio;
linepatternShader->u_blur = blur;
linepatternShader->u_pattern_size_a = {{imagePosA.size[0] * factor * properties.image.fromScale, imagePosA.size[1]}};
@@ -121,7 +120,7 @@ void Painter::renderLine(LineBucket& bucket, const StyleLayer &layer_desc, const
lineShader->u_matrix = vtxMatrix;
lineShader->u_exmatrix = extrudeMatrix;
lineShader->u_linewidth = {{ outset, inset }};
lineShader->u_ratio = ratio;
lineShader->u_ratio = pixelRatio;
lineShader->u_blur = blur;
lineShader->u_color = color;

View File

@@ -60,7 +60,7 @@ void Painter::renderSDF(SymbolBucket &bucket,
// The default gamma value has to be adjust for the current pixelratio so that we're not
// drawing blurry font on retina screens.
const float gamma = 0.105 * sdfFontSize / fontSize / state.getPixelRatio();
const float gamma = 0.105 * sdfFontSize / fontSize / pixelRatio;
const float sdfPx = 8.0f;
const float blurOffset = 1.19f;

View File

@@ -1,5 +1,6 @@
#include <mbgl/style/style.hpp>
#include <mbgl/map/sprite.hpp>
#include <mbgl/map/map_data.hpp>
#include <mbgl/map/source.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/style/style_layer.hpp>
@@ -67,12 +68,11 @@ Style::~Style() {
void Style::update(MapData& data,
const TransformState& transform,
TexturePool& texturePool) {
const float pixelRatio = transform.getPixelRatio();
if (!sprite || !sprite->hasPixelRatio(pixelRatio)) {
sprite = std::make_unique<Sprite>(spriteURL, pixelRatio);
if (!sprite || !sprite->hasPixelRatio(data.pixelRatio)) {
sprite = std::make_unique<Sprite>(spriteURL, data.pixelRatio);
sprite->setObserver(this);
spriteAtlas->resize(pixelRatio);
spriteAtlas->resize(data.pixelRatio);
spriteAtlas->setSprite(sprite);
}

View File

@@ -17,11 +17,11 @@ TEST(API, RenderWithoutCallback) {
Log::setObserver(std::unique_ptr<Log::Observer>(log));
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display);
HeadlessView view(display, 1);
view.resize(128, 512);
DefaultFileSource fileSource(nullptr);
std::unique_ptr<Map> map = std::make_unique<Map>(view, fileSource, MapMode::Still);
map->resize(128, 512, 1);
map->renderStill(nullptr);
// Force Map thread to join.
@@ -39,11 +39,11 @@ TEST(API, RenderWithoutCallback) {
TEST(API, RenderWithoutStyle) {
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display);
HeadlessView view(display, 1);
view.resize(128, 512);
DefaultFileSource fileSource(nullptr);
Map map(view, fileSource, MapMode::Still);
map.resize(128, 512, 1);
std::promise<std::exception_ptr> promise;
map.renderStill([&promise](std::exception_ptr error, std::unique_ptr<const StillImage>) {

View File

@@ -17,7 +17,7 @@ TEST(API, RepeatedRender) {
const auto style = util::read_file("test/fixtures/api/water.json");
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display);
HeadlessView view(display, 1, 256, 512);
DefaultFileSource fileSource(nullptr);
Log::setObserver(std::make_unique<FixtureLogObserver>());
@@ -25,29 +25,27 @@ TEST(API, RepeatedRender) {
Map map(view, fileSource, MapMode::Still);
{
map.resize(128, 512, 1);
map.setStyleJSON(style, "test/suite");
std::promise<std::unique_ptr<const StillImage>> promise;
map.renderStill([&promise](std::exception_ptr, std::unique_ptr<const StillImage> image) {
promise.set_value(std::move(image));
});
auto result = promise.get_future().get();
ASSERT_EQ(128, result->width);
ASSERT_EQ(256, result->width);
ASSERT_EQ(512, result->height);
const std::string png = util::compress_png(result->width, result->height, result->pixels.get());
util::write_file("test/fixtures/api/1.png", png);
}
{
map.resize(512, 512, 2);
map.setStyleJSON(style, "TEST_DATA/suite");
std::promise<std::unique_ptr<const StillImage>> promise;
map.renderStill([&promise](std::exception_ptr, std::unique_ptr<const StillImage> image) {
promise.set_value(std::move(image));
});
auto result = promise.get_future().get();
ASSERT_EQ(1024, result->width);
ASSERT_EQ(1024, result->height);
ASSERT_EQ(256, result->width);
ASSERT_EQ(512, result->height);
const std::string png = util::compress_png(result->width, result->height, result->pixels.get());
util::write_file("test/fixtures/api/2.png", png);
}

View File

@@ -11,7 +11,7 @@ TEST(API, SetStyle) {
using namespace mbgl;
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display);
HeadlessView view(display, 1);
DefaultFileSource fileSource(nullptr);
Log::setObserver(std::make_unique<FixtureLogObserver>());

View File

@@ -3,6 +3,8 @@
#include <mbgl/map/view.hpp>
#include <array>
namespace mbgl {
class MockView : public View {
@@ -10,6 +12,10 @@ public:
MockView() = default;
// View implementation.
float getPixelRatio() const { return 1; }
std::array<uint16_t, 2> getSize() const { return {{ 0, 0 }}; }
std::array<uint16_t, 2> getFramebufferSize() const { return {{ 0, 0 }}; }
void activate() override {};
void deactivate() override {};
void notify() override {};

View File

@@ -141,11 +141,10 @@ TEST_P(HeadlessTest, render) {
std::promise<void> promise;
HeadlessView view(display, width, height, pixelRatio);
HeadlessView view(display, pixelRatio, width, height);
DefaultFileSource fileSource(nullptr);
Map map(view, fileSource, MapMode::Still);
map.resize(width, height, pixelRatio);
map.setClasses(classes);
map.setStyleJSON(style, "test/suite");
map.setLatLngZoom(mbgl::LatLng(latitude, longitude), zoom);

View File

@@ -11,7 +11,7 @@ TEST(Map, PauseResume) {
using namespace mbgl;
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display);
HeadlessView view(display, 1);
DefaultFileSource fileSource(nullptr);
Map map(view, fileSource, MapMode::Continuous);
@@ -24,7 +24,7 @@ TEST(Map, DoublePause) {
using namespace mbgl;
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display);
HeadlessView view(display, 1);
DefaultFileSource fileSource(nullptr);
Map map(view, fileSource, MapMode::Continuous);
@@ -38,7 +38,7 @@ TEST(Map, ResumeWithoutPause) {
using namespace mbgl;
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display);
HeadlessView view(display, 1);
DefaultFileSource fileSource(nullptr);
Map map(view, fileSource, MapMode::Continuous);
@@ -50,7 +50,7 @@ TEST(Map, DestroyPaused) {
using namespace mbgl;
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display);
HeadlessView view(display, 1);
DefaultFileSource fileSource(nullptr);
Map map(view, fileSource, MapMode::Continuous);

View File

@@ -11,9 +11,9 @@ using namespace mbgl;
TEST(MapContext, DoubleStyleLoad) {
std::shared_ptr<HeadlessDisplay> display = std::make_shared<HeadlessDisplay>();
HeadlessView view(display, 512, 512, 1);
HeadlessView view(display, 1, 512, 512);
DefaultFileSource fileSource(nullptr);
MapData data(MapMode::Continuous);
MapData data(MapMode::Continuous, view.getPixelRatio());
util::Thread<MapContext> context({"Map", util::ThreadType::Map, util::ThreadPriority::Regular}, view, fileSource, data);

View File

@@ -29,7 +29,7 @@ TEST_P(PendingResources, DeleteMapObjectWithPendingRequest) {
util::RunLoop loop(uv_default_loop());
auto display = std::make_shared<mbgl::HeadlessDisplay>();
HeadlessView view(display);
HeadlessView view(display, 1, 1000, 1000);
MockFileSource fileSource(MockFileSource::SuccessWithDelay, GetParam());
std::unique_ptr<Map> map = std::make_unique<Map>(view, fileSource, MapMode::Still);
@@ -43,7 +43,6 @@ TEST_P(PendingResources, DeleteMapObjectWithPendingRequest) {
fileSource.setOnRequestDelayedCallback([&endTest] { endTest.send(); });
const std::string style = util::read_file("test/fixtures/resources/style.json");
map->resize(1000, 1000, 1.0);
map->setStyleJSON(style, ".");
map->renderStill([&endTest](std::exception_ptr, std::unique_ptr<const StillImage>) {

View File

@@ -23,12 +23,12 @@ public:
MockMapContext(View& view,
FileSource& fileSource,
const std::function<void(std::exception_ptr error)>& callback)
: data_(MapMode::Still),
: data_(MapMode::Still, view.getPixelRatio()),
transform_(view),
callback_(callback) {
util::ThreadContext::setFileSource(&fileSource);
transform_.resize(1000, 1000, 1.0, 1000, 1000);
transform_.resize({{ 1000, 1000 }});
transform_.setLatLngZoom({0, 0}, 16);
const std::string style = util::read_file("test/fixtures/resources/style.json");