[android] async rendering

- introduces GLSurfaceView
- introduces Orchestration thread
- renders on the gl thread
This commit is contained in:
Ivo van Dongen
2017-07-21 16:15:30 +03:00
committed by Ivo van Dongen
parent e780cdc29e
commit 347d7c19c0
11 changed files with 713 additions and 644 deletions

View File

@@ -1,72 +1,188 @@
#include "android_renderer_frontend.hpp"
#include <mbgl/renderer/backend_scope.hpp>
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/actor/scheduler.hpp>
#include <mbgl/renderer/renderer_observer.hpp>
#include <mbgl/storage/file_source.hpp>
#include <mbgl/util/thread.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/logging.hpp>
#include "android_renderer_backend.hpp"
namespace mbgl {
namespace android {
AndroidRendererFrontend::AndroidRendererFrontend(
std::unique_ptr<Renderer> renderer_,
RendererBackend& backend_,
InvalidateCallback invalidate)
: renderer(std::move(renderer_))
, backend(backend_)
, asyncInvalidate([=, invalidate=std::move(invalidate)]() {
// Forwards RendererObserver signals to the given
// Delegate RendererObserver on the given RunLoop
class ForwardingRendererObserver : public RendererObserver {
public:
ForwardingRendererObserver(util::RunLoop& mapRunLoop, RendererObserver& delegate_)
: mailbox(std::make_shared<Mailbox>(mapRunLoop))
, delegate(delegate_, mailbox) {
}
~ForwardingRendererObserver() {
mailbox->close();
}
void onInvalidate() override {
delegate.invoke(&RendererObserver::onInvalidate);
}
void onResourceError(std::exception_ptr err) override {
delegate.invoke(&RendererObserver::onResourceError, err);
}
void onWillStartRenderingMap() override {
delegate.invoke(&RendererObserver::onWillStartRenderingMap);
}
void onWillStartRenderingFrame() override {
delegate.invoke(&RendererObserver::onWillStartRenderingFrame);
}
void onDidFinishRenderingFrame(RenderMode mode, bool repaintNeeded) override {
delegate.invoke(&RendererObserver::onDidFinishRenderingFrame, mode, repaintNeeded);
}
void onDidFinishRenderingMap() override {
delegate.invoke(&RendererObserver::onDidFinishRenderingMap);
}
private:
std::shared_ptr<Mailbox> mailbox;
ActorRef<RendererObserver> delegate;
};
AndroidRendererFrontend::AndroidRendererFrontend(float pixelRatio,
FileSource& fileSource,
Scheduler& scheduler,
std::string programCacheDir,
InvalidateCallback invalidate)
: backend(std::make_unique<AndroidRendererBackend>())
, glThread(std::make_unique<AndroidGLThread>(
invalidate,
*backend,
pixelRatio,
fileSource,
scheduler,
GLContextMode::Unique,
programCacheDir
))
, asyncInvalidate([=]() {
invalidate();
}) {
})
, mapRunLoop(util::RunLoop::Get()) {
}
AndroidRendererFrontend::~AndroidRendererFrontend() = default;
void AndroidRendererFrontend::reset() {
assert (renderer);
if (renderer) {
renderer.reset();
}
assert(glThread);
glThread.reset();
}
void AndroidRendererFrontend::setObserver(RendererObserver& observer) {
assert (renderer);
renderer->setObserver(&observer);
assert (glThread);
assert (util::RunLoop::Get());
rendererObserver = std::make_unique<ForwardingRendererObserver>(*mapRunLoop, observer);
glThread->actor().invoke(&Renderer::setObserver, rendererObserver.get());
}
void AndroidRendererFrontend::update(std::shared_ptr<UpdateParameters> params) {
updateParameters = std::move(params);
{
// Lock on the parameters
std::lock_guard<std::mutex> lock(updateMutex);
updateParameters = std::move(params);
}
asyncInvalidate.send();
}
// Called on OpenGL thread
void AndroidRendererFrontend::render() {
assert (renderer);
if (!updateParameters) return;
assert (glThread);
BackendScope guard { backend };
std::shared_ptr<UpdateParameters> params;
{
// Lock on the parameters
std::unique_lock<std::mutex> lock(updateMutex);
if (!updateParameters) return;
renderer->render(*updateParameters);
// Hold on to the update parameters during render
params = updateParameters;
}
// Process the gl thread mailbox
glThread->process();
// Activate the backend
BackendScope backendGuard { *backend };
// Ensure that the "current" scheduler on the render thread is
// actually the scheduler from the orchestration thread
Scheduler::SetCurrent(glThread.get());
if (framebufferSizeChanged) {
backend->updateViewPort();
framebufferSizeChanged = false;
}
glThread->renderer->render(*params);
}
void AndroidRendererFrontend::onLowMemory() {
assert (renderer);
renderer->onLowMemory();
assert (glThread);
glThread->actor().invoke(&Renderer::onLowMemory);
}
std::vector<Feature> AndroidRendererFrontend::querySourceFeatures(const std::string& sourceID,
const SourceQueryOptions& options) const {
return renderer->querySourceFeatures(sourceID, options);
assert (glThread);
// Waits for the result from the orchestration thread and returns
return glThread->actor().ask(&Renderer::querySourceFeatures, sourceID, options).get();
}
std::vector<Feature> AndroidRendererFrontend::queryRenderedFeatures(const ScreenBox& box,
const RenderedQueryOptions& options) const {
return renderer->queryRenderedFeatures(box, options);
assert (glThread);
// Select the right overloaded method
std::vector<Feature> (Renderer::*fn)(const ScreenBox&, const RenderedQueryOptions&) const = &Renderer::queryRenderedFeatures;
// Waits for the result from the orchestration thread and returns
return glThread->actor().ask(fn, box, options).get();
}
std::vector<Feature> AndroidRendererFrontend::queryRenderedFeatures(const ScreenCoordinate& point,
const RenderedQueryOptions& options) const {
return renderer->queryRenderedFeatures(point, options);
assert (glThread);
// Select the right overloaded method
std::vector<Feature> (Renderer::*fn)(const ScreenCoordinate&, const RenderedQueryOptions&) const = &Renderer::queryRenderedFeatures;
// Waits for the result from the orchestration thread and returns
return glThread->actor().ask(fn, point, options).get();
}
AnnotationIDs AndroidRendererFrontend::queryPointAnnotations(const ScreenBox& box) const {
return renderer->queryPointAnnotations(box);
assert (glThread);
// Waits for the result from the orchestration thread and returns
return glThread->actor().ask(&Renderer::queryPointAnnotations, box).get();
}
void AndroidRendererFrontend::requestSnapshot(SnapshotCallback callback_) {
snapshotCallback = std::make_unique<SnapshotCallback>([callback=std::move(callback_), runloop=util::RunLoop::Get()](PremultipliedImage image){
runloop->invoke([&]() {
callback(std::move(image));
});
});
}
void AndroidRendererFrontend::resizeFramebuffer(int width, int height) {
backend->resizeFramebuffer(width, height);
framebufferSizeChanged = true;
asyncInvalidate.send();
}
} // namespace android