]> git.tdb.fi Git - libs/gl.git/blob - source/bufferable.cpp
Align uniform blocks properly
[libs/gl.git] / source / bufferable.cpp
1 #include <stdexcept>
2 #include "buffer.h"
3 #include "bufferable.h"
4
5 using namespace std;
6
7 namespace Msp {
8 namespace GL {
9
10 Bufferable::Bufferable():
11         buffer(0),
12         buffer_offset(0),
13         next_in_buffer(0),
14         prev_in_buffer(0),
15         dirty(false)
16 { }
17
18 Bufferable::~Bufferable()
19 {
20         unlink_from_buffer();
21 }
22
23 void Bufferable::use_buffer(Buffer *buf, Bufferable *prev)
24 {
25         if(prev && buf!=prev->buffer)
26                 throw invalid_argument("Bufferable::use_buffer");
27
28         if(buffer)
29                 unlink_from_buffer();
30
31         buffer = buf;
32         if(buffer)
33         {
34                 prev_in_buffer = prev;
35                 if(prev_in_buffer)
36                         prev_in_buffer->next_in_buffer = this;
37         }
38
39         update_buffer_offset();
40 }
41
42 void Bufferable::unlink_from_buffer()
43 {
44         if(prev_in_buffer)
45                 prev_in_buffer->next_in_buffer = next_in_buffer;
46         if(next_in_buffer)
47         {
48                 next_in_buffer->prev_in_buffer = prev_in_buffer;
49                 next_in_buffer->update_buffer_offset();
50         }
51         prev_in_buffer = 0;
52         next_in_buffer = 0;
53 }
54
55 void Bufferable::update_buffer_offset()
56 {
57         unsigned offset = 0;
58         if(prev_in_buffer)
59                 offset = prev_in_buffer->buffer_offset+prev_in_buffer->get_data_size();
60
61         unsigned align = get_alignment();
62         offset += align-1;
63         offset -= offset%align;
64         if(offset!=buffer_offset)
65         {
66                 buffer_offset = offset;
67                 dirty = true;
68                 offset_changed();
69         }
70
71         if(next_in_buffer)
72                 next_in_buffer->update_buffer_offset();
73
74         /* Do not resize the buffer here, as the offsets may change multiple times
75         before the buffer is actually used */
76 }
77
78 void Bufferable::update_buffer_data() const
79 {
80         if(buffer_offset+get_data_size()>=buffer->get_size())
81         {
82                 const Bufferable *last = this;
83                 for(; last->next_in_buffer; last=last->next_in_buffer) ;
84
85                 unsigned total_size = last->buffer_offset+last->get_data_size();
86
87                 if(total_size>buffer->get_size())
88                 {
89                         buffer->data(total_size, 0);
90                         /* Resizing the buffer invalidates its contents.  Non-dirty data may
91                         be in use, so reupload it. */
92                         for(const Bufferable *b=last; b; b=b->prev_in_buffer)
93                                 if(!b->dirty)
94                                         b->upload_data();
95                 }
96         }
97
98         upload_data();
99         dirty = false;
100 }
101
102 } // namespace GL
103 } // namespace Msp