LCOV - code coverage report
Current view: top level - source/renderer - VertexArray.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 0 148 0.0 %
Date: 2021-09-24 14:46:47 Functions: 0 23 0.0 %

          Line data    Source code
       1             : /* Copyright (C) 2015 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       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.
       8             :  *
       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.
      13             :  *
      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/>.
      16             :  */
      17             : 
      18             : #include "precompiled.h"
      19             : 
      20             : #include "lib/alignment.h"
      21             : #include "lib/ogl.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"
      31             : 
      32             : 
      33           0 : VertexArray::VertexArray(GLenum usage, GLenum target)
      34             : {
      35           0 :     m_Usage = usage;
      36           0 :     m_Target = target;
      37           0 :     m_NumVertices = 0;
      38             : 
      39           0 :     m_VB = 0;
      40           0 :     m_BackingStore = 0;
      41           0 :     m_Stride = 0;
      42           0 : }
      43             : 
      44             : 
      45           0 : VertexArray::~VertexArray()
      46             : {
      47           0 :     Free();
      48           0 : }
      49             : 
      50             : // Free all resources on destruction or when a layout parameter changes
      51           0 : void VertexArray::Free()
      52             : {
      53           0 :     rtl_FreeAligned(m_BackingStore);
      54           0 :     m_BackingStore = 0;
      55             : 
      56           0 :     if (m_VB)
      57             :     {
      58           0 :         g_VBMan.Release(m_VB);
      59           0 :         m_VB = 0;
      60             :     }
      61           0 : }
      62             : 
      63             : 
      64             : // Set the number of vertices stored in the array
      65           0 : void VertexArray::SetNumVertices(size_t num)
      66             : {
      67           0 :     if (num == m_NumVertices)
      68             :         return;
      69             : 
      70           0 :     Free();
      71           0 :     m_NumVertices = num;
      72             : }
      73             : 
      74             : 
      75             : // Add vertex attributes like Position, Normal, UV
      76           0 : void VertexArray::AddAttribute(Attribute* attr)
      77             : {
      78           0 :     ENSURE(
      79             :         (attr->type == GL_FLOAT || attr->type == GL_SHORT || attr->type == GL_UNSIGNED_SHORT || attr->type == GL_UNSIGNED_BYTE)
      80             :         && "Unsupported attribute type"
      81             :     );
      82           0 :     ENSURE(attr->elems >= 1 && attr->elems <= 4);
      83             : 
      84           0 :     attr->vertexArray = this;
      85           0 :     m_Attributes.push_back(attr);
      86             : 
      87           0 :     Free();
      88           0 : }
      89             : 
      90             : 
      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.
      94             : template<>
      95           0 : VertexArrayIterator<CVector3D> VertexArray::Attribute::GetIterator<CVector3D>() const
      96             : {
      97           0 :     ENSURE(vertexArray);
      98           0 :     ENSURE(type == GL_FLOAT);
      99           0 :     ENSURE(elems >= 3);
     100             : 
     101           0 :     return vertexArray->MakeIterator<CVector3D>(this);
     102             : }
     103             : 
     104             : template<>
     105           0 : VertexArrayIterator<CVector4D> VertexArray::Attribute::GetIterator<CVector4D>() const
     106             : {
     107           0 :     ENSURE(vertexArray);
     108           0 :     ENSURE(type == GL_FLOAT);
     109           0 :     ENSURE(elems >= 4);
     110             : 
     111           0 :     return vertexArray->MakeIterator<CVector4D>(this);
     112             : }
     113             : 
     114             : template<>
     115           0 : VertexArrayIterator<float[2]> VertexArray::Attribute::GetIterator<float[2]>() const
     116             : {
     117           0 :     ENSURE(vertexArray);
     118           0 :     ENSURE(type == GL_FLOAT);
     119           0 :     ENSURE(elems >= 2);
     120             : 
     121           0 :     return vertexArray->MakeIterator<float[2]>(this);
     122             : }
     123             : 
     124             : template<>
     125           0 : VertexArrayIterator<SColor3ub> VertexArray::Attribute::GetIterator<SColor3ub>() const
     126             : {
     127           0 :     ENSURE(vertexArray);
     128           0 :     ENSURE(type == GL_UNSIGNED_BYTE);
     129           0 :     ENSURE(elems >= 3);
     130             : 
     131           0 :     return vertexArray->MakeIterator<SColor3ub>(this);
     132             : }
     133             : 
     134             : template<>
     135           0 : VertexArrayIterator<SColor4ub> VertexArray::Attribute::GetIterator<SColor4ub>() const
     136             : {
     137           0 :     ENSURE(vertexArray);
     138           0 :     ENSURE(type == GL_UNSIGNED_BYTE);
     139           0 :     ENSURE(elems >= 4);
     140             : 
     141           0 :     return vertexArray->MakeIterator<SColor4ub>(this);
     142             : }
     143             : 
     144             : template<>
     145           0 : VertexArrayIterator<u16> VertexArray::Attribute::GetIterator<u16>() const
     146             : {
     147           0 :     ENSURE(vertexArray);
     148           0 :     ENSURE(type == GL_UNSIGNED_SHORT);
     149           0 :     ENSURE(elems >= 1);
     150             : 
     151           0 :     return vertexArray->MakeIterator<u16>(this);
     152             : }
     153             : 
     154             : template<>
     155           0 : VertexArrayIterator<u16[2]> VertexArray::Attribute::GetIterator<u16[2]>() const
     156             : {
     157           0 :     ENSURE(vertexArray);
     158           0 :     ENSURE(type == GL_UNSIGNED_SHORT);
     159           0 :     ENSURE(elems >= 2);
     160             : 
     161           0 :     return vertexArray->MakeIterator<u16[2]>(this);
     162             : }
     163             : 
     164             : template<>
     165           0 : VertexArrayIterator<u8> VertexArray::Attribute::GetIterator<u8>() const
     166             : {
     167           0 :     ENSURE(vertexArray);
     168           0 :     ENSURE(type == GL_UNSIGNED_BYTE);
     169           0 :     ENSURE(elems >= 1);
     170             : 
     171           0 :     return vertexArray->MakeIterator<u8>(this);
     172             : }
     173             : 
     174             : template<>
     175           0 : VertexArrayIterator<u8[4]> VertexArray::Attribute::GetIterator<u8[4]>() const
     176             : {
     177           0 :     ENSURE(vertexArray);
     178           0 :     ENSURE(type == GL_UNSIGNED_BYTE);
     179           0 :     ENSURE(elems >= 4);
     180             : 
     181           0 :     return vertexArray->MakeIterator<u8[4]>(this);
     182             : }
     183             : 
     184             : template<>
     185           0 : VertexArrayIterator<short> VertexArray::Attribute::GetIterator<short>() const
     186             : {
     187           0 :     ENSURE(vertexArray);
     188           0 :     ENSURE(type == GL_SHORT);
     189           0 :     ENSURE(elems >= 1);
     190             : 
     191           0 :     return vertexArray->MakeIterator<short>(this);
     192             : }
     193             : 
     194             : template<>
     195           0 : VertexArrayIterator<short[2]> VertexArray::Attribute::GetIterator<short[2]>() const
     196             : {
     197           0 :     ENSURE(vertexArray);
     198           0 :     ENSURE(type == GL_SHORT);
     199           0 :     ENSURE(elems >= 2);
     200             : 
     201           0 :     return vertexArray->MakeIterator<short[2]>(this);
     202             : }
     203             : 
     204             : static size_t RoundStride(size_t stride)
     205             : {
     206           0 :     if (stride <= 0)
     207             :         return 0;
     208           0 :     if (stride <= 4)
     209             :         return 4;
     210           0 :     if (stride <= 8)
     211             :         return 8;
     212           0 :     if (stride <= 16)
     213             :         return 16;
     214             : 
     215           0 :     return Align<32>(stride);
     216             : }
     217             : 
     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           0 : void VertexArray::Layout()
     222             : {
     223           0 :     Free();
     224             : 
     225           0 :     m_Stride = 0;
     226             : 
     227             :     //debug_printf("Layouting VertexArray\n");
     228             : 
     229           0 :     for (ssize_t idx = m_Attributes.size()-1; idx >= 0; --idx)
     230             :     {
     231           0 :         Attribute* attr = m_Attributes[idx];
     232             : 
     233           0 :         if (!attr->type || !attr->elems)
     234             :             continue;
     235             : 
     236           0 :         size_t attrSize = 0;
     237           0 :         switch(attr->type)
     238             :         {
     239             :         case GL_UNSIGNED_BYTE:
     240             :             attrSize = sizeof(GLubyte);
     241             :             break;
     242           0 :         case GL_SHORT:
     243           0 :             attrSize = sizeof(GLshort);
     244           0 :             break;
     245           0 :         case GL_UNSIGNED_SHORT:
     246           0 :             attrSize = sizeof(GLushort);
     247           0 :             break;
     248           0 :         case GL_FLOAT:
     249           0 :             attrSize = sizeof(GLfloat);
     250           0 :             break;
     251           0 :         default:
     252           0 :             attrSize = 0;
     253           0 :             debug_warn(L"Bad Attribute::type"); break;
     254             :         }
     255             : 
     256           0 :         attrSize *= attr->elems;
     257             : 
     258           0 :         attr->offset = m_Stride;
     259             : 
     260           0 :         m_Stride += attrSize;
     261             : 
     262           0 :         if (m_Target == GL_ARRAY_BUFFER)
     263           0 :             m_Stride = Align<4>(m_Stride);
     264             : 
     265             :         //debug_printf("%i: offset: %u\n", idx, attr->offset);
     266             :     }
     267             : 
     268           0 :     if (m_Target == GL_ARRAY_BUFFER)
     269           0 :         m_Stride = RoundStride(m_Stride);
     270             : 
     271             :     //debug_printf("Stride: %u\n", m_Stride);
     272             : 
     273           0 :     if (m_Stride)
     274           0 :         m_BackingStore = (char*)rtl_AllocateAligned(m_Stride * m_NumVertices, 16);
     275           0 : }
     276             : 
     277           0 : void VertexArray::PrepareForRendering()
     278             : {
     279           0 :     m_VB->m_Owner->PrepareForRendering(m_VB);
     280           0 : }
     281             : 
     282             : // (Re-)Upload the attributes.
     283             : // Create the VBO if necessary.
     284           0 : void VertexArray::Upload()
     285             : {
     286           0 :     ENSURE(m_BackingStore);
     287             : 
     288           0 :     if (!m_VB)
     289           0 :         m_VB = g_VBMan.Allocate(m_Stride, m_NumVertices, m_Usage, m_Target, m_BackingStore);
     290             : 
     291           0 :     if (!m_VB)
     292             :     {
     293           0 :         LOGERROR("Failed to allocate VBO for vertex array");
     294           0 :         return;
     295             :     }
     296             : 
     297           0 :     m_VB->m_Owner->UpdateChunkVertices(m_VB, m_BackingStore);
     298             : }
     299             : 
     300             : 
     301             : // Bind this array, returns the base address for calls to glVertexPointer etc.
     302           0 : u8* VertexArray::Bind()
     303             : {
     304           0 :     if (!m_VB)
     305             :         return NULL;
     306             : 
     307           0 :     u8* base = m_VB->m_Owner->Bind();
     308           0 :     base += m_VB->m_Index*m_Stride;
     309           0 :     return base;
     310             : }
     311             : 
     312             : 
     313             : // Free the backing store to save some memory
     314           0 : void VertexArray::FreeBackingStore()
     315             : {
     316             :     // In streaming modes, the backing store must be retained
     317           0 :     ENSURE(!CVertexBuffer::UseStreaming(m_Usage));
     318             : 
     319           0 :     rtl_FreeAligned(m_BackingStore);
     320           0 :     m_BackingStore = 0;
     321           0 : }
     322             : 
     323             : 
     324             : 
     325           0 : VertexIndexArray::VertexIndexArray(GLenum usage) :
     326           0 :     VertexArray(usage, GL_ELEMENT_ARRAY_BUFFER)
     327             : {
     328           0 :     m_Attr.type = GL_UNSIGNED_SHORT;
     329           0 :     m_Attr.elems = 1;
     330           0 :     AddAttribute(&m_Attr);
     331           0 : }
     332             : 
     333           0 : VertexArrayIterator<u16> VertexIndexArray::GetIterator() const
     334             : {
     335           0 :     return m_Attr.GetIterator<u16>();
     336             : }

Generated by: LCOV version 1.13