123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879 |
- /*
- ===========================================================================
- Doom 3 BFG Edition GPL Source Code
- Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
- This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
- Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
- Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
- In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
- If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
- ===========================================================================
- */
- #pragma hdrstop
- #include "../idlib/precompiled.h"
- #include "tr_local.h"
- // do this with a pointer, in case we want to make the actual manager
- // a private virtual subclass
- idImageManager imageManager;
- idImageManager * globalImages = &imageManager;
- idCVar preLoad_Images( "preLoad_Images", "1", CVAR_SYSTEM | CVAR_BOOL, "preload images during beginlevelload" );
- /*
- ===============
- R_ReloadImages_f
- Regenerate all images that came directly from files that have changed, so
- any saved changes will show up in place.
- New r_texturesize/r_texturedepth variables will take effect on reload
- reloadImages <all>
- ===============
- */
- void R_ReloadImages_f( const idCmdArgs &args ) {
- bool all = false;
- if ( args.Argc() == 2 ) {
- if ( !idStr::Icmp( args.Argv(1), "all" ) ) {
- all = true;
- } else {
- common->Printf( "USAGE: reloadImages <all>\n" );
- return;
- }
- }
- globalImages->ReloadImages( all );
- }
- typedef struct {
- idImage *image;
- int size;
- int index;
- } sortedImage_t;
- /*
- =======================
- R_QsortImageSizes
- =======================
- */
- static int R_QsortImageSizes( const void *a, const void *b ) {
- const sortedImage_t *ea, *eb;
- ea = (sortedImage_t *)a;
- eb = (sortedImage_t *)b;
- if ( ea->size > eb->size ) {
- return -1;
- }
- if ( ea->size < eb->size ) {
- return 1;
- }
- return idStr::Icmp( ea->image->GetName(), eb->image->GetName() );
- }
- /*
- =======================
- R_QsortImageName
- =======================
- */
- static int R_QsortImageName( const void* a, const void* b ) {
- const sortedImage_t *ea, *eb;
- ea = (sortedImage_t *)a;
- eb = (sortedImage_t *)b;
- return idStr::Icmp( ea->image->GetName(), eb->image->GetName() );
- }
- /*
- ===============
- R_ListImages_f
- ===============
- */
- void R_ListImages_f( const idCmdArgs &args ) {
- int i, partialSize;
- idImage *image;
- int totalSize;
- int count = 0;
- bool uncompressedOnly = false;
- bool unloaded = false;
- bool failed = false;
- bool sorted = false;
- bool duplicated = false;
- bool overSized = false;
- bool sortByName = false;
- if ( args.Argc() == 1 ) {
- } else if ( args.Argc() == 2 ) {
- if ( idStr::Icmp( args.Argv( 1 ), "uncompressed" ) == 0 ) {
- uncompressedOnly = true;
- } else if ( idStr::Icmp( args.Argv( 1 ), "sorted" ) == 0 ) {
- sorted = true;
- } else if ( idStr::Icmp( args.Argv( 1 ), "namesort" ) == 0 ) {
- sortByName = true;
- } else if ( idStr::Icmp( args.Argv( 1 ), "unloaded" ) == 0 ) {
- unloaded = true;
- } else if ( idStr::Icmp( args.Argv( 1 ), "duplicated" ) == 0 ) {
- duplicated = true;
- } else if ( idStr::Icmp( args.Argv( 1 ), "oversized" ) == 0 ) {
- sorted = true;
- overSized = true;
- } else {
- failed = true;
- }
- } else {
- failed = true;
- }
- if ( failed ) {
- common->Printf( "usage: listImages [ sorted | namesort | unloaded | duplicated | showOverSized ]\n" );
- return;
- }
- const char *header = " -w-- -h-- filt -fmt-- wrap size --name-------\n";
- common->Printf( "\n%s", header );
- totalSize = 0;
- sortedImage_t *sortedArray = (sortedImage_t *)alloca( sizeof( sortedImage_t ) * globalImages->images.Num() );
- for ( i = 0 ; i < globalImages->images.Num() ; i++ ) {
- image = globalImages->images[ i ];
- if ( uncompressedOnly ) {
- if ( image->IsCompressed() ) {
- continue;
- }
- }
- if ( unloaded == image->IsLoaded() ) {
- continue;
- }
- // only print duplicates (from mismatched wrap / clamp, etc)
- if ( duplicated ) {
- int j;
- for ( j = i+1 ; j < globalImages->images.Num() ; j++ ) {
- if ( idStr::Icmp( image->GetName(), globalImages->images[ j ]->GetName() ) == 0 ) {
- break;
- }
- }
- if ( j == globalImages->images.Num() ) {
- continue;
- }
- }
- if ( sorted || sortByName ) {
- sortedArray[count].image = image;
- sortedArray[count].size = image->StorageSize();
- sortedArray[count].index = i;
- } else {
- common->Printf( "%4i:", i );
- image->Print();
- }
- totalSize += image->StorageSize();
- count++;
- }
- if ( sorted || sortByName ) {
- if ( sortByName) {
- qsort( sortedArray, count, sizeof( sortedImage_t ), R_QsortImageName );
- } else {
- qsort( sortedArray, count, sizeof( sortedImage_t ), R_QsortImageSizes );
- }
- partialSize = 0;
- for ( i = 0 ; i < count ; i++ ) {
- common->Printf( "%4i:", sortedArray[i].index );
- sortedArray[i].image->Print();
- partialSize += sortedArray[i].image->StorageSize();
- if ( ( (i+1) % 10 ) == 0 ) {
- common->Printf( "-------- %5.1f of %5.1f megs --------\n",
- partialSize / (1024*1024.0), totalSize / (1024*1024.0) );
- }
- }
- }
- common->Printf( "%s", header );
- common->Printf( " %i images (%i total)\n", count, globalImages->images.Num() );
- common->Printf( " %5.1f total megabytes of images\n\n\n", totalSize / (1024*1024.0) );
- }
- /*
- ==============
- AllocImage
- Allocates an idImage, adds it to the list,
- copies the name, and adds it to the hash chain.
- ==============
- */
- idImage *idImageManager::AllocImage( const char *name ) {
- if (strlen(name) >= MAX_IMAGE_NAME ) {
- common->Error ("idImageManager::AllocImage: \"%s\" is too long\n", name);
- }
- int hash = idStr( name ).FileNameHash();
- idImage * image = new (TAG_IMAGE) idImage( name );
- imageHash.Add( hash, images.Append( image ) );
- return image;
- }
- /*
- ==============
- AllocStandaloneImage
- Allocates an idImage,does not add it to the list or hash chain
- ==============
- */
- idImage *idImageManager::AllocStandaloneImage( const char *name ) {
- if (strlen(name) >= MAX_IMAGE_NAME ) {
- common->Error ("idImageManager::AllocImage: \"%s\" is too long\n", name);
- }
- idImage * image = new (TAG_IMAGE) idImage( name );
- return image;
- }
- /*
- ==================
- ImageFromFunction
- Images that are procedurally generated are allways specified
- with a callback which must work at any time, allowing the OpenGL
- system to be completely regenerated if needed.
- ==================
- */
- idImage *idImageManager::ImageFromFunction( const char *_name, void (*generatorFunction)( idImage *image ) ) {
- // strip any .tga file extensions from anywhere in the _name
- idStr name = _name;
- name.Replace( ".tga", "" );
- name.BackSlashesToSlashes();
- // see if the image already exists
- int hash = name.FileNameHash();
- for ( int i = imageHash.First( hash ); i != -1; i = imageHash.Next( i ) ) {
- idImage * image = images[i];
- if ( name.Icmp( image->GetName() ) == 0 ) {
- if ( image->generatorFunction != generatorFunction ) {
- common->DPrintf( "WARNING: reused image %s with mixed generators\n", name.c_str() );
- }
- return image;
- }
- }
- // create the image and issue the callback
- idImage * image = AllocImage( name );
- image->generatorFunction = generatorFunction;
- // check for precompressed, load is from the front end
- image->referencedOutsideLevelLoad = true;
- image->ActuallyLoadImage( false );
- return image;
- }
- /*
- ===============
- GetImageWithParameters
- ==============
- */
- idImage *idImageManager::GetImageWithParameters( const char *_name, textureFilter_t filter, textureRepeat_t repeat, textureUsage_t usage, cubeFiles_t cubeMap ) const {
- if ( !_name || !_name[0] || idStr::Icmp( _name, "default" ) == 0 || idStr::Icmp( _name, "_default" ) == 0 ) {
- declManager->MediaPrint( "DEFAULTED\n" );
- return globalImages->defaultImage;
- }
- if ( idStr::Icmpn( _name, "fonts", 5 ) == 0 || idStr::Icmpn( _name, "newfonts", 8 ) == 0 ) {
- usage = TD_FONT;
- }
- if ( idStr::Icmpn( _name, "lights", 6 ) == 0 ) {
- usage = TD_LIGHT;
- }
- // strip any .tga file extensions from anywhere in the _name, including image program parameters
- idStrStatic< MAX_OSPATH > name = _name;
- name.Replace( ".tga", "" );
- name.BackSlashesToSlashes();
- int hash = name.FileNameHash();
- for ( int i = imageHash.First( hash ); i != -1; i = imageHash.Next( i ) ) {
- idImage * image = images[i];
- if ( name.Icmp( image->GetName() ) == 0 ) {
- // the built in's, like _white and _flat always match the other options
- if ( name[0] == '_' ) {
- return image;
- }
- if ( image->cubeFiles != cubeMap ) {
- common->Error( "Image '%s' has been referenced with conflicting cube map states", _name );
- }
- if ( image->filter != filter || image->repeat != repeat ) {
- // we might want to have the system reset these parameters on every bind and
- // share the image data
- continue;
- }
- if ( image->usage != usage ) {
- // If an image is used differently then we need 2 copies of it because usage affects the way it's compressed and swizzled
- continue;
- }
- return image;
- }
- }
- return NULL;
- }
- /*
- ===============
- ImageFromFile
- Finds or loads the given image, always returning a valid image pointer.
- Loading of the image may be deferred for dynamic loading.
- ==============
- */
- idImage *idImageManager::ImageFromFile( const char *_name, textureFilter_t filter,
- textureRepeat_t repeat, textureUsage_t usage, cubeFiles_t cubeMap ) {
- if ( !_name || !_name[0] || idStr::Icmp( _name, "default" ) == 0 || idStr::Icmp( _name, "_default" ) == 0 ) {
- declManager->MediaPrint( "DEFAULTED\n" );
- return globalImages->defaultImage;
- }
- if ( idStr::Icmpn( _name, "fonts", 5 ) == 0 || idStr::Icmpn( _name, "newfonts", 8 ) == 0 ) {
- usage = TD_FONT;
- }
- if ( idStr::Icmpn( _name, "lights", 6 ) == 0 ) {
- usage = TD_LIGHT;
- }
- // strip any .tga file extensions from anywhere in the _name, including image program parameters
- idStrStatic< MAX_OSPATH > name = _name;
- name.Replace( ".tga", "" );
- name.BackSlashesToSlashes();
- //
- // see if the image is already loaded, unless we
- // are in a reloadImages call
- //
- int hash = name.FileNameHash();
- for ( int i = imageHash.First( hash ); i != -1; i = imageHash.Next( i ) ) {
- idImage * image = images[i];
- if ( name.Icmp( image->GetName() ) == 0 ) {
- // the built in's, like _white and _flat always match the other options
- if ( name[0] == '_' ) {
- return image;
- }
- if ( image->cubeFiles != cubeMap ) {
- common->Error( "Image '%s' has been referenced with conflicting cube map states", _name );
- }
- if ( image->filter != filter || image->repeat != repeat ) {
- // we might want to have the system reset these parameters on every bind and
- // share the image data
- continue;
- }
- if ( image->usage != usage ) {
- // If an image is used differently then we need 2 copies of it because usage affects the way it's compressed and swizzled
- continue;
- }
- image->usage = usage;
- image->levelLoadReferenced = true;
- if ( ( !insideLevelLoad || preloadingMapImages ) && !image->IsLoaded() ) {
- image->referencedOutsideLevelLoad = ( !insideLevelLoad && !preloadingMapImages );
- image->ActuallyLoadImage( false ); // load is from front end
- declManager->MediaPrint( "%ix%i %s (reload for mixed referneces)\n", image->GetUploadWidth(), image->GetUploadHeight(), image->GetName() );
- }
- return image;
- }
- }
- //
- // create a new image
- //
- idImage * image = AllocImage( name );
- image->cubeFiles = cubeMap;
- image->usage = usage;
- image->filter = filter;
- image->repeat = repeat;
- image->levelLoadReferenced = true;
- // load it if we aren't in a level preload
- if ( !insideLevelLoad || preloadingMapImages ) {
- image->referencedOutsideLevelLoad = ( !insideLevelLoad && !preloadingMapImages );
- image->ActuallyLoadImage( false ); // load is from front end
- declManager->MediaPrint( "%ix%i %s\n", image->GetUploadWidth(), image->GetUploadHeight(), image->GetName() );
- } else {
- declManager->MediaPrint( "%s\n", image->GetName() );
- }
- return image;
- }
- /*
- ========================
- idImageManager::ScratchImage
- ========================
- */
- idImage * idImageManager::ScratchImage( const char *_name, idImageOpts *imgOpts, textureFilter_t filter, textureRepeat_t repeat, textureUsage_t usage ) {
- if ( !_name || !_name[0] ) {
- idLib::FatalError( "idImageManager::ScratchImage called with empty name" );
- }
- if ( imgOpts == NULL ) {
- idLib::FatalError( "idImageManager::ScratchImage called with NULL imgOpts" );
- }
- idStr name = _name;
- //
- // see if the image is already loaded, unless we
- // are in a reloadImages call
- //
- int hash = name.FileNameHash();
- for ( int i = imageHash.First( hash ); i != -1; i = imageHash.Next( i ) ) {
- idImage * image = images[i];
- if ( name.Icmp( image->GetName() ) == 0 ) {
- // the built in's, like _white and _flat always match the other options
- if ( name[0] == '_' ) {
- return image;
- }
- if ( image->filter != filter || image->repeat != repeat ) {
- // we might want to have the system reset these parameters on every bind and
- // share the image data
- continue;
- }
- if ( image->usage != usage ) {
- // If an image is used differently then we need 2 copies of it because usage affects the way it's compressed and swizzled
- continue;
- }
- image->usage = usage;
- image->levelLoadReferenced = true;
- image->referencedOutsideLevelLoad = true;
- return image;
- }
- }
- // clamp is the only repeat mode that makes sense for cube maps, but
- // some platforms let them stay in repeat mode and get border seam issues
- if ( imgOpts->textureType == TT_CUBIC && repeat != TR_CLAMP ) {
- repeat = TR_CLAMP;
- }
- //
- // create a new image
- //
- idImage* newImage = AllocImage( name );
- if ( newImage != NULL ) {
- newImage->AllocImage( *imgOpts, filter, repeat );
- }
- return newImage;
- }
- /*
- ===============
- idImageManager::GetImage
- ===============
- */
- idImage *idImageManager::GetImage( const char *_name ) const {
- if ( !_name || !_name[0] || idStr::Icmp( _name, "default" ) == 0 || idStr::Icmp( _name, "_default" ) == 0 ) {
- declManager->MediaPrint( "DEFAULTED\n" );
- return globalImages->defaultImage;
- }
- // strip any .tga file extensions from anywhere in the _name, including image program parameters
- idStr name = _name;
- name.Replace( ".tga", "" );
- name.BackSlashesToSlashes();
- //
- // look in loaded images
- //
- int hash = name.FileNameHash();
- for ( int i = imageHash.First( hash ); i != -1; i = imageHash.Next( i ) ) {
- idImage * image = images[i];
- if ( name.Icmp( image->GetName() ) == 0 ) {
- return image;
- }
- }
- return NULL;
- }
- /*
- ===============
- PurgeAllImages
- ===============
- */
- void idImageManager::PurgeAllImages() {
- int i;
- idImage *image;
- for ( i = 0; i < images.Num() ; i++ ) {
- image = images[i];
- image->PurgeImage();
- }
- }
- /*
- ===============
- ReloadImages
- ===============
- */
- void idImageManager::ReloadImages( bool all ) {
- for ( int i = 0 ; i < globalImages->images.Num() ; i++ ) {
- globalImages->images[ i ]->Reload( all );
- }
- }
- /*
- ===============
- R_CombineCubeImages_f
- Used to combine animations of six separate tga files into
- a serials of 6x taller tga files, for preparation to roq compress
- ===============
- */
- void R_CombineCubeImages_f( const idCmdArgs &args ) {
- if ( args.Argc() != 2 ) {
- common->Printf( "usage: combineCubeImages <baseName>\n" );
- common->Printf( " combines basename[1-6][0001-9999].tga to basenameCM[0001-9999].tga\n" );
- common->Printf( " 1: forward 2:right 3:back 4:left 5:up 6:down\n" );
- return;
- }
- idStr baseName = args.Argv( 1 );
- common->SetRefreshOnPrint( true );
- for ( int frameNum = 1 ; frameNum < 10000 ; frameNum++ ) {
- char filename[MAX_IMAGE_NAME];
- byte *pics[6];
- int width = 0, height = 0;
- int side;
- int orderRemap[6] = { 1,3,4,2,5,6 };
- for ( side = 0 ; side < 6 ; side++ ) {
- sprintf( filename, "%s%i%04i.tga", baseName.c_str(), orderRemap[side], frameNum );
- common->Printf( "reading %s\n", filename );
- R_LoadImage( filename, &pics[side], &width, &height, NULL, true );
- if ( !pics[side] ) {
- common->Printf( "not found.\n" );
- break;
- }
- // convert from "camera" images to native cube map images
- switch( side ) {
- case 0: // forward
- R_RotatePic( pics[side], width);
- break;
- case 1: // back
- R_RotatePic( pics[side], width);
- R_HorizontalFlip( pics[side], width, height );
- R_VerticalFlip( pics[side], width, height );
- break;
- case 2: // left
- R_VerticalFlip( pics[side], width, height );
- break;
- case 3: // right
- R_HorizontalFlip( pics[side], width, height );
- break;
- case 4: // up
- R_RotatePic( pics[side], width);
- break;
- case 5: // down
- R_RotatePic( pics[side], width);
- break;
- }
- }
- if ( side != 6 ) {
- for ( int i = 0 ; i < side ; side++ ) {
- Mem_Free( pics[side] );
- }
- break;
- }
- idTempArray<byte> buf( width*height*6*4 );
- byte *combined = (byte *)buf.Ptr();
- for ( side = 0 ; side < 6 ; side++ ) {
- memcpy( combined+width*height*4*side, pics[side], width*height*4 );
- Mem_Free( pics[side] );
- }
- sprintf( filename, "%sCM%04i.tga", baseName.c_str(), frameNum );
- common->Printf( "writing %s\n", filename );
- R_WriteTGA( filename, combined, width, height*6 );
- }
- common->SetRefreshOnPrint( false );
- }
- /*
- ===============
- UnbindAll
- ===============
- */
- void idImageManager::UnbindAll() {
- int oldTMU = backEnd.glState.currenttmu;
- for ( int i = 0; i < MAX_PROG_TEXTURE_PARMS; ++i ) {
- backEnd.glState.currenttmu = i;
- BindNull();
- }
- backEnd.glState.currenttmu = oldTMU;
- }
- /*
- ===============
- BindNull
- ===============
- */
- void idImageManager::BindNull() {
- RENDERLOG_PRINTF( "BindNull()\n" );
- }
- /*
- ===============
- Init
- ===============
- */
- void idImageManager::Init() {
- images.Resize( 1024, 1024 );
- imageHash.ResizeIndex( 1024 );
- CreateIntrinsicImages();
- cmdSystem->AddCommand( "reloadImages", R_ReloadImages_f, CMD_FL_RENDERER, "reloads images" );
- cmdSystem->AddCommand( "listImages", R_ListImages_f, CMD_FL_RENDERER, "lists images" );
- cmdSystem->AddCommand( "combineCubeImages", R_CombineCubeImages_f, CMD_FL_RENDERER, "combines six images for roq compression" );
- // should forceLoadImages be here?
- }
- /*
- ===============
- Shutdown
- ===============
- */
- void idImageManager::Shutdown() {
- images.DeleteContents( true );
- imageHash.Clear();
- }
- /*
- ====================
- idImageManager::BeginLevelLoad
- Frees all images used by the previous level
- ====================
- */
- void idImageManager::BeginLevelLoad() {
- insideLevelLoad = true;
- for ( int i = 0 ; i < images.Num() ; i++ ) {
- idImage *image = images[ i ];
- // generator function images are always kept around
- if ( image->generatorFunction ) {
- continue;
- }
- if ( !image->referencedOutsideLevelLoad && image->IsLoaded() ) {
- image->PurgeImage();
- //idLib::Printf( "purging %s\n", image->GetName() );
- } else {
- //idLib::Printf( "not purging %s\n", image->GetName() );
- }
- image->levelLoadReferenced = false;
- }
- }
- /*
- ====================
- idImageManager::ExcludePreloadImage
- ====================
- */
- bool idImageManager::ExcludePreloadImage( const char *name ) {
- idStrStatic< MAX_OSPATH > imgName = name;
- imgName.ToLower();
- if ( imgName.Find( "newfonts/", false ) >= 0 ) {
- return true;
- }
- if ( imgName.Find( "generated/swf/", false ) >= 0 ) {
- return true;
- }
- if ( imgName.Find( "/loadscreens/", false ) >= 0 ) {
- return true;
- }
- return false;
- }
- /*
- ====================
- idImageManager::Preload
- ====================
- */
- void idImageManager::Preload( const idPreloadManifest &manifest, const bool & mapPreload ) {
- if ( preLoad_Images.GetBool() && manifest.NumResources() > 0 ) {
- // preload this levels images
- common->Printf( "Preloading images...\n" );
- preloadingMapImages = mapPreload;
- int start = Sys_Milliseconds();
- int numLoaded = 0;
- //fileSystem->StartPreload( preloadImageFiles );
- for ( int i = 0; i < manifest.NumResources(); i++ ) {
- const preloadEntry_s & p = manifest.GetPreloadByIndex( i );
- if ( p.resType == PRELOAD_IMAGE && !ExcludePreloadImage( p.resourceName ) ) {
- globalImages->ImageFromFile( p.resourceName, ( textureFilter_t )p.imgData.filter, ( textureRepeat_t )p.imgData.repeat, ( textureUsage_t )p.imgData.usage, ( cubeFiles_t )p.imgData.cubeMap );
- numLoaded++;
- }
- }
- //fileSystem->StopPreload();
- int end = Sys_Milliseconds();
- common->Printf( "%05d images preloaded ( or were already loaded ) in %5.1f seconds\n", numLoaded, ( end - start ) * 0.001 );
- common->Printf( "----------------------------------------\n" );
- preloadingMapImages = false;
- }
- }
- /*
- ===============
- idImageManager::LoadLevelImages
- ===============
- */
- int idImageManager::LoadLevelImages( bool pacifier ) {
- int loadCount = 0;
- for ( int i = 0 ; i < images.Num() ; i++ ) {
- if ( pacifier ) {
- common->UpdateLevelLoadPacifier();
- }
- idImage *image = images[ i ];
- if ( image->generatorFunction ) {
- continue;
- }
- if ( image->levelLoadReferenced && !image->IsLoaded() ) {
- loadCount++;
- image->ActuallyLoadImage( false );
- }
- }
- return loadCount;
- }
- /*
- ===============
- idImageManager::EndLevelLoad
- ===============
- */
- void idImageManager::EndLevelLoad() {
- insideLevelLoad = false;
- common->Printf( "----- idImageManager::EndLevelLoad -----\n" );
- int start = Sys_Milliseconds();
- int loadCount = LoadLevelImages( true );
- int end = Sys_Milliseconds();
- common->Printf( "%5i images loaded in %5.1f seconds\n", loadCount, (end-start) * 0.001 );
- common->Printf( "----------------------------------------\n" );
- //R_ListImages_f( idCmdArgs( "sorted sorted", false ) );
- }
- /*
- ===============
- idImageManager::StartBuild
- ===============
- */
- void idImageManager::StartBuild() {
- }
- /*
- ===============
- idImageManager::FinishBuild
- ===============
- */
- void idImageManager::FinishBuild( bool removeDups ) {
- }
- /*
- ===============
- idImageManager::PrintMemInfo
- ===============
- */
- void idImageManager::PrintMemInfo( MemInfo_t *mi ) {
- int i, j, total = 0;
- int *sortIndex;
- idFile *f;
- f = fileSystem->OpenFileWrite( mi->filebase + "_images.txt" );
- if ( !f ) {
- return;
- }
- // sort first
- sortIndex = new (TAG_IMAGE) int[images.Num()];
- for ( i = 0; i < images.Num(); i++ ) {
- sortIndex[i] = i;
- }
- for ( i = 0; i < images.Num() - 1; i++ ) {
- for ( j = i + 1; j < images.Num(); j++ ) {
- if ( images[sortIndex[i]]->StorageSize() < images[sortIndex[j]]->StorageSize() ) {
- int temp = sortIndex[i];
- sortIndex[i] = sortIndex[j];
- sortIndex[j] = temp;
- }
- }
- }
- // print next
- for ( i = 0; i < images.Num(); i++ ) {
- idImage *im = images[sortIndex[i]];
- int size;
- size = im->StorageSize();
- total += size;
- f->Printf( "%s %3i %s\n", idStr::FormatNumber( size ).c_str(), im->refCount, im->GetName() );
- }
- delete [] sortIndex;
- mi->imageAssetsTotal = total;
- f->Printf( "\nTotal image bytes allocated: %s\n", idStr::FormatNumber( total ).c_str() );
- fileSystem->CloseFile( f );
- }
|