uint32_t
MEMGetAllocatableSizeForExpHeapEx(MEMHeapHandle handle,
                                  int32_t alignment)
{
   auto heap = virt_cast<MEMExpHeap *>(handle);
   auto largestFree = 0u;
   internal::HeapLock lock { virt_addrof(heap->header) };

   if (alignment > 0) {
      decaf_check((alignment & 0x3) == 0);

      for (auto block = heap->freeList.head; block; block = block->next) {
         auto alignedSize = getAlignedBlockSize(block, alignment, MEMExpHeapDirection::FromStart);

         if (alignedSize > largestFree) {
            largestFree = alignedSize;
         }
      }
   } else {
      alignment = -alignment;

      decaf_check((alignment & 0x3) == 0);

      for (auto block = heap->freeList.head; block; block = block->next) {
         auto alignedSize = getAlignedBlockSize(block, alignment, MEMExpHeapDirection::FromEnd);

         if (alignedSize > largestFree) {
            largestFree = alignedSize;
         }
      }
   }

   return largestFree;
}
      dp::rix::core::ContainerSharedHandle BufferManagerOffset::allocationGetBufferContainer( AllocationHandle allocation )
      {
        AllocationImplHandle allocationImpl = dp::rix::core::handleCast<AllocationImpl>(allocation);
        dp::rix::core::ContainerSharedHandle container = getRenderer()->containerCreate( m_descriptor );

        dp::rix::core::ContainerDataBuffer cdb( allocationImpl->m_chunk->m_buffer, allocationImpl->m_blockIndex * getAlignedBlockSize(), getBlockSize() );
        getRenderer()->containerSetData( container, m_entry, cdb );

        return container;
      }
virt_ptr<void>
MEMAllocFromExpHeapEx(MEMHeapHandle handle,
                      uint32_t size,
                      int32_t alignment)
{
   auto heap = virt_cast<MEMExpHeap *>(handle);
   decaf_check(heap->header.tag == MEMHeapTag::ExpandedHeap);
   auto expHeapFlags = heap->attribs.value();

   if (size == 0) {
      size = 1;
   }

   decaf_check(alignment != 0);

   internal::HeapLock lock { virt_addrof(heap->header) };
   virt_ptr<MEMExpHeapBlock> newBlock = nullptr;

   size = align_up(size, 4);

   if (alignment > 0) {
      auto foundBlock = virt_ptr<MEMExpHeapBlock> { nullptr };
      auto bestAlignedSize = 0xFFFFFFFFu;

      alignment = std::max(4, alignment);
      decaf_check((alignment & 0x3) == 0);

      for (auto block = heap->freeList.head; block; block = block->next) {
         auto alignedSize = getAlignedBlockSize(block,
                                                alignment,
                                                MEMExpHeapDirection::FromStart);

         if (alignedSize >= size) {
            if (expHeapFlags.allocMode() == MEMExpHeapMode::FirstFree) {
               foundBlock = block;
               break;
            } else {
               if (alignedSize < bestAlignedSize) {
                  foundBlock = block;
                  bestAlignedSize = alignedSize;
               }
            }
         }
      }

      if (foundBlock) {
         newBlock = createUsedBlockFromFreeBlock(heap,
                                                 foundBlock,
                                                 size,
                                                 alignment,
                                                 MEMExpHeapDirection::FromStart);
      }
   } else {
      alignment = std::max(4, -alignment);
      decaf_check((alignment & 0x3) == 0);

      auto foundBlock = virt_ptr<MEMExpHeapBlock> { nullptr };
      auto bestAlignedSize = 0xFFFFFFFFu;

      for (auto block = heap->freeList.head; block; block = block->next) {
         auto alignedSize = getAlignedBlockSize(block,
                                                alignment,
                                                MEMExpHeapDirection::FromEnd);

         if (alignedSize >= size) {
            if (expHeapFlags.allocMode() == MEMExpHeapMode::FirstFree) {
               foundBlock = block;
               break;
            } else {
               if (alignedSize < bestAlignedSize) {
                  foundBlock = block;
                  bestAlignedSize = alignedSize;
               }
            }
         }
      }

      if (foundBlock) {
         newBlock = createUsedBlockFromFreeBlock(heap,
                                                 foundBlock,
                                                 size,
                                                 alignment,
                                                 MEMExpHeapDirection::FromEnd);
      }
   }

   if (!newBlock) {
      MEMDumpHeap(virt_addrof(heap->header));
      return nullptr;
   }

   return getBlockDataStart(newBlock);
}
 dp::rix::fx::SmartChunk BufferManagerIndexed::allocateChunk()
 {
   return new Chunk( this, getAlignedBlockSize(), getChunkSize() );
 }