123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472 |
- /*
- Copyright (C) 1997-2001 Id Software, Inc.
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- See the GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
- /*
- ** RW_IMP.C
- **
- ** This file contains ALL Win32 specific stuff having to do with the
- ** software refresh. When a port is being made the following functions
- ** must be implemented by the port:
- **
- ** SWimp_EndFrame
- ** SWimp_Init
- ** SWimp_SetPalette
- ** SWimp_Shutdown
- */
- #include "..\ref_soft\r_local.h"
- #include "rw_win.h"
- #include "winquake.h"
- // Console variables that we need to access from this module
- swwstate_t sww_state;
- /*
- ** VID_CreateWindow
- */
- #define WINDOW_CLASS_NAME "Quake 2"
- void VID_CreateWindow( int width, int height, int stylebits )
- {
- WNDCLASS wc;
- RECT r;
- cvar_t *vid_xpos, *vid_ypos, *vid_fullscreen;
- int x, y, w, h;
- int exstyle;
- vid_xpos = ri.Cvar_Get ("vid_xpos", "0", 0);
- vid_ypos = ri.Cvar_Get ("vid_ypos", "0", 0);
- vid_fullscreen = ri.Cvar_Get ("vid_fullscreen", "0", CVAR_ARCHIVE );
- if ( vid_fullscreen->value )
- exstyle = WS_EX_TOPMOST;
- else
- exstyle = 0;
- /* Register the frame class */
- wc.style = 0;
- wc.lpfnWndProc = (WNDPROC)sww_state.wndproc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = sww_state.hInstance;
- wc.hIcon = 0;
- wc.hCursor = LoadCursor (NULL,IDC_ARROW);
- wc.hbrBackground = (void *)COLOR_GRAYTEXT;
- wc.lpszMenuName = 0;
- wc.lpszClassName = WINDOW_CLASS_NAME;
- if (!RegisterClass (&wc) )
- ri.Sys_Error (ERR_FATAL, "Couldn't register window class");
- r.left = 0;
- r.top = 0;
- r.right = width;
- r.bottom = height;
- AdjustWindowRect (&r, stylebits, FALSE);
- w = r.right - r.left;
- h = r.bottom - r.top;
- x = vid_xpos->value;
- y = vid_ypos->value;
- sww_state.hWnd = CreateWindowEx (
- exstyle,
- WINDOW_CLASS_NAME,
- "Quake 2",
- stylebits,
- x, y, w, h,
- NULL,
- NULL,
- sww_state.hInstance,
- NULL);
- if (!sww_state.hWnd)
- ri.Sys_Error (ERR_FATAL, "Couldn't create window");
-
- ShowWindow( sww_state.hWnd, SW_SHOWNORMAL );
- UpdateWindow( sww_state.hWnd );
- SetForegroundWindow( sww_state.hWnd );
- SetFocus( sww_state.hWnd );
- // let the sound and input subsystems know about the new window
- ri.Vid_NewWindow (width, height);
- }
- /*
- ** SWimp_Init
- **
- ** This routine is responsible for initializing the implementation
- ** specific stuff in a software rendering subsystem.
- */
- int SWimp_Init( void *hInstance, void *wndProc )
- {
- sww_state.hInstance = ( HINSTANCE ) hInstance;
- sww_state.wndproc = wndProc;
- return true;
- }
- /*
- ** SWimp_InitGraphics
- **
- ** This initializes the software refresh's implementation specific
- ** graphics subsystem. In the case of Windows it creates DIB or
- ** DDRAW surfaces.
- **
- ** The necessary width and height parameters are grabbed from
- ** vid.width and vid.height.
- */
- static qboolean SWimp_InitGraphics( qboolean fullscreen )
- {
- // free resources in use
- SWimp_Shutdown ();
- // create a new window
- VID_CreateWindow (vid.width, vid.height, WINDOW_STYLE);
- // initialize the appropriate subsystem
- if ( !fullscreen )
- {
- if ( !DIB_Init( &vid.buffer, &vid.rowbytes ) )
- {
- vid.buffer = 0;
- vid.rowbytes = 0;
- return false;
- }
- }
- else
- {
- if ( !DDRAW_Init( &vid.buffer, &vid.rowbytes ) )
- {
- vid.buffer = 0;
- vid.rowbytes = 0;
- return false;
- }
- }
- return true;
- }
- /*
- ** SWimp_EndFrame
- **
- ** This does an implementation specific copy from the backbuffer to the
- ** front buffer. In the Win32 case it uses BitBlt or BltFast depending
- ** on whether we're using DIB sections/GDI or DDRAW.
- */
- void SWimp_EndFrame (void)
- {
- if ( !sw_state.fullscreen )
- {
- if ( sww_state.palettized )
- {
- // holdpal = SelectPalette(hdcScreen, hpalDIB, FALSE);
- // RealizePalette(hdcScreen);
- }
-
- BitBlt( sww_state.hDC,
- 0, 0,
- vid.width,
- vid.height,
- sww_state.hdcDIBSection,
- 0, 0,
- SRCCOPY );
- if ( sww_state.palettized )
- {
- // SelectPalette(hdcScreen, holdpal, FALSE);
- }
- }
- else
- {
- RECT r;
- HRESULT rval;
- DDSURFACEDESC ddsd;
- r.left = 0;
- r.top = 0;
- r.right = vid.width;
- r.bottom = vid.height;
- sww_state.lpddsOffScreenBuffer->lpVtbl->Unlock( sww_state.lpddsOffScreenBuffer, vid.buffer );
- if ( sww_state.modex )
- {
- if ( ( rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsBackBuffer,
- 0, 0,
- sww_state.lpddsOffScreenBuffer,
- &r,
- DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST )
- {
- sww_state.lpddsBackBuffer->lpVtbl->Restore( sww_state.lpddsBackBuffer );
- sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsBackBuffer,
- 0, 0,
- sww_state.lpddsOffScreenBuffer,
- &r,
- DDBLTFAST_WAIT );
- }
- if ( ( rval = sww_state.lpddsFrontBuffer->lpVtbl->Flip( sww_state.lpddsFrontBuffer,
- NULL, DDFLIP_WAIT ) ) == DDERR_SURFACELOST )
- {
- sww_state.lpddsFrontBuffer->lpVtbl->Restore( sww_state.lpddsFrontBuffer );
- sww_state.lpddsFrontBuffer->lpVtbl->Flip( sww_state.lpddsFrontBuffer, NULL, DDFLIP_WAIT );
- }
- }
- else
- {
- if ( ( rval = sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsFrontBuffer,
- 0, 0,
- sww_state.lpddsOffScreenBuffer,
- &r,
- DDBLTFAST_WAIT ) ) == DDERR_SURFACELOST )
- {
- sww_state.lpddsBackBuffer->lpVtbl->Restore( sww_state.lpddsFrontBuffer );
- sww_state.lpddsBackBuffer->lpVtbl->BltFast( sww_state.lpddsFrontBuffer,
- 0, 0,
- sww_state.lpddsOffScreenBuffer,
- &r,
- DDBLTFAST_WAIT );
- }
- }
- memset( &ddsd, 0, sizeof( ddsd ) );
- ddsd.dwSize = sizeof( ddsd );
-
- sww_state.lpddsOffScreenBuffer->lpVtbl->Lock( sww_state.lpddsOffScreenBuffer, NULL, &ddsd, DDLOCK_WAIT, NULL );
- vid.buffer = ddsd.lpSurface;
- vid.rowbytes = ddsd.lPitch;
- }
- }
- /*
- ** SWimp_SetMode
- */
- rserr_t SWimp_SetMode( int *pwidth, int *pheight, int mode, qboolean fullscreen )
- {
- const char *win_fs[] = { "W", "FS" };
- rserr_t retval = rserr_ok;
- ri.Con_Printf (PRINT_ALL, "setting mode %d:", mode );
- if ( !ri.Vid_GetModeInfo( pwidth, pheight, mode ) )
- {
- ri.Con_Printf( PRINT_ALL, " invalid mode\n" );
- return rserr_invalid_mode;
- }
- ri.Con_Printf( PRINT_ALL, " %d %d %s\n", *pwidth, *pheight, win_fs[fullscreen] );
- sww_state.initializing = true;
- if ( fullscreen )
- {
- if ( !SWimp_InitGraphics( 1 ) )
- {
- if ( SWimp_InitGraphics( 0 ) )
- {
- // mode is legal but not as fullscreen
- fullscreen = 0;
- retval = rserr_invalid_fullscreen;
- }
- else
- {
- // failed to set a valid mode in windowed mode
- retval = rserr_unknown;
- }
- }
- }
- else
- {
- // failure to set a valid mode in windowed mode
- if ( !SWimp_InitGraphics( fullscreen ) )
- {
- sww_state.initializing = true;
- return rserr_unknown;
- }
- }
- sw_state.fullscreen = fullscreen;
- #if 0
- if ( retval != rserr_unknown )
- {
- if ( retval == rserr_invalid_fullscreen ||
- ( retval == rserr_ok && !fullscreen ) )
- {
- SetWindowLong( sww_state.hWnd, GWL_STYLE, WINDOW_STYLE );
- }
- }
- #endif
- R_GammaCorrectAndSetPalette( ( const unsigned char * ) d_8to24table );
- sww_state.initializing = true;
- return retval;
- }
- /*
- ** SWimp_SetPalette
- **
- ** System specific palette setting routine. A NULL palette means
- ** to use the existing palette. The palette is expected to be in
- ** a padded 4-byte xRGB format.
- */
- void SWimp_SetPalette( const unsigned char *palette )
- {
- // MGL - what the fuck was kendall doing here?!
- // clear screen to black and change palette
- // for (i=0 ; i<vid.height ; i++)
- // memset (vid.buffer + i*vid.rowbytes, 0, vid.width);
- if ( !palette )
- palette = ( const unsigned char * ) sw_state.currentpalette;
- if ( !sw_state.fullscreen )
- {
- DIB_SetPalette( ( const unsigned char * ) palette );
- }
- else
- {
- DDRAW_SetPalette( ( const unsigned char * ) palette );
- }
- }
- /*
- ** SWimp_Shutdown
- **
- ** System specific graphics subsystem shutdown routine. Destroys
- ** DIBs or DDRAW surfaces as appropriate.
- */
- void SWimp_Shutdown( void )
- {
- ri.Con_Printf( PRINT_ALL, "Shutting down SW imp\n" );
- DIB_Shutdown();
- DDRAW_Shutdown();
- if ( sww_state.hWnd )
- {
- ri.Con_Printf( PRINT_ALL, "...destroying window\n" );
- ShowWindow( sww_state.hWnd, SW_SHOWNORMAL ); // prevents leaving empty slots in the taskbar
- DestroyWindow (sww_state.hWnd);
- sww_state.hWnd = NULL;
- UnregisterClass (WINDOW_CLASS_NAME, sww_state.hInstance);
- }
- }
- /*
- ** SWimp_AppActivate
- */
- void SWimp_AppActivate( qboolean active )
- {
- if ( active )
- {
- if ( sww_state.hWnd )
- {
- SetForegroundWindow( sww_state.hWnd );
- ShowWindow( sww_state.hWnd, SW_RESTORE );
- }
- }
- else
- {
- if ( sww_state.hWnd )
- {
- if ( sww_state.initializing )
- return;
- if ( vid_fullscreen->value )
- ShowWindow( sww_state.hWnd, SW_MINIMIZE );
- }
- }
- }
- //===============================================================================
- /*
- ================
- Sys_MakeCodeWriteable
- ================
- */
- void Sys_MakeCodeWriteable (unsigned long startaddr, unsigned long length)
- {
- DWORD flOldProtect;
- if (!VirtualProtect((LPVOID)startaddr, length, PAGE_READWRITE, &flOldProtect))
- ri.Sys_Error(ERR_FATAL, "Protection change failed\n");
- }
- /*
- ** Sys_SetFPCW
- **
- ** For reference:
- **
- ** 1
- ** 5 0
- ** xxxxRRPP.xxxxxxxx
- **
- ** PP = 00 = 24-bit single precision
- ** PP = 01 = reserved
- ** PP = 10 = 53-bit double precision
- ** PP = 11 = 64-bit extended precision
- **
- ** RR = 00 = round to nearest
- ** RR = 01 = round down (towards -inf, floor)
- ** RR = 10 = round up (towards +inf, ceil)
- ** RR = 11 = round to zero (truncate/towards 0)
- **
- */
- #if !id386
- void Sys_SetFPCW (void)
- {
- }
- #else
- unsigned fpu_ceil_cw, fpu_chop_cw, fpu_full_cw, fpu_cw, fpu_pushed_cw;
- unsigned fpu_sp24_cw, fpu_sp24_ceil_cw;
- void Sys_SetFPCW( void )
- {
- __asm xor eax, eax
- __asm fnstcw word ptr fpu_cw
- __asm mov ax, word ptr fpu_cw
- __asm and ah, 0f0h
- __asm or ah, 003h ; round to nearest mode, extended precision
- __asm mov fpu_full_cw, eax
- __asm and ah, 0f0h
- __asm or ah, 00fh ; RTZ/truncate/chop mode, extended precision
- __asm mov fpu_chop_cw, eax
- __asm and ah, 0f0h
- __asm or ah, 00bh ; ceil mode, extended precision
- __asm mov fpu_ceil_cw, eax
- __asm and ah, 0f0h ; round to nearest, 24-bit single precision
- __asm mov fpu_sp24_cw, eax
- __asm and ah, 0f0h ; ceil mode, 24-bit single precision
- __asm or ah, 008h ;
- __asm mov fpu_sp24_ceil_cw, eax
- }
- #endif
|