4coder-non-source/test_data/lots_of_files/handmade_asset.h

339 lines
7.0 KiB
C

#if !defined(HANDMADE_ASSET_H)
/* ========================================================================
$File: $
$Date: $
$Revision: $
$Creator: Casey Muratori $
$Notice: (C) Copyright 2015 by Molly Rocket, Inc. All Rights Reserved. $
======================================================================== */
struct loaded_sound
{
int16 *Samples[2];
u32 SampleCount; // NOTE(casey): This is the sample count divided by 8
u32 ChannelCount;
};
struct loaded_font
{
hha_font_glyph *Glyphs;
r32 *HorizontalAdvance;
u32 BitmapIDOffset;
u16 *UnicodeMap;
};
// TODO(casey): Streamling this, by using header pointer as an indicator of unloaded status?
enum asset_state
{
AssetState_Unloaded,
AssetState_Queued,
AssetState_Loaded,
};
struct asset_memory_header
{
asset_memory_header *Next;
asset_memory_header *Prev;
u32 AssetIndex;
u32 TotalSize;
u32 GenerationID;
union
{
loaded_bitmap Bitmap;
loaded_sound Sound;
loaded_font Font;
};
};
struct asset
{
u32 State;
asset_memory_header *Header;
hha_asset HHA;
u32 FileIndex;
};
struct asset_vector
{
real32 E[Tag_Count];
};
struct asset_type
{
uint32 FirstAssetIndex;
uint32 OnePastLastAssetIndex;
};
struct asset_file
{
platform_file_handle Handle;
// TODO(casey): If we ever do thread stacks, AssetTypeArray
// doesn't actually need to be kept here probably.
hha_header Header;
hha_asset_type *AssetTypeArray;
u32 TagBase;
s32 FontBitmapIDOffset;
};
enum asset_memory_block_flags
{
AssetMemory_Used = 0x1,
};
struct asset_memory_block
{
asset_memory_block *Prev;
asset_memory_block *Next;
u64 Flags;
memory_index Size;
};
struct game_assets
{
u32 NextGenerationID;
// TODO(casey): Not thrilled about this back-pointer
struct transient_state *TranState;
asset_memory_block MemorySentinel;
asset_memory_header LoadedAssetSentinel;
real32 TagRange[Tag_Count];
u32 FileCount;
asset_file *Files;
uint32 TagCount;
hha_tag *Tags;
uint32 AssetCount;
asset *Assets;
asset_type AssetTypes[Asset_Count];
u32 OperationLock;
u32 InFlightGenerationCount;
u32 InFlightGenerations[16];
};
inline void
BeginAssetLock(game_assets *Assets)
{
for(;;)
{
if(AtomicCompareExchangeUInt32(&Assets->OperationLock, 1, 0) == 0)
{
break;
}
}
}
inline void
EndAssetLock(game_assets *Assets)
{
CompletePreviousWritesBeforeFutureWrites;
Assets->OperationLock = 0;
}
inline void
InsertAssetHeaderAtFront(game_assets *Assets, asset_memory_header *Header)
{
asset_memory_header *Sentinel = &Assets->LoadedAssetSentinel;
Header->Prev = Sentinel;
Header->Next = Sentinel->Next;
Header->Next->Prev = Header;
Header->Prev->Next = Header;
}
inline void
RemoveAssetHeaderFromList(asset_memory_header *Header)
{
Header->Prev->Next = Header->Next;
Header->Next->Prev = Header->Prev;
Header->Next = Header->Prev = 0;
}
inline asset_memory_header *GetAsset(game_assets *Assets, u32 ID, u32 GenerationID)
{
Assert(ID <= Assets->AssetCount);
asset *Asset = Assets->Assets + ID;
asset_memory_header *Result = 0;
BeginAssetLock(Assets);
if(Asset->State == AssetState_Loaded)
{
Result = Asset->Header;
RemoveAssetHeaderFromList(Result);
InsertAssetHeaderAtFront(Assets, Result);
if(Asset->Header->GenerationID < GenerationID)
{
Asset->Header->GenerationID = GenerationID;
}
CompletePreviousWritesBeforeFutureWrites;
}
EndAssetLock(Assets);
return(Result);
}
inline loaded_bitmap *
GetBitmap(game_assets *Assets, bitmap_id ID, u32 GenerationID)
{
asset_memory_header *Header = GetAsset(Assets, ID.Value, GenerationID);
loaded_bitmap *Result = Header ? &Header->Bitmap : 0;
return(Result);
}
inline hha_bitmap *
GetBitmapInfo(game_assets *Assets, bitmap_id ID)
{
Assert(ID.Value <= Assets->AssetCount);
hha_bitmap *Result = &Assets->Assets[ID.Value].HHA.Bitmap;
return(Result);
}
inline loaded_sound *
GetSound(game_assets *Assets, sound_id ID, u32 GenerationID)
{
asset_memory_header *Header = GetAsset(Assets, ID.Value, GenerationID);
loaded_sound *Result = Header ? &Header->Sound : 0;
return(Result);
}
inline hha_sound *
GetSoundInfo(game_assets *Assets, sound_id ID)
{
Assert(ID.Value <= Assets->AssetCount);
hha_sound *Result = &Assets->Assets[ID.Value].HHA.Sound;
return(Result);
}
inline loaded_font *
GetFont(game_assets *Assets, font_id ID, u32 GenerationID)
{
asset_memory_header *Header = GetAsset(Assets, ID.Value, GenerationID);
loaded_font *Result = Header ? &Header->Font : 0;
return(Result);
}
inline hha_font *
GetFontInfo(game_assets *Assets, font_id ID)
{
Assert(ID.Value <= Assets->AssetCount);
hha_font *Result = &Assets->Assets[ID.Value].HHA.Font;
return(Result);
}
inline bool32
IsValid(bitmap_id ID)
{
bool32 Result = (ID.Value != 0);
return(Result);
}
inline bool32
IsValid(sound_id ID)
{
bool32 Result = (ID.Value != 0);
return(Result);
}
internal void LoadBitmap(game_assets *Assets, bitmap_id ID, b32 Immediate);
inline void PrefetchBitmap(game_assets *Assets, bitmap_id ID) {LoadBitmap(Assets, ID, false);}
internal void LoadSound(game_assets *Assets, sound_id ID);
inline void PrefetchSound(game_assets *Assets, sound_id ID) {LoadSound(Assets, ID);}
internal void LoadFont(game_assets *Assets, font_id ID, b32 Immediate);
inline void PrefetchFont(game_assets *Assets, font_id ID) {LoadFont(Assets, ID, false);}
inline sound_id GetNextSoundInChain(game_assets *Assets, sound_id ID)
{
sound_id Result = {};
hha_sound *Info = GetSoundInfo(Assets, ID);
switch(Info->Chain)
{
case HHASoundChain_None:
{
// NOTE(casey): Nothing to do.
} break;
case HHASoundChain_Loop:
{
Result = ID;
} break;
case HHASoundChain_Advance:
{
Result.Value = ID.Value + 1;
} break;
default:
{
InvalidCodePath;
} break;
}
return(Result);
}
inline u32
BeginGeneration(game_assets *Assets)
{
BeginAssetLock(Assets);
Assert(Assets->InFlightGenerationCount < ArrayCount(Assets->InFlightGenerations));
u32 Result = Assets->NextGenerationID++;
Assets->InFlightGenerations[Assets->InFlightGenerationCount++] = Result;
EndAssetLock(Assets);
return(Result);
}
inline void
EndGeneration(game_assets *Assets, u32 GenerationID)
{
BeginAssetLock(Assets);
for(u32 Index = 0;
Index < Assets->InFlightGenerationCount;
++Index)
{
if(Assets->InFlightGenerations[Index] == GenerationID)
{
Assets->InFlightGenerations[Index] =
Assets->InFlightGenerations[--Assets->InFlightGenerationCount];
break;
}
}
EndAssetLock(Assets);
}
#define HANDMADE_ASSET_H
#endif