/// Reallocate a block of memory for FreeType. /// /// @param[in] pMemory Handle to the source memory manager. /// @param[in] currentSize Current block size, in bytes. /// @param[in] newSize New block size, in bytes. /// @param[in] pBlock Block to reallocate. /// /// @return Pointer to the reallocated block of memory, or null if reallocation failed. /// /// @see FreeTypeAllocate(), FreeTypeFree() static void* FreeTypeReallocate( FT_Memory /*pMemory*/, long currentSize, long newSize, void* pBlock ) { DefaultAllocator allocator; // We cannot call Reallocate() if either the old or new size requires SIMD alignment (see FreeTypeAllocate() for // more information about why we need to align some allocations), so call Free()/Allocate()/AllocateAligned() // instead as appropriate. if( newSize < HELIUM_SIMD_SIZE ) { if( currentSize < HELIUM_SIMD_SIZE ) { // Our allocators allow for null pointers to be passed to their reallocate functions, so we do not need to // validate the block parameter. pBlock = allocator.ReallocateAligned( pBlock, HELIUM_SIMD_ALIGNMENT, newSize ); } else { void* pOldBlock = pBlock; // Our allocators treat a realloc() with a size of zero as a free, so simulate that functionality here. pBlock = NULL; if( newSize ) { pBlock = allocator.AllocateAligned( HELIUM_SIMD_ALIGNMENT, newSize ); if( pBlock ) { HELIUM_ASSERT( newSize < currentSize ); MemoryCopy( pBlock, pOldBlock, newSize ); } } allocator.FreeAligned( pOldBlock ); } } else { void* pOldBlock = pBlock; // Note that newSize >= HELIUM_SIMD_SIZE, so we don't need to check for non-zero sizes here. pBlock = allocator.AllocateAligned( HELIUM_SIMD_ALIGNMENT, newSize ); if( pBlock ) { MemoryCopy( pBlock, pOldBlock, Min( currentSize, newSize ) ); } allocator.FreeAligned( pOldBlock ); } return pBlock; }
/// Allocate a block of memory for FreeType. /// /// @param[in] pMemory Handle to the source memory manager. /// @param[in] size Number of bytes to allocate. /// /// @return Address of the newly allocated block of memory, or null if allocation failed. /// /// @see FreeTypeFree(), FreeTypeReallocate() static void* FreeTypeAllocate( FT_Memory /*pMemory*/, long size ) { // FreeType uses setjmp()/longjmp(), and because our SSE settings bleed into dependency projects, jmp_buf needs to // be 16-byte aligned for backing up SSE register states. To avoid misaligned jmp_buf instances, we align all // allocations of 16 bytes or greater to 16-byte boundaries. DefaultAllocator allocator; return allocator.AllocateAligned( HELIUM_SIMD_ALIGNMENT, size ); }
/// Create a new object. /// /// @param[out] rspObject Pointer to the newly created object if object creation was successful. Note that /// any object reference stored in this strong pointer prior to calling this function /// will always be cleared by this function, regardless of whether object creation is /// successful. /// @param[in] pType Type of object to create. /// @param[in] name Object name. /// @param[in] pOwner Object owner. /// @param[in] pTemplate Optional override template object. If null, the default template for the /// specified type will be used. /// @param[in] bAssignInstanceIndex True to assign an instance index to the object, false to leave the index /// invalid. /// /// @return True if object creation was successful, false if not. /// /// @see Create() bool GameObject::CreateObject( GameObjectPtr& rspObject, const GameObjectType* pType, Name name, GameObject* pOwner, GameObject* pTemplate, bool bAssignInstanceIndex ) { HELIUM_ASSERT( pType ); HELIUM_TRACE( TraceLevels::Debug, TXT( "GameObject::CreateObject(): Creating object named \"%s\" of type \"%s\" owned by \"%s\".\n"), *name, *pType->GetName(), !pOwner ? TXT("[none]") : *pOwner->GetPath().ToString()); rspObject.Release(); // Get the appropriate template object. GameObject* pObjectTemplate = pTemplate; if( pObjectTemplate ) { if( pType->GetFlags() & GameObjectType::FLAG_NO_TEMPLATE && pType->GetTemplate() != pObjectTemplate ) { HELIUM_TRACE( TraceLevels::Error, TXT( "GameObject::CreateObject(): Objects of type \"%s\" cannot be used as templates.\n" ), *pType->GetName() ); return false; } } else { pObjectTemplate = pType->GetTemplate(); HELIUM_ASSERT( pObjectTemplate ); } // Make sure the object template is of the correct type. if( !pObjectTemplate->IsInstanceOf( pType ) ) { HELIUM_TRACE( TraceLevels::Error, TXT( "GameObject::CreateObject: Template object \"%s\" is not of type \"%s\".\n" ), *pTemplate->GetPath().ToString(), pType->GetName().Get() ); HELIUM_ASSERT_FALSE(); return false; } // Allocate memory for and create the object. DefaultAllocator allocator; size_t bufferSize = pObjectTemplate->GetInstanceSize(); void* pObjectMemory = allocator.AllocateAligned( HELIUM_SIMD_ALIGNMENT, bufferSize ); HELIUM_ASSERT( pObjectMemory ); GameObject* pObject = pObjectTemplate->InPlaceConstruct( pObjectMemory, StandardCustomDestroy ); HELIUM_ASSERT( pObject == pObjectMemory ); rspObject = pObject; pObject->m_spTemplate = pTemplate; // Initialize the object based on its default. pObjectTemplate->CopyTo(pObject); // Attempt to register the object and set its name. RenameParameters nameParameters; nameParameters.name = name; nameParameters.spOwner = pOwner; if( bAssignInstanceIndex ) { nameParameters.instanceIndex = INSTANCE_INDEX_AUTO; } if ( !RegisterObject( pObject ) ) { HELIUM_TRACE( TraceLevels::Error, TXT( "GameObject::CreateObject(): RegisterObject() failed for GameObject \"%s\" owned by \"%s\".\n" ), *name, !pOwner ? TXT("[none]") : *pOwner->GetPath().ToString()); HELIUM_ASSERT_FALSE(); rspObject.Release(); return false; } if( !pObject->Rename( nameParameters ) ) { HELIUM_TRACE( TraceLevels::Error, TXT( "GameObject::CreateObject(): Rename() failed for GameObject \"%s\" owned by \"%s\".\n" ), *name, !pOwner ? TXT("[none]") : *pOwner->GetPath().ToString()); HELIUM_ASSERT_FALSE(); rspObject.Release(); return false; } return true; }