[core] Move OpenGL extension initialization to Backend

This commit is contained in:
Konstantin Käfer
2017-02-27 18:33:16 +01:00
committed by John Firebaugh
parent 8e5214144e
commit 234384ece9
25 changed files with 102 additions and 110 deletions

View File

@@ -3,11 +3,13 @@
#include <mbgl/map/map_observer.hpp>
#include <memory>
#include <mutex>
namespace mbgl {
namespace gl {
class Context;
using ProcAddress = void (*)();
} // namespace gl
class BackendScope;
@@ -25,6 +27,11 @@ public:
virtual void invalidate() = 0;
protected:
// Called with the name of an OpenGL extension that should be loaded. Backend 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 initializeExtension(const char*) = 0;
// Called when the backend's GL context needs to be made active or inactive. These are called,
// as a matched pair, in four situations:
//
@@ -38,8 +45,12 @@ protected:
virtual void activate() = 0;
virtual void deactivate() = 0;
protected:
std::unique_ptr<gl::Context> context;
private:
std::once_flag initialized;
friend class BackendScope;
};

View File

@@ -15,7 +15,6 @@
#include <jni/jni.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/extension.hpp>
#include <mbgl/map/backend_scope.hpp>
#include <mbgl/util/constants.hpp>
#include <mbgl/util/event.hpp>
@@ -108,6 +107,10 @@ void NativeMapView::bind() {
/**
* From mbgl::Backend.
*/
gl::ProcAddress NativeMapView::initializeExtension(const char* name) {
return eglGetProcAddress(name);
}
void NativeMapView::activate() {
if (active++) {
return;
@@ -1394,10 +1397,6 @@ void NativeMapView::_createSurface(ANativeWindow *window_) {
eglGetError());
throw std::runtime_error("eglMakeCurrent() failed");
}
mbgl::gl::InitializeExtensions([] (const char * name) {
return reinterpret_cast<mbgl::gl::glProc>(eglGetProcAddress(name));
});
}
}

View File

@@ -262,6 +262,7 @@ public:
protected:
// mbgl::Backend //
gl::ProcAddress initializeExtension(const char*) override;
void activate() override;
void deactivate() override;

View File

@@ -36,7 +36,7 @@ struct CGLImpl : public HeadlessBackend::Impl {
CGLContextObj glContext = nullptr;
};
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
if (!framework) {
throw std::runtime_error("Failed to load OpenGL framework.");
@@ -46,7 +46,7 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) {
void* symbol = CFBundleGetFunctionPointerForName(framework, str);
CFRelease(str);
return reinterpret_cast<gl::glProc>(symbol);
return reinterpret_cast<gl::ProcAddress>(symbol);
}
bool HeadlessBackend::hasDisplay() {

View File

@@ -1,7 +1,5 @@
#include <mbgl/gl/headless_backend.hpp>
#include <mbgl/gl/extension.hpp>
#include <OpenGLES/EAGL.h>
#include <stdexcept>
@@ -29,7 +27,7 @@ struct EAGLImpl : public HeadlessBackend::Impl {
EAGLContext* glContext = nullptr;
};
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
if (!framework) {
throw std::runtime_error("Failed to load OpenGL framework.");
@@ -39,7 +37,7 @@ gl::glProc HeadlessBackend::initializeExtension(const char* name) {
void* symbol = CFBundleGetFunctionPointerForName(framework, str);
CFRelease(str);
return reinterpret_cast<gl::glProc>(symbol);
return reinterpret_cast<gl::ProcAddress>(symbol);
}
bool HeadlessBackend::hasDisplay() {

View File

@@ -25,7 +25,7 @@ struct OSMesaImpl : public HeadlessBackend::Impl {
GLubyte fakeBuffer = 0;
};
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
return OSMesaGetProcAddress(name);
}

View File

@@ -33,11 +33,6 @@ void HeadlessBackend::activate() {
assert(hasContext());
impl->activateContext();
if (!extensionsLoaded) {
gl::InitializeExtensions(initializeExtension);
extensionsLoaded = true;
}
}
void HeadlessBackend::deactivate() {

View File

@@ -1,7 +1,5 @@
#pragma once
#include <mbgl/gl/extension.hpp>
#include <mbgl/map/backend.hpp>
#include <memory>
@@ -27,7 +25,7 @@ public:
private:
// Implementation specific functions
static gl::glProc initializeExtension(const char*);
gl::ProcAddress initializeExtension(const char*) override;
void activate() override;
void deactivate() override;
@@ -40,7 +38,6 @@ private:
std::unique_ptr<Impl> impl;
std::shared_ptr<HeadlessDisplay> display;
bool extensionsLoaded = false;
bool active = false;
};

View File

@@ -4,7 +4,6 @@
#include <mbgl/sprite/sprite_image.hpp>
#include <mbgl/style/transition_options.hpp>
#include <mbgl/gl/gl.hpp>
#include <mbgl/gl/extension.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/util/logging.hpp>
#include <mbgl/util/platform.hpp>
@@ -86,8 +85,6 @@ GLFWView::GLFWView(bool fullscreen_, bool benchmark_)
glfwSetScrollCallback(window, onScroll);
glfwSetKeyCallback(window, onKey);
mbgl::gl::InitializeExtensions(glfwGetProcAddress);
glfwGetWindowSize(window, &width, &height);
glfwGetFramebufferSize(window, &fbWidth, &fbHeight);
pixelRatio = static_cast<float>(fbWidth) / width;
@@ -499,6 +496,10 @@ mbgl::Size GLFWView::getFramebufferSize() const {
return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) };
}
mbgl::gl::ProcAddress GLFWView::initializeExtension(const char* name) {
return glfwGetProcAddress(name);
}
void GLFWView::activate() {
glfwMakeContextCurrent(window);
}

View File

@@ -44,9 +44,13 @@ public:
mbgl::Size getFramebufferSize() const;
// mbgl::Backend implementation
void invalidate() override;
protected:
// mbgl::Backend implementation
mbgl::gl::ProcAddress initializeExtension(const char*) override;
void activate() override;
void deactivate() override;
void invalidate() override;
private:
// Window callbacks

View File

@@ -1,7 +1,6 @@
#import "MGLMapView_Private.h"
#include <mbgl/util/logging.hpp>
#include <mbgl/gl/extension.hpp>
#include <mbgl/gl/context.hpp>
#import <GLKit/GLKit.h>
@@ -610,21 +609,6 @@ public:
[_glView bindDrawable];
[self insertSubview:_glView atIndex:0];
_glView.contentMode = UIViewContentModeCenter;
// load extensions
//
mbgl::gl::InitializeExtensions([](const char * name) {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
if (!framework) {
throw std::runtime_error("Failed to load OpenGL framework.");
}
CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
void* symbol = CFBundleGetFunctionPointerForName(framework, str);
CFRelease(str);
return reinterpret_cast<mbgl::gl::glProc>(symbol);
});
}
- (UIImage *)compassImage
@@ -5436,6 +5420,20 @@ public:
[nativeView didFinishLoadingStyle];
}
mbgl::gl::ProcAddress initializeExtension(const char* name) override {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
if (!framework) {
throw std::runtime_error("Failed to load OpenGL framework.");
}
CFStringRef str =
CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
void* symbol = CFBundleGetFunctionPointerForName(framework, str);
CFRelease(str);
return reinterpret_cast<mbgl::gl::ProcAddress>(symbol);
}
void invalidate() override
{
[nativeView setNeedsGLDisplay];

View File

@@ -60,7 +60,7 @@ struct EGLImpl : public HeadlessBackend::Impl {
EGLSurface glSurface = EGL_NO_SURFACE;
};
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
return eglGetProcAddress(name);
}

View File

@@ -44,7 +44,7 @@ struct GLXImpl : public HeadlessBackend::Impl {
GLXFBConfig* fbConfigs = nullptr;
};
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
}

View File

@@ -26,7 +26,6 @@
#import <mbgl/map/camera.hpp>
#import <mbgl/storage/reachability.h>
#import <mbgl/util/default_thread_pool.hpp>
#import <mbgl/gl/extension.hpp>
#import <mbgl/gl/context.hpp>
#import <mbgl/map/backend.hpp>
#import <mbgl/map/backend_scope.hpp>
@@ -768,19 +767,6 @@ public:
- (void)renderSync {
if (!self.dormant) {
// Enable vertex buffer objects.
mbgl::gl::InitializeExtensions([](const char *name) {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
if (!framework) {
throw std::runtime_error("Failed to load OpenGL framework.");
}
CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
void *symbol = CFBundleGetFunctionPointerForName(framework, str);
CFRelease(str);
return reinterpret_cast<mbgl::gl::glProc>(symbol);
});
// The OpenGL implementation automatically enables the OpenGL context for us.
mbgl::BackendScope scope { *_mbglView, mbgl::BackendScope::ScopeType::Implicit };
@@ -2846,6 +2832,19 @@ public:
[nativeView sourceDidChange];
}
mbgl::gl::ProcAddress initializeExtension(const char* name) override {
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
if (!framework) {
throw std::runtime_error("Failed to load OpenGL framework.");
}
CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
void *symbol = CFBundleGetFunctionPointerForName(framework, str);
CFRelease(str);
return reinterpret_cast<mbgl::gl::ProcAddress>(symbol);
}
void invalidate() override {
[nativeView setNeedsGLDisplay];
}

View File

@@ -372,8 +372,6 @@ void MapWindow::wheelEvent(QWheelEvent *ev)
void MapWindow::initializeGL()
{
QMapbox::initializeGLExtensions();
m_map.reset(new QMapboxGL(nullptr, m_settings, size(), pixelRatio()));
connect(m_map.data(), SIGNAL(needsRendering()), this, SLOT(update()));

View File

@@ -97,8 +97,6 @@ typedef void (*CustomLayerInitializeFunction)(void* context) ;
typedef void (*CustomLayerRenderFunction)(void* context, const CustomLayerRenderParameters&);
typedef void (*CustomLayerDeinitializeFunction)(void* context);
Q_DECL_EXPORT void initializeGLExtensions();
} // namespace QMapbox
Q_DECLARE_METATYPE(QMapbox::Coordinate);

View File

@@ -1,6 +1,5 @@
#include "qmapbox.hpp"
#include <mbgl/gl/extension.hpp>
#include <mbgl/storage/network_status.hpp>
#include <mbgl/util/default_styles.hpp>
#include <mbgl/util/geometry.hpp>
@@ -255,26 +254,4 @@ Q_DECL_EXPORT QList<QPair<QString, QString> >& defaultStyles()
return styles;
}
/*!
\fn void QMapbox::initializeGLExtensions()
Initializes the OpenGL extensions such as Vertex Array Objects (VAOs),
required by Mapbox GL Native engine.
Should be called only once, after an OpenGL context is available.
Consecutive calls are ignored.
*/
Q_DECL_EXPORT void initializeGLExtensions()
{
mbgl::gl::InitializeExtensions([](const char* name) {
#if QT_VERSION >= 0x050000
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
return thisContext->getProcAddress(name);
#else
const QGLContext* thisContext = QGLContext::currentContext();
return reinterpret_cast<mbgl::gl::glProc>(thisContext->getProcAddress(name));
#endif
});
}
} // namespace QMapbox

View File

@@ -1678,6 +1678,20 @@ void QMapboxGLPrivate::onSourceChanged(mbgl::style::Source&)
emit mapChanged(QMapboxGL::MapChangeSourceDidChange);
}
/*!
Initializes an OpenGL extension function such as Vertex Array Objects (VAOs),
required by Mapbox GL Native engine.
*/
mbgl::gl::ProcAddress QMapboxGLPrivate::initializeExtension(const char* name) {
#if QT_VERSION >= 0x050000
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
return thisContext->getProcAddress(name);
#else
const QGLContext* thisContext = QGLContext::currentContext();
return reinterpret_cast<mbgl::gl::ProcAddress>(thisContext->getProcAddress(name));
#endif
}
void QMapboxGLPrivate::connectionEstablished()
{
mbgl::NetworkStatus::Reachable();

View File

@@ -58,6 +58,9 @@ public:
bool dirty { false };
private:
mbgl::gl::ProcAddress initializeExtension(const char*) override;
public slots:
void connectionEstablished();

View File

@@ -24,13 +24,13 @@ struct QtImpl : public HeadlessBackend::Impl {
QGLWidget widget;
};
gl::glProc HeadlessBackend::initializeExtension(const char* name) {
gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
#if QT_VERSION >= 0x050000
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
return thisContext->getProcAddress(name);
#else
const QGLContext* thisContext = QGLContext::currentContext();
return reinterpret_cast<mbgl::gl::glProc>(thisContext->getProcAddress(name));
return reinterpret_cast<gl::ProcAddress>(thisContext->getProcAddress(name));
#endif
}

View File

@@ -20,8 +20,6 @@ public:
this, SLOT(onMapChanged(QMapboxGL::MapChange)));
connect(&map, SIGNAL(needsRendering()),
this, SLOT(onNeedsRendering()));
QMapbox::initializeGLExtensions();
map.resize(fbo.size(), fbo.size());
map.setFramebufferObject(fbo.handle());
map.setCoordinateZoom(QMapbox::Coordinate(60.170448, 24.942046), 14);

View File

@@ -1,7 +1,6 @@
#include <mbgl/gl/extension.hpp>
#include <mbgl/gl/gl.hpp>
#include <mutex>
#include <string>
#include <vector>
#include <cstring>
@@ -11,7 +10,7 @@ namespace gl {
namespace detail {
using Probes = std::vector<ExtensionFunctionBase::Probe>;
using ExtensionFunctions = std::vector<std::pair<glProc*, Probes>>;
using ExtensionFunctions = std::vector<std::pair<ProcAddress*, Probes>>;
ExtensionFunctions& extensionFunctions() {
static ExtensionFunctions functions;
return functions;
@@ -23,22 +22,18 @@ ExtensionFunctionBase::ExtensionFunctionBase(std::initializer_list<Probe> probes
} // namespace detail
static std::once_flag initializeExtensionsOnce;
void InitializeExtensions(glProc (*getProcAddress)(const char*)) {
std::call_once(initializeExtensionsOnce, [getProcAddress] {
if (const char* extensions =
reinterpret_cast<const char*>(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)))) {
for (auto fn : detail::extensionFunctions()) {
for (auto probe : fn.second) {
if (strstr(extensions, probe.first) != nullptr) {
*fn.first = getProcAddress(probe.second);
break;
}
void initializeExtensions(const std::function<ProcAddress(const char*)>& getProcAddress) {
if (const char* extensions =
reinterpret_cast<const char*>(MBGL_CHECK_ERROR(glGetString(GL_EXTENSIONS)))) {
for (auto fn : detail::extensionFunctions()) {
for (auto probe : fn.second) {
if (strstr(extensions, probe.first) != nullptr) {
*fn.first = getProcAddress(probe.second);
break;
}
}
}
});
}
}
} // namespace gl

View File

@@ -2,12 +2,13 @@
#include <initializer_list>
#include <utility>
#include <functional>
namespace mbgl {
namespace gl {
using glProc = void (*)();
void InitializeExtensions(glProc (*getProcAddress)(const char*));
using ProcAddress = void (*)();
void initializeExtensions(const std::function<ProcAddress(const char*)>&);
namespace detail {
@@ -15,7 +16,7 @@ class ExtensionFunctionBase {
public:
using Probe = std::pair<const char*, const char*>;
ExtensionFunctionBase(std::initializer_list<Probe>);
glProc ptr;
ProcAddress ptr;
};
} // namespace detail

View File

@@ -1,16 +1,23 @@
#include <mbgl/map/backend.hpp>
#include <mbgl/map/backend_scope.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/extension.hpp>
#include <mbgl/gl/debugging.hpp>
#include <cassert>
namespace mbgl {
Backend::Backend() : context(std::make_unique<gl::Context>()) {
}
Backend::Backend() = default;
gl::Context& Backend::getContext() {
assert(BackendScope::exists());
std::call_once(initialized, [this] {
context = std::make_unique<gl::Context>();
gl::debugging::enable();
gl::initializeExtensions(
std::bind(&Backend::initializeExtension, this, std::placeholders::_1));
});
return *context;
}

View File

@@ -94,8 +94,6 @@ Painter::Painter(gl::Context& context_,
tileBorderSegments.emplace_back(0, 0, 4, 5);
rasterSegments.emplace_back(0, 0, 4, 6);
gl::debugging::enable();
programs = std::make_unique<Programs>(context,
ProgramParameters{ pixelRatio, false, programCacheDir });
#ifndef NDEBUG