summaryrefslogtreecommitdiff
path: root/src/mbgl/gl/gl_object_store.hpp
blob: 6a115df0cbfd543f694238f83fd01fa56b0126c8 (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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#ifndef MBGL_MAP_UTIL_GL_OBJECT_STORE
#define MBGL_MAP_UTIL_GL_OBJECT_STORE

#include <mbgl/gl/gl.hpp>
#include <mbgl/util/noncopyable.hpp>

#include <array>
#include <algorithm>
#include <memory>
#include <vector>

namespace mbgl {
namespace gl {

class GLHolder : private util::noncopyable {
public:
    GLHolder() {}

    GLHolder(GLHolder&& o) noexcept : id(o.id) { o.id = 0; }
    GLHolder& operator=(GLHolder&& o) noexcept { id = o.id; o.id = 0; return *this; }

    explicit operator bool() const { return id; }
    GLuint getID() const { return id; }

protected:
    GLuint id = 0;
};

class ProgramHolder : public GLHolder {
public:
    ProgramHolder() = default;
    ~ProgramHolder() { reset(); }

    ProgramHolder(ProgramHolder&& o) noexcept : GLHolder(std::move(o)) {}
    ProgramHolder& operator=(ProgramHolder&& o) noexcept { GLHolder::operator=(std::move(o)); return *this; }

    void create();
    void reset();
};

class ShaderHolder : public GLHolder {
public:
    ShaderHolder(GLenum type_) : type(type_) {}
    ~ShaderHolder() { reset(); }

    ShaderHolder(ShaderHolder&& o) noexcept : GLHolder(std::move(o)), type(o.type) {}
    ShaderHolder& operator=(ShaderHolder&& o) noexcept { GLHolder::operator=(std::move(o)); type = o.type; return *this; }

    void create();
    void reset();

private:
    GLenum type = 0;
};

class BufferHolder : public GLHolder {
public:
    BufferHolder() = default;
    ~BufferHolder() { reset(); }

    BufferHolder(BufferHolder&& o) noexcept : GLHolder(std::move(o)) {}
    BufferHolder& operator=(BufferHolder&& o) noexcept { GLHolder::operator=(std::move(o)); return *this; }

    void create();
    void reset();
};

class TextureHolder : public GLHolder {
public:
    TextureHolder() = default;
    ~TextureHolder() { reset(); }

    TextureHolder(TextureHolder&& o) noexcept : GLHolder(std::move(o)) {}
    TextureHolder& operator=(TextureHolder&& o) noexcept { GLHolder::operator=(std::move(o)); return *this; }

    void create();
    void reset();
};

class TexturePoolHolder : private util::noncopyable {
public:
    static const GLsizei TextureMax = 64;

    TexturePoolHolder() { ids.fill(0); }
    ~TexturePoolHolder() { reset(); }

    TexturePoolHolder(TexturePoolHolder&& o) noexcept : ids(std::move(o.ids)) {}
    TexturePoolHolder& operator=(TexturePoolHolder&& o) noexcept { ids = std::move(o.ids); return *this; }

    explicit operator bool() { return std::none_of(ids.begin(), ids.end(), [](int id) { return id == 0; }); }
    const std::array<GLuint, TextureMax>& getIDs() const { return ids; }
    const GLuint& operator[](size_t pos) { return ids[pos]; }

    void create();
    void reset();

private:
    std::array<GLuint, TextureMax> ids;
};

class GLObjectStore : private util::noncopyable {
public:
    // Mark OpenGL objects for deletion
    void abandonVAO(GLuint vao);
    void abandon(BufferHolder&&);
    void abandon(TextureHolder&&);
    void abandon(TexturePoolHolder&&);

    // Actually remove the objects we marked as abandoned with the above methods.
    // Only call this while the OpenGL context is exclusive to this thread.
    void performCleanup();

private:
    // We split the holder objects in separate containers because each
    // GLHolder-derived object can vary in size.
    std::vector<GLuint> abandonedVAOs;
    std::vector<BufferHolder> abandonedBuffers;
    std::vector<TextureHolder> abandonedTextures;
    std::vector<TexturePoolHolder> abandonedTexturePools;
};

} // namespace gl
} // namespace mbgl

#endif