drive map rendering from main thread
This commit is contained in:
committed by
John Firebaugh
parent
740281cc89
commit
84e2ea886d
@@ -124,12 +124,16 @@ void NativeMapView::deactivate() {
|
||||
}
|
||||
}
|
||||
|
||||
void NativeMapView::invalidate(std::function<void()> render) {
|
||||
void NativeMapView::invalidate() {
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::invalidate");
|
||||
|
||||
// TODO: inform the main thread that it must call map->renderSync();
|
||||
}
|
||||
|
||||
void NativeMapView::swap() {
|
||||
mbgl::Log::Debug(mbgl::Event::Android, "NativeMapView::invalidate");
|
||||
|
||||
if ((display != EGL_NO_DISPLAY) && (surface != EGL_NO_SURFACE)) {
|
||||
render();
|
||||
|
||||
if (!eglSwapBuffers(display, surface)) {
|
||||
mbgl::Log::Error(mbgl::Event::OpenGL, "eglSwapBuffers() returned error %d",
|
||||
eglGetError());
|
||||
|
||||
@@ -23,7 +23,8 @@ public:
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
void notify() override;
|
||||
void invalidate(std::function<void()> render) override;
|
||||
void invalidate() override;
|
||||
void swap() override;
|
||||
|
||||
void notifyMapChange(mbgl::MapChange change, Duration delay = Duration::zero()) override;
|
||||
|
||||
|
||||
@@ -44,9 +44,11 @@ public:
|
||||
virtual void resize(uint16_t width, uint16_t height, float pixelRatio);
|
||||
|
||||
// Called from the render thread. The implementation must trigger a rerender.
|
||||
// (i.e. either the passed render() function for rendering immediately on the map thread,
|
||||
// or map->renderSync() from the main thread must be called as a result of this)
|
||||
virtual void invalidate(std::function<void()> render) = 0;
|
||||
// (map->renderSync() from the main thread must be called as a result of this)
|
||||
virtual void invalidate() = 0;
|
||||
|
||||
// Called from the render thread after the render is complete.
|
||||
virtual void swap() = 0;
|
||||
|
||||
// Reads the pixel data from the current framebuffer. If your View implementation
|
||||
// doesn't support reading from the framebuffer, return a null pointer.
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#endif
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
class GLFWView : public mbgl::View {
|
||||
public:
|
||||
GLFWView(bool fullscreen = false);
|
||||
@@ -17,7 +19,8 @@ public:
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
void notify() override;
|
||||
void invalidate(std::function<void()> render) override;
|
||||
void invalidate() override;
|
||||
void swap() override;
|
||||
|
||||
static void onKey(GLFWwindow *window, int key, int scancode, int action, int mods);
|
||||
static void onScroll(GLFWwindow *window, double xoffset, double yoffset);
|
||||
@@ -62,6 +65,7 @@ private:
|
||||
std::function<void()> changeStyleCallback;
|
||||
|
||||
GLFWwindow *window = nullptr;
|
||||
std::atomic_flag clean = ATOMIC_FLAG_INIT;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -33,7 +33,8 @@ public:
|
||||
void deactivate() override;
|
||||
void notify() override;
|
||||
void resize(uint16_t width, uint16_t height, float pixelRatio) override;
|
||||
void invalidate(std::function<void()> render) override;
|
||||
void invalidate() override;
|
||||
void swap() override;
|
||||
std::unique_ptr<StillImage> readStillImage() override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -282,6 +282,10 @@ void GLFWView::onMouseMove(GLFWwindow *window, double x, double y) {
|
||||
void GLFWView::run() {
|
||||
while (!glfwWindowShouldClose(window)) {
|
||||
glfwWaitEvents();
|
||||
const bool dirty = !clean.test_and_set();
|
||||
if (dirty) {
|
||||
map->renderSync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,8 +301,12 @@ void GLFWView::notify() {
|
||||
glfwPostEmptyEvent();
|
||||
}
|
||||
|
||||
void GLFWView::invalidate(std::function<void()> render) {
|
||||
render();
|
||||
void GLFWView::invalidate() {
|
||||
clean.clear();
|
||||
glfwPostEmptyEvent();
|
||||
}
|
||||
|
||||
void GLFWView::swap() {
|
||||
glfwSwapBuffers(window);
|
||||
fps();
|
||||
}
|
||||
|
||||
@@ -280,8 +280,12 @@ void HeadlessView::deactivate() {
|
||||
#endif
|
||||
}
|
||||
|
||||
void HeadlessView::invalidate(std::function<void()> render) {
|
||||
render();
|
||||
void HeadlessView::invalidate() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
void HeadlessView::swap() {
|
||||
// no-op
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2755,13 +2755,18 @@ class MBGLView : public mbgl::View
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
|
||||
void invalidate(std::function<void()>) override
|
||||
void invalidate() override
|
||||
{
|
||||
[nativeView performSelectorOnMainThread:@selector(invalidate)
|
||||
withObject:nil
|
||||
waitUntilDone:NO];
|
||||
}
|
||||
|
||||
void swap() override
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
private:
|
||||
__weak MGLMapView *nativeView = nullptr;
|
||||
};
|
||||
|
||||
@@ -43,7 +43,7 @@ void Map::renderStill(StillImageCallback callback) {
|
||||
}
|
||||
|
||||
void Map::renderSync() {
|
||||
context->invokeSync(&MapContext::render);
|
||||
context->invokeSync(&MapContext::renderSync);
|
||||
}
|
||||
|
||||
void Map::update(Update update_) {
|
||||
|
||||
@@ -269,7 +269,11 @@ void MapContext::update() {
|
||||
}
|
||||
}
|
||||
|
||||
view.invalidate([this] { render(); });
|
||||
if (mayRender) {
|
||||
render();
|
||||
} else {
|
||||
view.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
updated = static_cast<UpdateType>(Update::Nothing);
|
||||
@@ -302,9 +306,16 @@ void MapContext::renderStill(StillImageCallback fn) {
|
||||
}
|
||||
|
||||
callback = fn;
|
||||
mayRender = true;
|
||||
triggerUpdate(Update::RenderStill);
|
||||
}
|
||||
|
||||
void MapContext::renderSync() {
|
||||
mayRender = true;
|
||||
render();
|
||||
mayRender = false;
|
||||
}
|
||||
|
||||
void MapContext::render() {
|
||||
assert(util::ThreadContext::currentlyOn(util::ThreadType::Map));
|
||||
|
||||
@@ -326,11 +337,15 @@ void MapContext::render() {
|
||||
painter->setDebug(data.getDebug());
|
||||
painter->render(*style, transformState, data.getAnimationTime());
|
||||
|
||||
mayRender = false;
|
||||
|
||||
if (data.mode == MapMode::Still) {
|
||||
callback(nullptr, view.readStillImage());
|
||||
callback = nullptr;
|
||||
}
|
||||
|
||||
view.swap();
|
||||
|
||||
// Schedule another rerender when we definitely need a next frame.
|
||||
if (data.transform.needsTransition() || style->hasTransitions()) {
|
||||
triggerUpdate();
|
||||
@@ -351,7 +366,7 @@ void MapContext::setSourceTileCacheSize(size_t size) {
|
||||
for (const auto &source : style->sources) {
|
||||
source->setCacheSize(sourceCacheSize);
|
||||
}
|
||||
view.invalidate([this] { render(); });
|
||||
view.invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,7 +376,7 @@ void MapContext::onLowMemory() {
|
||||
for (const auto &source : style->sources) {
|
||||
source->onLowMemory();
|
||||
}
|
||||
view.invalidate([this] { render(); });
|
||||
view.invalidate();
|
||||
}
|
||||
|
||||
void MapContext::onTileDataChanged() {
|
||||
|
||||
@@ -34,12 +34,12 @@ public:
|
||||
~MapContext();
|
||||
|
||||
void pause();
|
||||
void render();
|
||||
|
||||
void resize(uint16_t width, uint16_t height, float ratio);
|
||||
|
||||
using StillImageCallback = std::function<void(std::exception_ptr, std::unique_ptr<const StillImage>)>;
|
||||
void renderStill(StillImageCallback callback);
|
||||
void renderSync();
|
||||
|
||||
void triggerUpdate(Update = Update::Nothing);
|
||||
|
||||
@@ -62,6 +62,7 @@ public:
|
||||
|
||||
private:
|
||||
void updateTiles();
|
||||
void render();
|
||||
|
||||
// Style-related updates.
|
||||
void cascadeClasses();
|
||||
@@ -88,6 +89,7 @@ private:
|
||||
std::string styleURL;
|
||||
std::string styleJSON;
|
||||
|
||||
bool mayRender = false;
|
||||
StillImageCallback callback;
|
||||
size_t sourceCacheSize;
|
||||
TransformState transformState;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#ifndef TEST_RESOURCES_MOCK_VIEW
|
||||
#define TEST_RESOURCES_MOCK_VIEW
|
||||
#ifndef TEST_FIXTURES_MOCK_VIEW
|
||||
#define TEST_FIXTURES_MOCK_VIEW
|
||||
|
||||
#include <mbgl/map/view.hpp>
|
||||
|
||||
@@ -13,7 +13,8 @@ public:
|
||||
void activate() override {};
|
||||
void deactivate() override {};
|
||||
void notify() override {};
|
||||
void invalidate(std::function<void()>) override {};
|
||||
void invalidate() override {}
|
||||
void swap() override {}
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../fixtures/util.hpp"
|
||||
#include "../fixtures/mock_view.hpp"
|
||||
|
||||
#include <mbgl/util/run_loop.hpp>
|
||||
#include <mbgl/map/map_data.hpp>
|
||||
@@ -11,18 +12,6 @@
|
||||
|
||||
using namespace mbgl;
|
||||
|
||||
class MockView : public View {
|
||||
public:
|
||||
void activate() override {
|
||||
}
|
||||
void deactivate() override {
|
||||
}
|
||||
void notify() override {
|
||||
}
|
||||
void invalidate(std::function<void()>) override {
|
||||
}
|
||||
};
|
||||
|
||||
TEST(Transform, InvalidScale) {
|
||||
MockView view;
|
||||
Transform transform(view);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "../fixtures/fixture_log_observer.hpp"
|
||||
#include "../fixtures/util.hpp"
|
||||
#include "../fixtures/mock_view.hpp"
|
||||
#include "mock_file_source.hpp"
|
||||
#include "mock_view.hpp"
|
||||
|
||||
#include <mbgl/map/map_data.hpp>
|
||||
#include <mbgl/map/transform_state.hpp>
|
||||
|
||||
Reference in New Issue
Block a user