Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

260 lines
7.6 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Image Byte Swapping. Isolate routines to own module to allow librarian
  4. // to ignore xbox 360 dependenices in non-applicable win32 projects.
  5. //
  6. //=============================================================================//
  7. #if defined( _WIN32 ) && !defined( _X360 ) && !defined( DX_TO_GL_ABSTRACTION )
  8. #include <windows.h>
  9. #endif
  10. #include "tier0/platform.h"
  11. #include "tier0/dbg.h"
  12. #include "bitmap/imageformat.h"
  13. // Should be last include
  14. #include "tier0/memdbgon.h"
  15. #if defined( _WIN32 ) && !defined( _X360 ) && !defined( NO_X360_XDK ) && !defined( DX_TO_GL_ABSTRACTION )
  16. // the x86 version of the 360 (used by win32 tools)
  17. // It would have been nice to use the 360 D3DFORMAT bit encodings, but the codes
  18. // are different for WIN32, and this routine is used by a WIN32 library to
  19. // manipulate 360 data, so there can be no reliance on WIN32 D3DFORMAT bits
  20. #pragma warning(push)
  21. #pragma warning(disable : 4458) // warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc (disabled due to std headers having exception syntax)
  22. #include "..\x360xdk\include\win32\vs2005\d3d9.h"
  23. #include "..\x360xdk\include\win32\vs2005\XGraphics.h"
  24. #pragma warning(pop)
  25. #endif
  26. namespace ImageLoader
  27. {
  28. //-----------------------------------------------------------------------------
  29. // Known formats that can be converted. Used as a trap for 360 formats
  30. // that may occur but have not been validated yet.
  31. //-----------------------------------------------------------------------------
  32. bool IsFormatValidForConversion( ImageFormat fmt )
  33. {
  34. switch ( fmt )
  35. {
  36. case IMAGE_FORMAT_RGBA8888:
  37. case IMAGE_FORMAT_ABGR8888:
  38. case IMAGE_FORMAT_RGB888:
  39. case IMAGE_FORMAT_BGR888:
  40. case IMAGE_FORMAT_ARGB8888:
  41. case IMAGE_FORMAT_BGRA8888:
  42. case IMAGE_FORMAT_BGRX8888:
  43. case IMAGE_FORMAT_UVWQ8888:
  44. case IMAGE_FORMAT_RGBA16161616F:
  45. case IMAGE_FORMAT_RGBA16161616:
  46. case IMAGE_FORMAT_UVLX8888:
  47. case IMAGE_FORMAT_DXT1:
  48. case IMAGE_FORMAT_DXT1_ONEBITALPHA:
  49. case IMAGE_FORMAT_DXT3:
  50. case IMAGE_FORMAT_DXT5:
  51. case IMAGE_FORMAT_UV88:
  52. return true;
  53. // untested formats
  54. default:
  55. case IMAGE_FORMAT_RGB565:
  56. case IMAGE_FORMAT_I8:
  57. case IMAGE_FORMAT_IA88:
  58. case IMAGE_FORMAT_A8:
  59. case IMAGE_FORMAT_RGB888_BLUESCREEN:
  60. case IMAGE_FORMAT_BGR888_BLUESCREEN:
  61. case IMAGE_FORMAT_BGR565:
  62. case IMAGE_FORMAT_BGRX5551:
  63. case IMAGE_FORMAT_BGRA4444:
  64. case IMAGE_FORMAT_BGRA5551:
  65. case IMAGE_FORMAT_ATI1N:
  66. case IMAGE_FORMAT_ATI2N:
  67. break;
  68. }
  69. return false;
  70. }
  71. //-----------------------------------------------------------------------------
  72. // Swaps the image element type within the format.
  73. // This is to ensure that >8 bit channels are in the correct endian format
  74. // as expected by the conversion process, which varies according to format,
  75. // input, and output.
  76. //-----------------------------------------------------------------------------
  77. void PreConvertSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width, int stride )
  78. {
  79. Assert( IsFormatValidForConversion( imageFormat ) );
  80. #if !defined( DX_TO_GL_ABSTRACTION ) && !defined( NO_X360_XDK )
  81. if ( IsPC() )
  82. {
  83. // running as a win32 tool, data is in expected order
  84. // for conversion code
  85. return;
  86. }
  87. // running on 360 and converting, input data must be x86 order
  88. // swap to ensure conversion code gets valid data
  89. XGENDIANTYPE xEndian;
  90. switch ( imageFormat )
  91. {
  92. default:
  93. return;
  94. case IMAGE_FORMAT_RGBA16161616F:
  95. case IMAGE_FORMAT_RGBA16161616:
  96. xEndian = XGENDIAN_8IN16;
  97. break;
  98. }
  99. int count;
  100. if ( !stride )
  101. {
  102. stride = XGENDIANTYPE_GET_DATA_SIZE( xEndian );
  103. count = nImageSize / stride;
  104. XGEndianSwapMemory( pImageData, pImageData, xEndian, stride, count );
  105. }
  106. else
  107. {
  108. int nRows = nImageSize/stride;
  109. for ( int i=0; i<nRows; i++ )
  110. {
  111. XGEndianSwapMemory( pImageData, pImageData, xEndian, XGENDIANTYPE_GET_DATA_SIZE( xEndian ), width );
  112. pImageData += stride;
  113. }
  114. }
  115. #endif
  116. }
  117. //-----------------------------------------------------------------------------
  118. // Swaps image bytes for use on a big endian platform. This is used after the conversion
  119. // process to match the 360 d3dformats.
  120. //-----------------------------------------------------------------------------
  121. void PostConvertSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width, int stride )
  122. {
  123. Assert( IsFormatValidForConversion( imageFormat ) );
  124. #if !defined( DX_TO_GL_ABSTRACTION ) && !defined( NO_X360_XDK )
  125. // It would have been nice to use the 360 D3DFORMAT bit encodings, but the codes
  126. // are different for win32, and this routine is used by a win32 library to
  127. // manipulate 360 data, so there can be no reliance on D3DFORMAT bits
  128. XGENDIANTYPE xEndian;
  129. switch ( imageFormat )
  130. {
  131. default:
  132. return;
  133. case IMAGE_FORMAT_RGBA16161616:
  134. if ( IsX360() )
  135. {
  136. // running on 360 the conversion output is correct
  137. return;
  138. }
  139. // running on the pc, the output needs to be in 360 order
  140. xEndian = XGENDIAN_8IN16;
  141. break;
  142. case IMAGE_FORMAT_DXT1:
  143. case IMAGE_FORMAT_DXT1_ONEBITALPHA:
  144. case IMAGE_FORMAT_DXT3:
  145. case IMAGE_FORMAT_DXT5:
  146. case IMAGE_FORMAT_UV88:
  147. case IMAGE_FORMAT_ATI1N:
  148. case IMAGE_FORMAT_ATI2N:
  149. xEndian = XGENDIAN_8IN16;
  150. break;
  151. case IMAGE_FORMAT_BGRA8888:
  152. case IMAGE_FORMAT_BGRX8888:
  153. case IMAGE_FORMAT_UVWQ8888:
  154. case IMAGE_FORMAT_UVLX8888:
  155. xEndian = XGENDIAN_8IN32;
  156. break;
  157. }
  158. int count;
  159. if ( !stride )
  160. {
  161. stride = XGENDIANTYPE_GET_DATA_SIZE( xEndian );
  162. count = nImageSize / stride;
  163. XGEndianSwapMemory( pImageData, pImageData, xEndian, stride, count );
  164. }
  165. else
  166. {
  167. int nRows = nImageSize/stride;
  168. for ( int i=0; i<nRows; i++ )
  169. {
  170. XGEndianSwapMemory( pImageData, pImageData, xEndian, XGENDIANTYPE_GET_DATA_SIZE( xEndian ), width );
  171. pImageData += stride;
  172. }
  173. }
  174. #endif
  175. }
  176. //-----------------------------------------------------------------------------
  177. // Swaps image bytes.
  178. //-----------------------------------------------------------------------------
  179. void ByteSwapImageData( unsigned char *pImageData, int nImageSize, ImageFormat imageFormat, int width, int stride )
  180. {
  181. Assert( IsFormatValidForConversion( imageFormat ) );
  182. #if !defined( DX_TO_GL_ABSTRACTION ) && !defined( NO_X360_XDK )
  183. XGENDIANTYPE xEndian;
  184. switch ( imageFormat )
  185. {
  186. case IMAGE_FORMAT_BGR888:
  187. case IMAGE_FORMAT_I8:
  188. case IMAGE_FORMAT_A8:
  189. default:
  190. return;
  191. case IMAGE_FORMAT_BGRA8888:
  192. case IMAGE_FORMAT_BGRX8888:
  193. case IMAGE_FORMAT_UVWQ8888:
  194. case IMAGE_FORMAT_UVLX8888:
  195. case IMAGE_FORMAT_R32F:
  196. case IMAGE_FORMAT_RGBA32323232F:
  197. xEndian = XGENDIAN_8IN32;
  198. break;
  199. case IMAGE_FORMAT_BGR565:
  200. case IMAGE_FORMAT_BGRX5551:
  201. case IMAGE_FORMAT_BGRA5551:
  202. case IMAGE_FORMAT_BGRA4444:
  203. case IMAGE_FORMAT_IA88:
  204. case IMAGE_FORMAT_DXT1:
  205. case IMAGE_FORMAT_DXT1_ONEBITALPHA:
  206. case IMAGE_FORMAT_DXT3:
  207. case IMAGE_FORMAT_DXT5:
  208. case IMAGE_FORMAT_ATI1N:
  209. case IMAGE_FORMAT_ATI2N:
  210. case IMAGE_FORMAT_UV88:
  211. case IMAGE_FORMAT_RGBA16161616F:
  212. case IMAGE_FORMAT_RGBA16161616:
  213. xEndian = XGENDIAN_8IN16;
  214. break;
  215. }
  216. int count;
  217. if ( !stride )
  218. {
  219. stride = XGENDIANTYPE_GET_DATA_SIZE( xEndian );
  220. count = nImageSize / stride;
  221. XGEndianSwapMemory( pImageData, pImageData, xEndian, stride, count );
  222. }
  223. else
  224. {
  225. int nRows = nImageSize/stride;
  226. for ( int i=0; i<nRows; i++ )
  227. {
  228. XGEndianSwapMemory( pImageData, pImageData, xEndian, XGENDIANTYPE_GET_DATA_SIZE( xEndian ), width );
  229. pImageData += stride;
  230. }
  231. }
  232. #endif
  233. }
  234. }