[core] move HeadlessBackend extension initialization code into Impl
This commit is contained in:
@@ -41,7 +41,7 @@ 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 initializeExtension(const char*) = 0;
|
||||
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:
|
||||
|
||||
@@ -66,7 +66,6 @@ macro(mbgl_platform_core)
|
||||
PRIVATE platform/default/mbgl/map/map_snapshotter.cpp
|
||||
PRIVATE platform/default/mbgl/map/map_snapshotter.hpp
|
||||
PRIVATE platform/linux/src/headless_backend_egl.cpp
|
||||
PRIVATE platform/linux/src/headless_display_egl.cpp
|
||||
)
|
||||
|
||||
target_include_directories(mbgl-core
|
||||
@@ -341,15 +340,6 @@ macro(mbgl_platform_test)
|
||||
|
||||
# Main test entry point
|
||||
platform/android/src/test/main.jni.cpp
|
||||
|
||||
# Headless view
|
||||
platform/default/mbgl/gl/headless_frontend.cpp
|
||||
platform/default/mbgl/gl/headless_frontend.hpp
|
||||
platform/default/mbgl/gl/headless_backend.cpp
|
||||
platform/default/mbgl/gl/headless_backend.hpp
|
||||
|
||||
platform/linux/src/headless_backend_egl.cpp
|
||||
platform/linux/src/headless_display_egl.cpp
|
||||
)
|
||||
|
||||
target_include_directories(mbgl-test
|
||||
|
||||
@@ -21,7 +21,7 @@ void AndroidRendererBackend::bind() {
|
||||
/**
|
||||
* From mbgl::RendererBackend.
|
||||
*/
|
||||
gl::ProcAddress AndroidRendererBackend::initializeExtension(const char* name) {
|
||||
gl::ProcAddress AndroidRendererBackend::getExtensionFunctionPointer(const char* name) {
|
||||
assert(BackendScope::exists());
|
||||
return eglGetProcAddress(name);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ public:
|
||||
|
||||
protected:
|
||||
// mbgl::RendererBackend //
|
||||
gl::ProcAddress initializeExtension(const char*) override;
|
||||
gl::ProcAddress getExtensionFunctionPointer(const char*) override;
|
||||
void activate() override {};
|
||||
void deactivate() override {};
|
||||
|
||||
|
||||
@@ -65,8 +65,9 @@ public:
|
||||
CGLPixelFormatObj pixelFormat = nullptr;
|
||||
};
|
||||
|
||||
struct CGLImpl : public HeadlessBackend::Impl {
|
||||
CGLImpl() {
|
||||
class CGLBackendImpl : public HeadlessBackend::Impl {
|
||||
public:
|
||||
CGLBackendImpl() {
|
||||
CGLError error = CGLCreateContext(cglDisplay->pixelFormat, nullptr, &glContext);
|
||||
if (error != kCGLNoError) {
|
||||
throw std::runtime_error(std::string("Error creating GL context object:") +
|
||||
@@ -80,10 +81,24 @@ struct CGLImpl : public HeadlessBackend::Impl {
|
||||
}
|
||||
}
|
||||
|
||||
~CGLImpl() final {
|
||||
~CGLBackendImpl() final {
|
||||
CGLDestroyContext(glContext);
|
||||
}
|
||||
|
||||
gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
|
||||
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<gl::ProcAddress>(symbol);
|
||||
}
|
||||
|
||||
void activateContext() final {
|
||||
CGLError error = CGLSetCurrentContext(glContext);
|
||||
if (error != kCGLNoError) {
|
||||
@@ -105,23 +120,9 @@ private:
|
||||
CGLContextObj glContext = nullptr;
|
||||
};
|
||||
|
||||
gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
|
||||
assert(hasContext());
|
||||
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<gl::ProcAddress>(symbol);
|
||||
}
|
||||
|
||||
void HeadlessBackend::createContext() {
|
||||
assert(!hasContext());
|
||||
impl = std::make_unique<CGLImpl>();
|
||||
void HeadlessBackend::createImpl() {
|
||||
assert(!impl);
|
||||
impl = std::make_unique<CGLBackendImpl>();
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -6,8 +6,9 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
struct EAGLImpl : public HeadlessBackend::Impl {
|
||||
EAGLImpl() {
|
||||
class EAGLBackendImpl : public HeadlessBackend::Impl {
|
||||
public:
|
||||
EAGLBackendImpl() {
|
||||
glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
if (glContext == nil) {
|
||||
throw std::runtime_error("Error creating GL context object");
|
||||
@@ -16,7 +17,21 @@ struct EAGLImpl : public HeadlessBackend::Impl {
|
||||
}
|
||||
|
||||
// Required for ARC to deallocate correctly.
|
||||
~EAGLImpl() final = default;
|
||||
~EAGLBackendImpl() final = default;
|
||||
|
||||
gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
|
||||
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<gl::ProcAddress>(symbol);
|
||||
}
|
||||
|
||||
void activateContext() final {
|
||||
[EAGLContext setCurrentContext:glContext];
|
||||
@@ -30,22 +45,9 @@ private:
|
||||
EAGLContext* glContext = nullptr;
|
||||
};
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
CFStringRef str = CFStringCreateWithCString(kCFAllocatorDefault, name, kCFStringEncodingASCII);
|
||||
void* symbol = CFBundleGetFunctionPointerForName(framework, str);
|
||||
CFRelease(str);
|
||||
|
||||
return reinterpret_cast<gl::ProcAddress>(symbol);
|
||||
}
|
||||
|
||||
void HeadlessBackend::createContext() {
|
||||
assert(!hasContext());
|
||||
impl = std::make_unique<EAGLImpl>();
|
||||
void HeadlessBackend::createImpl() {
|
||||
assert(!impl);
|
||||
impl = std::make_unique<EAGLBackendImpl>();
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -7,8 +7,9 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
struct OSMesaImpl : public HeadlessBackend::Impl {
|
||||
OSMesaImpl() {
|
||||
class OSMesaBackendImpl : public HeadlessBackend::Impl {
|
||||
public:
|
||||
OSMesaBackendImpl() {
|
||||
#if OSMESA_MAJOR_VERSION * 100 + OSMESA_MINOR_VERSION >= 305
|
||||
glContext = OSMesaCreateContextExt(OSMESA_RGBA, 16, 0, 0, nullptr);
|
||||
#else
|
||||
@@ -19,10 +20,14 @@ struct OSMesaImpl : public HeadlessBackend::Impl {
|
||||
}
|
||||
}
|
||||
|
||||
~OSMesaImpl() final {
|
||||
~OSMesaBackendImpl() final {
|
||||
OSMesaDestroyContext(glContext);
|
||||
}
|
||||
|
||||
gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
|
||||
return OSMesaGetProcAddress(name);
|
||||
}
|
||||
|
||||
void activateContext() final {
|
||||
if (!OSMesaMakeCurrent(glContext, &fakeBuffer, GL_UNSIGNED_BYTE, 1, 1)) {
|
||||
throw std::runtime_error("Switching OpenGL context failed.\n");
|
||||
@@ -34,13 +39,9 @@ private:
|
||||
GLubyte fakeBuffer = 0;
|
||||
};
|
||||
|
||||
gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
|
||||
return OSMesaGetProcAddress(name);
|
||||
}
|
||||
|
||||
void HeadlessBackend::createContext() {
|
||||
assert(!hasContext());
|
||||
impl = std::make_unique<OSMesaImpl>();
|
||||
void HeadlessBackend::createImpl() {
|
||||
assert(!impl);
|
||||
impl = std::make_unique<OSMesaBackendImpl>();
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -31,19 +31,24 @@ HeadlessBackend::~HeadlessBackend() {
|
||||
context.reset();
|
||||
}
|
||||
|
||||
gl::ProcAddress HeadlessBackend::getExtensionFunctionPointer(const char* name) {
|
||||
assert(impl);
|
||||
return impl->getExtensionFunctionPointer(name);
|
||||
}
|
||||
|
||||
void HeadlessBackend::activate() {
|
||||
active = true;
|
||||
|
||||
if (!hasContext()) {
|
||||
createContext();
|
||||
if (!impl) {
|
||||
createImpl();
|
||||
}
|
||||
|
||||
assert(hasContext());
|
||||
assert(impl);
|
||||
impl->activateContext();
|
||||
}
|
||||
|
||||
void HeadlessBackend::deactivate() {
|
||||
assert(hasContext());
|
||||
assert(impl);
|
||||
impl->deactivateContext();
|
||||
active = false;
|
||||
}
|
||||
|
||||
@@ -19,23 +19,24 @@ public:
|
||||
void setSize(Size);
|
||||
PremultipliedImage readStillImage();
|
||||
|
||||
struct Impl {
|
||||
class Impl {
|
||||
public:
|
||||
virtual ~Impl() = default;
|
||||
virtual gl::ProcAddress getExtensionFunctionPointer(const char*) = 0;
|
||||
virtual void activateContext() = 0;
|
||||
virtual void deactivateContext() {}
|
||||
};
|
||||
|
||||
private:
|
||||
// Implementation specific functions
|
||||
gl::ProcAddress initializeExtension(const char*) override;
|
||||
gl::ProcAddress getExtensionFunctionPointer(const char*) override;
|
||||
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
bool hasContext() const { return bool(impl); }
|
||||
|
||||
void createContext();
|
||||
void createImpl();
|
||||
|
||||
private:
|
||||
std::unique_ptr<Impl> impl;
|
||||
|
||||
Size size;
|
||||
|
||||
@@ -540,7 +540,7 @@ mbgl::Size GLFWView::getFramebufferSize() const {
|
||||
return { static_cast<uint32_t>(fbWidth), static_cast<uint32_t>(fbHeight) };
|
||||
}
|
||||
|
||||
mbgl::gl::ProcAddress GLFWView::initializeExtension(const char* name) {
|
||||
mbgl::gl::ProcAddress GLFWView::getExtensionFunctionPointer(const char* name) {
|
||||
return glfwGetProcAddress(name);
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
|
||||
protected:
|
||||
// mbgl::Backend implementation
|
||||
mbgl::gl::ProcAddress initializeExtension(const char*) override;
|
||||
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override;
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
|
||||
|
||||
@@ -6031,7 +6031,7 @@ public:
|
||||
[nativeView didFinishLoadingStyle];
|
||||
}
|
||||
|
||||
mbgl::gl::ProcAddress initializeExtension(const char* name) override {
|
||||
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char* name) override {
|
||||
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengles"));
|
||||
if (!framework) {
|
||||
throw std::runtime_error("Failed to load OpenGL framework.");
|
||||
|
||||
@@ -66,8 +66,9 @@ public:
|
||||
EGLConfig config = 0;
|
||||
};
|
||||
|
||||
struct EGLImpl : public HeadlessBackend::Impl {
|
||||
EGLImpl() {
|
||||
class EGLBackendImpl : public HeadlessBackend::Impl {
|
||||
public:
|
||||
EGLBackendImpl() {
|
||||
// EGL initializes the context client version to 1 by default. We want to
|
||||
// use OpenGL ES 2.0 which has the ability to create shader and program
|
||||
// objects and also to write vertex and fragment shaders in the OpenGL ES
|
||||
@@ -101,7 +102,7 @@ struct EGLImpl : public HeadlessBackend::Impl {
|
||||
}
|
||||
}
|
||||
|
||||
~EGLImpl() final {
|
||||
~EGLBackendImpl() final {
|
||||
if (eglSurface != EGL_NO_SURFACE) {
|
||||
if (!eglDestroySurface(eglDisplay->display, eglSurface)) {
|
||||
Log::Error(Event::OpenGL, "Failed to destroy EGL surface.");
|
||||
@@ -113,6 +114,10 @@ struct EGLImpl : public HeadlessBackend::Impl {
|
||||
}
|
||||
}
|
||||
|
||||
gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
|
||||
return eglGetProcAddress(name);
|
||||
}
|
||||
|
||||
void activateContext() final {
|
||||
if (!eglMakeCurrent(eglDisplay->display, eglSurface, eglSurface, eglContext)) {
|
||||
throw std::runtime_error("Switching OpenGL context failed.\n");
|
||||
@@ -131,13 +136,9 @@ private:
|
||||
EGLSurface eglSurface = EGL_NO_SURFACE;
|
||||
};
|
||||
|
||||
gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
|
||||
return eglGetProcAddress(name);
|
||||
}
|
||||
|
||||
void HeadlessBackend::createContext() {
|
||||
assert(!hasContext());
|
||||
impl = std::make_unique<EGLImpl>();
|
||||
void HeadlessBackend::createImpl() {
|
||||
assert(!impl);
|
||||
impl = std::make_unique<EGLBackendImpl>();
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -70,8 +70,9 @@ public:
|
||||
GLXFBConfig* fbConfigs = nullptr;
|
||||
};
|
||||
|
||||
struct GLXImpl : public HeadlessBackend::Impl {
|
||||
GLXImpl() {
|
||||
class GLXBackendImpl : public HeadlessBackend::Impl {
|
||||
public:
|
||||
GLXBackendImpl() {
|
||||
// Try to create a legacy context.
|
||||
glContext = glXCreateNewContext(glxDisplay->xDisplay, glxDisplay->fbConfigs[0],
|
||||
GLX_RGBA_TYPE, None, True);
|
||||
@@ -91,13 +92,17 @@ struct GLXImpl : public HeadlessBackend::Impl {
|
||||
glXCreatePbuffer(glxDisplay->xDisplay, glxDisplay->fbConfigs[0], pbufferAttributes);
|
||||
}
|
||||
|
||||
~GLXImpl() final {
|
||||
~GLXBackendImpl() final {
|
||||
if (glxPbuffer) {
|
||||
glXDestroyPbuffer(glxDisplay->xDisplay, glxPbuffer);
|
||||
}
|
||||
glXDestroyContext(glxDisplay->xDisplay, glContext);
|
||||
}
|
||||
|
||||
gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
|
||||
return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
|
||||
}
|
||||
|
||||
void activateContext() final {
|
||||
if (!glXMakeContextCurrent(glxDisplay->xDisplay, glxPbuffer, glxPbuffer, glContext)) {
|
||||
throw std::runtime_error("Switching OpenGL context failed.\n");
|
||||
@@ -117,13 +122,9 @@ private:
|
||||
GLXPbuffer glxPbuffer = 0;
|
||||
};
|
||||
|
||||
gl::ProcAddress HeadlessBackend::initializeExtension(const char* name) {
|
||||
return glXGetProcAddress(reinterpret_cast<const GLubyte*>(name));
|
||||
}
|
||||
|
||||
void HeadlessBackend::createContext() {
|
||||
assert(!hasContext());
|
||||
impl = std::make_unique<GLXImpl>();
|
||||
void HeadlessBackend::createImpl() {
|
||||
assert(!impl);
|
||||
impl = std::make_unique<GLXBackendImpl>();
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -2887,7 +2887,7 @@ public:
|
||||
[nativeView sourceDidChange:nativeSource];
|
||||
}
|
||||
|
||||
mbgl::gl::ProcAddress initializeExtension(const char* name) override {
|
||||
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char* name) override {
|
||||
static CFBundleRef framework = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl"));
|
||||
if (!framework) {
|
||||
throw std::runtime_error("Failed to load OpenGL framework.");
|
||||
|
||||
@@ -12,9 +12,19 @@
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class QtImpl : public HeadlessBackend::Impl {
|
||||
class QtBackendImpl : public HeadlessBackend::Impl {
|
||||
public:
|
||||
~QtImpl() final = default;
|
||||
~QtBackendImpl() final = default;
|
||||
|
||||
gl::ProcAddress getExtensionFunctionPointer(const char* name) final {
|
||||
#if QT_VERSION >= 0x050000
|
||||
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
|
||||
return thisContext->getProcAddress(name);
|
||||
#else
|
||||
const QGLContext* thisContext = QGLContext::currentContext();
|
||||
return reinterpret_cast<gl::ProcAddress>(thisContext->getProcAddress(name));
|
||||
#endif
|
||||
}
|
||||
|
||||
void activateContext() final {
|
||||
widget.makeCurrent();
|
||||
@@ -28,19 +38,9 @@ private:
|
||||
QGLWidget widget;
|
||||
};
|
||||
|
||||
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<gl::ProcAddress>(thisContext->getProcAddress(name));
|
||||
#endif
|
||||
}
|
||||
|
||||
void HeadlessBackend::createContext() {
|
||||
assert(!hasContext());
|
||||
impl = std::make_unique<QtImpl>();
|
||||
void HeadlessBackend::createImpl() {
|
||||
assert(!impl);
|
||||
impl = std::make_unique<QtBackendImpl>();
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1695,7 +1695,7 @@ void QMapboxGLPrivate::onSourceChanged(mbgl::style::Source&)
|
||||
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) {
|
||||
mbgl::gl::ProcAddress QMapboxGLPrivate::getExtensionFunctionPointer(const char* name) {
|
||||
#if QT_VERSION >= 0x050000
|
||||
QOpenGLContext* thisContext = QOpenGLContext::currentContext();
|
||||
return thisContext->getProcAddress(name);
|
||||
|
||||
@@ -61,7 +61,7 @@ public:
|
||||
bool dirty { false };
|
||||
|
||||
private:
|
||||
mbgl::gl::ProcAddress initializeExtension(const char*) override;
|
||||
mbgl::gl::ProcAddress getExtensionFunctionPointer(const char*) override;
|
||||
|
||||
public slots:
|
||||
void connectionEstablished();
|
||||
|
||||
@@ -16,7 +16,7 @@ gl::Context& RendererBackend::getContext() {
|
||||
context = std::make_unique<gl::Context>();
|
||||
context->enableDebugging();
|
||||
context->initializeExtensions(
|
||||
std::bind(&RendererBackend::initializeExtension, this, std::placeholders::_1));
|
||||
std::bind(&RendererBackend::getExtensionFunctionPointer, this, std::placeholders::_1));
|
||||
});
|
||||
return *context;
|
||||
}
|
||||
|
||||
@@ -28,18 +28,13 @@ public:
|
||||
if (updateAssumedStateFunction) updateAssumedStateFunction();
|
||||
}
|
||||
|
||||
gl::ProcAddress initializeExtension(const char* ext) override {
|
||||
if (initializeExtensionFunction) {
|
||||
return initializeExtensionFunction(ext);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
gl::ProcAddress getExtensionFunctionPointer(const char*) override {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::function<void ()> activateFunction;
|
||||
std::function<void ()> deactivateFunction;
|
||||
std::function<void ()> updateAssumedStateFunction;
|
||||
std::function<gl::ProcAddress (const char*)> initializeExtensionFunction;
|
||||
};
|
||||
|
||||
// A scope should activate on construction
|
||||
|
||||
Reference in New Issue
Block a user