mirror of
https://github.com/DaedalusX64/daedalus.git
synced 2025-04-02 10:21:48 -04:00
278 lines
7.1 KiB
C++
278 lines
7.1 KiB
C++
/*
|
|
Copyright (C) 2007 StrmnNrmn
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU General Public License
|
|
as published by the Free Software Foundation; either version 2
|
|
of the License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
|
|
*/
|
|
|
|
//Define line below to show amount of allocated VRAM //Corn
|
|
//#define SHOW_MEM
|
|
|
|
#include "BuildOptions.h"
|
|
#include "Base/Types.h"
|
|
#include "Utility/MemoryHeap.h"
|
|
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "Base/MathUtil.h"
|
|
|
|
|
|
//
|
|
// Allocator taken from.
|
|
// Taken from http://svn.ps2dev.org/filedetails.php?repname=psp&path=%2Ftrunk%2Fpspgl%2Fpspgl_vidmem.c&rev=0&sc=0
|
|
//
|
|
// We probably need something a bit more suitable for our requirements eventually.
|
|
//
|
|
|
|
|
|
struct Chunk
|
|
{
|
|
u8 * Ptr;
|
|
u32 Length;
|
|
#ifdef DAEDALUS_DEBUG_MEMORY
|
|
u32 Tag;
|
|
#endif
|
|
};
|
|
|
|
|
|
class IMemoryHeap : public CMemoryHeap
|
|
{
|
|
public:
|
|
IMemoryHeap( u32 size );
|
|
IMemoryHeap( void * base_ptr, u32 size );
|
|
|
|
~IMemoryHeap();
|
|
|
|
virtual void * Alloc( u32 size );
|
|
virtual void Free( void * ptr );
|
|
|
|
virtual bool IsFromHeap( void * ptr ) const;
|
|
#ifdef DAEDALUS_DEBUG_MEMORY
|
|
//virtual u32 GetAvailableMemory() const;
|
|
virtual void DisplayDebugInfo() const;
|
|
#endif
|
|
private:
|
|
void * InsertNew( u32 idx, u8 * adr, u32 size );
|
|
|
|
|
|
private:
|
|
u8 * mBasePtr;
|
|
u32 mTotalSize;
|
|
bool mDeleteOnDestruction;
|
|
|
|
Chunk * mpMemMap;
|
|
u32 mMemMapLen;
|
|
#ifdef SHOW_MEM
|
|
u32 mMemAlloc;
|
|
#endif
|
|
};
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
CMemoryHeap * CMemoryHeap::Create( u32 size )
|
|
{
|
|
return new IMemoryHeap( size );
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
CMemoryHeap * CMemoryHeap::Create( void * base_ptr, u32 size )
|
|
{
|
|
return new IMemoryHeap( base_ptr, size );
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
CMemoryHeap::~CMemoryHeap()
|
|
{
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
IMemoryHeap::IMemoryHeap( u32 size )
|
|
: mBasePtr( new u8[ size ] )
|
|
, mTotalSize( size )
|
|
, mDeleteOnDestruction( true )
|
|
, mpMemMap( NULL )
|
|
, mMemMapLen( 0 )
|
|
#ifdef SHOW_MEM
|
|
, mMemAlloc( 0 )
|
|
#endif
|
|
{
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
IMemoryHeap::IMemoryHeap( void * base_ptr, u32 size )
|
|
: mBasePtr( reinterpret_cast< u8 * >( base_ptr ) )
|
|
, mTotalSize( size )
|
|
, mDeleteOnDestruction( false )
|
|
, mpMemMap( NULL )
|
|
, mMemMapLen( 0 )
|
|
#ifdef SHOW_MEM
|
|
, mMemAlloc( 0 )
|
|
#endif
|
|
{
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
IMemoryHeap::~IMemoryHeap()
|
|
{
|
|
if( mDeleteOnDestruction )
|
|
{
|
|
delete [] mBasePtr;
|
|
}
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
bool IMemoryHeap::IsFromHeap( void * ptr ) const
|
|
{
|
|
return ptr >= mBasePtr && ptr < (mBasePtr + mTotalSize);
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
void * IMemoryHeap::InsertNew( u32 idx, u8 * adr, u32 size )
|
|
{
|
|
Chunk *tmp = reinterpret_cast< Chunk * >( realloc(mpMemMap, (mMemMapLen + 1) * sizeof(mpMemMap[0]) ) );
|
|
if( tmp == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
mpMemMap = tmp;
|
|
memmove(&mpMemMap[idx+1], &mpMemMap[idx], (mMemMapLen-idx) * sizeof(mpMemMap[0]));
|
|
mMemMapLen++;
|
|
mpMemMap[idx].Ptr = adr;
|
|
mpMemMap[idx].Length = size;
|
|
//Tag seems broken - Kreationz
|
|
//#ifdef DAEDALUS_DEBUG_MEMORY
|
|
// mpMemMap[idx].Tag = tag;
|
|
//#endif
|
|
|
|
return mpMemMap[idx].Ptr;
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
void* IMemoryHeap::Alloc( u32 size )
|
|
{
|
|
// FIXME(strmnnrmn): This code was removed at some point - does something else help guarantee alignment?
|
|
// Might be that we just want to lower it to 4 or 8.
|
|
// Ensure that all memory is 16-byte aligned
|
|
//size = AlignPow2( size, 16 );
|
|
|
|
u8 * adr = mBasePtr;
|
|
u32 i;
|
|
|
|
for (i=0; i<mMemMapLen; ++i)
|
|
{
|
|
if( mpMemMap[i].Ptr != NULL )
|
|
{
|
|
u8 * new_adr = mpMemMap[i].Ptr;
|
|
if( adr + size <= new_adr )
|
|
{
|
|
#ifdef SHOW_MEM
|
|
mMemAlloc += size;
|
|
printf("VRAM %d +\n", mMemAlloc);
|
|
#endif
|
|
return InsertNew( i, adr, size );
|
|
}
|
|
|
|
adr = new_adr + mpMemMap[i].Length;
|
|
}
|
|
}
|
|
|
|
if( adr + size > mBasePtr + mTotalSize )
|
|
{
|
|
#ifdef DAEDALUS_ENABLE_ASSERTS
|
|
DAEDALUS_ASSERT( false, "Out of VRAM/RAM memory" );
|
|
#endif
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef SHOW_MEM
|
|
mMemAlloc += size;
|
|
printf("VRAM %d +\n", mMemAlloc);
|
|
#endif
|
|
return InsertNew( mMemMapLen, adr, size );
|
|
}
|
|
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
void IMemoryHeap::Free( void * ptr )
|
|
{
|
|
#ifdef DAEDALUS_ENABLE_ASSERTS
|
|
DAEDALUS_ASSERT( ptr == NULL || IsFromHeap( ptr ), "Memory is not from this heap" );
|
|
#endif
|
|
if( ptr == NULL )
|
|
return;
|
|
|
|
for ( u32 i=0; i < mMemMapLen; ++i )
|
|
{
|
|
if( mpMemMap[i].Ptr == ptr )
|
|
{
|
|
Chunk *tmp;
|
|
|
|
#ifdef SHOW_MEM
|
|
mMemAlloc -= mpMemMap[i].Length;
|
|
#endif
|
|
mMemMapLen--;
|
|
memmove( &mpMemMap[i], &mpMemMap[i+1], (mMemMapLen-i) * sizeof(mpMemMap[0]) );
|
|
tmp = reinterpret_cast< Chunk * >( realloc( mpMemMap, mMemMapLen * sizeof(mpMemMap[0]) ) );
|
|
if( tmp != NULL )
|
|
{
|
|
mpMemMap = tmp;
|
|
}
|
|
}
|
|
}
|
|
#ifdef SHOW_MEM
|
|
printf("VRAM %d -\n", mMemAlloc);
|
|
#endif
|
|
}
|
|
|
|
#ifdef DAEDALUS_DEBUG_MEMORY
|
|
//*****************************************************************************
|
|
//
|
|
//*****************************************************************************
|
|
void IMemoryHeap::DisplayDebugInfo() const
|
|
{
|
|
printf( " # Address Length Tag\n" );
|
|
|
|
for (u32 i=0; i<mMemMapLen; ++i)
|
|
{
|
|
const Chunk & chunk( mpMemMap[ i ] );
|
|
|
|
printf( "%02d: %p %8d", i, chunk.Ptr, chunk.Length );
|
|
#ifdef DAEDALUS_DEBUG_MEMORY
|
|
printf( " %05d", chunk.Tag );
|
|
#endif
|
|
printf( "\n" );
|
|
}
|
|
}
|
|
#endif
|