]> git.tdb.fi Git - libs/gl.git/blob - source/core/buffer.cpp
Remove remaining deprecated things from the core classes
[libs/gl.git] / source / core / buffer.cpp
1 #include <stdexcept>
2 #include <msp/gl/extensions/arb_buffer_storage.h>
3 #include <msp/gl/extensions/arb_direct_state_access.h>
4 #include <msp/gl/extensions/arb_map_buffer_range.h>
5 #include <msp/gl/extensions/arb_vertex_buffer_object.h>
6 #include <msp/gl/extensions/khr_debug.h>
7 #include <msp/gl/extensions/oes_mapbuffer.h>
8 #include <msp/strings/format.h>
9 #include "buffer.h"
10 #include "error.h"
11
12 using namespace std;
13
14 namespace Msp {
15 namespace GL {
16
17 Buffer *Buffer::scratch_binding = 0;
18
19 Buffer::Buffer():
20         size(0),
21         allocated(false)
22 {
23         static Require _req(ARB_vertex_buffer_object);
24
25         if(ARB_direct_state_access)
26                 glCreateBuffers(1, &id);
27         else
28                 glGenBuffers(1, &id);
29 }
30
31 Buffer::~Buffer()
32 {
33         if(this==scratch_binding)
34                 unbind_scratch();
35         glDeleteBuffers(1, &id);
36 }
37
38 void Buffer::storage(unsigned sz)
39 {
40         if(size>0)
41         {
42                 if(sz!=size)
43                         throw incompatible_data("Buffer::storage");
44                 return;
45         }
46         if(sz==0)
47                 throw invalid_argument("Buffer::storage");
48
49         size = sz;
50 }
51
52 void Buffer::allocate()
53 {
54         if(size==0)
55                 throw invalid_operation("Buffer::allocate");
56         if(allocated)
57                 return;
58
59         if(ARB_buffer_storage)
60         {
61                 static const int flags = GL_MAP_READ_BIT|GL_MAP_WRITE_BIT|GL_DYNAMIC_STORAGE_BIT;
62                 if(ARB_direct_state_access)
63                         glNamedBufferStorage(id, size, 0, flags);
64                 else
65                 {
66                         bind_scratch();
67                         glBufferStorage(GL_ARRAY_BUFFER, size, 0, flags);
68                 }
69
70                 allocated = true;
71         }
72         else
73                 data(0);
74 }
75
76 void Buffer::data(const void *d)
77 {
78         if(size==0)
79                 throw invalid_operation("Buffer::data");
80
81         if(ARB_buffer_storage)
82                 return sub_data(0, size, d);
83
84         if(ARB_direct_state_access)
85                 glNamedBufferData(id, size, d, GL_STATIC_DRAW);
86         else
87         {
88                 bind_scratch();
89                 glBufferData(GL_ARRAY_BUFFER, size, d, GL_STATIC_DRAW);
90         }
91
92         allocated = true;
93 }
94
95 void Buffer::sub_data(unsigned off, unsigned sz, const void *d)
96 {
97         if(size==0)
98                 throw invalid_operation("Buffer::sub_data");
99
100         allocate();
101
102         if(ARB_direct_state_access)
103                 glNamedBufferSubData(id, off, sz, d);
104         else
105         {
106                 bind_scratch();
107                 glBufferSubData(GL_ARRAY_BUFFER, off, sz, d);
108         }
109 }
110
111 void Buffer::require_size(unsigned req_sz) const
112 {
113         if(size<req_sz)
114                 throw buffer_too_small(format("buffer has %d bytes; %d required", size, req_sz));
115 }
116
117 void *Buffer::map()
118 {
119         static Require _req(ARB_map_buffer_range);
120
121         allocate();
122         if(ARB_direct_state_access)
123                 return glMapNamedBufferRange(id, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
124         else
125         {
126                 bind_scratch();
127                 void *result = glMapBufferRange(GL_ARRAY_BUFFER, 0, size, GL_MAP_READ_BIT|GL_MAP_WRITE_BIT);
128                 return result;
129         }
130 }
131
132 bool Buffer::unmap()
133 {
134         // TODO check if it's mapped
135         if(ARB_direct_state_access)
136                 return glUnmapNamedBuffer(id);
137         else if(OES_mapbuffer)
138         {
139                 bind_scratch();
140                 bool result = glUnmapBuffer(GL_ARRAY_BUFFER);
141                 return result;
142         }
143         else
144                 return true;
145 }
146
147 void Buffer::set_debug_name(const string &name)
148 {
149 #ifdef DEBUG
150         if(KHR_debug)
151                 glObjectLabel(GL_BUFFER, id, name.size(), name.c_str());
152 #else
153         (void)name;
154 #endif
155 }
156
157 void Buffer::bind_scratch()
158 {
159         if(scratch_binding!=this)
160         {
161                 glBindBuffer(GL_ARRAY_BUFFER, id);
162                 scratch_binding = this;
163         }
164 }
165
166 void Buffer::unbind_scratch()
167 {
168         if(scratch_binding)
169         {
170                 glBindBuffer(GL_ARRAY_BUFFER, 0);
171                 scratch_binding = 0;
172         }
173 }
174
175 } // namespace GL
176 } // namespace Msp