1 #include "graphicsbuffer.h"
3 #define GL_GLEXT_PROTOTYPES
4 #include <SDL_opengl.h>
9 static GLenum BufferUsageToGLUsage(GraphicsBuffer::BufferUsage buffer_usage)
14 case GraphicsBuffer::BufferUsageStaticDraw:
15 usage = GL_STATIC_DRAW;
17 case GraphicsBuffer::BufferUsageStaticRead:
18 usage = GL_STATIC_READ;
20 case GraphicsBuffer::BufferUsageStaticCopy:
21 usage = GL_STATIC_COPY;
23 case GraphicsBuffer::BufferUsageDynamicDraw:
24 usage = GL_DYNAMIC_DRAW;
26 case GraphicsBuffer::BufferUsageDynamicRead:
27 usage = GL_DYNAMIC_READ;
29 case GraphicsBuffer::BufferUsageDynamicCopy:
30 usage = GL_DYNAMIC_COPY;
32 case GraphicsBuffer::BufferUsageStreamDraw:
33 usage = GL_STREAM_DRAW;
35 case GraphicsBuffer::BufferUsageStreamRead:
36 usage = GL_STREAM_READ;
38 case GraphicsBuffer::BufferUsageStreamCopy:
39 usage = GL_STREAM_COPY;
42 SDL_assert(false && "Unknown buffer usage type.");
43 usage = GL_DYNAMIC_DRAW;
48 static GLenum BufferTypeToGLType(GraphicsBuffer::BufferType buffer_type)
52 case GraphicsBuffer::BufferTypeVertex:
53 return GL_ARRAY_BUFFER;
54 case GraphicsBuffer::BufferTypeIndex:
55 return GL_ELEMENT_ARRAY_BUFFER;
56 case GraphicsBuffer::BufferTypePixelPack:
57 return GL_PIXEL_PACK_BUFFER;
58 case GraphicsBuffer::BufferTypePixelUnpack:
59 return GL_PIXEL_UNPACK_BUFFER;
60 case GraphicsBuffer::BufferTypeUniform:
61 return GL_UNIFORM_BUFFER;
62 case GraphicsBuffer::BufferTypeDrawIndirect:
63 return GL_DRAW_INDIRECT_BUFFER;
65 return GL_COPY_READ_BUFFER;
69 GraphicsBuffer::GraphicsBuffer()
72 m_map_pointer = nullptr;
74 m_buffer_shape_dirty = true;
75 SetUsage(BufferUsageStaticDraw);
78 GraphicsBuffer::~GraphicsBuffer()
84 glDeleteBuffers(1, &m_buffer_handle);
87 void GraphicsBuffer::SetType(GraphicsBuffer::BufferType bufType)
89 m_buffer_type = bufType;
92 void GraphicsBuffer::SetUsage(GraphicsBuffer::BufferUsage bufUsage)
94 if (bufUsage != m_buffer_usage)
96 m_buffer_usage = bufUsage;
97 m_buffer_shape_dirty = true;
101 void GraphicsBuffer::Invalidate()
103 m_invalidated = true;
104 // Apparently not supported.
105 //glInvalidateBufferData(m_buffer_handle);
108 void GraphicsBuffer::RecreateBuffer()
110 // If the buffer is not dirty, don't recreate it.
111 if (!m_buffer_shape_dirty) return;
112 // If the buffer is mapped, don't recreate it.
113 if (m_map_pointer) return;
114 // If the buffer has data in it we need, don't recreate it.
115 if (!m_invalidated) return;
118 glDeleteBuffers(1, &m_buffer_handle);
120 glGenBuffers(1, &m_buffer_handle);
121 m_buffer_shape_dirty = false;
123 Upload(m_buffer_size, nullptr);
126 void* GraphicsBuffer::Map(bool read, bool write, bool invalidate)
128 GLbitfield access = ((read)?GL_MAP_READ_BIT:0) | ((write)?GL_MAP_WRITE_BIT:0) | ((invalidate)?GL_MAP_INVALIDATE_BUFFER_BIT:0);
129 GLenum target = BufferTypeToGLType(m_buffer_type);
132 m_invalidated = true;
135 Warn("Tried to map already mapped buffer!");
141 m_map_pointer = glMapBufferRange(target, 0, m_buffer_size, access);
143 return m_map_pointer;
146 void* GraphicsBuffer::MapRange(int offset, int length, bool read, bool write, bool invalidate)
148 GLbitfield access = ((read)?GL_MAP_READ_BIT:0) | ((write)?GL_MAP_WRITE_BIT:0) | ((invalidate)?GL_MAP_INVALIDATE_RANGE_BIT:0);
149 GLenum target = BufferTypeToGLType(m_buffer_type);
152 Warn("Tried to map already mapped buffer!");
158 m_map_pointer = glMapBufferRange(target, offset, length, access);
159 return m_map_pointer;
162 void GraphicsBuffer::UnMap()
164 GLenum target = BufferTypeToGLType(m_buffer_type);
167 glUnmapBuffer(target);
168 m_map_pointer = nullptr;
171 void GraphicsBuffer::Upload(size_t length, const void* data)
173 GLenum target = BufferTypeToGLType(m_buffer_type);
175 GLenum usage = BufferUsageToGLUsage(m_buffer_usage);
177 m_invalidated = true;
181 glBufferData(target, length, data, usage);
182 m_buffer_size = length;
185 void GraphicsBuffer::UploadRange(size_t length, intptr_t offset, const void* data)
187 GLenum target = BufferTypeToGLType(m_buffer_type);
192 glBufferSubData(target, offset, length, data);
195 void GraphicsBuffer::Resize(size_t length)
199 m_buffer_size = length;
204 // Create a new buffer and copy the old data into it.
206 GLuint old_buffer = m_buffer_handle;
207 glGenBuffers(1, &m_buffer_handle);
208 Upload(length, nullptr);
209 glBindBuffer(GL_COPY_READ_BUFFER, old_buffer);
210 glBindBuffer(GL_COPY_WRITE_BUFFER, m_buffer_handle);
211 glCopyBufferSubData(GL_COPY_READ_BUFFER, GL_COPY_WRITE_BUFFER, 0, 0, m_buffer_size);
212 glDeleteBuffers(1, &old_buffer);
213 m_buffer_size = length;
217 void GraphicsBuffer::Bind()
219 if (m_buffer_type == BufferTypeUniform)
220 glBindBufferBase(GL_UNIFORM_BUFFER, 0, m_buffer_handle);
222 glBindBuffer(BufferTypeToGLType(m_buffer_type), m_buffer_handle);