]> git.tdb.fi Git - libs/gl.git/blob - source/backends/opengl/buffer_backend.cpp
a0404e7b143066a479efe1c67f33adb117aa0676
[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()
28 {
29         if(this==scratch_binding)
30                 unbind_scratch();
31         glDeleteBuffers(1, &id);
32 }
33
34 void OpenGLBuffer::allocate()
35 {
36         size_t size = static_cast<const Buffer *>(this)->size;
37
38         if(ARB_buffer_storage)
39         {
40                 static const int flags = GL_MAP_READ_BIT|GL_MAP_WRITE_BIT|GL_DYNAMIC_STORAGE_BIT;
41                 if(ARB_direct_state_access)
42                         glNamedBufferStorage(id, size, 0, flags);
43                 else
44                 {
45                         bind_scratch();
46                         glBufferStorage(GL_ARRAY_BUFFER, size, 0, flags);
47                 }
48         }
49         else if(ARB_direct_state_access)
50                 glNamedBufferData(id, size, 0, GL_STATIC_DRAW);
51         else
52         {
53                 bind_scratch();
54                 glBufferData(GL_ARRAY_BUFFER, size, 0, GL_STATIC_DRAW);
55         }
56 }
57
58 void OpenGLBuffer::sub_data(size_t off, size_t sz, const void *d)
59 {
60         if(ARB_direct_state_access)
61                 glNamedBufferSubData(id, off, sz, d);
62         else
63         {
64                 bind_scratch();
65                 glBufferSubData(GL_ARRAY_BUFFER, off, sz, d);
66         }
67 }
68
69 void *OpenGLBuffer::map()
70 {
71         static Require _req(ARB_map_buffer_range);
72
73         size_t size = static_cast<const Buffer *>(this)->size;
74
75         if(ARB_direct_state_access)
76                 return glMapNamedBufferRange(id, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
77         else
78         {
79                 bind_scratch();
80                 void *result = glMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
81                 return result;
82         }
83 }
84
85 bool OpenGLBuffer::unmap()
86 {
87         // TODO check if it's mapped
88         if(ARB_direct_state_access)
89                 return glUnmapNamedBuffer(id);
90         else if(OES_mapbuffer)
91         {
92                 bind_scratch();
93                 bool result = glUnmapBuffer(GL_ARRAY_BUFFER);
94                 return result;
95         }
96         else
97                 return true;
98 }
99
100 void OpenGLBuffer::set_debug_name(const string &name)
101 {
102 #ifdef DEBUG
103         if(KHR_debug)
104                 glObjectLabel(GL_BUFFER, id, name.size(), name.c_str());
105 #else
106         (void)name;
107 #endif
108 }
109
110 void OpenGLBuffer::bind_scratch()
111 {
112         if(scratch_binding!=this)
113         {
114                 glBindBuffer(GL_ARRAY_BUFFER, id);
115                 scratch_binding = this;
116         }
117 }
118
119 void OpenGLBuffer::unbind_scratch()
120 {
121         if(scratch_binding)
122         {
123                 glBindBuffer(GL_ARRAY_BUFFER, 0);
124                 scratch_binding = 0;
125         }
126 }
127
128 } // namespace GL
129 } // namespace Msp