diff options
Diffstat (limited to 'gfx/src/core/buffer.c')
-rw-r--r-- | gfx/src/core/buffer.c | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/gfx/src/core/buffer.c b/gfx/src/core/buffer.c new file mode 100644 index 0000000..3b7e4bc --- /dev/null +++ b/gfx/src/core/buffer.c | |||
@@ -0,0 +1,85 @@ | |||
1 | #include "buffer.h" | ||
2 | |||
3 | #include <gfx/core.h> | ||
4 | #include <gfx_assert.h> | ||
5 | |||
6 | #include <math/vec2.h> | ||
7 | #include <math/vec3.h> | ||
8 | #include <math/vec4.h> | ||
9 | |||
10 | static size_t get_buffer_size_bytes( | ||
11 | BufferType type, const BufferDataDesc* desc) { | ||
12 | return desc->count * gfx_get_buffer_type_size_bytes(type); | ||
13 | } | ||
14 | |||
15 | static GLenum get_buffer_usage(BufferUsage usage) { | ||
16 | switch (usage) { | ||
17 | case BufferStatic: | ||
18 | return GL_STATIC_DRAW; | ||
19 | case BufferDynamic: | ||
20 | return GL_DYNAMIC_DRAW; | ||
21 | } | ||
22 | FAIL("Unhandled buffer usage"); | ||
23 | return GL_STATIC_DRAW; | ||
24 | } | ||
25 | |||
26 | size_t gfx_get_buffer_type_size_bytes(BufferType type) { | ||
27 | switch (type) { | ||
28 | case BufferUntyped: | ||
29 | return 1; | ||
30 | case Buffer2d: | ||
31 | return sizeof(vec2); | ||
32 | case Buffer3d: | ||
33 | return sizeof(vec3); | ||
34 | case Buffer4d: | ||
35 | return sizeof(vec4); | ||
36 | case BufferFloat: | ||
37 | return sizeof(float); | ||
38 | case BufferU8: | ||
39 | return sizeof(uint8_t); | ||
40 | case BufferU16: | ||
41 | return sizeof(uint16_t); | ||
42 | } | ||
43 | FAIL("Unhandled buffer type"); | ||
44 | return 0; | ||
45 | } | ||
46 | |||
47 | bool gfx_init_buffer(Buffer* buffer, const BufferDesc* desc) { | ||
48 | assert(buffer); | ||
49 | |||
50 | buffer->type = desc->type; | ||
51 | buffer->usage = desc->usage; | ||
52 | buffer->size_bytes = get_buffer_size_bytes(desc->type, &desc->data); | ||
53 | const GLenum usage = get_buffer_usage(desc->usage); | ||
54 | |||
55 | glGenBuffers(1, &buffer->vbo); | ||
56 | glBindBuffer(GL_ARRAY_BUFFER, buffer->vbo); | ||
57 | glBufferData(GL_ARRAY_BUFFER, buffer->size_bytes, desc->data.data, usage); | ||
58 | glBindBuffer(GL_ARRAY_BUFFER, 0); | ||
59 | ASSERT_GL; | ||
60 | |||
61 | return true; | ||
62 | } | ||
63 | |||
64 | void gfx_del_buffer(Buffer* buffer) { | ||
65 | assert(buffer); | ||
66 | if (buffer->vbo) { | ||
67 | glDeleteBuffers(1, &buffer->vbo); | ||
68 | buffer->vbo = 0; | ||
69 | } | ||
70 | } | ||
71 | |||
72 | void gfx_update_buffer(Buffer* buffer, const BufferDataDesc* desc) { | ||
73 | assert(buffer); | ||
74 | assert(desc); | ||
75 | // OpenGL allows updating static buffers, but it is not optimal for | ||
76 | // performance, so we enforce data in static buffers remain static. | ||
77 | assert(buffer->usage == BufferDynamic); | ||
78 | |||
79 | const size_t update_size_bytes = get_buffer_size_bytes(buffer->type, desc); | ||
80 | assert(update_size_bytes <= buffer->size_bytes); | ||
81 | |||
82 | glBindBuffer(GL_ARRAY_BUFFER, buffer->vbo); | ||
83 | glBufferSubData(GL_ARRAY_BUFFER, 0, update_size_bytes, desc->data); | ||
84 | glBindBuffer(GL_ARRAY_BUFFER, 0); | ||
85 | } | ||