1 /*
2  *  GLClientAndServerBuffer.cpp
3  *  FreeOrion
4  *
5  *  Created by Rainer Kupke on 06.02.11.
6  *  Copyright 2011. All rights reserved.
7  *
8  */
9 
10 #include <GG/GLClientAndServerBuffer.h>
11 
12 namespace GG {
13 
14 ///////////////////////////////////////////////////////////////////////////
15 // GLBufferBase
16 ///////////////////////////////////////////////////////////////////////////
GLBufferBase()17 GLBufferBase::GLBufferBase() :
18     b_name(0)
19 {}
20 
~GLBufferBase()21 GLBufferBase::~GLBufferBase()
22 { dropServerBuffer(); }
23 
dropServerBuffer()24 void GLBufferBase::dropServerBuffer()
25 {
26     if (b_name) {
27         glDeleteBuffers(1, &b_name);
28         b_name = 0;
29     }
30 }
31 
harmonizeBufferType(GLBufferBase & other)32 void GLBufferBase::harmonizeBufferType(GLBufferBase& other)
33 {
34     if (b_name && other.b_name) return; // OK, both have server buffer
35 
36     if (b_name || other.b_name) {       // NOT OK, only one has server buffer, drop buffer
37         dropServerBuffer();
38         other.dropServerBuffer();
39     }
40 }
41 
42 ///////////////////////////////////////////////////////////////////////////
43 // GLClientAndServerBufferBase<vtype> template
44 ///////////////////////////////////////////////////////////////////////////
45 template <typename vtype>
GLClientAndServerBufferBase(std::size_t elementsPerItem)46 GLClientAndServerBufferBase<vtype>::GLClientAndServerBufferBase(std::size_t elementsPerItem) :
47     GLBufferBase(),
48     b_data(),
49     b_size(0),
50     b_elements_per_item(elementsPerItem)
51 {}
52 
53 template <typename vtype>
size() const54 std::size_t GLClientAndServerBufferBase<vtype>::size() const
55 { return b_size; }
56 
57 template <typename vtype>
empty() const58 bool GLClientAndServerBufferBase<vtype>::empty() const
59 { return b_size == 0; }
60 
61 template <typename vtype>
reserve(std::size_t num_items)62 void GLClientAndServerBufferBase<vtype>::reserve(std::size_t num_items)
63 { b_data.reserve(num_items * b_elements_per_item); }
64 
65 template <typename vtype>
store(vtype item)66 void GLClientAndServerBufferBase<vtype>::store(vtype item)
67 {
68     b_data.push_back(item);
69     b_size=b_data.size() / b_elements_per_item;
70 }
71 
72 template <typename vtype>
store(vtype item1,vtype item2)73 void GLClientAndServerBufferBase<vtype>::store(vtype item1, vtype item2)
74 {
75     b_data.push_back(item1);
76     b_data.push_back(item2);
77     b_size=b_data.size() / b_elements_per_item;
78 }
79 
80 template <typename vtype>
store(vtype item1,vtype item2,vtype item3)81 void GLClientAndServerBufferBase<vtype>::store(vtype item1, vtype item2, vtype item3)
82 {
83     b_data.push_back(item1);
84     b_data.push_back(item2);
85     b_data.push_back(item3);
86     b_size=b_data.size() / b_elements_per_item;
87 }
88 
89 template <typename vtype>
store(vtype item1,vtype item2,vtype item3,vtype item4)90 void GLClientAndServerBufferBase<vtype>::store(vtype item1, vtype item2, vtype item3, vtype item4)
91 {
92     b_data.push_back(item1);
93     b_data.push_back(item2);
94     b_data.push_back(item3);
95     b_data.push_back(item4);
96     b_size=b_data.size() / b_elements_per_item;
97 }
98 
99 template <typename vtype>
createServerBuffer()100 void GLClientAndServerBufferBase<vtype>::createServerBuffer()
101 {
102     glGenBuffers(1, &b_name);
103     if (!b_name)
104         return;
105     glBindBuffer(GL_ARRAY_BUFFER, b_name);
106     glBufferData(GL_ARRAY_BUFFER,
107                  b_data.size() * sizeof(vtype),
108                  b_data.empty() ? nullptr : &b_data[0],
109                  GL_STATIC_DRAW);
110     glBindBuffer(GL_ARRAY_BUFFER, 0);
111 }
112 
113 template <typename vtype>
clear()114 void GLClientAndServerBufferBase<vtype>::clear()
115 {
116     dropServerBuffer();
117     b_size = 0;
118     b_data.clear();
119 }
120 
121 ///////////////////////////////////////////////////////////////////////////
122 // GLRGBAColorBuffer
123 ///////////////////////////////////////////////////////////////////////////
124 template class GLClientAndServerBufferBase<unsigned char>;
125 
GLRGBAColorBuffer()126 GLRGBAColorBuffer::GLRGBAColorBuffer() :
127 GLClientAndServerBufferBase<unsigned char>(4)
128 {}
129 
store(const Clr & color)130 void GLRGBAColorBuffer::store(const Clr& color)
131 { GLClientAndServerBufferBase::store(color.r, color.g, color.b, color.a); }
132 
activate() const133 void GLRGBAColorBuffer::activate() const
134 {
135     if (b_name) {
136         glBindBuffer(GL_ARRAY_BUFFER, b_name);
137         glColorPointer(4, GL_UNSIGNED_BYTE, 0, nullptr);
138         glBindBuffer(GL_ARRAY_BUFFER, 0);
139     } else {
140         glColorPointer(4, GL_UNSIGNED_BYTE, 0, b_data.empty() ? nullptr: &b_data[0]);
141     }
142 }
143 
144 ///////////////////////////////////////////////////////////////////////////
145 // GL2DVertexBuffer
146 ///////////////////////////////////////////////////////////////////////////
147 template class GLClientAndServerBufferBase<float>;
148 
GL2DVertexBuffer()149 GL2DVertexBuffer::GL2DVertexBuffer() :
150     GLClientAndServerBufferBase<float>(2)
151 {}
152 
store(const Pt & pt)153 void GL2DVertexBuffer::store(const Pt& pt)
154 { store(pt.x, pt.y); }
155 
store(X x,Y y)156 void GL2DVertexBuffer::store(X x, Y y)
157 { GLClientAndServerBufferBase::store(Value(x), Value(y)); }
158 
store(X x,float y)159 void GL2DVertexBuffer::store(X x, float y)
160 { GLClientAndServerBufferBase::store(Value(x), y); }
161 
store(float x,Y y)162 void GL2DVertexBuffer::store(float x, Y y)
163 { GLClientAndServerBufferBase::store(x, Value(y)); }
164 
store(float x,float y)165 void GL2DVertexBuffer::store(float x, float y)
166 { GLClientAndServerBufferBase::store(x, y); }
167 
activate() const168 void GL2DVertexBuffer::activate() const
169 {
170     if (b_name) {
171         glBindBuffer(GL_ARRAY_BUFFER, b_name);
172         glVertexPointer(2, GL_FLOAT, 0, nullptr);
173         glBindBuffer(GL_ARRAY_BUFFER, 0);
174     } else {
175         glVertexPointer(2, GL_FLOAT, 0, b_data.empty() ? nullptr: &b_data[0]);
176     }
177 }
178 
179 
180 ///////////////////////////////////////////////////////////////////////////
181 // GLTexCoordBuffer
182 ///////////////////////////////////////////////////////////////////////////
GLTexCoordBuffer()183 GLTexCoordBuffer::GLTexCoordBuffer() :
184     GLClientAndServerBufferBase<float>(2)
185 {}
186 
activate() const187 void GLTexCoordBuffer::activate() const
188 {
189     if (b_name) {
190         glBindBuffer(GL_ARRAY_BUFFER, b_name);
191         glTexCoordPointer(2, GL_FLOAT, 0, nullptr);
192         glBindBuffer(GL_ARRAY_BUFFER, 0);
193     } else {
194         glTexCoordPointer(2, GL_FLOAT, 0, b_data.empty() ? nullptr: &b_data[0]);
195     }
196 }
197 
198 
199 ///////////////////////////////////////////////////////////////////////////
200 // GL3DVertexBuffer
201 ///////////////////////////////////////////////////////////////////////////
GL3DVertexBuffer()202 GL3DVertexBuffer::GL3DVertexBuffer() :
203     GLClientAndServerBufferBase<float>(3)
204 {}
205 
store(float x,float y,float z)206 void GL3DVertexBuffer::store(float x, float y, float z)
207 { GLClientAndServerBufferBase::store(x, y, z); }
208 
activate() const209 void GL3DVertexBuffer::activate() const
210 {
211     if (b_name) {
212         glBindBuffer(GL_ARRAY_BUFFER, b_name);
213         glVertexPointer(3, GL_FLOAT, 0, nullptr);
214         glBindBuffer(GL_ARRAY_BUFFER, 0);
215     } else {
216         glVertexPointer(3, GL_FLOAT, 0, b_data.empty() ? nullptr: &b_data[0]);
217     }
218 }
219 
220 
221 ///////////////////////////////////////////////////////////////////////////
222 // GLNormalBuffer
223 ///////////////////////////////////////////////////////////////////////////
GLNormalBuffer()224 GLNormalBuffer::GLNormalBuffer() :
225     GLClientAndServerBufferBase<float>(3)
226 {}
227 
activate() const228 void GLNormalBuffer::activate() const
229 {
230     if (b_name) {
231         glBindBuffer(GL_ARRAY_BUFFER, b_name);
232         glNormalPointer(GL_FLOAT, 0, nullptr);
233         glBindBuffer(GL_ARRAY_BUFFER, 0);
234     } else {
235         glNormalPointer(GL_FLOAT, 0, b_data.empty() ? nullptr: &b_data[0]);
236     }
237 }
238 
239 }
240