icculus quake2 doxygen  1.0 dev
rw_imp.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13 See the GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 */
20 /*
21 ** RW_IMP.C
22 **
23 ** This file contains ALL Win32 specific stuff having to do with the
24 ** software refresh. When a port is being made the following functions
25 ** must be implemented by the port:
26 **
27 ** SWimp_EndFrame
28 ** SWimp_Init
29 ** SWimp_SetPalette
30 ** SWimp_Shutdown
31 */
32 #include "..\ref_soft\r_local.h"
33 #include "rw_win.h"
34 #include "winquake.h"
35 
36 // Console variables that we need to access from this module
37 
39 
40 /*
41 ** VID_CreateWindow
42 */
43 #define WINDOW_CLASS_NAME "Quake 2"
44 
45 void VID_CreateWindow( int width, int height, int stylebits )
46 {
47  WNDCLASS wc;
48  RECT r;
50  int x, y, w, h;
51  int exstyle;
52 
53  vid_xpos = ri.Cvar_Get ("vid_xpos", "0", 0);
54  vid_ypos = ri.Cvar_Get ("vid_ypos", "0", 0);
55  vid_fullscreen = ri.Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE );
56 
57  if ( vid_fullscreen->value )
58  exstyle = WS_EX_TOPMOST;
59  else
60  exstyle = 0;
61 
62  /* Register the frame class */
63  wc.style = 0;
64  wc.lpfnWndProc = (WNDPROC)sww_state.wndproc;
65  wc.cbClsExtra = 0;
66  wc.cbWndExtra = 0;
67  wc.hInstance = sww_state.hInstance;
68  wc.hIcon = 0;
69  wc.hCursor = LoadCursor (NULL,IDC_ARROW);
70  wc.hbrBackground = (void *)COLOR_GRAYTEXT;
71  wc.lpszMenuName = 0;
72  wc.lpszClassName = WINDOW_CLASS_NAME;
73 
74  if (!RegisterClass (&wc) )
75  ri.Sys_Error (ERR_FATAL, "Couldn't register window class");
76 
77  r.left = 0;
78  r.top = 0;
79  r.right = width;
80  r.bottom = height;
81 
82  AdjustWindowRect (&r, stylebits, FALSE);
83 
84  w = r.right - r.left;
85  h = r.bottom - r.top;
86  x = vid_xpos->value;
87  y = vid_ypos->value;
88 
89  sww_state.hWnd = CreateWindowEx (
90  exstyle,
92  "Quake 2",
93  stylebits,
94  x, y, w, h,
95  NULL,
96  NULL,
98  NULL);
99 
100  if (!sww_state.hWnd)
101  ri.Sys_Error (ERR_FATAL, "Couldn't create window");
102 
103  ShowWindow( sww_state.hWnd, SW_SHOWNORMAL );
104  UpdateWindow( sww_state.hWnd );
105  SetForegroundWindow( sww_state.hWnd );
106  SetFocus( sww_state.hWnd );
107 
108  // let the sound and input subsystems know about the new window
110 }
111 
112 /*
113 ** SWimp_Init
114 **
115 ** This routine is responsible for initializing the implementation
116 ** specific stuff in a software rendering subsystem.
117 */
118 int SWimp_Init( void *hInstance, void *wndProc )
119 {
120  sww_state.hInstance = ( HINSTANCE ) hInstance;
121  sww_state.wndproc = wndProc;
122 
123  return true;
124 }
125 
126 /*
127 ** SWimp_InitGraphics
128 **
129 ** This initializes the software refresh's implementation specific
130 ** graphics subsystem. In the case of Windows it creates DIB or
131 ** DDRAW surfaces.
132 **
133 ** The necessary width and height parameters are grabbed from
134 ** vid.width and vid.height.
135 */
137 {
138  // free resources in use
139  SWimp_Shutdown ();
140 
141  // create a new window
143 
144  // initialize the appropriate subsystem
145  if ( !fullscreen )
146  {
147  if ( !DIB_Init( &vid.buffer, &vid.rowbytes ) )
148  {
149  vid.buffer = 0;
150  vid.rowbytes = 0;
151 
152  return false;
153  }
154  }
155  else
156  {
157  if ( !DDRAW_Init( &vid.buffer, &vid.rowbytes ) )
158  {
159  vid.buffer = 0;
160  vid.rowbytes = 0;
161 
162  return false;
163  }
164  }
165 
166  return true;
167 }
168 
169 /*
170 ** SWimp_EndFrame
171 **
172 ** This does an implementation specific copy from the backbuffer to the
173 ** front buffer. In the Win32 case it uses BitBlt or BltFast depending
174 ** on whether we're using DIB sections/GDI or DDRAW.
175 */
176 void SWimp_EndFrame (void)
177 {
178  if ( !sw_state.fullscreen )
179  {
180  if ( sww_state.palettized )
181  {
182 // holdpal = SelectPalette(hdcScreen, hpalDIB, FALSE);
183 // RealizePalette(hdcScreen);
184  }
185 
186 
187  BitBlt( sww_state.hDC,
188  0, 0,
189  vid.width,
190  vid.height,
192  0, 0,
193  SRCCOPY );
194 
195  if ( sww_state.palettized )
196  {
197 // SelectPalette(hdcScreen, holdpal, FALSE);
198  }
199  }
200  else
201  {
202  RECT r;
203  HRESULT rval;
204  DDSURFACEDESC ddsd;
205 
206  r.left = 0;
207  r.top = 0;
208  r.right = vid.width;
209  r.bottom = vid.height;
210 
212 
213  if ( sww_state.modex )
214  {
215  if ( ( rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsBackBuffer,
216  0, 0,
218  &r,
219  DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST )
220  {
223  0, 0,
225  &r,
226  DDBLTFAST_WAIT );
227  }
228 
229  if ( ( rval = sww_state.lpddsFrontBuffer->lpVtbl->Flip( sww_state.lpddsFrontBuffer,
230  NULL, DDFLIP_WAIT ) ) == DDERR_SURFACELOST )
231  {
233  sww_state.lpddsFrontBuffer->lpVtbl->Flip( sww_state.lpddsFrontBuffer, NULL, DDFLIP_WAIT );
234  }
235  }
236  else
237  {
238  if ( ( rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsFrontBuffer,
239  0, 0,
241  &r,
242  DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST )
243  {
246  0, 0,
248  &r,
249  DDBLTFAST_WAIT );
250  }
251  }
252 
253  memset( &ddsd, 0, sizeof( ddsd ) );
254  ddsd.dwSize = sizeof( ddsd );
255 
256  sww_state.lpddsOffScreenBuffer->lpVtbl->Lock( sww_state.lpddsOffScreenBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL );
257 
258  vid.buffer = ddsd.lpSurface;
259  vid.rowbytes = ddsd.lPitch;
260  }
261 }
262 
263 /*
264 ** SWimp_SetMode
265 */
266 rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
267 {
268  const char *win_fs[] = { "W", "FS" };
269  rserr_t retval = rserr_ok;
270 
271  ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode );
272 
273  if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) )
274  {
275  ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
276  return rserr_invalid_mode;
277  }
278 
279  ri.Con_Printf( PRINT_ALL, " %d %d %s\n", *pwidth, *pheight, win_fs[fullscreen] );
280 
281  sww_state.initializing = true;
282  if ( fullscreen )
283  {
284  if ( !SWimp_InitGraphics( 1 ) )
285  {
286  if ( SWimp_InitGraphics( 0 ) )
287  {
288  // mode is legal but not as fullscreen
289  fullscreen = 0;
290  retval = rserr_invalid_fullscreen;
291  }
292  else
293  {
294  // failed to set a valid mode in windowed mode
295  retval = rserr_unknown;
296  }
297  }
298  }
299  else
300  {
301  // failure to set a valid mode in windowed mode
302  if ( !SWimp_InitGraphics( fullscreen ) )
303  {
304  sww_state.initializing = true;
305  return rserr_unknown;
306  }
307  }
308 
309  sw_state.fullscreen = fullscreen;
310 #if 0
311  if ( retval != rserr_unknown )
312  {
313  if ( retval == rserr_invalid_fullscreen ||
314  ( retval == rserr_ok && !fullscreen ) )
315  {
316  SetWindowLong( sww_state.hWnd, GWL_STYLE, WINDOW_STYLE );
317  }
318  }
319 #endif
320  R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
321  sww_state.initializing = true;
322 
323  return retval;
324 }
325 
326 /*
327 ** SWimp_SetPalette
328 **
329 ** System specific palette setting routine. A NULL palette means
330 ** to use the existing palette. The palette is expected to be in
331 ** a padded 4-byte xRGB format.
332 */
333 void SWimp_SetPalette( const unsigned char *palette )
334 {
335  // MGL - what the fuck was kendall doing here?!
336  // clear screen to black and change palette
337  // for (i=0 ; i<vid.height ; i++)
338  // memset (vid.buffer + i*vid.rowbytes, 0, vid.width);
339 
340  if ( !palette )
341  palette = ( const unsigned char * ) sw_state.currentpalette;
342 
343  if ( !sw_state.fullscreen )
344  {
345  DIB_SetPalette( ( const unsigned char * ) palette );
346  }
347  else
348  {
349  DDRAW_SetPalette( ( const unsigned char * ) palette );
350  }
351 }
352 
353 /*
354 ** SWimp_Shutdown
355 **
356 ** System specific graphics subsystem shutdown routine. Destroys
357 ** DIBs or DDRAW surfaces as appropriate.
358 */
359 void SWimp_Shutdown( void )
360 {
361  ri.Con_Printf( PRINT_ALL, "Shutting down SW imp\n" );
362  DIB_Shutdown();
363  DDRAW_Shutdown();
364 
365  if ( sww_state.hWnd )
366  {
367  ri.Con_Printf( PRINT_ALL, "...destroying window\n" );
368  ShowWindow( sww_state.hWnd, SW_SHOWNORMAL ); // prevents leaving empty slots in the taskbar
369  DestroyWindow (sww_state.hWnd);
370  sww_state.hWnd = NULL;
371  UnregisterClass (WINDOW_CLASS_NAME, sww_state.hInstance);
372  }
373 }
374 
375 /*
376 ** SWimp_AppActivate
377 */
379 {
380  if ( active )
381  {
382  if ( sww_state.hWnd )
383  {
384  SetForegroundWindow( sww_state.hWnd );
385  ShowWindow( sww_state.hWnd, SW_RESTORE );
386  }
387  }
388  else
389  {
390  if ( sww_state.hWnd )
391  {
392  if ( sww_state.initializing )
393  return;
394  if ( vid_fullscreen->value )
395  ShowWindow( sww_state.hWnd, SW_MINIMIZE );
396  }
397  }
398 }
399 
400 //===============================================================================
401 
402 
403 /*
404 ================
405 Sys_MakeCodeWriteable
406 ================
407 */
408 void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
409 {
410  DWORD flOldProtect;
411 
412  if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
413  ri.Sys_Error(ERR_FATAL, "Protection change failed\n");
414 }
415 
416 /*
417 ** Sys_SetFPCW
418 **
419 ** For reference:
420 **
421 ** 1
422 ** 5 0
423 ** xxxxRRPP.xxxxxxxx
424 **
425 ** PP = 00 = 24-bit single precision
426 ** PP = 01 = reserved
427 ** PP = 10 = 53-bit double precision
428 ** PP = 11 = 64-bit extended precision
429 **
430 ** RR = 00 = round to nearest
431 ** RR = 01 = round down (towards -inf, floor)
432 ** RR = 10 = round up (towards +inf, ceil)
433 ** RR = 11 = round to zero (truncate/towards 0)
434 **
435 */
436 #if !id386
437 void Sys_SetFPCW (void)
438 {
439 }
440 #else
441 unsigned fpu_ceil_cw, fpu_chop_cw, fpu_full_cw, fpu_cw, fpu_pushed_cw;
442 unsigned fpu_sp24_cw, fpu_sp24_ceil_cw;
443 
444 void Sys_SetFPCW( void )
445 {
446  __asm xor eax, eax
447 
448  __asm fnstcw word ptr fpu_cw
449  __asm mov ax, word ptr fpu_cw
450 
451  __asm and ah, 0f0h
452  __asm or ah, 003h ; round to nearest mode, extended precision
453  __asm mov fpu_full_cw, eax
454 
455  __asm and ah, 0f0h
456  __asm or ah, 00fh ; RTZ/truncate/chop mode, extended precision
457  __asm mov fpu_chop_cw, eax
458 
459  __asm and ah, 0f0h
460  __asm or ah, 00bh ; ceil mode, extended precision
461  __asm mov fpu_ceil_cw, eax
462 
463  __asm and ah, 0f0h ; round to nearest, 24-bit single precision
464  __asm mov fpu_sp24_cw, eax
465 
466  __asm and ah, 0f0h ; ceil mode, 24-bit single precision
467  __asm or ah, 008h ;
468  __asm mov fpu_sp24_ceil_cw, eax
469 }
470 #endif
471 
swwstate_t
Definition: rw_win.h:26
vid_fullscreen
cvar_t * vid_fullscreen
Definition: vid_dll.c:46
rserr_t
rserr_t
Definition: r_local.h:97
height
GLsizei height
Definition: qgl_win.c:69
DIB_Init
qboolean DIB_Init(unsigned char **ppbuffer, int *ppitch)
Definition: rw_dib.c:88
DIB_SetPalette
void DIB_SetPalette(const unsigned char *_pal)
Definition: rw_dib.c:215
WINDOW_CLASS_NAME
#define WINDOW_CLASS_NAME
Definition: rw_imp.c:43
rw_win.h
Sys_SetFPCW
void Sys_SetFPCW(void)
Definition: rw_imp.c:437
swwstate_t::initializing
qboolean initializing
Definition: rw_win.h:52
Sys_MakeCodeWriteable
void Sys_MakeCodeWriteable(unsigned long startaddr, unsigned long length)
Definition: rw_imp.c:408
viddef_t::buffer
pixel_t * buffer
Definition: r_local.h:88
R_GammaCorrectAndSetPalette
void R_GammaCorrectAndSetPalette(const unsigned char *pal)
Definition: r_main.c:1160
ri
refimport_t ri
Definition: r_main.c:25
DDRAW_Shutdown
void DDRAW_Shutdown(void)
Definition: rw_ddraw.c:317
refimport_t::Vid_NewWindow
void(* Vid_NewWindow)(int width, int height)
Definition: ref.h:248
swwstate_t::lpddsFrontBuffer
LPDIRECTDRAWSURFACE lpddsFrontBuffer
Definition: rw_win.h:44
refimport_t::Cvar_Get
cvar_t *(* Cvar_Get)(char *name, char *value, int flags)
Definition: ref.h:242
qboolean
qboolean
Definition: q_shared.h:56
x
GLint GLenum GLint x
Definition: qgl_win.c:116
viddef_t::width
int width
Definition: vid.h:29
SWimp_AppActivate
void SWimp_AppActivate(qboolean active)
Definition: rw_imp.c:378
winquake.h
viddef_t::height
int height
Definition: vid.h:29
swwstate_t::lpddsOffScreenBuffer
LPDIRECTDRAWSURFACE lpddsOffScreenBuffer
Definition: rw_win.h:46
SWimp_Shutdown
void SWimp_Shutdown(void)
Definition: rw_imp.c:359
width
GLint GLsizei width
Definition: qgl_win.c:115
cvar_s
Definition: q_shared.h:317
SWimp_SetPalette
void SWimp_SetPalette(const unsigned char *palette)
Definition: rw_imp.c:333
rserr_unknown
@ rserr_unknown
Definition: r_local.h:104
refimport_t::Vid_GetModeInfo
qboolean(* Vid_GetModeInfo)(int *width, int *height, int mode)
Definition: ref.h:246
refimport_t::Con_Printf
void(* Con_Printf)(int print_level, char *str,...)
Definition: ref.h:228
PRINT_ALL
#define PRINT_ALL
Definition: qcommon.h:743
SWimp_InitGraphics
static qboolean SWimp_InitGraphics(qboolean fullscreen)
Definition: rw_imp.c:136
swwstate_t::palettized
qboolean palettized
Definition: rw_win.h:49
SWimp_EndFrame
void SWimp_EndFrame(void)
Definition: rw_imp.c:176
viddef_t::rowbytes
int rowbytes
Definition: r_local.h:91
r
GLdouble GLdouble r
Definition: qgl_win.c:336
rserr_invalid_mode
@ rserr_invalid_mode
Definition: r_local.h:102
swwstate_t::hInstance
HINSTANCE hInstance
Definition: rw_win.h:28
refimport_t::Sys_Error
void(* Sys_Error)(int err_level, char *str,...)
Definition: ref.h:220
DDRAW_SetPalette
void DDRAW_SetPalette(const unsigned char *pal)
Definition: rw_ddraw.c:288
CVAR_ARCHIVE
#define CVAR_ARCHIVE
Definition: q_shared.h:309
cvar_s::value
float value
Definition: q_shared.h:324
swwstate_t::modex
qboolean modex
Definition: rw_win.h:50
NULL
#define NULL
Definition: q_shared.h:60
DIB_Shutdown
void DIB_Shutdown(void)
Definition: rw_dib.c:320
SWimp_SetMode
rserr_t SWimp_SetMode(int *pwidth, int *pheight, int mode, qboolean fullscreen)
Definition: rw_imp.c:266
ERR_FATAL
#define ERR_FATAL
Definition: qcommon.h:735
VID_CreateWindow
void VID_CreateWindow(int width, int height, int stylebits)
Definition: rw_imp.c:45
y
GLint y
Definition: qgl_win.c:115
WINDOW_STYLE
#define WINDOW_STYLE
Definition: winquake.h:28
d_8to24table
unsigned d_8to24table[256]
Definition: r_main.c:27
rserr_ok
@ rserr_ok
Definition: r_local.h:99
SWimp_Init
int SWimp_Init(void *hInstance, void *wndProc)
Definition: rw_imp.c:118
swstate_s::fullscreen
qboolean fullscreen
Definition: r_local.h:819
swwstate_t::wndproc
void * wndproc
Definition: rw_win.h:29
vid_xpos
cvar_t * vid_xpos
Definition: vid_dll.c:44
swwstate_t::hdcDIBSection
HDC hdcDIBSection
Definition: rw_win.h:33
DWORD
DWORD
Definition: qgl_win.c:49
w
GLdouble GLdouble GLdouble w
Definition: qgl_win.c:291
mode
GLenum mode
Definition: qgl_win.c:113
DDRAW_Init
qboolean DDRAW_Init(unsigned char **ppbuffer, int *ppitch)
Definition: rw_ddraw.c:42
sww_state
swwstate_t sww_state
Definition: rw_imp.c:38
swwstate_t::hWnd
HWND hWnd
Definition: rw_win.h:31
swwstate_t::hDC
HDC hDC
Definition: rw_win.h:30
vid_ypos
cvar_t * vid_ypos
Definition: vid_dll.c:45
swstate_s::currentpalette
byte currentpalette[1024]
Definition: r_local.h:823
sw_state
swstate_t sw_state
Definition: r_main.c:43
ax
LEnter16_16 al cl movb ah addl edx movb ch esi ax edx movw ax
Definition: block16.h:11
rserr_invalid_fullscreen
@ rserr_invalid_fullscreen
Definition: r_local.h:101
HRESULT
HRESULT(WINAPI *pDirectSoundCreate)(GUID FAR *lpGUID
swwstate_t::lpddsBackBuffer
LPDIRECTDRAWSURFACE lpddsBackBuffer
Definition: rw_win.h:45
vid
viddef_t vid
Definition: r_main.c:24