Image_load.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716
  1. /*
  2. ===========================================================================
  3. Doom 3 BFG Edition GPL Source Code
  4. Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
  5. This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
  6. Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation, either version 3 of the License, or
  9. (at your option) any later version.
  10. Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
  16. 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.
  17. 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.
  18. ===========================================================================
  19. */
  20. #pragma hdrstop
  21. #include "../idlib/precompiled.h"
  22. #include "tr_local.h"
  23. /*
  24. ================
  25. BitsForFormat
  26. ================
  27. */
  28. int BitsForFormat( textureFormat_t format ) {
  29. switch ( format ) {
  30. case FMT_NONE: return 0;
  31. case FMT_RGBA8: return 32;
  32. case FMT_XRGB8: return 32;
  33. case FMT_RGB565: return 16;
  34. case FMT_L8A8: return 16;
  35. case FMT_ALPHA: return 8;
  36. case FMT_LUM8: return 8;
  37. case FMT_INT8: return 8;
  38. case FMT_DXT1: return 4;
  39. case FMT_DXT5: return 8;
  40. case FMT_DEPTH: return 32;
  41. case FMT_X16: return 16;
  42. case FMT_Y16_X16: return 32;
  43. default:
  44. assert( 0 );
  45. return 0;
  46. }
  47. }
  48. /*
  49. ========================
  50. idImage::DeriveOpts
  51. ========================
  52. */
  53. ID_INLINE void idImage::DeriveOpts() {
  54. if ( opts.format == FMT_NONE ) {
  55. opts.colorFormat = CFM_DEFAULT;
  56. switch ( usage ) {
  57. case TD_COVERAGE:
  58. opts.format = FMT_DXT1;
  59. opts.colorFormat = CFM_GREEN_ALPHA;
  60. break;
  61. case TD_DEPTH:
  62. opts.format = FMT_DEPTH;
  63. break;
  64. case TD_DIFFUSE:
  65. // TD_DIFFUSE gets only set to when its a diffuse texture for an interaction
  66. opts.gammaMips = true;
  67. opts.format = FMT_DXT5;
  68. opts.colorFormat = CFM_YCOCG_DXT5;
  69. break;
  70. case TD_SPECULAR:
  71. opts.gammaMips = true;
  72. opts.format = FMT_DXT1;
  73. opts.colorFormat = CFM_DEFAULT;
  74. break;
  75. case TD_DEFAULT:
  76. opts.gammaMips = true;
  77. opts.format = FMT_DXT5;
  78. opts.colorFormat = CFM_DEFAULT;
  79. break;
  80. case TD_BUMP:
  81. opts.format = FMT_DXT5;
  82. opts.colorFormat = CFM_NORMAL_DXT5;
  83. break;
  84. case TD_FONT:
  85. opts.format = FMT_DXT1;
  86. opts.colorFormat = CFM_GREEN_ALPHA;
  87. opts.numLevels = 4; // We only support 4 levels because we align to 16 in the exporter
  88. opts.gammaMips = true;
  89. break;
  90. case TD_LIGHT:
  91. opts.format = FMT_RGB565;
  92. opts.gammaMips = true;
  93. break;
  94. case TD_LOOKUP_TABLE_MONO:
  95. opts.format = FMT_INT8;
  96. break;
  97. case TD_LOOKUP_TABLE_ALPHA:
  98. opts.format = FMT_ALPHA;
  99. break;
  100. case TD_LOOKUP_TABLE_RGB1:
  101. case TD_LOOKUP_TABLE_RGBA:
  102. opts.format = FMT_RGBA8;
  103. break;
  104. default:
  105. assert( false );
  106. opts.format = FMT_RGBA8;
  107. }
  108. }
  109. if ( opts.numLevels == 0 ) {
  110. opts.numLevels = 1;
  111. if ( filter == TF_LINEAR || filter == TF_NEAREST ) {
  112. // don't create mip maps if we aren't going to be using them
  113. } else {
  114. int temp_width = opts.width;
  115. int temp_height = opts.height;
  116. while ( temp_width > 1 || temp_height > 1 ) {
  117. temp_width >>= 1;
  118. temp_height >>= 1;
  119. if ( ( opts.format == FMT_DXT1 || opts.format == FMT_DXT5 ) &&
  120. ( ( temp_width & 0x3 ) != 0 || ( temp_height & 0x3 ) != 0 ) ) {
  121. break;
  122. }
  123. opts.numLevels++;
  124. }
  125. }
  126. }
  127. }
  128. /*
  129. ========================
  130. idImage::AllocImage
  131. ========================
  132. */
  133. void idImage::AllocImage( const idImageOpts &imgOpts, textureFilter_t tf, textureRepeat_t tr ) {
  134. filter = tf;
  135. repeat = tr;
  136. opts = imgOpts;
  137. DeriveOpts();
  138. AllocImage();
  139. }
  140. /*
  141. ================
  142. GenerateImage
  143. ================
  144. */
  145. void idImage::GenerateImage( const byte *pic, int width, int height, textureFilter_t filterParm, textureRepeat_t repeatParm, textureUsage_t usageParm ) {
  146. PurgeImage();
  147. filter = filterParm;
  148. repeat = repeatParm;
  149. usage = usageParm;
  150. cubeFiles = CF_2D;
  151. opts.textureType = TT_2D;
  152. opts.width = width;
  153. opts.height = height;
  154. opts.numLevels = 0;
  155. DeriveOpts();
  156. // if we don't have a rendering context, just return after we
  157. // have filled in the parms. We must have the values set, or
  158. // an image match from a shader before the render starts would miss
  159. // the generated texture
  160. if ( !R_IsInitialized() ) {
  161. return;
  162. }
  163. idBinaryImage im( GetName() );
  164. im.Load2DFromMemory( width, height, pic, opts.numLevels, opts.format, opts.colorFormat, opts.gammaMips );
  165. AllocImage();
  166. for ( int i = 0; i < im.NumImages(); i++ ) {
  167. const bimageImage_t & img = im.GetImageHeader( i );
  168. const byte * data = im.GetImageData( i );
  169. SubImageUpload( img.level, 0, 0, img.destZ, img.width, img.height, data );
  170. }
  171. }
  172. /*
  173. ====================
  174. GenerateCubeImage
  175. Non-square cube sides are not allowed
  176. ====================
  177. */
  178. void idImage::GenerateCubeImage( const byte *pic[6], int size, textureFilter_t filterParm, textureUsage_t usageParm ) {
  179. PurgeImage();
  180. filter = filterParm;
  181. repeat = TR_CLAMP;
  182. usage = usageParm;
  183. cubeFiles = CF_NATIVE;
  184. opts.textureType = TT_CUBIC;
  185. opts.width = size;
  186. opts.height = size;
  187. opts.numLevels = 0;
  188. DeriveOpts();
  189. // if we don't have a rendering context, just return after we
  190. // have filled in the parms. We must have the values set, or
  191. // an image match from a shader before the render starts would miss
  192. // the generated texture
  193. if ( !R_IsInitialized() ) {
  194. return;
  195. }
  196. idBinaryImage im( GetName() );
  197. im.LoadCubeFromMemory( size, pic, opts.numLevels, opts.format, opts.gammaMips );
  198. AllocImage();
  199. for ( int i = 0; i < im.NumImages(); i++ ) {
  200. const bimageImage_t & img = im.GetImageHeader( i );
  201. const byte * data = im.GetImageData( i );
  202. SubImageUpload( img.level, 0, 0, img.destZ, img.width, img.height, data );
  203. }
  204. }
  205. /*
  206. ===============
  207. GetGeneratedName
  208. name contains GetName() upon entry
  209. ===============
  210. */
  211. void idImage::GetGeneratedName( idStr &_name, const textureUsage_t &_usage, const cubeFiles_t &_cube ) {
  212. idStrStatic< 64 > extension;
  213. _name.ExtractFileExtension( extension );
  214. _name.StripFileExtension();
  215. _name += va( "#__%02d%02d", (int)_usage, (int)_cube );
  216. if ( extension.Length() > 0 ) {
  217. _name.SetFileExtension( extension );
  218. }
  219. }
  220. /*
  221. ===============
  222. ActuallyLoadImage
  223. Absolutely every image goes through this path
  224. On exit, the idImage will have a valid OpenGL texture number that can be bound
  225. ===============
  226. */
  227. void idImage::ActuallyLoadImage( bool fromBackEnd ) {
  228. // if we don't have a rendering context yet, just return
  229. if ( !R_IsInitialized() ) {
  230. return;
  231. }
  232. // this is the ONLY place generatorFunction will ever be called
  233. if ( generatorFunction ) {
  234. generatorFunction( this );
  235. return;
  236. }
  237. if ( com_productionMode.GetInteger() != 0 ) {
  238. sourceFileTime = FILE_NOT_FOUND_TIMESTAMP;
  239. if ( cubeFiles != CF_2D ) {
  240. opts.textureType = TT_CUBIC;
  241. repeat = TR_CLAMP;
  242. }
  243. } else {
  244. if ( cubeFiles != CF_2D ) {
  245. opts.textureType = TT_CUBIC;
  246. repeat = TR_CLAMP;
  247. R_LoadCubeImages( GetName(), cubeFiles, NULL, NULL, &sourceFileTime );
  248. } else {
  249. opts.textureType = TT_2D;
  250. R_LoadImageProgram( GetName(), NULL, NULL, NULL, &sourceFileTime, &usage );
  251. }
  252. }
  253. // Figure out opts.colorFormat and opts.format so we can make sure the binary image is up to date
  254. DeriveOpts();
  255. idStrStatic< MAX_OSPATH > generatedName = GetName();
  256. GetGeneratedName( generatedName, usage, cubeFiles );
  257. idBinaryImage im( generatedName );
  258. binaryFileTime = im.LoadFromGeneratedFile( sourceFileTime );
  259. // BFHACK, do not want to tweak on buildgame so catch these images here
  260. if ( binaryFileTime == FILE_NOT_FOUND_TIMESTAMP && fileSystem->UsingResourceFiles() ) {
  261. int c = 1;
  262. while ( c-- > 0 ) {
  263. if ( generatedName.Find( "guis/assets/white#__0000", false ) >= 0 ) {
  264. generatedName.Replace( "white#__0000", "white#__0200" );
  265. im.SetName( generatedName );
  266. binaryFileTime = im.LoadFromGeneratedFile( sourceFileTime );
  267. break;
  268. }
  269. if ( generatedName.Find( "guis/assets/white#__0100", false ) >= 0 ) {
  270. generatedName.Replace( "white#__0100", "white#__0200" );
  271. im.SetName( generatedName );
  272. binaryFileTime = im.LoadFromGeneratedFile( sourceFileTime );
  273. break;
  274. }
  275. if ( generatedName.Find( "textures/black#__0100", false ) >= 0 ) {
  276. generatedName.Replace( "black#__0100", "black#__0200" );
  277. im.SetName( generatedName );
  278. binaryFileTime = im.LoadFromGeneratedFile( sourceFileTime );
  279. break;
  280. }
  281. if ( generatedName.Find( "textures/decals/bulletglass1_d#__0100", false ) >= 0 ) {
  282. generatedName.Replace( "bulletglass1_d#__0100", "bulletglass1_d#__0200" );
  283. im.SetName( generatedName );
  284. binaryFileTime = im.LoadFromGeneratedFile( sourceFileTime );
  285. break;
  286. }
  287. if ( generatedName.Find( "models/monsters/skeleton/skeleton01_d#__1000", false ) >= 0 ) {
  288. generatedName.Replace( "skeleton01_d#__1000", "skeleton01_d#__0100" );
  289. im.SetName( generatedName );
  290. binaryFileTime = im.LoadFromGeneratedFile( sourceFileTime );
  291. break;
  292. }
  293. }
  294. }
  295. const bimageFile_t & header = im.GetFileHeader();
  296. if ( ( fileSystem->InProductionMode() && binaryFileTime != FILE_NOT_FOUND_TIMESTAMP ) || ( ( binaryFileTime != FILE_NOT_FOUND_TIMESTAMP )
  297. && ( header.colorFormat == opts.colorFormat )
  298. && ( header.format == opts.format )
  299. && ( header.textureType == opts.textureType )
  300. ) ) {
  301. opts.width = header.width;
  302. opts.height = header.height;
  303. opts.numLevels = header.numLevels;
  304. opts.colorFormat = (textureColor_t)header.colorFormat;
  305. opts.format = (textureFormat_t)header.format;
  306. opts.textureType = (textureType_t)header.textureType;
  307. if ( cvarSystem->GetCVarBool( "fs_buildresources" ) ) {
  308. // for resource gathering write this image to the preload file for this map
  309. fileSystem->AddImagePreload( GetName(), filter, repeat, usage, cubeFiles );
  310. }
  311. } else {
  312. if ( cubeFiles != CF_2D ) {
  313. int size;
  314. byte * pics[6];
  315. if ( !R_LoadCubeImages( GetName(), cubeFiles, pics, &size, &sourceFileTime ) || size == 0 ) {
  316. idLib::Warning( "Couldn't load cube image: %s", GetName() );
  317. return;
  318. }
  319. opts.textureType = TT_CUBIC;
  320. repeat = TR_CLAMP;
  321. opts.width = size;
  322. opts.height = size;
  323. opts.numLevels = 0;
  324. DeriveOpts();
  325. im.LoadCubeFromMemory( size, (const byte **)pics, opts.numLevels, opts.format, opts.gammaMips );
  326. repeat = TR_CLAMP;
  327. for ( int i = 0; i < 6; i++ ) {
  328. if ( pics[i] ) {
  329. Mem_Free( pics[i] );
  330. }
  331. }
  332. } else {
  333. int width, height;
  334. byte * pic;
  335. // load the full specification, and perform any image program calculations
  336. R_LoadImageProgram( GetName(), &pic, &width, &height, &sourceFileTime, &usage );
  337. if ( pic == NULL ) {
  338. idLib::Warning( "Couldn't load image: %s : %s", GetName(), generatedName.c_str() );
  339. // create a default so it doesn't get continuously reloaded
  340. opts.width = 8;
  341. opts.height = 8;
  342. opts.numLevels = 1;
  343. DeriveOpts();
  344. AllocImage();
  345. // clear the data so it's not left uninitialized
  346. idTempArray<byte> clear( opts.width * opts.height * 4 );
  347. memset( clear.Ptr(), 0, clear.Size() );
  348. for ( int level = 0; level < opts.numLevels; level++ ) {
  349. SubImageUpload( level, 0, 0, 0, opts.width >> level, opts.height >> level, clear.Ptr() );
  350. }
  351. return;
  352. }
  353. opts.width = width;
  354. opts.height = height;
  355. opts.numLevels = 0;
  356. DeriveOpts();
  357. im.Load2DFromMemory( opts.width, opts.height, pic, opts.numLevels, opts.format, opts.colorFormat, opts.gammaMips );
  358. Mem_Free( pic );
  359. }
  360. binaryFileTime = im.WriteGeneratedFile( sourceFileTime );
  361. }
  362. AllocImage();
  363. for ( int i = 0; i < im.NumImages(); i++ ) {
  364. const bimageImage_t & img = im.GetImageHeader( i );
  365. const byte * data = im.GetImageData( i );
  366. SubImageUpload( img.level, 0, 0, img.destZ, img.width, img.height, data );
  367. }
  368. }
  369. /*
  370. ==============
  371. Bind
  372. Automatically enables 2D mapping or cube mapping if needed
  373. ==============
  374. */
  375. void idImage::Bind() {
  376. RENDERLOG_PRINTF( "idImage::Bind( %s )\n", GetName() );
  377. // load the image if necessary (FIXME: not SMP safe!)
  378. if ( !IsLoaded() ) {
  379. // load the image on demand here, which isn't our normal game operating mode
  380. ActuallyLoadImage( true );
  381. }
  382. const int texUnit = backEnd.glState.currenttmu;
  383. tmu_t * tmu = &backEnd.glState.tmu[texUnit];
  384. // bind the texture
  385. if ( opts.textureType == TT_2D ) {
  386. if ( tmu->current2DMap != texnum ) {
  387. tmu->current2DMap = texnum;
  388. qglBindMultiTextureEXT( GL_TEXTURE0_ARB + texUnit, GL_TEXTURE_2D, texnum );
  389. }
  390. } else if ( opts.textureType == TT_CUBIC ) {
  391. if ( tmu->currentCubeMap != texnum ) {
  392. tmu->currentCubeMap = texnum;
  393. qglBindMultiTextureEXT( GL_TEXTURE0_ARB + texUnit, GL_TEXTURE_CUBE_MAP_EXT, texnum );
  394. }
  395. }
  396. }
  397. /*
  398. ================
  399. MakePowerOfTwo
  400. ================
  401. */
  402. int MakePowerOfTwo( int num ) {
  403. int pot;
  404. for ( pot = 1; pot < num; pot <<= 1 ) {
  405. }
  406. return pot;
  407. }
  408. /*
  409. ====================
  410. CopyFramebuffer
  411. ====================
  412. */
  413. void idImage::CopyFramebuffer( int x, int y, int imageWidth, int imageHeight ) {
  414. qglBindTexture( ( opts.textureType == TT_CUBIC ) ? GL_TEXTURE_CUBE_MAP_EXT : GL_TEXTURE_2D, texnum );
  415. qglReadBuffer( GL_BACK );
  416. opts.width = imageWidth;
  417. opts.height = imageHeight;
  418. qglCopyTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA8, x, y, imageWidth, imageHeight, 0 );
  419. // these shouldn't be necessary if the image was initialized properly
  420. qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  421. qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  422. qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
  423. qglTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
  424. backEnd.pc.c_copyFrameBuffer++;
  425. }
  426. /*
  427. ====================
  428. CopyDepthbuffer
  429. ====================
  430. */
  431. void idImage::CopyDepthbuffer( int x, int y, int imageWidth, int imageHeight ) {
  432. qglBindTexture( ( opts.textureType == TT_CUBIC ) ? GL_TEXTURE_CUBE_MAP_EXT : GL_TEXTURE_2D, texnum );
  433. opts.width = imageWidth;
  434. opts.height = imageHeight;
  435. qglCopyTexImage2D( GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, x, y, imageWidth, imageHeight, 0 );
  436. backEnd.pc.c_copyFrameBuffer++;
  437. }
  438. /*
  439. =============
  440. RB_UploadScratchImage
  441. if rows = cols * 6, assume it is a cube map animation
  442. =============
  443. */
  444. void idImage::UploadScratch( const byte * data, int cols, int rows ) {
  445. // if rows = cols * 6, assume it is a cube map animation
  446. if ( rows == cols * 6 ) {
  447. rows /= 6;
  448. const byte * pic[6];
  449. for ( int i = 0; i < 6; i++ ) {
  450. pic[i] = data + cols * rows * 4 * i;
  451. }
  452. if ( opts.textureType != TT_CUBIC || usage != TD_LOOKUP_TABLE_RGBA ) {
  453. GenerateCubeImage( pic, cols, TF_LINEAR, TD_LOOKUP_TABLE_RGBA );
  454. return;
  455. }
  456. if ( opts.width != cols || opts.height != rows ) {
  457. opts.width = cols;
  458. opts.height = rows;
  459. AllocImage();
  460. }
  461. SetSamplerState( TF_LINEAR, TR_CLAMP );
  462. for ( int i = 0; i < 6; i++ ) {
  463. SubImageUpload( 0, 0, 0, i, opts.width, opts.height, pic[i] );
  464. }
  465. } else {
  466. if ( opts.textureType != TT_2D || usage != TD_LOOKUP_TABLE_RGBA ) {
  467. GenerateImage( data, cols, rows, TF_LINEAR, TR_REPEAT, TD_LOOKUP_TABLE_RGBA );
  468. return;
  469. }
  470. if ( opts.width != cols || opts.height != rows ) {
  471. opts.width = cols;
  472. opts.height = rows;
  473. AllocImage();
  474. }
  475. SetSamplerState( TF_LINEAR, TR_REPEAT );
  476. SubImageUpload( 0, 0, 0, 0, opts.width, opts.height, data );
  477. }
  478. }
  479. /*
  480. ==================
  481. StorageSize
  482. ==================
  483. */
  484. int idImage::StorageSize() const {
  485. if ( !IsLoaded() ) {
  486. return 0;
  487. }
  488. int baseSize = opts.width * opts.height;
  489. if ( opts.numLevels > 1 ) {
  490. baseSize *= 4;
  491. baseSize /= 3;
  492. }
  493. baseSize *= BitsForFormat( opts.format );
  494. baseSize /= 8;
  495. return baseSize;
  496. }
  497. /*
  498. ==================
  499. Print
  500. ==================
  501. */
  502. void idImage::Print() const {
  503. if ( generatorFunction ) {
  504. common->Printf( "F" );
  505. } else {
  506. common->Printf( " " );
  507. }
  508. switch ( opts.textureType ) {
  509. case TT_2D:
  510. common->Printf( " " );
  511. break;
  512. case TT_CUBIC:
  513. common->Printf( "C" );
  514. break;
  515. default:
  516. common->Printf( "<BAD TYPE:%i>", opts.textureType );
  517. break;
  518. }
  519. common->Printf( "%4i %4i ", opts.width, opts.height );
  520. switch ( opts.format ) {
  521. #define NAME_FORMAT( x ) case FMT_##x: common->Printf( "%-6s ", #x ); break;
  522. NAME_FORMAT( NONE );
  523. NAME_FORMAT( RGBA8 );
  524. NAME_FORMAT( XRGB8 );
  525. NAME_FORMAT( RGB565 );
  526. NAME_FORMAT( L8A8 );
  527. NAME_FORMAT( ALPHA );
  528. NAME_FORMAT( LUM8 );
  529. NAME_FORMAT( INT8 );
  530. NAME_FORMAT( DXT1 );
  531. NAME_FORMAT( DXT5 );
  532. NAME_FORMAT( DEPTH );
  533. NAME_FORMAT( X16 );
  534. NAME_FORMAT( Y16_X16 );
  535. default:
  536. common->Printf( "<%3i>", opts.format );
  537. break;
  538. }
  539. switch( filter ) {
  540. case TF_DEFAULT:
  541. common->Printf( "mip " );
  542. break;
  543. case TF_LINEAR:
  544. common->Printf( "linr " );
  545. break;
  546. case TF_NEAREST:
  547. common->Printf( "nrst " );
  548. break;
  549. default:
  550. common->Printf( "<BAD FILTER:%i>", filter );
  551. break;
  552. }
  553. switch ( repeat ) {
  554. case TR_REPEAT:
  555. common->Printf( "rept " );
  556. break;
  557. case TR_CLAMP_TO_ZERO:
  558. common->Printf( "zero " );
  559. break;
  560. case TR_CLAMP_TO_ZERO_ALPHA:
  561. common->Printf( "azro " );
  562. break;
  563. case TR_CLAMP:
  564. common->Printf( "clmp " );
  565. break;
  566. default:
  567. common->Printf( "<BAD REPEAT:%i>", repeat );
  568. break;
  569. }
  570. common->Printf( "%4ik ", StorageSize() / 1024 );
  571. common->Printf( " %s\n", GetName() );
  572. }
  573. /*
  574. ===============
  575. idImage::Reload
  576. ===============
  577. */
  578. void idImage::Reload( bool force ) {
  579. // always regenerate functional images
  580. if ( generatorFunction ) {
  581. common->DPrintf( "regenerating %s.\n", GetName() );
  582. generatorFunction( this );
  583. return;
  584. }
  585. // check file times
  586. if ( !force ) {
  587. ID_TIME_T current;
  588. if ( cubeFiles != CF_2D ) {
  589. R_LoadCubeImages( imgName, cubeFiles, NULL, NULL, &current );
  590. } else {
  591. // get the current values
  592. R_LoadImageProgram( imgName, NULL, NULL, NULL, &current );
  593. }
  594. if ( current <= sourceFileTime ) {
  595. return;
  596. }
  597. }
  598. common->DPrintf( "reloading %s.\n", GetName() );
  599. PurgeImage();
  600. // Load is from the front end, so the back end must be synced
  601. ActuallyLoadImage( false );
  602. }
  603. /*
  604. ========================
  605. idImage::SetSamplerState
  606. ========================
  607. */
  608. void idImage::SetSamplerState( textureFilter_t tf, textureRepeat_t tr ) {
  609. if ( tf == filter && tr == repeat ) {
  610. return;
  611. }
  612. filter = tf;
  613. repeat = tr;
  614. qglBindTexture( ( opts.textureType == TT_CUBIC ) ? GL_TEXTURE_CUBE_MAP_EXT : GL_TEXTURE_2D, texnum );
  615. SetTexParameters();
  616. }