#include #include #include #include #include #include #include namespace mbgl { namespace gl { class HeadlessRenderableResource final : public gl::RenderableResource { public: HeadlessRenderableResource(HeadlessBackend& backend_, gl::Context& context_, Size size_) : backend(backend_), context(context_), color(context.createRenderbuffer(size_)), depthStencil(context.createRenderbuffer(size_)), framebuffer(context.createFramebuffer(color, depthStencil)) {} void bind() override { context.bindFramebuffer = framebuffer.framebuffer; context.scissorTest = false; context.viewport = { 0, 0, framebuffer.size }; } void swap() override { backend.swap(); } HeadlessBackend& backend; gl::Context& context; gfx::Renderbuffer color; gfx::Renderbuffer depthStencil; gl::Framebuffer framebuffer; }; HeadlessBackend::HeadlessBackend(const Size size_, gfx::HeadlessBackend::SwapBehaviour swapBehaviour_, const gfx::ContextMode contextMode_) : mbgl::gl::RendererBackend(contextMode_), mbgl::gfx::HeadlessBackend(size_), swapBehaviour(swapBehaviour_) {} HeadlessBackend::~HeadlessBackend() { gfx::BackendScope guard{*this}; resource.reset(); // Explicitly reset the context so that it is destructed and cleaned up before we destruct // the impl object. context.reset(); } gl::ProcAddress HeadlessBackend::getExtensionFunctionPointer(const char* name) { assert(impl); return impl->getExtensionFunctionPointer(name); } void HeadlessBackend::activate() { active = true; if (!impl) { createImpl(); } assert(impl); impl->activateContext(); } void HeadlessBackend::deactivate() { assert(impl); impl->deactivateContext(); active = false; } gfx::Renderable& HeadlessBackend::getDefaultRenderable() { if (!resource) { resource = std::make_unique(*this, static_cast(getContext()), size); } return *this; } void HeadlessBackend::swap() { if (swapBehaviour == SwapBehaviour::Flush) static_cast(getContext()).finish(); } void HeadlessBackend::updateAssumedState() { // no-op } PremultipliedImage HeadlessBackend::readStillImage() { return static_cast(getContext()).readFramebuffer(size); } RendererBackend* HeadlessBackend::getRendererBackend() { return this; } } // namespace gl namespace gfx { template <> std::unique_ptr Backend::Create( const Size size, gfx::HeadlessBackend::SwapBehaviour swapBehavior, const gfx::ContextMode contextMode) { return std::make_unique(size, swapBehavior, contextMode); } } // namespace gfx } // namespace mbgl