rw_imp.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472
  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_IMP.C
  17. **
  18. ** This file contains ALL Win32 specific stuff having to do with the
  19. ** software refresh. When a port is being made the following functions
  20. ** must be implemented by the port:
  21. **
  22. ** SWimp_EndFrame
  23. ** SWimp_Init
  24. ** SWimp_SetPalette
  25. ** SWimp_Shutdown
  26. */
  27. #include "..\ref_soft\r_local.h"
  28. #include "rw_win.h"
  29. #include "winquake.h"
  30. // Console variables that we need to access from this module
  31. swwstate_t sww_state;
  32. /*
  33. ** VID_CreateWindow
  34. */
  35. #define WINDOW_CLASS_NAME "Quake 2"
  36. void VID_CreateWindow( int width, int height, int stylebits )
  37. {
  38. WNDCLASS wc;
  39. RECT r;
  40. cvar_t *vid_xpos, *vid_ypos, *vid_fullscreen;
  41. int x, y, w, h;
  42. int exstyle;
  43. vid_xpos = ri.Cvar_Get ("vid_xpos", "0", 0);
  44. vid_ypos = ri.Cvar_Get ("vid_ypos", "0", 0);
  45. vid_fullscreen = ri.Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE );
  46. if ( vid_fullscreen->value )
  47. exstyle = WS_EX_TOPMOST;
  48. else
  49. exstyle = 0;
  50. /* Register the frame class */
  51. wc.style = 0;
  52. wc.lpfnWndProc = (WNDPROC)sww_state.wndproc;
  53. wc.cbClsExtra = 0;
  54. wc.cbWndExtra = 0;
  55. wc.hInstance = sww_state.hInstance;
  56. wc.hIcon = 0;
  57. wc.hCursor = LoadCursor (NULL,IDC_ARROW);
  58. wc.hbrBackground = (void *)COLOR_GRAYTEXT;
  59. wc.lpszMenuName = 0;
  60. wc.lpszClassName = WINDOW_CLASS_NAME;
  61. if (!RegisterClass (&wc) )
  62. ri.Sys_Error (ERR_FATAL, "Couldn't register window class");
  63. r.left = 0;
  64. r.top = 0;
  65. r.right = width;
  66. r.bottom = height;
  67. AdjustWindowRect (&r, stylebits, FALSE);
  68. w = r.right - r.left;
  69. h = r.bottom - r.top;
  70. x = vid_xpos->value;
  71. y = vid_ypos->value;
  72. sww_state.hWnd = CreateWindowEx (
  73. exstyle,
  74. WINDOW_CLASS_NAME,
  75. "Quake 2",
  76. stylebits,
  77. x, y, w, h,
  78. NULL,
  79. NULL,
  80. sww_state.hInstance,
  81. NULL);
  82. if (!sww_state.hWnd)
  83. ri.Sys_Error (ERR_FATAL, "Couldn't create window");
  84. ShowWindow( sww_state.hWnd, SW_SHOWNORMAL );
  85. UpdateWindow( sww_state.hWnd );
  86. SetForegroundWindow( sww_state.hWnd );
  87. SetFocus( sww_state.hWnd );
  88. // let the sound and input subsystems know about the new window
  89. ri.Vid_NewWindow (width, height);
  90. }
  91. /*
  92. ** SWimp_Init
  93. **
  94. ** This routine is responsible for initializing the implementation
  95. ** specific stuff in a software rendering subsystem.
  96. */
  97. int SWimp_Init( void *hInstance, void *wndProc )
  98. {
  99. sww_state.hInstance = ( HINSTANCE ) hInstance;
  100. sww_state.wndproc = wndProc;
  101. return true;
  102. }
  103. /*
  104. ** SWimp_InitGraphics
  105. **
  106. ** This initializes the software refresh's implementation specific
  107. ** graphics subsystem. In the case of Windows it creates DIB or
  108. ** DDRAW surfaces.
  109. **
  110. ** The necessary width and height parameters are grabbed from
  111. ** vid.width and vid.height.
  112. */
  113. static qboolean SWimp_InitGraphics( qboolean fullscreen )
  114. {
  115. // free resources in use
  116. SWimp_Shutdown ();
  117. // create a new window
  118. VID_CreateWindow (vid.width, vid.height, WINDOW_STYLE);
  119. // initialize the appropriate subsystem
  120. if ( !fullscreen )
  121. {
  122. if ( !DIB_Init( &vid.buffer, &vid.rowbytes ) )
  123. {
  124. vid.buffer = 0;
  125. vid.rowbytes = 0;
  126. return false;
  127. }
  128. }
  129. else
  130. {
  131. if ( !DDRAW_Init( &vid.buffer, &vid.rowbytes ) )
  132. {
  133. vid.buffer = 0;
  134. vid.rowbytes = 0;
  135. return false;
  136. }
  137. }
  138. return true;
  139. }
  140. /*
  141. ** SWimp_EndFrame
  142. **
  143. ** This does an implementation specific copy from the backbuffer to the
  144. ** front buffer. In the Win32 case it uses BitBlt or BltFast depending
  145. ** on whether we're using DIB sections/GDI or DDRAW.
  146. */
  147. void SWimp_EndFrame (void)
  148. {
  149. if ( !sw_state.fullscreen )
  150. {
  151. if ( sww_state.palettized )
  152. {
  153. // holdpal = SelectPalette(hdcScreen, hpalDIB, FALSE);
  154. // RealizePalette(hdcScreen);
  155. }
  156. BitBlt( sww_state.hDC,
  157. 0, 0,
  158. vid.width,
  159. vid.height,
  160. sww_state.hdcDIBSection,
  161. 0, 0,
  162. SRCCOPY );
  163. if ( sww_state.palettized )
  164. {
  165. // SelectPalette(hdcScreen, holdpal, FALSE);
  166. }
  167. }
  168. else
  169. {
  170. RECT r;
  171. HRESULT rval;
  172. DDSURFACEDESC ddsd;
  173. r.left = 0;
  174. r.top = 0;
  175. r.right = vid.width;
  176. r.bottom = vid.height;
  177. sww_state.lpddsOffScreenBuffer->lpVtbl->Unlock( sww_state.lpddsOffScreenBuffer, vid.buffer );
  178. if ( sww_state.modex )
  179. {
  180. if ( ( rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsBackBuffer,
  181. 0, 0,
  182. sww_state.lpddsOffScreenBuffer,
  183. &r,
  184. DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST )
  185. {
  186. sww_state.lpddsBackBuffer->lpVtbl->Restore( sww_state.lpddsBackBuffer );
  187. sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsBackBuffer,
  188. 0, 0,
  189. sww_state.lpddsOffScreenBuffer,
  190. &r,
  191. DDBLTFAST_WAIT );
  192. }
  193. if ( ( rval = sww_state.lpddsFrontBuffer->lpVtbl->Flip( sww_state.lpddsFrontBuffer,
  194. NULL, DDFLIP_WAIT ) ) == DDERR_SURFACELOST )
  195. {
  196. sww_state.lpddsFrontBuffer->lpVtbl->Restore( sww_state.lpddsFrontBuffer );
  197. sww_state.lpddsFrontBuffer->lpVtbl->Flip( sww_state.lpddsFrontBuffer, NULL, DDFLIP_WAIT );
  198. }
  199. }
  200. else
  201. {
  202. if ( ( rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsFrontBuffer,
  203. 0, 0,
  204. sww_state.lpddsOffScreenBuffer,
  205. &r,
  206. DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST )
  207. {
  208. sww_state.lpddsBackBuffer->lpVtbl->Restore( sww_state.lpddsFrontBuffer );
  209. sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsFrontBuffer,
  210. 0, 0,
  211. sww_state.lpddsOffScreenBuffer,
  212. &r,
  213. DDBLTFAST_WAIT );
  214. }
  215. }
  216. memset( &ddsd, 0, sizeof( ddsd ) );
  217. ddsd.dwSize = sizeof( ddsd );
  218. sww_state.lpddsOffScreenBuffer->lpVtbl->Lock( sww_state.lpddsOffScreenBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL );
  219. vid.buffer = ddsd.lpSurface;
  220. vid.rowbytes = ddsd.lPitch;
  221. }
  222. }
  223. /*
  224. ** SWimp_SetMode
  225. */
  226. rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
  227. {
  228. const char *win_fs[] = { "W", "FS" };
  229. rserr_t retval = rserr_ok;
  230. ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode );
  231. if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) )
  232. {
  233. ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
  234. return rserr_invalid_mode;
  235. }
  236. ri.Con_Printf( PRINT_ALL, " %d %d %s\n", *pwidth, *pheight, win_fs[fullscreen] );
  237. sww_state.initializing = true;
  238. if ( fullscreen )
  239. {
  240. if ( !SWimp_InitGraphics( 1 ) )
  241. {
  242. if ( SWimp_InitGraphics( 0 ) )
  243. {
  244. // mode is legal but not as fullscreen
  245. fullscreen = 0;
  246. retval = rserr_invalid_fullscreen;
  247. }
  248. else
  249. {
  250. // failed to set a valid mode in windowed mode
  251. retval = rserr_unknown;
  252. }
  253. }
  254. }
  255. else
  256. {
  257. // failure to set a valid mode in windowed mode
  258. if ( !SWimp_InitGraphics( fullscreen ) )
  259. {
  260. sww_state.initializing = true;
  261. return rserr_unknown;
  262. }
  263. }
  264. sw_state.fullscreen = fullscreen;
  265. #if 0
  266. if ( retval != rserr_unknown )
  267. {
  268. if ( retval == rserr_invalid_fullscreen ||
  269. ( retval == rserr_ok && !fullscreen ) )
  270. {
  271. SetWindowLong( sww_state.hWnd, GWL_STYLE, WINDOW_STYLE );
  272. }
  273. }
  274. #endif
  275. R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
  276. sww_state.initializing = true;
  277. return retval;
  278. }
  279. /*
  280. ** SWimp_SetPalette
  281. **
  282. ** System specific palette setting routine. A NULL palette means
  283. ** to use the existing palette. The palette is expected to be in
  284. ** a padded 4-byte xRGB format.
  285. */
  286. void SWimp_SetPalette( const unsigned char *palette )
  287. {
  288. // MGL - what the fuck was kendall doing here?!
  289. // clear screen to black and change palette
  290. // for (i=0 ; i<vid.height ; i++)
  291. // memset (vid.buffer + i*vid.rowbytes, 0, vid.width);
  292. if ( !palette )
  293. palette = ( const unsigned char * ) sw_state.currentpalette;
  294. if ( !sw_state.fullscreen )
  295. {
  296. DIB_SetPalette( ( const unsigned char * ) palette );
  297. }
  298. else
  299. {
  300. DDRAW_SetPalette( ( const unsigned char * ) palette );
  301. }
  302. }
  303. /*
  304. ** SWimp_Shutdown
  305. **
  306. ** System specific graphics subsystem shutdown routine. Destroys
  307. ** DIBs or DDRAW surfaces as appropriate.
  308. */
  309. void SWimp_Shutdown( void )
  310. {
  311. ri.Con_Printf( PRINT_ALL, "Shutting down SW imp\n" );
  312. DIB_Shutdown();
  313. DDRAW_Shutdown();
  314. if ( sww_state.hWnd )
  315. {
  316. ri.Con_Printf( PRINT_ALL, "...destroying window\n" );
  317. ShowWindow( sww_state.hWnd, SW_SHOWNORMAL ); // prevents leaving empty slots in the taskbar
  318. DestroyWindow (sww_state.hWnd);
  319. sww_state.hWnd = NULL;
  320. UnregisterClass (WINDOW_CLASS_NAME, sww_state.hInstance);
  321. }
  322. }
  323. /*
  324. ** SWimp_AppActivate
  325. */
  326. void SWimp_AppActivate( qboolean active )
  327. {
  328. if ( active )
  329. {
  330. if ( sww_state.hWnd )
  331. {
  332. SetForegroundWindow( sww_state.hWnd );
  333. ShowWindow( sww_state.hWnd, SW_RESTORE );
  334. }
  335. }
  336. else
  337. {
  338. if ( sww_state.hWnd )
  339. {
  340. if ( sww_state.initializing )
  341. return;
  342. if ( vid_fullscreen->value )
  343. ShowWindow( sww_state.hWnd, SW_MINIMIZE );
  344. }
  345. }
  346. }
  347. //===============================================================================
  348. /*
  349. ================
  350. Sys_MakeCodeWriteable
  351. ================
  352. */
  353. void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
  354. {
  355. DWORD flOldProtect;
  356. if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
  357. ri.Sys_Error(ERR_FATAL, "Protection change failed\n");
  358. }
  359. /*
  360. ** Sys_SetFPCW
  361. **
  362. ** For reference:
  363. **
  364. ** 1
  365. ** 5 0
  366. ** xxxxRRPP.xxxxxxxx
  367. **
  368. ** PP = 00 = 24-bit single precision
  369. ** PP = 01 = reserved
  370. ** PP = 10 = 53-bit double precision
  371. ** PP = 11 = 64-bit extended precision
  372. **
  373. ** RR = 00 = round to nearest
  374. ** RR = 01 = round down (towards -inf, floor)
  375. ** RR = 10 = round up (towards +inf, ceil)
  376. ** RR = 11 = round to zero (truncate/towards 0)
  377. **
  378. */
  379. #if !id386
  380. void Sys_SetFPCW (void)
  381. {
  382. }
  383. #else
  384. unsigned fpu_ceil_cw, fpu_chop_cw, fpu_full_cw, fpu_cw, fpu_pushed_cw;
  385. unsigned fpu_sp24_cw, fpu_sp24_ceil_cw;
  386. void Sys_SetFPCW( void )
  387. {
  388. __asm xor eax, eax
  389. __asm fnstcw word ptr fpu_cw
  390. __asm mov ax, word ptr fpu_cw
  391. __asm and ah, 0f0h
  392. __asm or ah, 003h ; round to nearest mode, extended precision
  393. __asm mov fpu_full_cw, eax
  394. __asm and ah, 0f0h
  395. __asm or ah, 00fh ; RTZ/truncate/chop mode, extended precision
  396. __asm mov fpu_chop_cw, eax
  397. __asm and ah, 0f0h
  398. __asm or ah, 00bh ; ceil mode, extended precision
  399. __asm mov fpu_ceil_cw, eax
  400. __asm and ah, 0f0h ; round to nearest, 24-bit single precision
  401. __asm mov fpu_sp24_cw, eax
  402. __asm and ah, 0f0h ; ceil mode, 24-bit single precision
  403. __asm or ah, 008h ;
  404. __asm mov fpu_sp24_ceil_cw, eax
  405. }
  406. #endif