[core] refactor RendererBackend

This commit is contained in:
Konstantin Käfer
2019-04-01 16:56:24 +02:00
parent a782a6d15b
commit 66c020034e
54 changed files with 664 additions and 410 deletions

View File

@@ -5,6 +5,9 @@ add_executable(mbgl-glfw
target_sources(mbgl-glfw
PRIVATE platform/glfw/glfw_view.hpp
PRIVATE platform/glfw/glfw_view.cpp
PRIVATE platform/glfw/glfw_backend.hpp
PRIVATE platform/glfw/glfw_gl_backend.hpp
PRIVATE platform/glfw/glfw_gl_backend.cpp
PRIVATE platform/glfw/glfw_renderer_frontend.hpp
PRIVATE platform/glfw/glfw_renderer_frontend.cpp
PRIVATE platform/glfw/settings_json.hpp

View File

@@ -1,11 +1,10 @@
#pragma once
namespace mbgl {
namespace gfx {
class RendererBackend;
namespace gfx {
class BackendScope {
public:
// There are two types of scopes: Creating an "Implicit" scope tells Mapbox GL that the

View File

@@ -0,0 +1,57 @@
#pragma once
#include <mbgl/util/util.hpp>
#include <memory>
#include <mutex>
namespace mbgl {
namespace gfx {
class Context;
class Renderable;
class BackendScope;
// TODO: Rename to "Device"
class RendererBackend {
protected:
explicit RendererBackend();
public:
virtual ~RendererBackend();
RendererBackend(const RendererBackend&) = delete;
RendererBackend& operator=(const RendererBackend&) = delete;
// Returns the device's context.
Context& getContext();
// Returns a reference to the default surface that should be rendered on.
virtual Renderable& getDefaultRenderable() = 0;
protected:
virtual std::unique_ptr<Context> createContext() = 0;
// Called when the backend's GL context needs to be made active or inactive. These are called,
// as a matched pair, exclusively through BackendScope, in two situations:
//
// 1. When releasing GL resources during Renderer destruction
// (Including calling CustomLayerHost::deinitialize during RenderCustomLayer destruction)
// 2. When renderering through Renderer::render()
// (Including calling CustomLayerHost::initialize for newly added custom layers and
// CustomLayerHost::deinitialize on layer removal)
virtual void activate() = 0;
virtual void deactivate() = 0;
protected:
std::unique_ptr<Context> context;
std::once_flag initialized;
friend class BackendScope;
};
MBGL_CONSTEXPR bool operator==(const RendererBackend& a, const RendererBackend& b) {
return &a == &b;
}
} // namespace gfx
} // namespace mbgl

View File

@@ -0,0 +1,59 @@
#pragma once
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/size.hpp>
#include <mbgl/util/util.hpp>
namespace mbgl {
namespace gl {
class Context;
using ProcAddress = void (*)();
using FramebufferID = uint32_t;
class RendererBackend : public gfx::RendererBackend {
public:
RendererBackend();
~RendererBackend() override;
// Returns the backend's context which manages OpenGL state.
Context& getGLContext();
// Called prior to rendering to update the internally assumed OpenGL state.
virtual void updateAssumedState() = 0;
protected:
std::unique_ptr<gfx::Context> createContext() override;
// Called with the name of an OpenGL extension that should be loaded. RendererBackend implementations
// must call the API-specific version that obtains the function pointer for this function,
// or a null pointer if unsupported/unavailable.
virtual ProcAddress getExtensionFunctionPointer(const char*) = 0;
// Reads the color pixel data from the currently bound framebuffer.
PremultipliedImage readFramebuffer(const Size&);
// A constant to signal that a framebuffer is bound, but with an unknown ID.
static constexpr const FramebufferID ImplicitFramebufferBinding =
std::numeric_limits<FramebufferID>::max();
// Tells the renderer that OpenGL state has already been set by the windowing toolkit.
// It sets the internal assumed state to the supplied values.
void assumeFramebufferBinding(FramebufferID fbo);
void assumeViewport(int32_t x, int32_t y, const Size&);
void assumeScissorTest(bool);
// Returns true when assumed framebuffer binding hasn't changed from the implicit binding.
bool implicitFramebufferBound();
public:
// Triggers an OpenGL state update if the internal assumed state doesn't match the
// supplied values.
void setFramebufferBinding(FramebufferID fbo);
void setViewport(int32_t x, int32_t y, const Size&);
void setScissorTest(bool);
};
} // namespace gl
} // namespace mbgl

View File

@@ -13,16 +13,19 @@
namespace mbgl {
class RendererBackend;
class RendererObserver;
class RenderedQueryOptions;
class Scheduler;
class SourceQueryOptions;
class UpdateParameters;
namespace gfx {
class RendererBackend;
} // namespace gfx
class Renderer {
public:
Renderer(RendererBackend&, float pixelRatio_, Scheduler&,
Renderer(gfx::RendererBackend&, float pixelRatio_, Scheduler&,
GLContextMode = GLContextMode::Unique,
const optional<std::string> programCacheDir = {},
const optional<std::string> localFontFamily = {});

View File

@@ -1,92 +0,0 @@
#pragma once
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/util/image.hpp>
#include <mbgl/util/size.hpp>
#include <mbgl/util/util.hpp>
#include <memory>
#include <mutex>
namespace mbgl {
namespace gl {
class Context;
using ProcAddress = void (*)();
using FramebufferID = uint32_t;
} // namespace gl
// The RendererBackend is used by the Renderer to facilitate
// the actual rendering.
class RendererBackend {
public:
RendererBackend();
virtual ~RendererBackend();
// Returns the backend's context which manages OpenGL state.
gl::Context& getContext();
// Called prior to rendering to update the internally assumed OpenGL state.
virtual void updateAssumedState() = 0;
// Called when this backend is used for rendering. Implementations should ensure that a renderable
// object is bound and glClear/glDraw* calls can be done. They should also make sure that
// calling .bind() repeatedly is a no-op and that the appropriate gl::Context values are
// set to the current state.
virtual void bind() = 0;
virtual Size getFramebufferSize() const = 0;
protected:
// Called with the name of an OpenGL extension that should be loaded. RendererBackend implementations
// must call the API-specific version that obtains the function pointer for this function,
// or a null pointer if unsupported/unavailable.
virtual gl::ProcAddress getExtensionFunctionPointer(const char*) = 0;
// Called when the backend's GL context needs to be made active or inactive. These are called,
// as a matched pair, exclusively through BackendScope, in two situations:
//
// 1. When releasing GL resources during Renderer destruction
// (Including calling CustomLayerHost::deinitialize during RenderCustomLayer destruction)
// 2. When renderering through Renderer::render()
// (Including calling CustomLayerHost::initialize for newly added custom layers and
// CustomLayerHost::deinitialize on layer removal)
virtual void activate() = 0;
virtual void deactivate() = 0;
// Reads the color pixel data from the currently bound framebuffer.
PremultipliedImage readFramebuffer(const Size&) const;
// A constant to signal that a framebuffer is bound, but with an unknown ID.
static constexpr const gl::FramebufferID ImplicitFramebufferBinding =
std::numeric_limits<gl::FramebufferID>::max();
// Tells the renderer that OpenGL state has already been set by the windowing toolkit.
// It sets the internal assumed state to the supplied values.
void assumeFramebufferBinding(gl::FramebufferID fbo);
void assumeViewport(int32_t x, int32_t y, const Size&);
void assumeScissorTest(bool);
// Returns true when assumed framebuffer binding hasn't changed from the implicit binding.
bool implicitFramebufferBound();
// Triggers an OpenGL state update if the internal assumed state doesn't match the
// supplied values.
void setFramebufferBinding(gl::FramebufferID fbo);
void setViewport(int32_t x, int32_t y, const Size&);
void setScissorTest(bool);
protected:
std::unique_ptr<gl::Context> context;
private:
std::once_flag initialized;
friend class gfx::BackendScope;
};
MBGL_CONSTEXPR bool operator==(const RendererBackend& a, const RendererBackend& b) {
return &a == &b;
}
} // namespace mbgl

View File

@@ -1,6 +1,8 @@
#include "android_renderer_backend.hpp"
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <EGL/egl.h>
@@ -9,18 +11,27 @@
namespace mbgl {
namespace android {
/**
* From mbgl::View
*/
void AndroidRendererBackend::bind() {
assert(gfx::BackendScope::exists());
setFramebufferBinding(0);
setViewport(0, 0, getFramebufferSize());
class AndroidGLRenderableResource final : public mbgl::gl::RenderableResource {
public:
AndroidGLRenderableResource(AndroidRendererBackend& backend_) : backend(backend_) {
}
void bind() override {
assert(gfx::BackendScope::exists());
backend.setFramebufferBinding(0);
backend.setViewport(0, 0, backend.getSize());
}
private:
AndroidRendererBackend& backend;
};
AndroidRendererBackend::AndroidRendererBackend()
: mbgl::gfx::Renderable({ 64, 64 }, std::make_unique<AndroidGLRenderableResource>(*this)) {
}
/**
* From mbgl::RendererBackend.
*/
AndroidRendererBackend::~AndroidRendererBackend() = default;
gl::ProcAddress AndroidRendererBackend::getExtensionFunctionPointer(const char* name) {
assert(gfx::BackendScope::exists());
return eglGetProcAddress(name);
@@ -28,34 +39,26 @@ gl::ProcAddress AndroidRendererBackend::getExtensionFunctionPointer(const char*
void AndroidRendererBackend::updateViewPort() {
assert(gfx::BackendScope::exists());
setViewport(0, 0, getFramebufferSize());
setViewport(0, 0, size);
}
void AndroidRendererBackend::resizeFramebuffer(int width, int height) {
fbWidth = width;
fbHeight = height;
size = { static_cast<uint32_t>(width), static_cast<uint32_t>(height) };
}
PremultipliedImage AndroidRendererBackend::readFramebuffer() const {
PremultipliedImage AndroidRendererBackend::readFramebuffer() {
assert(gfx::BackendScope::exists());
return RendererBackend::readFramebuffer(getFramebufferSize());
return gl::RendererBackend::readFramebuffer(size);
}
mbgl::Size AndroidRendererBackend::getFramebufferSize() const {
return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) };
}
/**
* From mbgl::RendererBackend.
*/
void AndroidRendererBackend::updateAssumedState() {
assumeFramebufferBinding(0);
assumeViewport(0, 0, getFramebufferSize());
assumeViewport(0, 0, size);
}
void AndroidRendererBackend::markContextLost() {
if (context) {
context->setCleanupOnDestruction(false);
getGLContext().setCleanupOnDestruction(false);
}
}

View File

@@ -1,40 +1,42 @@
#pragma once
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/gfx/renderable.hpp>
#include <mbgl/gl/renderer_backend.hpp>
namespace mbgl {
namespace android {
class AndroidRendererBackend : public RendererBackend {
class AndroidRendererBackend : public gl::RendererBackend, public mbgl::gfx::Renderable {
public:
// mbgl::RendererBackend //
void bind() override;
void updateAssumedState() override;
mbgl::Size getFramebufferSize() const override;
// Ensures the current context is not
// cleaned up when destroyed
void markContextLost();
AndroidRendererBackend();
~AndroidRendererBackend() override;
void updateViewPort();
// Ensures the current context is not cleaned up when destroyed
void markContextLost();
void resizeFramebuffer(int width, int height);
PremultipliedImage readFramebuffer() const;
PremultipliedImage readFramebuffer();
// mbgl::gfx::RendererBackend implementation
public:
mbgl::gfx::Renderable& getDefaultRenderable() override {
return *this;
}
protected:
// mbgl::RendererBackend //
gl::ProcAddress getExtensionFunctionPointer(const char*) override;
void activate() override {};
void deactivate() override {};
private:
// Minimum texture size according to OpenGL ES 2.0 specification.
int fbWidth = 64;
int fbHeight = 64;
void activate() override {
// no-op
}
void deactivate() override {
// no-op
}
// mbgl::gl::RendererBackend implementation
protected:
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override;
void updateAssumedState() override;
};
} // namespace android

View File

@@ -1,6 +1,7 @@
#include "map_renderer.hpp"
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/util/shared_thread_pool.hpp>
#include <mbgl/util/run_loop.hpp>
@@ -159,6 +160,9 @@ void MapRenderer::onSurfaceCreated(JNIEnv&) {
// Lock as the initialization can come from the main thread or the GL thread first
std::lock_guard<std::mutex> lock(initialisationMutex);
// The GL context is already active if get a new surface.
gfx::BackendScope backendGuard { *backend, gfx::BackendScope::ScopeType::Implicit };
// The android system will have already destroyed the underlying
// GL resources if this is not the first initialization and an
// attempt to clean them up will fail

View File

@@ -1,7 +1,7 @@
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/renderer/renderer_frontend.hpp>
#include <mbgl/gl/renderer_backend.hpp>
#include <mbgl/util/async_task.hpp>
#include <mbgl/util/optional.hpp>
@@ -13,7 +13,7 @@
class MGLRenderFrontend : public mbgl::RendererFrontend
{
public:
MGLRenderFrontend(std::unique_ptr<mbgl::Renderer> renderer_, MGLMapView* nativeView_, mbgl::RendererBackend& mbglBackend_, bool async = false)
MGLRenderFrontend(std::unique_ptr<mbgl::Renderer> renderer_, MGLMapView* nativeView_, mbgl::gl::RendererBackend& mbglBackend_, bool async = false)
: renderer(std::move(renderer_))
, nativeView(nativeView_)
, mbglBackend(mbglBackend_) {
@@ -69,7 +69,7 @@ public:
private:
std::unique_ptr<mbgl::Renderer> renderer;
__weak MGLMapView *nativeView = nullptr;
mbgl::RendererBackend& mbglBackend;
mbgl::gl::RendererBackend& mbglBackend;
std::shared_ptr<mbgl::UpdateParameters> updateParameters;
mbgl::optional<mbgl::util::AsyncTask> asyncInvalidate;
};

View File

@@ -8,6 +8,7 @@
#include <stdexcept>
namespace mbgl {
namespace gl {
// This class provides a singleton that contains information about the pixel format used for
// instantiating new headless rendering contexts.
@@ -125,4 +126,5 @@ void HeadlessBackend::createImpl() {
impl = std::make_unique<CGLBackendImpl>();
}
} // namespace gl
} // namespace mbgl

View File

@@ -5,6 +5,7 @@
#include <stdexcept>
namespace mbgl {
namespace gl {
class EAGLBackendImpl : public HeadlessBackend::Impl {
public:
@@ -50,4 +51,5 @@ void HeadlessBackend::createImpl() {
impl = std::make_unique<EAGLBackendImpl>();
}
} // namespace gl
} // namespace mbgl

View File

@@ -1,19 +1,22 @@
#pragma once
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/gfx/renderable.hpp>
#include <mbgl/gl/renderer_backend.hpp>
#include <memory>
#include <functional>
namespace mbgl {
namespace gl {
class HeadlessBackend : public RendererBackend {
class HeadlessBackend final : public gl::RendererBackend, public gfx::Renderable {
public:
HeadlessBackend(Size = { 256, 256 });
~HeadlessBackend() override;
void bind() override;
Size getFramebufferSize() const override;
gfx::Renderable& getDefaultRenderable() override;
Size getFramebufferSize() const;
void updateAssumedState() override;
void setSize(Size);
@@ -39,12 +42,9 @@ private:
private:
std::unique_ptr<Impl> impl;
Size size;
float pixelRatio;
bool active = false;
class View;
std::unique_ptr<View> view;
};
} // namespace gl
} // namespace mbgl

View File

@@ -13,10 +13,13 @@ namespace mbgl {
class Scheduler;
class Renderer;
class RendererBackend;
class Map;
class TransformState;
namespace gfx {
class RendererBackend;
} // namespace gfx
class HeadlessFrontend : public RendererFrontend {
public:
HeadlessFrontend(float pixelRatio_, Scheduler&, const optional<std::string> programCacheDir = {}, GLContextMode mode = GLContextMode::Unique, const optional<std::string> localFontFamily = {});
@@ -31,7 +34,7 @@ public:
void setSize(Size);
Renderer* getRenderer();
RendererBackend* getBackend();
gfx::RendererBackend* getBackend();
CameraOptions getCameraOptions();
bool hasImage(const std::string&);
@@ -50,7 +53,7 @@ private:
Size size;
float pixelRatio;
HeadlessBackend backend;
gl::HeadlessBackend backend;
util::AsyncTask asyncInvalidate;
std::unique_ptr<Renderer> renderer;

View File

@@ -1,4 +1,5 @@
#include <mbgl/gl/headless_backend.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gfx/backend_scope.hpp>
@@ -7,27 +8,38 @@
#include <type_traits>
namespace mbgl {
namespace gl {
class HeadlessBackend::View {
class HeadlessRenderableResource final : public gl::RenderableResource {
public:
View(gl::Context& context, Size size_)
: color(context.createRenderbuffer<gfx::RenderbufferPixelType::RGBA>(size_)),
HeadlessRenderableResource(gl::Context& context_, Size size_)
: context(context_),
color(context.createRenderbuffer<gfx::RenderbufferPixelType::RGBA>(size_)),
depthStencil(context.createRenderbuffer<gfx::RenderbufferPixelType::DepthStencil>(size_)),
framebuffer(context.createFramebuffer(color, depthStencil)) {
}
void bind() override {
context.bindFramebuffer = framebuffer.framebuffer;
context.scissorTest = false;
context.viewport = { 0, 0, framebuffer.size };
}
gl::Context& context;
gfx::Renderbuffer<gfx::RenderbufferPixelType::RGBA> color;
gfx::Renderbuffer<gfx::RenderbufferPixelType::DepthStencil> depthStencil;
gl::Framebuffer framebuffer;
};
HeadlessBackend::HeadlessBackend(Size size_)
: size(size_) {
: mbgl::gfx::Renderable(size_, nullptr) {
}
HeadlessBackend::~HeadlessBackend() {
gfx::BackendScope guard { *this };
view.reset();
resource.reset();
// Explicitly reset the context so that it is destructed and cleaned up before we destruct
// the impl object.
context.reset();
}
@@ -53,16 +65,11 @@ void HeadlessBackend::deactivate() {
active = false;
}
void HeadlessBackend::bind() {
gl::Context& context_ = getContext();
if (!view) {
view = std::make_unique<View>(context_, size);
gfx::Renderable& HeadlessBackend::getDefaultRenderable() {
if (!resource) {
resource = std::make_unique<HeadlessRenderableResource>(static_cast<gl::Context&>(getContext()), size);
}
context_.bindFramebuffer = view->framebuffer.framebuffer;
context_.scissorTest = false;
context_.viewport = { 0, 0, size };
return *this;
}
Size HeadlessBackend::getFramebufferSize() const {
@@ -75,11 +82,12 @@ void HeadlessBackend::updateAssumedState() {
void HeadlessBackend::setSize(Size size_) {
size = size_;
view.reset();
resource.reset();
}
PremultipliedImage HeadlessBackend::readStillImage() {
return getContext().readFramebuffer<PremultipliedImage>(size);
return static_cast<gl::Context&>(getContext()).readFramebuffer<PremultipliedImage>(size);
}
} // namespace gl
} // namespace mbgl

View File

@@ -1,4 +1,5 @@
#include <mbgl/gl/headless_frontend.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/renderer/renderer_state.hpp>
#include <mbgl/renderer/update_parameters.hpp>
@@ -58,7 +59,7 @@ Renderer* HeadlessFrontend::getRenderer() {
return renderer.get();
}
RendererBackend* HeadlessFrontend::getBackend() {
gfx::RendererBackend* HeadlessFrontend::getBackend() {
return &backend;
}

View File

@@ -0,0 +1,21 @@
#pragma once
#include <mbgl/util/size.hpp>
namespace mbgl {
namespace gfx {
class RendererBackend;
} // namespace gfx
} // namespace mbgl
class GLFWBackend {
public:
explicit GLFWBackend() = default;
GLFWBackend(const GLFWBackend&) = delete;
GLFWBackend& operator=(const GLFWBackend&) = delete;
virtual ~GLFWBackend() = default;
virtual mbgl::gfx::RendererBackend& getRendererBackend() = 0;
virtual mbgl::Size getSize() const = 0;
virtual void setSize(mbgl::Size) = 0;
};

View File

@@ -0,0 +1,58 @@
#include "glfw_gl_backend.hpp"
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <GLFW/glfw3.h>
class GLFWGLRenderableResource final : public mbgl::gl::RenderableResource {
public:
GLFWGLRenderableResource(GLFWGLBackend& backend_) : backend(backend_) {
}
void bind() override {
backend.setFramebufferBinding(0);
backend.setViewport(0, 0, backend.getSize());
}
private:
GLFWGLBackend& backend;
};
GLFWGLBackend::GLFWGLBackend(GLFWwindow* window_)
: mbgl::gfx::Renderable(
[window_] {
int fbWidth, fbHeight;
glfwGetFramebufferSize(window_, &fbWidth, &fbHeight);
return mbgl::Size{ static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) };
}(),
std::make_unique<GLFWGLRenderableResource>(*this)),
window(window_) {
}
GLFWGLBackend::~GLFWGLBackend() = default;
void GLFWGLBackend::activate() {
glfwMakeContextCurrent(window);
}
void GLFWGLBackend::deactivate() {
glfwMakeContextCurrent(nullptr);
}
mbgl::gl::ProcAddress GLFWGLBackend::getExtensionFunctionPointer(const char* name) {
return glfwGetProcAddress(name);
}
void GLFWGLBackend::updateAssumedState() {
assumeFramebufferBinding(0);
assumeViewport(0, 0, size);
}
mbgl::Size GLFWGLBackend::getSize() const {
return size;
}
void GLFWGLBackend::setSize(const mbgl::Size newSize) {
size = newSize;
}

View File

@@ -0,0 +1,42 @@
#pragma once
#include "glfw_backend.hpp"
#include <mbgl/gfx/renderable.hpp>
#include <mbgl/gl/renderer_backend.hpp>
struct GLFWwindow;
class GLFWGLBackend final : public GLFWBackend,
public mbgl::gl::RendererBackend,
public mbgl::gfx::Renderable {
public:
GLFWGLBackend(GLFWwindow*);
~GLFWGLBackend() override;
// GLFWRendererBackend implementation
public:
mbgl::gfx::RendererBackend& getRendererBackend() override {
return *this;
}
mbgl::Size getSize() const override;
void setSize(mbgl::Size) override;
// mbgl::gfx::RendererBackend implementation
public:
mbgl::gfx::Renderable& getDefaultRenderable() override {
return *this;
}
protected:
void activate() override;
void deactivate() override;
// mbgl::gl::RendererBackend implementation
protected:
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override;
void updateAssumedState() override;
private:
GLFWwindow* window;
};

View File

@@ -31,7 +31,7 @@ void GLFWRendererFrontend::render() {
if (!updateParameters) return;
mbgl::gfx::BackendScope guard { glfwView, mbgl::gfx::BackendScope::ScopeType::Implicit };
mbgl::gfx::BackendScope guard { glfwView.getRendererBackend(), mbgl::gfx::BackendScope::ScopeType::Implicit };
// onStyleImageMissing might be called during a render. The user implemented method
// could trigger a call to MGLRenderFrontend#update which overwrites `updateParameters`.

View File

@@ -1,4 +1,5 @@
#include "glfw_view.hpp"
#include "glfw_gl_backend.hpp"
#include "glfw_renderer_frontend.hpp"
#include "ny_route.hpp"
@@ -105,8 +106,10 @@ GLFWView::GLFWView(bool fullscreen_, bool benchmark_)
glfwSetKeyCallback(window, onKey);
glfwGetWindowSize(window, &width, &height);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
pixelRatio = static_cast<float>(fbWidth) / width;
backend = std::make_unique<GLFWGLBackend>(window);
pixelRatio = static_cast<float>(backend->getSize().width) / width;
glfwMakeContextCurrent(nullptr);
@@ -158,14 +161,8 @@ void GLFWView::setRenderFrontend(GLFWRendererFrontend* rendererFrontend_) {
rendererFrontend = rendererFrontend_;
}
void GLFWView::updateAssumedState() {
assumeFramebufferBinding(0);
assumeViewport(0, 0, getFramebufferSize());
}
void GLFWView::bind() {
setFramebufferBinding(0);
setViewport(0, 0, getFramebufferSize());
mbgl::gfx::RendererBackend& GLFWView::getRendererBackend() {
return backend->getRendererBackend();
}
void GLFWView::onKey(GLFWwindow *window, int key, int /*scancode*/, int action, int mods) {
@@ -499,11 +496,7 @@ void GLFWView::onWindowResize(GLFWwindow *window, int width, int height) {
void GLFWView::onFramebufferResize(GLFWwindow *window, int width, int height) {
auto *view = reinterpret_cast<GLFWView *>(glfwGetWindowUserPointer(window));
view->fbWidth = width;
view->fbHeight = height;
mbgl::gfx::BackendScope scope { *view, mbgl::gfx::BackendScope::ScopeType::Implicit };
view->bind();
view->backend->setSize({ static_cast<uint32_t>(width), static_cast<uint32_t>(height) });
// This is only triggered when the framebuffer is resized, but not the window. It can
// happen when you move the window between screens with a different pixel ratio.
@@ -578,7 +571,7 @@ void GLFWView::run() {
updateAnimatedAnnotations();
activate();
mbgl::gfx::BackendScope scope { backend->getRendererBackend() };
rendererFrontend->render();
@@ -608,22 +601,6 @@ mbgl::Size GLFWView::getSize() const {
return { static_cast<uint32_t>(width), static_cast<uint32_t>(height) };
}
mbgl::Size GLFWView::getFramebufferSize() const {
return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) };
}
mbgl::gl::ProcAddress GLFWView::getExtensionFunctionPointer(const char* name) {
return glfwGetProcAddress(name);
}
void GLFWView::activate() {
glfwMakeContextCurrent(window);
}
void GLFWView::deactivate() {
glfwMakeContextCurrent(nullptr);
}
void GLFWView::invalidate() {
dirty = true;
glfwPostEmptyEvent();

View File

@@ -1,15 +1,21 @@
#pragma once
#include <mbgl/map/map.hpp>
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/util/run_loop.hpp>
#include <mbgl/util/timer.hpp>
#include <mbgl/util/geometry.hpp>
struct GLFWwindow;
class GLFWBackend;
class GLFWRendererFrontend;
class GLFWView : public mbgl::RendererBackend, public mbgl::MapObserver {
namespace mbgl {
namespace gfx {
class RendererBackend;
} // namespace gfx
} // namespace mbgl
class GLFWView : public mbgl::MapObserver {
public:
GLFWView(bool fullscreen = false, bool benchmark = false);
~GLFWView() override;
@@ -20,6 +26,8 @@ public:
void setRenderFrontend(GLFWRendererFrontend*);
mbgl::gfx::RendererBackend& getRendererBackend();
// 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.
void setChangeStyleCallback(std::function<void()> callback);
@@ -41,20 +49,12 @@ public:
void invalidate();
mbgl::Size getSize() const;
mbgl::Size getFramebufferSize() const override;
// mbgl::RendererBackend implementation
void bind() override;
void updateAssumedState() override;
// mbgl::MapObserver implementation
void onDidFinishLoadingStyle() override;
protected:
// mbgl::Backend implementation
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override;
void activate() override;
void deactivate() override;
private:
// Window callbacks
@@ -95,6 +95,7 @@ private:
mbgl::Map* map = nullptr;
GLFWRendererFrontend* rendererFrontend = nullptr;
std::unique_ptr<GLFWBackend> backend;
bool fullscreen = false;
const bool benchmark = false;
@@ -110,8 +111,6 @@ private:
int width = 1024;
int height = 768;
int fbWidth;
int fbHeight;
float pixelRatio;
double lastX = 0, lastY = 0;

View File

@@ -109,9 +109,9 @@ int main(int argc, char *argv[]) {
}
mbgl::ThreadPool threadPool(4);
GLFWRendererFrontend rendererFrontend { std::make_unique<mbgl::Renderer>(backend, view->getPixelRatio(), threadPool), backend };
GLFWRendererFrontend rendererFrontend { std::make_unique<mbgl::Renderer>(view->getRendererBackend(), view->getPixelRatio(), threadPool), *view };
mbgl::Map map(rendererFrontend, backend, threadPool,
mbgl::Map map(rendererFrontend, *view, threadPool,
mbgl::MapOptions().withSize(view->getSize()).withPixelRatio(view->getPixelRatio()), resourceOptions);
backend.setMap(&map);

View File

@@ -19,7 +19,8 @@
#include <mbgl/style/layers/custom_layer.hpp>
#include <mbgl/renderer/mode.hpp>
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/renderer/renderer_backend.hpp>
#import <mbgl/gl/renderer_backend.hpp>
#import <mbgl/gl/renderable_resource.hpp>
#include <mbgl/math/wrap.hpp>
#include <mbgl/util/exception.hpp>
#include <mbgl/util/geo.hpp>
@@ -6719,10 +6720,26 @@ public:
return _annotationViewReuseQueueByIdentifier[identifier];
}
class MBGLView : public mbgl::RendererBackend, public mbgl::MapObserver
{
class MBGLView;
class MBGLMapViewRenderable final : public mbgl::gl::RenderableResource {
public:
MBGLView(MGLMapView* nativeView_) : nativeView(nativeView_) {
MBGLMapViewRenderable(MBGLView& backend_) : backend(backend_) {
}
void bind() override;
private:
MBGLView& backend;
};
class MBGLView : public mbgl::gl::RendererBackend,
public mbgl::gfx::Renderable,
public mbgl::MapObserver {
public:
MBGLView(MGLMapView* nativeView_) : mbgl::gfx::Renderable(
nativeView_.framebufferSize,
std::make_unique<MBGLMapViewRenderable>(*this)), nativeView(nativeView_) {
}
/// This function is called before we start rendering, when iOS invokes our rendering method.
@@ -6733,7 +6750,7 @@ public:
assumeViewport(0, 0, nativeView.framebufferSize);
}
void bind() override {
void restoreFramebufferBinding() {
if (!implicitFramebufferBound()) {
// Something modified our state, and we need to bind the original drawable again.
// Doing this also sets the viewport to the full framebuffer.
@@ -6747,10 +6764,6 @@ public:
}
}
mbgl::Size getFramebufferSize() const override {
return nativeView.framebufferSize;
}
void onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) override {
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
[nativeView cameraWillChangeAnimated:animated];
@@ -6855,6 +6868,10 @@ public:
return reinterpret_cast<mbgl::gl::ProcAddress>(symbol);
}
mbgl::gfx::Renderable& getDefaultRenderable() override {
return *this;
}
void activate() override
{
if (activationCount++)
@@ -6876,11 +6893,15 @@ public:
}
private:
__weak MGLMapView *nativeView = nullptr;
__weak MGLMapView* nativeView = nullptr;
NSUInteger activationCount = 0;
};
void MBGLMapViewRenderable::bind() {
backend.restoreFramebufferBinding();
}
@end
#pragma mark - IBAdditions methods

View File

@@ -8,6 +8,7 @@
#include <cassert>
namespace mbgl {
namespace gl {
// This class provides a singleton that contains information about the configuration used for
// instantiating new headless rendering contexts.
@@ -142,4 +143,5 @@ void HeadlessBackend::createImpl() {
impl = std::make_unique<EGLBackendImpl>();
}
} // namespace gl
} // namespace mbgl

View File

@@ -7,6 +7,7 @@
#include <GL/glx.h>
namespace mbgl {
namespace gl {
// This class provides a singleton that contains information about the configuration used for
// instantiating new headless rendering contexts.
@@ -127,4 +128,5 @@ void HeadlessBackend::createImpl() {
impl = std::make_unique<GLXBackendImpl>();
}
} // namespace gl
} // namespace mbgl

View File

@@ -34,7 +34,8 @@
#import <mbgl/util/default_thread_pool.hpp>
#import <mbgl/style/image.hpp>
#import <mbgl/renderer/renderer.hpp>
#import <mbgl/renderer/renderer_backend.hpp>
#import <mbgl/gl/renderer_backend.hpp>
#import <mbgl/gl/renderable_resource.hpp>
#import <mbgl/storage/network_status.hpp>
#import <mbgl/storage/resource_options.hpp>
#import <mbgl/math/wrap.hpp>
@@ -3041,10 +3042,27 @@ public:
_mbglMap->setDebug(options);
}
/// Adapter responsible for bridging calls from mbgl to MGLMapView and Cocoa.
class MGLMapViewImpl : public mbgl::RendererBackend, public mbgl::MapObserver {
class MGLMapViewImpl;
class MGLMapViewRenderable final : public mbgl::gl::RenderableResource {
public:
MGLMapViewImpl(MGLMapView *nativeView_) : nativeView(nativeView_) {}
MGLMapViewRenderable(MGLMapViewImpl& backend_) : backend(backend_) {
}
void bind() override;
private:
MGLMapViewImpl& backend;
};
/// Adapter responsible for bridging calls from mbgl to MGLMapView and Cocoa.
class MGLMapViewImpl : public mbgl::gl::RendererBackend,
public mbgl::gfx::Renderable,
public mbgl::MapObserver {
public:
MGLMapViewImpl(MGLMapView *nativeView_) : mbgl::gfx::Renderable(
nativeView_.framebufferSize,
std::make_unique<MGLMapViewRenderable>(*this)), nativeView(nativeView_) {}
void onCameraWillChange(mbgl::MapObserver::CameraChangeMode mode) override {
bool animated = mode == mbgl::MapObserver::CameraChangeMode::Animated;
@@ -3141,6 +3159,10 @@ public:
return reinterpret_cast<mbgl::gl::ProcAddress>(symbol);
}
mbgl::gfx::Renderable& getDefaultRenderable() override {
return *this;
}
void activate() override {
if (activationCount++) {
return;
@@ -3164,15 +3186,11 @@ public:
assumeViewport(0, 0, nativeView.framebufferSize);
}
void bind() override {
void restoreFramebufferBinding() {
setFramebufferBinding(fbo);
setViewport(0, 0, nativeView.framebufferSize);
}
mbgl::Size getFramebufferSize() const override {
return nativeView.framebufferSize;
}
mbgl::PremultipliedImage readStillImage() {
return readFramebuffer(nativeView.framebufferSize);
}
@@ -3188,4 +3206,8 @@ private:
NSUInteger activationCount = 0;
};
void MGLMapViewRenderable::bind() {
backend.restoreFramebufferBinding();
}
@end

View File

@@ -6,21 +6,22 @@
#include <cassert>
namespace mbgl {
namespace gl {
class QtBackendImpl : public HeadlessBackend::Impl {
class QtBackendImpl final : public HeadlessBackend::Impl {
public:
~QtBackendImpl() final = default;
~QtBackendImpl() = default;
gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
gl::ProcAddress getExtensionFunctionPointer(const char* name) {
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
return thisContext->getProcAddress(name);
}
void activateContext() final {
void activateContext() {
widget.makeCurrent();
}
void deactivateContext() final {
void deactivateContext() {
widget.doneCurrent();
}
@@ -33,4 +34,5 @@ void HeadlessBackend::createImpl() {
impl = std::make_unique<QtBackendImpl>();
}
} // namespace gl
} // namespace mbgl

View File

@@ -1,6 +1,8 @@
#include "qmapboxgl_map_renderer.hpp"
#include "qmapboxgl_scheduler.hpp"
#include <mbgl/gfx/backend_scope.hpp>
#include <QThreadStorage>
#include <QtGlobal>

View File

@@ -4,7 +4,6 @@
#include "qmapboxgl_renderer_backend.hpp"
#include <mbgl/renderer/renderer.hpp>
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/renderer/renderer_observer.hpp>
#include <mbgl/util/shared_thread_pool.hpp>
#include <mbgl/util/util.hpp>

View File

@@ -1,39 +1,51 @@
#include "qmapboxgl_renderer_backend.hpp"
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <QOpenGLContext>
#include <QtGlobal>
void QMapboxGLRendererBackend::updateAssumedState()
{
class QMapboxGLRenderableResource final : public mbgl::gl::RenderableResource {
public:
QMapboxGLRenderableResource(QMapboxGLRendererBackend& backend_) : backend(backend_) {
}
void bind() override {
assert(mbgl::gfx::BackendScope::exists());
backend.restoreFramebufferBinding();
backend.setViewport(0, 0, backend.getSize());
}
private:
QMapboxGLRendererBackend& backend;
};
QMapboxGLRendererBackend::QMapboxGLRendererBackend()
: mbgl::gfx::Renderable({ 0, 0 }, std::make_unique<QMapboxGLRenderableResource>(*this)) {
}
QMapboxGLRendererBackend::~QMapboxGLRendererBackend() = default;
void QMapboxGLRendererBackend::updateAssumedState() {
assumeFramebufferBinding(ImplicitFramebufferBinding);
assumeViewport(0, 0, m_size);
assumeViewport(0, 0, size);
}
void QMapboxGLRendererBackend::bind()
{
assert(mbgl::gfx::BackendScope::exists());
void QMapboxGLRendererBackend::restoreFramebufferBinding() {
setFramebufferBinding(m_fbo);
setViewport(0, 0, m_size);
}
mbgl::Size QMapboxGLRendererBackend::getFramebufferSize() const
{
return m_size;
}
void QMapboxGLRendererBackend::updateFramebuffer(quint32 fbo, const mbgl::Size &size)
{
void QMapboxGLRendererBackend::updateFramebuffer(quint32 fbo, const mbgl::Size& newSize) {
m_fbo = fbo;
m_size = size;
size = newSize;
}
/*!
Initializes an OpenGL extension function such as Vertex Array Objects (VAOs),
required by Mapbox GL Native engine.
*/
mbgl::gl::ProcAddress QMapboxGLRendererBackend::getExtensionFunctionPointer(const char* name)
{
mbgl::gl::ProcAddress QMapboxGLRendererBackend::getExtensionFunctionPointer(const char* name) {
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
return thisContext->getProcAddress(name);
}

View File

@@ -2,32 +2,37 @@
#include "qmapboxgl.hpp"
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/gfx/renderable.hpp>
#include <mbgl/gl/renderer_backend.hpp>
#include <mbgl/util/shared_thread_pool.hpp>
class QMapboxGLRendererBackend : public mbgl::RendererBackend
{
class QMapboxGLRendererBackend final : public mbgl::gl::RendererBackend,
public mbgl::gfx::Renderable {
public:
QMapboxGLRendererBackend() = default;
virtual ~QMapboxGLRendererBackend() = default;
QMapboxGLRendererBackend();
~QMapboxGLRendererBackend() override;
// mbgl::RendererBackend implementation
void updateAssumedState() final;
void bind() final;
mbgl::Size getFramebufferSize() const final;
void updateFramebuffer(quint32 fbo, const mbgl::Size&);
void restoreFramebufferBinding();
void updateFramebuffer(quint32 fbo, const mbgl::Size &);
// mbgl::gfx::RendererBackend implementation
public:
mbgl::gfx::Renderable& getDefaultRenderable() override {
return *this;
}
protected:
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) final;
// No-op, implicit mode.
void activate() final {}
void deactivate() final {}
void activate() override {}
void deactivate() override {}
// mbgl::gl::RendererBackend implementation
protected:
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override;
void updateAssumedState() override;
private:
quint32 m_fbo = 0;
mbgl::Size m_size = { 0, 0 };
Q_DISABLE_COPY(QMapboxGLRendererBackend)
};

View File

@@ -3,6 +3,8 @@
#include <mbgl/util/geometry.hpp>
#include <mbgl/util/feature.hpp>
#pragma clang diagnostic ignored "-Wenum-compare-switch"
namespace QMapbox {
mbgl::Point<double> asMapboxGLPoint(const QMapbox::Coordinate &coordinate) {

View File

@@ -17,6 +17,7 @@
"src/mbgl/geometry/feature_index.cpp",
"src/mbgl/geometry/line_atlas.cpp",
"src/mbgl/gfx/attribute.cpp",
"src/mbgl/gfx/renderer_backend.cpp",
"src/mbgl/gl/attribute.cpp",
"src/mbgl/gl/binary_program.cpp",
"src/mbgl/gl/command_encoder.cpp",
@@ -25,6 +26,7 @@
"src/mbgl/gl/enum.cpp",
"src/mbgl/gl/object.cpp",
"src/mbgl/gl/offscreen_texture.cpp",
"src/mbgl/gl/renderer_backend.cpp",
"src/mbgl/gl/texture.cpp",
"src/mbgl/gl/uniform.cpp",
"src/mbgl/gl/value.cpp",
@@ -130,7 +132,6 @@
"src/mbgl/renderer/render_static_data.cpp",
"src/mbgl/renderer/render_tile.cpp",
"src/mbgl/renderer/renderer.cpp",
"src/mbgl/renderer/renderer_backend.cpp",
"src/mbgl/renderer/renderer_impl.cpp",
"src/mbgl/renderer/renderer_state.cpp",
"src/mbgl/renderer/sources/render_custom_geometry_source.cpp",
@@ -323,7 +324,9 @@
"mbgl/annotation/annotation.hpp": "include/mbgl/annotation/annotation.hpp",
"mbgl/gfx/backend_scope.hpp": "include/mbgl/gfx/backend_scope.hpp",
"mbgl/gfx/renderable.hpp": "include/mbgl/gfx/renderable.hpp",
"mbgl/gfx/renderer_backend.hpp": "include/mbgl/gfx/renderer_backend.hpp",
"mbgl/gl/renderable_resource.hpp": "include/mbgl/gl/renderable_resource.hpp",
"mbgl/gl/renderer_backend.hpp": "include/mbgl/gl/renderer_backend.hpp",
"mbgl/layermanager/background_layer_factory.hpp": "include/mbgl/layermanager/background_layer_factory.hpp",
"mbgl/layermanager/circle_layer_factory.hpp": "include/mbgl/layermanager/circle_layer_factory.hpp",
"mbgl/layermanager/custom_layer_factory.hpp": "include/mbgl/layermanager/custom_layer_factory.hpp",
@@ -352,7 +355,6 @@
"mbgl/renderer/mode.hpp": "include/mbgl/renderer/mode.hpp",
"mbgl/renderer/query.hpp": "include/mbgl/renderer/query.hpp",
"mbgl/renderer/renderer.hpp": "include/mbgl/renderer/renderer.hpp",
"mbgl/renderer/renderer_backend.hpp": "include/mbgl/renderer/renderer_backend.hpp",
"mbgl/renderer/renderer_frontend.hpp": "include/mbgl/renderer/renderer_frontend.hpp",
"mbgl/renderer/renderer_observer.hpp": "include/mbgl/renderer/renderer_observer.hpp",
"mbgl/renderer/renderer_state.hpp": "include/mbgl/renderer/renderer_state.hpp",

View File

@@ -0,0 +1,22 @@
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/gfx/context.hpp>
namespace mbgl {
namespace gfx {
RendererBackend::RendererBackend() = default;
RendererBackend::~RendererBackend() = default;
gfx::Context& RendererBackend::getContext() {
assert(BackendScope::exists());
std::call_once(initialized, [this] {
context = createContext();
});
assert(context);
return *context;
}
} // namespace gfx
} // namespace mbgl

View File

@@ -1,5 +1,6 @@
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/enum.hpp>
#include <mbgl/gl/renderer_backend.hpp>
#include <mbgl/gl/vertex_buffer_resource.hpp>
#include <mbgl/gl/index_buffer_resource.hpp>
#include <mbgl/gl/texture_resource.hpp>
@@ -53,12 +54,12 @@ static_assert(underlying_type(UniformDataType::SamplerCube) == GL_SAMPLER_CUBE,
static_assert(std::is_same<BinaryProgramFormat, GLenum>::value, "OpenGL type mismatch");
Context::Context()
Context::Context(RendererBackend& backend_)
: gfx::Context(gfx::ContextType::OpenGL, [] {
GLint value;
MBGL_CHECK_ERROR(glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &value));
return value;
}()) {
}()), backend(backend_) {
}
Context::~Context() {
@@ -701,6 +702,7 @@ void Context::setColorMode(const gfx::ColorMode& color) {
}
std::unique_ptr<gfx::CommandEncoder> Context::createCommandEncoder() {
backend.updateAssumedState();
return std::make_unique<gl::CommandEncoder>(*this);
}

View File

@@ -27,6 +27,7 @@ namespace gl {
constexpr size_t TextureMax = 64;
using ProcAddress = void (*)();
class RendererBackend;
namespace extension {
class VertexArray;
@@ -36,7 +37,7 @@ class ProgramBinary;
class Context final : public gfx::Context {
public:
Context();
Context(RendererBackend&);
~Context() override;
Context(const Context&) = delete;
Context& operator=(const Context& other) = delete;
@@ -136,6 +137,7 @@ public:
}
private:
RendererBackend& backend;
bool cleanupOnDestruction = true;
std::unique_ptr<extension::Debugging> debugging;

View File

@@ -0,0 +1,71 @@
#include <mbgl/gl/renderer_backend.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/extension.hpp>
#include <cassert>
namespace mbgl {
namespace gl {
RendererBackend::RendererBackend() = default;
std::unique_ptr<gfx::Context> RendererBackend::createContext() {
auto result = std::make_unique<gl::Context>(*this);
result->enableDebugging();
result->initializeExtensions(
std::bind(&RendererBackend::getExtensionFunctionPointer, this, std::placeholders::_1));
// Needs move to placate GCC 4.9
return std::move(result);
}
gl::Context& RendererBackend::getGLContext() {
return static_cast<gl::Context&>(getContext());
}
PremultipliedImage RendererBackend::readFramebuffer(const Size& size) {
return getGLContext().readFramebuffer<PremultipliedImage>(size);
}
void RendererBackend::assumeFramebufferBinding(const gl::FramebufferID fbo) {
getGLContext().bindFramebuffer.setCurrentValue(fbo);
if (fbo != ImplicitFramebufferBinding) {
assert(gl::value::BindFramebuffer::Get() == getGLContext().bindFramebuffer.getCurrentValue());
}
}
void RendererBackend::assumeViewport(int32_t x, int32_t y, const Size& size) {
getGLContext().viewport.setCurrentValue({ x, y, size });
assert(gl::value::Viewport::Get() == getGLContext().viewport.getCurrentValue());
}
void RendererBackend::assumeScissorTest(bool enabled) {
getGLContext().scissorTest.setCurrentValue(enabled);
assert(gl::value::ScissorTest::Get() == getGLContext().scissorTest.getCurrentValue());
}
bool RendererBackend::implicitFramebufferBound() {
return getGLContext().bindFramebuffer.getCurrentValue() == ImplicitFramebufferBinding;
}
void RendererBackend::setFramebufferBinding(const gl::FramebufferID fbo) {
getGLContext().bindFramebuffer = fbo;
if (fbo != ImplicitFramebufferBinding) {
assert(gl::value::BindFramebuffer::Get() == getGLContext().bindFramebuffer.getCurrentValue());
}
}
void RendererBackend::setViewport(int32_t x, int32_t y, const Size& size) {
getGLContext().viewport = { x, y, size };
assert(gl::value::Viewport::Get() == getGLContext().viewport.getCurrentValue());
}
void RendererBackend::setScissorTest(bool enabled) {
getGLContext().scissorTest = enabled;
assert(gl::value::ScissorTest::Get() == getGLContext().scissorTest.getCurrentValue());
}
RendererBackend::~RendererBackend() = default;
} // namespace gl
} // namespace mbgl

View File

@@ -1,5 +1,5 @@
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/util/thread_local.hpp>
#include <cassert>

View File

@@ -1,12 +1,13 @@
#include <mbgl/renderer/layers/render_custom_layer.hpp>
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/renderer/bucket.hpp>
#include <mbgl/platform/gl_functions.hpp>
#include <mbgl/style/layers/custom_layer_impl.hpp>
#include <mbgl/map/transform_state.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <mbgl/util/mat4.hpp>
namespace mbgl {
@@ -86,7 +87,7 @@ void RenderCustomLayer::render(PaintParameters& paintParameters, RenderSource*)
// Reset the view back to our original one, just in case the CustomLayer changed
// the viewport or Framebuffer.
paintParameters.backend.bind();
paintParameters.backend.getDefaultRenderable().getResource<gl::RenderableResource>().bind();
glContext.setDirtyState();
}

View File

@@ -4,7 +4,6 @@
#include <mbgl/renderer/paint_parameters.hpp>
#include <mbgl/renderer/image_manager.hpp>
#include <mbgl/renderer/render_static_data.hpp>
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/programs/programs.hpp>
#include <mbgl/programs/fill_extrusion_program.hpp>
#include <mbgl/tile/tile.hpp>
@@ -13,6 +12,7 @@
#include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp>
#include <mbgl/tile/geometry_tile.hpp>
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/renderable_resource.hpp>

View File

@@ -8,8 +8,10 @@
#include <mbgl/tile/tile.hpp>
#include <mbgl/style/layers/fill_layer_impl.hpp>
#include <mbgl/geometry/feature_index.hpp>
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gfx/context.hpp>
#include <mbgl/gfx/renderable.hpp>
#include <mbgl/util/math.hpp>
#include <mbgl/util/intersection_tests.hpp>
#include <mbgl/tile/geometry_tile.hpp>
@@ -63,9 +65,6 @@ bool RenderFillLayer::hasCrossfade() const {
}
void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
// TODO: remove cast
gl::Context& glContext = static_cast<gl::Context&>(parameters.context);
if (unevaluated.get<FillPattern>().isUndefined()) {
for (const RenderTile& tile : renderTiles) {
auto bucket_ = tile.tile.getBucket<FillBucket>(*baseImpl);
@@ -89,7 +88,7 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
evaluated.get<FillTranslateAnchor>(),
parameters.state)
),
uniforms::world::Value( glContext.viewport.getCurrentValue().size ),
uniforms::world::Value( parameters.backend.getDefaultRenderable().getSize() ),
},
paintPropertyBinders,
evaluated,
@@ -174,7 +173,7 @@ void RenderFillLayer::render(PaintParameters& parameters, RenderSource*) {
tile.translatedMatrix(evaluated.get<FillTranslate>(),
evaluated.get<FillTranslateAnchor>(),
parameters.state),
glContext.viewport.getCurrentValue().size,
parameters.backend.getDefaultRenderable().getSize(),
geometryTile.iconAtlasTexture->size,
crossfade,
tile.id,

View File

@@ -9,7 +9,7 @@ namespace mbgl {
PaintParameters::PaintParameters(gfx::Context& context_,
float pixelRatio_,
GLContextMode contextMode_,
RendererBackend& backend_,
gfx::RendererBackend& backend_,
const UpdateParameters& updateParameters,
const EvaluatedLight& evaluatedLight_,
RenderStaticData& staticData_,

View File

@@ -15,7 +15,6 @@
namespace mbgl {
class RendererBackend;
class UpdateParameters;
class RenderStaticData;
class Programs;
@@ -26,6 +25,7 @@ class UnwrappedTileID;
namespace gfx {
class Context;
class RendererBackend;
class CommandEncoder;
} // namespace gfx
@@ -34,7 +34,7 @@ public:
PaintParameters(gfx::Context&,
float pixelRatio,
GLContextMode,
RendererBackend&,
gfx::RendererBackend&,
const UpdateParameters&,
const EvaluatedLight&,
RenderStaticData&,
@@ -44,7 +44,7 @@ public:
~PaintParameters();
gfx::Context& context;
RendererBackend& backend;
gfx::RendererBackend& backend;
const std::unique_ptr<gfx::CommandEncoder> encoder;
const TransformState& state;

View File

@@ -7,7 +7,7 @@
namespace mbgl {
Renderer::Renderer(RendererBackend& backend,
Renderer::Renderer(gfx::RendererBackend& backend,
float pixelRatio_,
Scheduler& scheduler_,
GLContextMode contextMode_,

View File

@@ -1,68 +0,0 @@
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/extension.hpp>
#include <cassert>
namespace mbgl {
RendererBackend::RendererBackend() = default;
gl::Context& RendererBackend::getContext() {
assert(gfx::BackendScope::exists());
std::call_once(initialized, [this] {
context = std::make_unique<gl::Context>();
context->enableDebugging();
context->initializeExtensions(
std::bind(&RendererBackend::getExtensionFunctionPointer, this, std::placeholders::_1));
});
return *context;
}
PremultipliedImage RendererBackend::readFramebuffer(const Size& size) const {
assert(context);
return context->readFramebuffer<PremultipliedImage>(size);
}
void RendererBackend::assumeFramebufferBinding(const gl::FramebufferID fbo) {
getContext().bindFramebuffer.setCurrentValue(fbo);
if (fbo != ImplicitFramebufferBinding) {
assert(gl::value::BindFramebuffer::Get() == getContext().bindFramebuffer.getCurrentValue());
}
}
void RendererBackend::assumeViewport(int32_t x, int32_t y, const Size& size) {
getContext().viewport.setCurrentValue({ x, y, size });
assert(gl::value::Viewport::Get() == getContext().viewport.getCurrentValue());
}
void RendererBackend::assumeScissorTest(bool enabled) {
getContext().scissorTest.setCurrentValue(enabled);
assert(gl::value::ScissorTest::Get() == getContext().scissorTest.getCurrentValue());
}
bool RendererBackend::implicitFramebufferBound() {
return getContext().bindFramebuffer.getCurrentValue() == ImplicitFramebufferBinding;
}
void RendererBackend::setFramebufferBinding(const gl::FramebufferID fbo) {
getContext().bindFramebuffer = fbo;
if (fbo != ImplicitFramebufferBinding) {
assert(gl::value::BindFramebuffer::Get() == getContext().bindFramebuffer.getCurrentValue());
}
}
void RendererBackend::setViewport(int32_t x, int32_t y, const Size& size) {
getContext().viewport = { x, y, size };
assert(gl::value::Viewport::Get() == getContext().viewport.getCurrentValue());
}
void RendererBackend::setScissorTest(bool enabled) {
getContext().scissorTest = enabled;
assert(gl::value::ScissorTest::Get() == getContext().scissorTest.getCurrentValue());
}
RendererBackend::~RendererBackend() = default;
} // namespace mbgl

View File

@@ -1,7 +1,6 @@
#include <mbgl/annotation/annotation_manager.hpp>
#include <mbgl/layermanager/layer_manager.hpp>
#include <mbgl/renderer/renderer_impl.hpp>
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/renderer/renderer_observer.hpp>
#include <mbgl/renderer/render_source.hpp>
#include <mbgl/renderer/render_layer.hpp>
@@ -16,7 +15,10 @@
#include <mbgl/renderer/query.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/renderer/image_manager.hpp>
#include <mbgl/gfx/renderer_backend.hpp>
#include <mbgl/gfx/cull_face_mode.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <mbgl/geometry/line_atlas.hpp>
#include <mbgl/style/source_impl.hpp>
#include <mbgl/style/transition_options.hpp>
@@ -35,7 +37,7 @@ static RendererObserver& nullObserver() {
return observer;
}
Renderer::Impl::Impl(RendererBackend& backend_,
Renderer::Impl::Impl(gfx::RendererBackend& backend_,
float pixelRatio_,
Scheduler& scheduler_,
GLContextMode contextMode_,
@@ -307,8 +309,6 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
observer->onWillStartRenderingFrame();
backend.updateAssumedState();
// Set render tiles to the render items.
for (auto& renderItem : renderItems) {
if (!renderItem.source) {
@@ -364,7 +364,6 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
}
}
// TODO: remove cast
gl::Context& glContext = static_cast<gl::Context&>(parameters.context);
@@ -392,7 +391,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
// Renders any 3D layers bottom-to-top to unique FBOs with texture attachments, but share the same
// depth rbo between them.
if (parameters.staticData.has3D) {
parameters.staticData.backendSize = parameters.backend.getFramebufferSize();
parameters.staticData.backendSize = parameters.backend.getDefaultRenderable().getSize();
const auto debugGroup(parameters.encoder->createDebugGroup("3d"));
parameters.pass = RenderPass::Pass3D;
@@ -420,7 +419,7 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
{
using namespace gl::value;
parameters.backend.bind();
parameters.backend.getDefaultRenderable().getResource<gl::RenderableResource>().bind();
if (parameters.debugOptions & MapDebugOptions::Overdraw) {
glContext.clear(Color::black(), ClearDepth::Default, ClearStencil::Default);
} else if (parameters.contextMode == GLContextMode::Shared) {
@@ -600,7 +599,8 @@ void Renderer::Impl::render(const UpdateParameters& updateParameters) {
void Renderer::Impl::flush() {
assert(gfx::BackendScope::exists());
backend.getContext().flush();
gl::Context& glContext = static_cast<gl::Context&>(backend.getContext());
glContext.flush();
}
std::vector<Feature> Renderer::Impl::queryRenderedFeatures(const ScreenLineString& geometry, const RenderedQueryOptions& options) const {

View File

@@ -20,7 +20,6 @@
namespace mbgl {
class RendererBackend;
class RendererObserver;
class RenderSource;
class RenderLayer;
@@ -34,11 +33,15 @@ class ImageManager;
class LineAtlas;
class CrossTileSymbolIndex;
namespace gfx {
class RendererBackend;
} // namespace gfx
class Renderer::Impl : public GlyphManagerObserver,
public ImageManagerObserver,
public RenderSourceObserver{
public:
Impl(RendererBackend&, float pixelRatio_, Scheduler&, GLContextMode,
Impl(gfx::RendererBackend&, float pixelRatio_, Scheduler&, GLContextMode,
const optional<std::string> programCacheDir, const optional<std::string> localFontFamily_);
~Impl() final;
@@ -95,7 +98,7 @@ private:
friend class Renderer;
RendererBackend& backend;
gfx::RendererBackend& backend;
Scheduler& scheduler;
RendererObserver* observer;

View File

@@ -43,10 +43,10 @@ PropertyMap properties;
} // namespace
TEST(Buckets, CircleBucket) {
HeadlessBackend backend({ 512, 256 });
gl::HeadlessBackend backend({ 512, 256 });
gfx::BackendScope scope { backend };
gl::Context context;
gl::Context context{ backend };
CircleBucket bucket { { {0, 0, 0}, MapMode::Static, 1.0, nullptr }, {} };
ASSERT_FALSE(bucket.hasData());
ASSERT_FALSE(bucket.needsUpload());
@@ -62,11 +62,11 @@ TEST(Buckets, CircleBucket) {
}
TEST(Buckets, FillBucket) {
HeadlessBackend backend({ 512, 256 });
gl::HeadlessBackend backend({ 512, 256 });
gfx::BackendScope scope { backend };
style::Properties<>::PossiblyEvaluated layout;
gl::Context context;
gl::Context context{ backend };
FillBucket bucket { layout, {}, 5.0f, 1};
ASSERT_FALSE(bucket.hasData());
ASSERT_FALSE(bucket.needsUpload());
@@ -81,11 +81,11 @@ TEST(Buckets, FillBucket) {
}
TEST(Buckets, LineBucket) {
HeadlessBackend backend({ 512, 256 });
gl::HeadlessBackend backend({ 512, 256 });
gfx::BackendScope scope { backend };
style::LineLayoutProperties::PossiblyEvaluated layout;
gl::Context context;
gl::Context context{ backend };
LineBucket bucket { layout, {}, 10.0f, 1 };
ASSERT_FALSE(bucket.hasData());
ASSERT_FALSE(bucket.needsUpload());
@@ -105,7 +105,7 @@ TEST(Buckets, LineBucket) {
}
TEST(Buckets, SymbolBucket) {
HeadlessBackend backend({ 512, 256 });
gl::HeadlessBackend backend({ 512, 256 });
gfx::BackendScope scope { backend };
style::SymbolLayoutProperties::PossiblyEvaluated layout;
@@ -115,7 +115,7 @@ TEST(Buckets, SymbolBucket) {
std::string bucketLeaderID = "test";
std::vector<SymbolInstance> symbolInstances;
gl::Context context;
gl::Context context{ backend };
SymbolBucket bucket { layout, {}, 16.0f, 1.0f, 0, sdfIcons, iconsNeedLinear, sortFeaturesByY, bucketLeaderID, std::move(symbolInstances), 1.0f };
ASSERT_FALSE(bucket.hasIconData());
ASSERT_FALSE(bucket.hasTextData());
@@ -139,10 +139,10 @@ TEST(Buckets, SymbolBucket) {
}
TEST(Buckets, RasterBucket) {
HeadlessBackend backend({ 512, 256 });
gl::HeadlessBackend backend({ 512, 256 });
gfx::BackendScope scope { backend };
gl::Context context;
gl::Context context{ backend };
PremultipliedImage rgba({ 1, 1 });
// RasterBucket::hasData() is always true.

View File

@@ -8,6 +8,7 @@
#include <mbgl/gfx/backend_scope.hpp>
#include <mbgl/gl/defines.hpp>
#include <mbgl/gl/headless_frontend.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/style/style.hpp>
#include <mbgl/style/layers/custom_layer.hpp>
@@ -104,8 +105,8 @@ TEST(GLContextMode, Shared) {
{
// Custom rendering outside of GL Native render loop.
frontend.getBackend()->bind();
gfx::BackendScope scope { *frontend.getBackend() };
frontend.getBackend()->getDefaultRenderable().getResource<gl::RenderableResource>().bind();
Shader paintShader(vertexShaderSource, fragmentShaderSource);
Buffer triangleBuffer({ 0, 0.5, 0.5, -0.5, -0.5, -0.5 });

View File

@@ -45,10 +45,10 @@ TEST(GLObject, Value) {
}
TEST(GLObject, Store) {
HeadlessBackend backend { { 256, 256 } };
gl::HeadlessBackend backend { { 256, 256 } };
gfx::BackendScope scope { backend };
gl::Context context;
gl::Context context{ backend };
EXPECT_TRUE(context.empty());
gl::UniqueTexture texture = context.createUniqueTexture();

View File

@@ -614,8 +614,8 @@ TEST(Map, AddLayer) {
TEST(Map, WithoutVAOExtension) {
MapTest<DefaultFileSource> test { ":memory:", "test/fixtures/api/assets" };
test.frontend.getBackend()->getContext().disableVAOExtension = true;
gfx::BackendScope scope { *test.frontend.getBackend() };
static_cast<gl::Context&>(test.frontend.getBackend()->getContext()).disableVAOExtension = true;
test.map.getStyle().loadJSON(util::read_file("test/fixtures/api/water.json"));

View File

@@ -1,21 +1,14 @@
#include <mbgl/test/util.hpp>
#include <mbgl/renderer/renderer_backend.hpp>
#include <mbgl/gl/renderer_backend.hpp>
#include <mbgl/gfx/backend_scope.hpp>
#include <functional>
using namespace mbgl;
class StubRendererBackend: public RendererBackend {
class StubRendererBackend: public gl::RendererBackend {
public:
void bind() override {
}
mbgl::Size getFramebufferSize() const override {
return mbgl::Size{};
}
void activate() override {
if (activateFunction) activateFunction();
}
@@ -29,7 +22,13 @@ public:
}
gl::ProcAddress getExtensionFunctionPointer(const char*) override {
return {};
abort();
return nullptr;
}
gfx::Renderable& getDefaultRenderable() override {
abort();
return reinterpret_cast<gfx::Renderable&>(*this);
}
std::function<void ()> activateFunction;

View File

@@ -14,14 +14,14 @@ using namespace mbgl;
using namespace mbgl::platform;
TEST(OffscreenTexture, EmptyRed) {
HeadlessBackend backend({ 512, 256 });
gl::HeadlessBackend backend({ 512, 256 });
gfx::BackendScope scope { backend };
// Scissor test shouldn't leak after HeadlessBackend::bind().
// Scissor test shouldn't leak after gl::HeadlessBackend::bind().
MBGL_CHECK_ERROR(glScissor(64, 64, 128, 128));
backend.getContext().scissorTest.setCurrentValue(true);
static_cast<gl::Context&>(backend.getContext()).scissorTest.setCurrentValue(true);
backend.bind();
backend.getDefaultRenderable().getResource<gl::RenderableResource>().bind();
MBGL_CHECK_ERROR(glClearColor(1.0f, 0.0f, 0.0f, 1.0f));
MBGL_CHECK_ERROR(glClear(GL_COLOR_BUFFER_BIT));
@@ -76,9 +76,9 @@ struct Buffer {
TEST(OffscreenTexture, RenderToTexture) {
HeadlessBackend backend({ 512, 256 });
auto& context = backend.getContext();
gl::HeadlessBackend backend({ 512, 256 });
gfx::BackendScope scope { backend };
auto& context = static_cast<gl::Context&>(backend.getContext());
MBGL_CHECK_ERROR(glEnable(GL_BLEND));
MBGL_CHECK_ERROR(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
@@ -126,7 +126,7 @@ void main() {
Buffer triangleBuffer({ 0, 0.5, 0.5, -0.5, -0.5, -0.5 });
Buffer viewportBuffer({ -1, -1, 1, -1, -1, 1, 1, 1 });
backend.bind();
backend.getDefaultRenderable().getResource<gl::RenderableResource>().bind();
// First, draw red to the bound FBO.
context.clear(Color::red(), {}, {});
@@ -154,7 +154,7 @@ void main() {
test::checkImage("test/fixtures/offscreen_texture/render-to-texture", image, 0, 0);
// Now reset the FBO back to normal and retrieve the original (restored) framebuffer.
backend.bind();
backend.getDefaultRenderable().getResource<gl::RenderableResource>().bind();
image = backend.readStillImage();
test::checkImage("test/fixtures/offscreen_texture/render-to-fbo", image, 0, 0);