summaryrefslogtreecommitdiff
path: root/platform/default/src/mbgl/gl/headless_backend.cpp
blob: 732e4babae02fcbcc49c843de07f5ea4ac443398 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <mbgl/gl/headless_backend.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gfx/backend_scope.hpp>

#include <cassert>
#include <stdexcept>
#include <type_traits>

namespace mbgl {
namespace gl {

class HeadlessRenderableResource final : public gl::RenderableResource {
public:
    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(const Size size_, const gfx::ContextMode contextMode_)
    : mbgl::gl::RendererBackend(contextMode_), mbgl::gfx::HeadlessBackend(size_) {
}

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<HeadlessRenderableResource>(static_cast<gl::Context&>(getContext()), size);
    }
    return *this;
}

void HeadlessBackend::updateAssumedState() {
    // no-op
}

PremultipliedImage HeadlessBackend::readStillImage() {
    return static_cast<gl::Context&>(getContext()).readFramebuffer<PremultipliedImage>(size);
}

RendererBackend* HeadlessBackend::getRendererBackend() {
    return this;
}

} // namespace gl

namespace gfx {

template <>
std::unique_ptr<gfx::HeadlessBackend>
Backend::Create<gfx::Backend::Type::OpenGL>(const Size size, const gfx::ContextMode contextMode) {
    return std::make_unique<gl::HeadlessBackend>(size, contextMode);
}

} // namespace gfx
} // namespace mbgl