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 151 0.0 %
Date: 2022-03-08 13:03:03 Functions: 0 24 0.0 %

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

Generated by: LCOV version 1.13