]> git.tdb.fi Git - libs/gl.git/blob - source/backends/opengl/buffer_backend.cpp
Add correct copy and move semantics to most classes
[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         // TODO check if it's mapped
95         if(ARB_direct_state_access)
96                 return glUnmapNamedBuffer(id);
97         else if(OES_mapbuffer)
98         {
99                 bind_scratch();
100                 bool result = glUnmapBuffer(GL_ARRAY_BUFFER);
101                 return result;
102         }
103         else
104                 return true;
105 }
106
107 void OpenGLBuffer::set_debug_name(const string &name)
108 {
109 #ifdef DEBUG
110         if(KHR_debug)
111                 glObjectLabel(GL_BUFFER, id, name.size(), name.c_str());
112 #else
113         (void)name;
114 #endif
115 }
116
117 void OpenGLBuffer::bind_scratch()
118 {
119         if(scratch_binding!=this)
120         {
121                 glBindBuffer(GL_ARRAY_BUFFER, id);
122                 scratch_binding = this;
123         }
124 }
125
126 void OpenGLBuffer::unbind_scratch()
127 {
128         if(scratch_binding)
129         {
130                 glBindBuffer(GL_ARRAY_BUFFER, 0);
131                 scratch_binding = 0;
132         }
133 }
134
135 } // namespace GL
136 } // namespace Msp