summaryrefslogtreecommitdiff
path: root/src/mbgl/gl/offscreen_texture.cpp
blob: 5feef95edfbde923695a428e166af12064f77549 (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
#include <mbgl/gl/offscreen_texture.hpp>
#include <mbgl/gl/renderable_resource.hpp>
#include <mbgl/gl/context.hpp>
#include <mbgl/gl/framebuffer.hpp>

namespace mbgl {
namespace gl {

class OffscreenTextureResource final : public gl::RenderableResource {
public:
    OffscreenTextureResource(gl::Context& context_,
                             const Size size_,
                             const gfx::TextureChannelDataType type_)
        : context(context_), size(size_), type(type_) {
        assert(!size.isEmpty());
    }

    OffscreenTextureResource(gl::Context& context_,
                             const Size size_,
                             gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>& depth_,
                             const gfx::TextureChannelDataType type_)
        : context(context_), size(size_), depth(&depth_), type(type_) {
        assert(!size.isEmpty());
    }

    void bind() override {
        if (!framebuffer) {
            assert(!texture);
            texture = context.createTexture(size, gfx::TexturePixelType::RGBA, type);
            if (depth) {
                framebuffer = context.createFramebuffer(*texture, *depth);
            } else {
                framebuffer = context.createFramebuffer(*texture);
            }
        } else {
            context.bindFramebuffer = framebuffer->framebuffer;
        }

        context.activeTextureUnit = 0;
        context.scissorTest = false;
        context.viewport = { 0, 0, size };
    }

    PremultipliedImage readStillImage() {
        assert(framebuffer);
        context.bindFramebuffer = framebuffer->framebuffer;
        return context.readFramebuffer<PremultipliedImage>(size);
    }

    gfx::Texture& getTexture() {
        assert(texture);
        return *texture;
    }

private:
    gl::Context& context;
    const Size size;
    optional<gfx::Texture> texture;
    gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>* depth = nullptr;
    const gfx::TextureChannelDataType type;
    optional<gl::Framebuffer> framebuffer;
};

OffscreenTexture::OffscreenTexture(gl::Context& context,
                                   const Size size_,
                                   const gfx::TextureChannelDataType type)
    : gfx::OffscreenTexture(size, std::make_unique<OffscreenTextureResource>(context, size_, type)) {
}

OffscreenTexture::OffscreenTexture(
    gl::Context& context,
    const Size size_,
    gfx::Renderbuffer<gfx::RenderbufferPixelType::Depth>& renderbuffer,
    const gfx::TextureChannelDataType type)
    : gfx::OffscreenTexture(
          size, std::make_unique<OffscreenTextureResource>(context, size_, renderbuffer, type)) {
}

bool OffscreenTexture::isRenderable() {
    try {
        getResource<OffscreenTextureResource>().bind();
        return true;
    } catch (const std::runtime_error& ex) {
        return false;
    }
}

PremultipliedImage OffscreenTexture::readStillImage() {
    return getResource<OffscreenTextureResource>().readStillImage();
}

gfx::Texture& OffscreenTexture::getTexture() {
    return getResource<OffscreenTextureResource>().getTexture();
}

} // namespace gl
} // namespace mbgl