1 /* Copyright (C) 2015 Wildfire Games.
2 * This file is part of 0 A.D.
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
18 #include "precompiled.h"
20 #include "lib/alignment.h"
22 #include "lib/sysdep/rtl.h"
23 #include "maths/Vector3D.h"
24 #include "maths/Vector4D.h"
25 #include "ps/CLogger.h"
26 #include "graphics/Color.h"
27 #include "graphics/SColor.h"
28 #include "renderer/VertexArray.h"
29 #include "renderer/VertexBuffer.h"
30 #include "renderer/VertexBufferManager.h"
33 VertexArray::VertexArray(GLenum usage
, GLenum target
)
45 VertexArray::~VertexArray()
50 // Free all resources on destruction or when a layout parameter changes
51 void VertexArray::Free()
53 rtl_FreeAligned(m_BackingStore
);
58 g_VBMan
.Release(m_VB
);
64 // Set the number of vertices stored in the array
65 void VertexArray::SetNumVertices(size_t num
)
67 if (num
== m_NumVertices
)
75 // Add vertex attributes like Position, Normal, UV
76 void VertexArray::AddAttribute(Attribute
* attr
)
79 (attr
->type
== GL_FLOAT
|| attr
->type
== GL_SHORT
|| attr
->type
== GL_UNSIGNED_SHORT
|| attr
->type
== GL_UNSIGNED_BYTE
)
80 && "Unsupported attribute type"
82 ENSURE(attr
->elems
>= 1 && attr
->elems
<= 4);
84 attr
->vertexArray
= this;
85 m_Attributes
.push_back(attr
);
91 // Template specialization for GetIterator().
92 // We can put this into the source file because only a fixed set of types
93 // is supported for type safety.
95 VertexArrayIterator
<CVector3D
> VertexArray::Attribute::GetIterator
<CVector3D
>() const
98 ENSURE(type
== GL_FLOAT
);
101 return vertexArray
->MakeIterator
<CVector3D
>(this);
105 VertexArrayIterator
<CVector4D
> VertexArray::Attribute::GetIterator
<CVector4D
>() const
108 ENSURE(type
== GL_FLOAT
);
111 return vertexArray
->MakeIterator
<CVector4D
>(this);
115 VertexArrayIterator
<float[2]> VertexArray::Attribute::GetIterator
<float[2]>() const
118 ENSURE(type
== GL_FLOAT
);
121 return vertexArray
->MakeIterator
<float[2]>(this);
125 VertexArrayIterator
<SColor3ub
> VertexArray::Attribute::GetIterator
<SColor3ub
>() const
128 ENSURE(type
== GL_UNSIGNED_BYTE
);
131 return vertexArray
->MakeIterator
<SColor3ub
>(this);
135 VertexArrayIterator
<SColor4ub
> VertexArray::Attribute::GetIterator
<SColor4ub
>() const
138 ENSURE(type
== GL_UNSIGNED_BYTE
);
141 return vertexArray
->MakeIterator
<SColor4ub
>(this);
145 VertexArrayIterator
<u16
> VertexArray::Attribute::GetIterator
<u16
>() const
148 ENSURE(type
== GL_UNSIGNED_SHORT
);
151 return vertexArray
->MakeIterator
<u16
>(this);
155 VertexArrayIterator
<u16
[2]> VertexArray::Attribute::GetIterator
<u16
[2]>() const
158 ENSURE(type
== GL_UNSIGNED_SHORT
);
161 return vertexArray
->MakeIterator
<u16
[2]>(this);
165 VertexArrayIterator
<u8
> VertexArray::Attribute::GetIterator
<u8
>() const
168 ENSURE(type
== GL_UNSIGNED_BYTE
);
171 return vertexArray
->MakeIterator
<u8
>(this);
175 VertexArrayIterator
<u8
[4]> VertexArray::Attribute::GetIterator
<u8
[4]>() const
178 ENSURE(type
== GL_UNSIGNED_BYTE
);
181 return vertexArray
->MakeIterator
<u8
[4]>(this);
185 VertexArrayIterator
<short> VertexArray::Attribute::GetIterator
<short>() const
188 ENSURE(type
== GL_SHORT
);
191 return vertexArray
->MakeIterator
<short>(this);
195 VertexArrayIterator
<short[2]> VertexArray::Attribute::GetIterator
<short[2]>() const
198 ENSURE(type
== GL_SHORT
);
201 return vertexArray
->MakeIterator
<short[2]>(this);
204 static size_t RoundStride(size_t stride
)
215 return Align
<32>(stride
);
218 // Re-layout by assigning offsets on a first-come first-serve basis,
219 // then round up to a reasonable stride.
220 // Backing store is also created here, VBOs are created on upload.
221 void VertexArray::Layout()
227 //debug_printf("Layouting VertexArray\n");
229 for (ssize_t idx
= m_Attributes
.size()-1; idx
>= 0; --idx
)
231 Attribute
* attr
= m_Attributes
[idx
];
233 if (!attr
->type
|| !attr
->elems
)
239 case GL_UNSIGNED_BYTE
:
240 attrSize
= sizeof(GLubyte
);
243 attrSize
= sizeof(GLshort
);
245 case GL_UNSIGNED_SHORT
:
246 attrSize
= sizeof(GLushort
);
249 attrSize
= sizeof(GLfloat
);
253 debug_warn(L
"Bad Attribute::type"); break;
256 attrSize
*= attr
->elems
;
258 attr
->offset
= m_Stride
;
260 m_Stride
+= attrSize
;
262 if (m_Target
== GL_ARRAY_BUFFER
)
263 m_Stride
= Align
<4>(m_Stride
);
265 //debug_printf("%i: offset: %u\n", idx, attr->offset);
268 if (m_Target
== GL_ARRAY_BUFFER
)
269 m_Stride
= RoundStride(m_Stride
);
271 //debug_printf("Stride: %u\n", m_Stride);
274 m_BackingStore
= (char*)rtl_AllocateAligned(m_Stride
* m_NumVertices
, 16);
277 void VertexArray::PrepareForRendering()
279 m_VB
->m_Owner
->PrepareForRendering(m_VB
);
282 // (Re-)Upload the attributes.
283 // Create the VBO if necessary.
284 void VertexArray::Upload()
286 ENSURE(m_BackingStore
);
289 m_VB
= g_VBMan
.Allocate(m_Stride
, m_NumVertices
, m_Usage
, m_Target
, m_BackingStore
);
293 LOGERROR("Failed to allocate VBO for vertex array");
297 m_VB
->m_Owner
->UpdateChunkVertices(m_VB
, m_BackingStore
);
301 // Bind this array, returns the base address for calls to glVertexPointer etc.
302 u8
* VertexArray::Bind()
307 u8
* base
= m_VB
->m_Owner
->Bind();
308 base
+= m_VB
->m_Index
*m_Stride
;
313 // Free the backing store to save some memory
314 void VertexArray::FreeBackingStore()
316 // In streaming modes, the backing store must be retained
317 ENSURE(!CVertexBuffer::UseStreaming(m_Usage
));
319 rtl_FreeAligned(m_BackingStore
);
325 VertexIndexArray::VertexIndexArray(GLenum usage
) :
326 VertexArray(usage
, GL_ELEMENT_ARRAY_BUFFER
)
328 m_Attr
.type
= GL_UNSIGNED_SHORT
;
330 AddAttribute(&m_Attr
);
333 VertexArrayIterator
<u16
> VertexIndexArray::GetIterator() const
335 return m_Attr
.GetIterator
<u16
>();