gl_Image.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483
  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. /*
  23. ================================================================================================
  24. Contains the Image implementation for OpenGL.
  25. ================================================================================================
  26. */
  27. #include "../tr_local.h"
  28. /*
  29. ========================
  30. idImage::SubImageUpload
  31. ========================
  32. */
  33. void idImage::SubImageUpload( int mipLevel, int x, int y, int z, int width, int height, const void * pic, int pixelPitch ) const {
  34. assert( x >= 0 && y >= 0 && mipLevel >= 0 && width >= 0 && height >= 0 && mipLevel < opts.numLevels );
  35. int compressedSize = 0;
  36. if ( IsCompressed() ) {
  37. assert( !(x&3) && !(y&3) );
  38. // compressed size may be larger than the dimensions due to padding to quads
  39. int quadW = ( width + 3 ) & ~3;
  40. int quadH = ( height + 3 ) & ~3;
  41. compressedSize = quadW * quadH * BitsForFormat( opts.format ) / 8;
  42. int padW = ( opts.width + 3 ) & ~3;
  43. int padH = ( opts.height + 3 ) & ~3;
  44. (void)padH;
  45. (void)padW;
  46. assert( x + width <= padW && y + height <= padH );
  47. // upload the non-aligned value, OpenGL understands that there
  48. // will be padding
  49. if ( x + width > opts.width ) {
  50. width = opts.width - x;
  51. }
  52. if ( y + height > opts.height ) {
  53. height = opts.height - x;
  54. }
  55. } else {
  56. assert( x + width <= opts.width && y + height <= opts.height );
  57. }
  58. int target;
  59. int uploadTarget;
  60. if ( opts.textureType == TT_2D ) {
  61. target = GL_TEXTURE_2D;
  62. uploadTarget = GL_TEXTURE_2D;
  63. } else if ( opts.textureType == TT_CUBIC ) {
  64. target = GL_TEXTURE_CUBE_MAP_EXT;
  65. uploadTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT + z;
  66. } else {
  67. assert( !"invalid opts.textureType" );
  68. target = GL_TEXTURE_2D;
  69. uploadTarget = GL_TEXTURE_2D;
  70. }
  71. qglBindTexture( target, texnum );
  72. if ( pixelPitch != 0 ) {
  73. qglPixelStorei( GL_UNPACK_ROW_LENGTH, pixelPitch );
  74. }
  75. if ( opts.format == FMT_RGB565 ) {
  76. glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_TRUE );
  77. }
  78. #ifdef DEBUG
  79. GL_CheckErrors();
  80. #endif
  81. if ( IsCompressed() ) {
  82. qglCompressedTexSubImage2DARB( uploadTarget, mipLevel, x, y, width, height, internalFormat, compressedSize, pic );
  83. } else {
  84. // make sure the pixel store alignment is correct so that lower mips get created
  85. // properly for odd shaped textures - this fixes the mip mapping issues with
  86. // fonts
  87. int unpackAlignment = width * BitsForFormat( (textureFormat_t)opts.format ) / 8;
  88. if ( ( unpackAlignment & 3 ) == 0 ) {
  89. qglPixelStorei( GL_UNPACK_ALIGNMENT, 4 );
  90. } else {
  91. qglPixelStorei( GL_UNPACK_ALIGNMENT, 1 );
  92. }
  93. qglTexSubImage2D( uploadTarget, mipLevel, x, y, width, height, dataFormat, dataType, pic );
  94. }
  95. #ifdef DEBUG
  96. GL_CheckErrors();
  97. #endif
  98. if ( opts.format == FMT_RGB565 ) {
  99. glPixelStorei( GL_UNPACK_SWAP_BYTES, GL_FALSE );
  100. }
  101. if ( pixelPitch != 0 ) {
  102. qglPixelStorei( GL_UNPACK_ROW_LENGTH, 0 );
  103. }
  104. }
  105. /*
  106. ========================
  107. idImage::SetPixel
  108. ========================
  109. */
  110. void idImage::SetPixel( int mipLevel, int x, int y, const void * data, int dataSize ) {
  111. SubImageUpload( mipLevel, x, y, 0, 1, 1, data );
  112. }
  113. /*
  114. ========================
  115. idImage::SetTexParameters
  116. ========================
  117. */
  118. void idImage::SetTexParameters() {
  119. int target = GL_TEXTURE_2D;
  120. switch ( opts.textureType ) {
  121. case TT_2D:
  122. target = GL_TEXTURE_2D;
  123. break;
  124. case TT_CUBIC:
  125. target = GL_TEXTURE_CUBE_MAP_EXT;
  126. break;
  127. default:
  128. idLib::FatalError( "%s: bad texture type %d", GetName(), opts.textureType );
  129. return;
  130. }
  131. // ALPHA, LUMINANCE, LUMINANCE_ALPHA, and INTENSITY have been removed
  132. // in OpenGL 3.2. In order to mimic those modes, we use the swizzle operators
  133. #if defined( USE_CORE_PROFILE )
  134. if ( opts.colorFormat == CFM_GREEN_ALPHA ) {
  135. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_R, GL_ONE );
  136. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_G, GL_ONE );
  137. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_B, GL_ONE );
  138. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_A, GL_GREEN );
  139. } else if ( opts.format == FMT_LUM8 ) {
  140. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_R, GL_RED );
  141. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_G, GL_RED );
  142. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_B, GL_RED );
  143. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_A, GL_ONE );
  144. } else if ( opts.format == FMT_L8A8 ) {
  145. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_R, GL_RED );
  146. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_G, GL_RED );
  147. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_B, GL_RED );
  148. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_A, GL_GREEN );
  149. } else if ( opts.format == FMT_ALPHA ) {
  150. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_R, GL_ONE );
  151. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_G, GL_ONE );
  152. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_B, GL_ONE );
  153. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_A, GL_RED );
  154. } else if ( opts.format == FMT_INT8 ) {
  155. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_R, GL_RED );
  156. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_G, GL_RED );
  157. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_B, GL_RED );
  158. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_A, GL_RED );
  159. } else {
  160. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_R, GL_RED );
  161. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_G, GL_GREEN );
  162. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_B, GL_BLUE );
  163. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_A, GL_ALPHA );
  164. }
  165. #else
  166. if ( opts.colorFormat == CFM_GREEN_ALPHA ) {
  167. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_R, GL_ONE );
  168. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_G, GL_ONE );
  169. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_B, GL_ONE );
  170. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_A, GL_GREEN );
  171. } else if ( opts.format == FMT_ALPHA ) {
  172. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_R, GL_ONE );
  173. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_G, GL_ONE );
  174. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_B, GL_ONE );
  175. qglTexParameteri( target, GL_TEXTURE_SWIZZLE_A, GL_RED );
  176. }
  177. #endif
  178. switch( filter ) {
  179. case TF_DEFAULT:
  180. if ( r_useTrilinearFiltering.GetBool() ) {
  181. qglTexParameterf( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
  182. } else {
  183. qglTexParameterf( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST );
  184. }
  185. qglTexParameterf( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  186. break;
  187. case TF_LINEAR:
  188. qglTexParameterf( target, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
  189. qglTexParameterf( target, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
  190. break;
  191. case TF_NEAREST:
  192. qglTexParameterf( target, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
  193. qglTexParameterf( target, GL_TEXTURE_MAG_FILTER, GL_NEAREST );
  194. break;
  195. default:
  196. common->FatalError( "%s: bad texture filter %d", GetName(), filter );
  197. }
  198. if ( glConfig.anisotropicFilterAvailable ) {
  199. // only do aniso filtering on mip mapped images
  200. if ( filter == TF_DEFAULT ) {
  201. int aniso = r_maxAnisotropicFiltering.GetInteger();
  202. if ( aniso > glConfig.maxTextureAnisotropy ) {
  203. aniso = glConfig.maxTextureAnisotropy;
  204. }
  205. if ( aniso < 0 ) {
  206. aniso = 0;
  207. }
  208. qglTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso );
  209. } else {
  210. qglTexParameterf(target, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1 );
  211. }
  212. }
  213. if ( glConfig.textureLODBiasAvailable && ( usage != TD_FONT ) ) {
  214. // use a blurring LOD bias in combination with high anisotropy to fix our aliasing grate textures...
  215. qglTexParameterf(target, GL_TEXTURE_LOD_BIAS_EXT, r_lodBias.GetFloat() );
  216. }
  217. // set the wrap/clamp modes
  218. switch( repeat ) {
  219. case TR_REPEAT:
  220. qglTexParameterf( target, GL_TEXTURE_WRAP_S, GL_REPEAT );
  221. qglTexParameterf( target, GL_TEXTURE_WRAP_T, GL_REPEAT );
  222. break;
  223. case TR_CLAMP_TO_ZERO: {
  224. float color[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
  225. qglTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, color );
  226. qglTexParameterf( target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
  227. qglTexParameterf( target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
  228. }
  229. break;
  230. case TR_CLAMP_TO_ZERO_ALPHA: {
  231. float color[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  232. qglTexParameterfv(target, GL_TEXTURE_BORDER_COLOR, color );
  233. qglTexParameterf( target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER );
  234. qglTexParameterf( target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER );
  235. }
  236. break;
  237. case TR_CLAMP:
  238. qglTexParameterf( target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
  239. qglTexParameterf( target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
  240. break;
  241. default:
  242. common->FatalError( "%s: bad texture repeat %d", GetName(), repeat );
  243. }
  244. }
  245. /*
  246. ========================
  247. idImage::AllocImage
  248. Every image will pass through this function. Allocates all the necessary MipMap levels for the
  249. Image, but doesn't put anything in them.
  250. This should not be done during normal game-play, if you can avoid it.
  251. ========================
  252. */
  253. void idImage::AllocImage() {
  254. GL_CheckErrors();
  255. PurgeImage();
  256. switch ( opts.format ) {
  257. case FMT_RGBA8:
  258. internalFormat = GL_RGBA8;
  259. dataFormat = GL_RGBA;
  260. dataType = GL_UNSIGNED_BYTE;
  261. break;
  262. case FMT_XRGB8:
  263. internalFormat = GL_RGB;
  264. dataFormat = GL_RGBA;
  265. dataType = GL_UNSIGNED_BYTE;
  266. break;
  267. case FMT_RGB565:
  268. internalFormat = GL_RGB;
  269. dataFormat = GL_RGB;
  270. dataType = GL_UNSIGNED_SHORT_5_6_5;
  271. break;
  272. case FMT_ALPHA:
  273. #if defined( USE_CORE_PROFILE )
  274. internalFormat = GL_R8;
  275. dataFormat = GL_RED;
  276. #else
  277. internalFormat = GL_ALPHA8;
  278. dataFormat = GL_ALPHA;
  279. #endif
  280. dataType = GL_UNSIGNED_BYTE;
  281. break;
  282. case FMT_L8A8:
  283. #if defined( USE_CORE_PROFILE )
  284. internalFormat = GL_RG8;
  285. dataFormat = GL_RG;
  286. #else
  287. internalFormat = GL_LUMINANCE8_ALPHA8;
  288. dataFormat = GL_LUMINANCE_ALPHA;
  289. #endif
  290. dataType = GL_UNSIGNED_BYTE;
  291. break;
  292. case FMT_LUM8:
  293. #if defined( USE_CORE_PROFILE )
  294. internalFormat = GL_R8;
  295. dataFormat = GL_RED;
  296. #else
  297. internalFormat = GL_LUMINANCE8;
  298. dataFormat = GL_LUMINANCE;
  299. #endif
  300. dataType = GL_UNSIGNED_BYTE;
  301. break;
  302. case FMT_INT8:
  303. #if defined( USE_CORE_PROFILE )
  304. internalFormat = GL_R8;
  305. dataFormat = GL_RED;
  306. #else
  307. internalFormat = GL_INTENSITY8;
  308. dataFormat = GL_LUMINANCE;
  309. #endif
  310. dataType = GL_UNSIGNED_BYTE;
  311. break;
  312. case FMT_DXT1:
  313. internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT1_EXT;
  314. dataFormat = GL_RGBA;
  315. dataType = GL_UNSIGNED_BYTE;
  316. break;
  317. case FMT_DXT5:
  318. internalFormat = GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
  319. dataFormat = GL_RGBA;
  320. dataType = GL_UNSIGNED_BYTE;
  321. break;
  322. case FMT_DEPTH:
  323. internalFormat = GL_DEPTH_COMPONENT;
  324. dataFormat = GL_DEPTH_COMPONENT;
  325. dataType = GL_UNSIGNED_BYTE;
  326. break;
  327. case FMT_X16:
  328. internalFormat = GL_INTENSITY16;
  329. dataFormat = GL_LUMINANCE;
  330. dataType = GL_UNSIGNED_SHORT;
  331. break;
  332. case FMT_Y16_X16:
  333. internalFormat = GL_LUMINANCE16_ALPHA16;
  334. dataFormat = GL_LUMINANCE_ALPHA;
  335. dataType = GL_UNSIGNED_SHORT;
  336. break;
  337. default:
  338. idLib::Error( "Unhandled image format %d in %s\n", opts.format, GetName() );
  339. }
  340. // if we don't have a rendering context, just return after we
  341. // have filled in the parms. We must have the values set, or
  342. // an image match from a shader before OpenGL starts would miss
  343. // the generated texture
  344. if ( !R_IsInitialized() ) {
  345. return;
  346. }
  347. // generate the texture number
  348. qglGenTextures( 1, (GLuint *)&texnum );
  349. assert( texnum != TEXTURE_NOT_LOADED );
  350. //----------------------------------------------------
  351. // allocate all the mip levels with NULL data
  352. //----------------------------------------------------
  353. int numSides;
  354. int target;
  355. int uploadTarget;
  356. if ( opts.textureType == TT_2D ) {
  357. target = uploadTarget = GL_TEXTURE_2D;
  358. numSides = 1;
  359. } else if ( opts.textureType == TT_CUBIC ) {
  360. target = GL_TEXTURE_CUBE_MAP_EXT;
  361. uploadTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X_EXT;
  362. numSides = 6;
  363. } else {
  364. assert( !"opts.textureType" );
  365. target = uploadTarget = GL_TEXTURE_2D;
  366. numSides = 1;
  367. }
  368. qglBindTexture( target, texnum );
  369. for ( int side = 0; side < numSides; side++ ) {
  370. int w = opts.width;
  371. int h = opts.height;
  372. if ( opts.textureType == TT_CUBIC ) {
  373. h = w;
  374. }
  375. for ( int level = 0; level < opts.numLevels; level++ ) {
  376. // clear out any previous error
  377. GL_CheckErrors();
  378. if ( IsCompressed() ) {
  379. int compressedSize = ( ((w+3)/4) * ((h+3)/4) * int64( 16 ) * BitsForFormat( opts.format ) ) / 8;
  380. // Even though the OpenGL specification allows the 'data' pointer to be NULL, for some
  381. // drivers we actually need to upload data to get it to allocate the texture.
  382. // However, on 32-bit systems we may fail to allocate a large block of memory for large
  383. // textures. We handle this case by using HeapAlloc directly and allowing the allocation
  384. // to fail in which case we simply pass down NULL to glCompressedTexImage2D and hope for the best.
  385. // As of 2011-10-6 using NVIDIA hardware and drivers we have to allocate the memory with HeapAlloc
  386. // with the exact size otherwise large image allocation (for instance for physical page textures)
  387. // may fail on Vista 32-bit.
  388. void * data = HeapAlloc( GetProcessHeap(), 0, compressedSize );
  389. qglCompressedTexImage2DARB( uploadTarget+side, level, internalFormat, w, h, 0, compressedSize, data );
  390. if ( data != NULL ) {
  391. HeapFree( GetProcessHeap(), 0, data );
  392. }
  393. } else {
  394. qglTexImage2D( uploadTarget + side, level, internalFormat, w, h, 0, dataFormat, dataType, NULL );
  395. }
  396. GL_CheckErrors();
  397. w = Max( 1, w >> 1 );
  398. h = Max( 1, h >> 1 );
  399. }
  400. }
  401. qglTexParameteri( target, GL_TEXTURE_MAX_LEVEL, opts.numLevels - 1 );
  402. // see if we messed anything up
  403. GL_CheckErrors();
  404. SetTexParameters();
  405. GL_CheckErrors();
  406. }
  407. /*
  408. ========================
  409. idImage::PurgeImage
  410. ========================
  411. */
  412. void idImage::PurgeImage() {
  413. if ( texnum != TEXTURE_NOT_LOADED ) {
  414. qglDeleteTextures( 1, (GLuint *)&texnum ); // this should be the ONLY place it is ever called!
  415. texnum = TEXTURE_NOT_LOADED;
  416. }
  417. // clear all the current binding caches, so the next bind will do a real one
  418. for ( int i = 0 ; i < MAX_MULTITEXTURE_UNITS ; i++ ) {
  419. backEnd.glState.tmu[i].current2DMap = TEXTURE_NOT_LOADED;
  420. backEnd.glState.tmu[i].currentCubeMap = TEXTURE_NOT_LOADED;
  421. }
  422. }
  423. /*
  424. ========================
  425. idImage::Resize
  426. ========================
  427. */
  428. void idImage::Resize( int width, int height ) {
  429. if ( opts.width == width && opts.height == height ) {
  430. return;
  431. }
  432. opts.width = width;
  433. opts.height = height;
  434. AllocImage();
  435. }