/// 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 );
}
Example #3
0
/// 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;
}