rw_dib.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3. This program is free software; you can redistribute it and/or
  4. modify it under the terms of the GNU General Public License
  5. as published by the Free Software Foundation; either version 2
  6. of the License, or (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  10. See the GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  14. */
  15. /*
  16. ** RW_DIB.C
  17. **
  18. ** This handles DIB section management under Windows.
  19. **
  20. */
  21. #include "..\ref_soft\r_local.h"
  22. #include "rw_win.h"
  23. #ifndef _WIN32
  24. # error You should not be trying to compile this file on this platform
  25. #endif
  26. static qboolean s_systemcolors_saved;
  27. static HGDIOBJ previously_selected_GDI_obj;
  28. static int s_syspalindices[] =
  29. {
  30. COLOR_ACTIVEBORDER,
  31. COLOR_ACTIVECAPTION,
  32. COLOR_APPWORKSPACE,
  33. COLOR_BACKGROUND,
  34. COLOR_BTNFACE,
  35. COLOR_BTNSHADOW,
  36. COLOR_BTNTEXT,
  37. COLOR_CAPTIONTEXT,
  38. COLOR_GRAYTEXT,
  39. COLOR_HIGHLIGHT,
  40. COLOR_HIGHLIGHTTEXT,
  41. COLOR_INACTIVEBORDER,
  42. COLOR_INACTIVECAPTION,
  43. COLOR_MENU,
  44. COLOR_MENUTEXT,
  45. COLOR_SCROLLBAR,
  46. COLOR_WINDOW,
  47. COLOR_WINDOWFRAME,
  48. COLOR_WINDOWTEXT
  49. };
  50. #define NUM_SYS_COLORS ( sizeof( s_syspalindices ) / sizeof( int ) )
  51. static int s_oldsyscolors[NUM_SYS_COLORS];
  52. typedef struct dibinfo
  53. {
  54. BITMAPINFOHEADER header;
  55. RGBQUAD acolors[256];
  56. } dibinfo_t;
  57. typedef struct
  58. {
  59. WORD palVersion;
  60. WORD palNumEntries;
  61. PALETTEENTRY palEntries[256];
  62. } identitypalette_t;
  63. static identitypalette_t s_ipal;
  64. static void DIB_SaveSystemColors( void );
  65. static void DIB_RestoreSystemColors( void );
  66. /*
  67. ** DIB_Init
  68. **
  69. ** Builds our DIB section
  70. */
  71. qboolean DIB_Init( unsigned char **ppbuffer, int *ppitch )
  72. {
  73. dibinfo_t dibheader;
  74. BITMAPINFO *pbmiDIB = ( BITMAPINFO * ) &dibheader;
  75. int i;
  76. memset( &dibheader, 0, sizeof( dibheader ) );
  77. /*
  78. ** grab a DC
  79. */
  80. if ( !sww_state.hDC )
  81. {
  82. if ( ( sww_state.hDC = GetDC( sww_state.hWnd ) ) == NULL )
  83. return false;
  84. }
  85. /*
  86. ** figure out if we're running in an 8-bit display mode
  87. */
  88. if ( GetDeviceCaps( sww_state.hDC, RASTERCAPS ) & RC_PALETTE )
  89. {
  90. sww_state.palettized = true;
  91. // save system colors
  92. if ( !s_systemcolors_saved )
  93. {
  94. DIB_SaveSystemColors();
  95. s_systemcolors_saved = true;
  96. }
  97. }
  98. else
  99. {
  100. sww_state.palettized = false;
  101. }
  102. /*
  103. ** fill in the BITMAPINFO struct
  104. */
  105. pbmiDIB->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  106. pbmiDIB->bmiHeader.biWidth = vid.width;
  107. pbmiDIB->bmiHeader.biHeight = vid.height;
  108. pbmiDIB->bmiHeader.biPlanes = 1;
  109. pbmiDIB->bmiHeader.biBitCount = 8;
  110. pbmiDIB->bmiHeader.biCompression = BI_RGB;
  111. pbmiDIB->bmiHeader.biSizeImage = 0;
  112. pbmiDIB->bmiHeader.biXPelsPerMeter = 0;
  113. pbmiDIB->bmiHeader.biYPelsPerMeter = 0;
  114. pbmiDIB->bmiHeader.biClrUsed = 256;
  115. pbmiDIB->bmiHeader.biClrImportant = 256;
  116. /*
  117. ** fill in the palette
  118. */
  119. for ( i = 0; i < 256; i++ )
  120. {
  121. dibheader.acolors[i].rgbRed = ( d_8to24table[i] >> 0 ) & 0xff;
  122. dibheader.acolors[i].rgbGreen = ( d_8to24table[i] >> 8 ) & 0xff;
  123. dibheader.acolors[i].rgbBlue = ( d_8to24table[i] >> 16 ) & 0xff;
  124. }
  125. /*
  126. ** create the DIB section
  127. */
  128. sww_state.hDIBSection = CreateDIBSection( sww_state.hDC,
  129. pbmiDIB,
  130. DIB_RGB_COLORS,
  131. &sww_state.pDIBBase,
  132. NULL,
  133. 0 );
  134. if ( sww_state.hDIBSection == NULL )
  135. {
  136. ri.Con_Printf( PRINT_ALL, "DIB_Init() - CreateDIBSection failed\n" );
  137. goto fail;
  138. }
  139. if ( pbmiDIB->bmiHeader.biHeight > 0 )
  140. {
  141. // bottom up
  142. *ppbuffer = sww_state.pDIBBase + ( vid.height - 1 ) * vid.width;
  143. *ppitch = -vid.width;
  144. }
  145. else
  146. {
  147. // top down
  148. *ppbuffer = sww_state.pDIBBase;
  149. *ppitch = vid.width;
  150. }
  151. /*
  152. ** clear the DIB memory buffer
  153. */
  154. memset( sww_state.pDIBBase, 0xff, vid.width * vid.height );
  155. if ( ( sww_state.hdcDIBSection = CreateCompatibleDC( sww_state.hDC ) ) == NULL )
  156. {
  157. ri.Con_Printf( PRINT_ALL, "DIB_Init() - CreateCompatibleDC failed\n" );
  158. goto fail;
  159. }
  160. if ( ( previously_selected_GDI_obj = SelectObject( sww_state.hdcDIBSection, sww_state.hDIBSection ) ) == NULL )
  161. {
  162. ri.Con_Printf( PRINT_ALL, "DIB_Init() - SelectObject failed\n" );
  163. goto fail;
  164. }
  165. return true;
  166. fail:
  167. DIB_Shutdown();
  168. return false;
  169. }
  170. /*
  171. ** DIB_SetPalette
  172. **
  173. ** Sets the color table in our DIB section, and also sets the system palette
  174. ** into an identity mode if we're running in an 8-bit palettized display mode.
  175. **
  176. ** The palette is expected to be 1024 bytes, in the format:
  177. **
  178. ** R = offset 0
  179. ** G = offset 1
  180. ** B = offset 2
  181. ** A = offset 3
  182. */
  183. void DIB_SetPalette( const unsigned char *_pal )
  184. {
  185. const unsigned char *pal = _pal;
  186. LOGPALETTE *pLogPal = ( LOGPALETTE * ) &s_ipal;
  187. RGBQUAD colors[256];
  188. int i;
  189. int ret;
  190. HDC hDC = sww_state.hDC;
  191. /*
  192. ** set the DIB color table
  193. */
  194. if ( sww_state.hdcDIBSection )
  195. {
  196. for ( i = 0; i < 256; i++, pal += 4 )
  197. {
  198. colors[i].rgbRed = pal[0];
  199. colors[i].rgbGreen = pal[1];
  200. colors[i].rgbBlue = pal[2];
  201. colors[i].rgbReserved = 0;
  202. }
  203. colors[0].rgbRed = 0;
  204. colors[0].rgbGreen = 0;
  205. colors[0].rgbBlue = 0;
  206. colors[255].rgbRed = 0xff;
  207. colors[255].rgbGreen = 0xff;
  208. colors[255].rgbBlue = 0xff;
  209. if ( SetDIBColorTable( sww_state.hdcDIBSection, 0, 256, colors ) == 0 )
  210. {
  211. ri.Con_Printf( PRINT_ALL, "DIB_SetPalette() - SetDIBColorTable failed\n" );
  212. }
  213. }
  214. /*
  215. ** for 8-bit color desktop modes we set up the palette for maximum
  216. ** speed by going into an identity palette mode.
  217. */
  218. if ( sww_state.palettized )
  219. {
  220. int i;
  221. HPALETTE hpalOld;
  222. if ( SetSystemPaletteUse( hDC, SYSPAL_NOSTATIC ) == SYSPAL_ERROR )
  223. {
  224. ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - SetSystemPaletteUse() failed\n" );
  225. }
  226. /*
  227. ** destroy our old palette
  228. */
  229. if ( sww_state.hPal )
  230. {
  231. DeleteObject( sww_state.hPal );
  232. sww_state.hPal = 0;
  233. }
  234. /*
  235. ** take up all physical palette entries to flush out anything that's currently
  236. ** in the palette
  237. */
  238. pLogPal->palVersion = 0x300;
  239. pLogPal->palNumEntries = 256;
  240. for ( i = 0, pal = _pal; i < 256; i++, pal += 4 )
  241. {
  242. pLogPal->palPalEntry[i].peRed = pal[0];
  243. pLogPal->palPalEntry[i].peGreen = pal[1];
  244. pLogPal->palPalEntry[i].peBlue = pal[2];
  245. pLogPal->palPalEntry[i].peFlags = PC_RESERVED | PC_NOCOLLAPSE;
  246. }
  247. pLogPal->palPalEntry[0].peRed = 0;
  248. pLogPal->palPalEntry[0].peGreen = 0;
  249. pLogPal->palPalEntry[0].peBlue = 0;
  250. pLogPal->palPalEntry[0].peFlags = 0;
  251. pLogPal->palPalEntry[255].peRed = 0xff;
  252. pLogPal->palPalEntry[255].peGreen = 0xff;
  253. pLogPal->palPalEntry[255].peBlue = 0xff;
  254. pLogPal->palPalEntry[255].peFlags = 0;
  255. if ( ( sww_state.hPal = CreatePalette( pLogPal ) ) == NULL )
  256. {
  257. ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - CreatePalette failed(%x)\n", GetLastError() );
  258. }
  259. if ( ( hpalOld = SelectPalette( hDC, sww_state.hPal, FALSE ) ) == NULL )
  260. {
  261. ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - SelectPalette failed(%x)\n",GetLastError() );
  262. }
  263. if ( sww_state.hpalOld == NULL )
  264. sww_state.hpalOld = hpalOld;
  265. if ( ( ret = RealizePalette( hDC ) ) != pLogPal->palNumEntries )
  266. {
  267. ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - RealizePalette set %d entries\n", ret );
  268. }
  269. }
  270. }
  271. /*
  272. ** DIB_Shutdown
  273. */
  274. void DIB_Shutdown( void )
  275. {
  276. if ( sww_state.palettized && s_systemcolors_saved )
  277. DIB_RestoreSystemColors();
  278. if ( sww_state.hPal )
  279. {
  280. DeleteObject( sww_state.hPal );
  281. sww_state.hPal = 0;
  282. }
  283. if ( sww_state.hpalOld )
  284. {
  285. SelectPalette( sww_state.hDC, sww_state.hpalOld, FALSE );
  286. RealizePalette( sww_state.hDC );
  287. sww_state.hpalOld = NULL;
  288. }
  289. if ( sww_state.hdcDIBSection )
  290. {
  291. SelectObject( sww_state.hdcDIBSection, previously_selected_GDI_obj );
  292. DeleteDC( sww_state.hdcDIBSection );
  293. sww_state.hdcDIBSection = NULL;
  294. }
  295. if ( sww_state.hDIBSection )
  296. {
  297. DeleteObject( sww_state.hDIBSection );
  298. sww_state.hDIBSection = NULL;
  299. sww_state.pDIBBase = NULL;
  300. }
  301. if ( sww_state.hDC )
  302. {
  303. ReleaseDC( sww_state.hWnd, sww_state.hDC );
  304. sww_state.hDC = 0;
  305. }
  306. }
  307. /*
  308. ** DIB_Save/RestoreSystemColors
  309. */
  310. static void DIB_RestoreSystemColors( void )
  311. {
  312. SetSystemPaletteUse( sww_state.hDC, SYSPAL_STATIC );
  313. SetSysColors( NUM_SYS_COLORS, s_syspalindices, s_oldsyscolors );
  314. }
  315. static void DIB_SaveSystemColors( void )
  316. {
  317. int i;
  318. for ( i = 0; i < NUM_SYS_COLORS; i++ )
  319. s_oldsyscolors[i] = GetSysColor( s_syspalindices[i] );
  320. }