]> git.tdb.fi Git - libs/gl.git/blob - source/backends/opengl/buffer_backend.cpp
Add support for padding in vertex formats
[libs/gl.git] / source / backends / opengl / buffer_backend.cpp
1 #include <msp/gl/extensions/arb_buffer_storage.h>
2 #include <msp/gl/extensions/arb_direct_state_access.h>
3 #include <msp/gl/extensions/arb_map_buffer_range.h>
4 #include <msp/gl/extensions/arb_vertex_buffer_object.h>
5 #include <msp/gl/extensions/khr_debug.h>
6 #include <msp/gl/extensions/oes_mapbuffer.h>
7 #include "buffer.h"
8 #include "buffer_backend.h"
9
10 using namespace std;
11
12 namespace Msp {
13 namespace GL {
14
15 OpenGLBuffer *OpenGLBuffer::scratch_binding = 0;
16
17 OpenGLBuffer::OpenGLBuffer()
18 {
19         static Require _req(ARB_vertex_buffer_object);
20
21         if(ARB_direct_state_access)
22                 glCreateBuffers(1, &id);
23         else
24                 glGenBuffers(1, &id);
25 }
26
27 OpenGLBuffer::OpenGLBuffer(OpenGLBuffer &&other):
28         id(other.id)
29 {
30         other.id = 0;
31 }
32
33 OpenGLBuffer::~OpenGLBuffer()
34 {
35         if(this==scratch_binding)
36                 unbind_scratch();
37         if(id)
38                 glDeleteBuffers(1, &id);
39 }
40
41 void OpenGLBuffer::allocate()
42 {
43         size_t size = static_cast<const Buffer *>(this)->size;
44
45         if(ARB_buffer_storage)
46         {
47                 static const int flags = GL_MAP_READ_BIT|GL_MAP_WRITE_BIT|GL_DYNAMIC_STORAGE_BIT;
48                 if(ARB_direct_state_access)
49                         glNamedBufferStorage(id, size, 0, flags);
50                 else
51                 {
52                         bind_scratch();
53                         glBufferStorage(GL_ARRAY_BUFFER, size, 0, flags);
54                 }
55         }
56         else if(ARB_direct_state_access)
57                 glNamedBufferData(id, size, 0, GL_STATIC_DRAW);
58         else
59         {
60                 bind_scratch();
61                 glBufferData(GL_ARRAY_BUFFER, size, 0, GL_STATIC_DRAW);
62         }
63 }
64
65 void OpenGLBuffer::sub_data(size_t off, size_t sz, const void *d)
66 {
67         if(ARB_direct_state_access)
68                 glNamedBufferSubData(id, off, sz, d);
69         else
70         {
71                 bind_scratch();
72                 glBufferSubData(GL_ARRAY_BUFFER, off, sz, d);
73         }
74 }
75
76 void *OpenGLBuffer::map()
77 {
78         static Require _req(ARB_map_buffer_range);
79
80         size_t size = static_cast<const Buffer *>(this)->size;
81
82         if(ARB_direct_state_access)
83                 return glMapNamedBufferRange(id, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
84         else
85         {
86                 bind_scratch();
87                 void *result = glMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
88                 return result;
89         }
90 }
91
92 bool OpenGLBuffer::unmap()
93 {
94         if(ARB_direct_state_access)
95                 return glUnmapNamedBuffer(id);
96         else if(OES_mapbuffer)
97         {
98                 bind_scratch();
99                 bool result = glUnmapBuffer(GL_ARRAY_BUFFER);
100                 return result;
101         }
102         else
103                 return true;
104 }
105
106 void OpenGLBuffer::set_debug_name(const string &name)
107 {
108 #ifdef DEBUG
109         if(KHR_debug)
110                 glObjectLabel(GL_BUFFER, id, name.size(), name.c_str());
111 #else
112         (void)name;
113 #endif
114 }
115
116 void OpenGLBuffer::bind_scratch()
117 {
118         if(scratch_binding!=this)
119         {
120                 glBindBuffer(GL_ARRAY_BUFFER, id);
121                 scratch_binding = this;
122         }
123 }
124
125 void OpenGLBuffer::unbind_scratch()
126 {
127         if(scratch_binding)
128         {
129                 glBindBuffer(GL_ARRAY_BUFFER, 0);
130                 scratch_binding = 0;
131         }
132 }
133
134 } // namespace GL
135 } // namespace Msp