#include "nw4r/snd/snd_FrameHeap.h" #include namespace nw4r { namespace snd { namespace detail { FrameHeap::FrameHeap() : mHandle(NULL) {} FrameHeap::~FrameHeap() { if (IsValid()) { Destroy(); } } bool FrameHeap::Create(void* pBase, u32 size) { if (IsValid()) { Destroy(); } void* pEnd = static_cast(pBase) + size; pBase = ut::RoundUp(pBase, 4); if (pBase > pEnd) { return false; } mHandle = MEMCreateFrmHeap(pBase, ut::GetOffsetFromPtr(pBase, pEnd)); if (mHandle == NULL) { return false; } if (!NewSection()) { return false; } return true; } void FrameHeap::Destroy() { if (!IsValid()) { return; } ClearSection(); MEMFreeToFrmHeap(mHandle, MEM_FRM_HEAP_FREE_ALL); MEMDestroyFrmHeap(mHandle); mHandle = NULL; } void FrameHeap::Clear() { ClearSection(); MEMFreeToFrmHeap(mHandle, MEM_FRM_HEAP_FREE_ALL); NewSection(); } void* FrameHeap::Alloc(u32 size, FreeCallback pCallback, void* pCallbackArg) { void* pBuffer = MEMAllocFromFrmHeapEx( mHandle, BLOCK_BUFFER_SIZE + ut::RoundUp(size, HEAP_ALIGN), HEAP_ALIGN); if (pBuffer == NULL) { return NULL; } void *pBuffer2 = ut::AddOffsetToPtr(pBuffer, BLOCK_BUFFER_SIZE); Block* pBlock = new (pBuffer) Block(pBuffer2, size, pCallback, pCallbackArg); mSectionList.GetBack().AppendBlock(pBlock); return pBuffer2; } int FrameHeap::SaveState() { if (!MEMRecordStateForFrmHeap(mHandle, mSectionList.GetSize())) { return -1; } if (!NewSection()) { MEMFreeByStateToFrmHeap(mHandle, 0); return -1; } return GetCurrentLevel(); } void FrameHeap::LoadState(int id) { if (id == 0) { Clear(); return; } while (id < static_cast(mSectionList.GetSize())) { Section& rSection = mSectionList.GetBack(); rSection.~Section(); mSectionList.Erase(&rSection); } MEMFreeByStateToFrmHeap(mHandle, id); MEMRecordStateForFrmHeap(mHandle, mSectionList.GetSize()); NewSection(); } int FrameHeap::GetCurrentLevel() const { return mSectionList.GetSize() - 1; } u32 FrameHeap::GetFreeSize() const { u32 freeSize = MEMGetAllocatableSizeForFrmHeapEx(mHandle, HEAP_ALIGN); if (freeSize < sizeof(Block)) { return 0; } return ut::RoundDown(freeSize - sizeof(Block), HEAP_ALIGN); } bool FrameHeap::NewSection() { void* pSection = MEMAllocFromFrmHeap(mHandle, sizeof(Section)); if (pSection == NULL) { return false; } mSectionList.PushBack(new (pSection) Section()); return true; } void FrameHeap::ClearSection() { while (!mSectionList.IsEmpty()) { Section& rSection = mSectionList.GetBack(); rSection.~Section(); mSectionList.Erase(&rSection); } } } // namespace detail } // namespace snd } // namespace nw4r