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