]> git.tdb.fi Git - libs/gl.git/blob - source/bufferable.cpp
Explicitly bind buffer in Bufferable::update_buffer
[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         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                 {
37                         next_in_buffer = prev_in_buffer->next_in_buffer;
38                         prev_in_buffer->next_in_buffer = this;
39                 }
40         }
41
42         update_offset();
43 }
44
45 void Bufferable::unlink_from_buffer()
46 {
47         if(prev_in_buffer)
48                 prev_in_buffer->next_in_buffer = next_in_buffer;
49         if(next_in_buffer)
50         {
51                 next_in_buffer->prev_in_buffer = prev_in_buffer;
52                 next_in_buffer->update_offset();
53         }
54         prev_in_buffer = 0;
55         next_in_buffer = 0;
56         buffer = 0;
57 }
58
59 void Bufferable::update_offset()
60 {
61         unsigned new_offset = 0;
62         if(prev_in_buffer)
63                 new_offset = prev_in_buffer->offset+prev_in_buffer->get_data_size();
64
65         unsigned align = get_alignment();
66         new_offset += align-1;
67         new_offset -= new_offset%align;
68         if(new_offset!=offset)
69         {
70                 offset = new_offset;
71                 dirty = true;
72                 offset_changed();
73         }
74
75         if(next_in_buffer)
76                 next_in_buffer->update_offset();
77
78         /* Do not resize the buffer here, as more bufferables may be added before
79         the buffer is actually used. */
80 }
81
82 void Bufferable::update_buffer() const
83 {
84         const Buffer *old_buffer = Buffer::current(buffer->get_type());
85         buffer->bind();
86         if(offset+get_data_size()>=buffer->get_size())
87         {
88                 const Bufferable *last = this;
89                 for(; last->next_in_buffer; last=last->next_in_buffer) ;
90
91                 unsigned total_size = last->offset+last->get_data_size();
92
93                 if(total_size>buffer->get_size())
94                 {
95                         buffer->data(total_size, 0);
96                         /* Resizing the buffer invalidates its contents.  Non-dirty data may
97                         be in use, so reupload it. */
98                         for(const Bufferable *b=last; b; b=b->prev_in_buffer)
99                                 if(!b->dirty)
100                                         b->upload_data();
101                 }
102         }
103
104         upload_data();
105         if(old_buffer)
106                 old_buffer->bind_to(buffer->get_type());
107         else
108                 buffer->unbind();
109         dirty = false;
110 }
111
112 } // namespace GL
113 } // namespace Msp