diff options
Diffstat (limited to 'source/win_swimp.c')
-rw-r--r-- | source/win_swimp.c | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/source/win_swimp.c b/source/win_swimp.c new file mode 100644 index 0000000..383e8c6 --- /dev/null +++ b/source/win_swimp.c @@ -0,0 +1,348 @@ +/* +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 "win_local.h" + +#ifndef PC_NOCOLLAPSE +#define PC_NOCOLLAPSE 0 +#endif + +typedef struct { + BITMAPINFOHEADER header; + RGBQUAD colors[256]; +} dibinfo_t; + +typedef struct { + WORD palVersion; + WORD palNumEntries; + PALETTEENTRY palEntries[256]; +} identitypalette_t; + +static const int s_syspalindices[] = { + COLOR_ACTIVEBORDER, + COLOR_ACTIVECAPTION, + COLOR_APPWORKSPACE, + COLOR_BACKGROUND, + COLOR_BTNFACE, + COLOR_BTNSHADOW, + COLOR_BTNTEXT, + COLOR_CAPTIONTEXT, + COLOR_GRAYTEXT, + COLOR_HIGHLIGHT, + COLOR_HIGHLIGHTTEXT, + COLOR_INACTIVEBORDER, + + COLOR_INACTIVECAPTION, + COLOR_MENU, + COLOR_MENUTEXT, + COLOR_SCROLLBAR, + COLOR_WINDOW, + COLOR_WINDOWFRAME, + COLOR_WINDOWTEXT +}; + +#define NUM_SYS_COLORS ( sizeof( s_syspalindices ) / sizeof( int ) ) + +typedef struct { + HDC dibdc; // DC compatible with DIB section + HBITMAP dibsect; // DIB section + byte *pixels; // DIB base pointer, NOT used directly for rendering! + + qboolean palettized; // qtrue if desktop is paletted + HPALETTE pal; // palette we're using + HPALETTE oldpal; // original system palette + COLORREF oldsyscolors[NUM_SYS_COLORS]; // original system colors + + HGDIOBJ prevobj; +} sww_t; + +static sww_t sww; + +/* +SWimp_Shutdown + +System specific graphics subsystem shutdown routine. +Destroys DIB surfaces as appropriate. +*/ +static void SWimp_Shutdown( void ) { + if ( sww.palettized ) { + SetSystemPaletteUse( win.dc, SYSPAL_STATIC ); + SetSysColors( NUM_SYS_COLORS, s_syspalindices, sww.oldsyscolors ); + } + + if( sww.pal ) { + DeleteObject( sww.pal ); + } + + if( sww.oldpal ) { + SelectPalette( win.dc, sww.oldpal, FALSE ); + RealizePalette( win.dc ); + } + + if( sww.dibdc ) { + SelectObject( sww.dibdc, sww.prevobj ); + DeleteDC( sww.dibdc ); + } + + if( sww.dibsect ) { + DeleteObject( sww.dibsect ); + } + + memset( &sww, 0, sizeof( sww ) ); + + Win_Shutdown(); +} + +void SWimp_ModeChanged( void ) { + dibinfo_t info; + BITMAPINFO *pbmiDIB = ( BITMAPINFO * )&info; + + if( !sww.dibdc ) { + return; + } + + // destroy previous DIB section + if( sww.dibsect ) { + SelectObject( sww.dibdc, sww.prevobj ); + DeleteObject( sww.dibsect ); + } + + // fill in the BITMAPINFO struct + memset( pbmiDIB, 0, sizeof( dibinfo_t ) ); + + pbmiDIB->bmiHeader.biSize = sizeof( BITMAPINFOHEADER ); + pbmiDIB->bmiHeader.biWidth = win.rc.width; + pbmiDIB->bmiHeader.biHeight = win.rc.height; + pbmiDIB->bmiHeader.biPlanes = 1; + pbmiDIB->bmiHeader.biCompression = BI_RGB; + pbmiDIB->bmiHeader.biBitCount = 8; + pbmiDIB->bmiHeader.biClrUsed = 256; + pbmiDIB->bmiHeader.biClrImportant = 256; + + // create the DIB section + sww.dibsect = CreateDIBSection( win.dc, + pbmiDIB, + DIB_RGB_COLORS, + ( void ** )&sww.pixels, + NULL, + 0 ); + + if ( !sww.dibsect ) { + Com_Error( ERR_FATAL, "DIB_Init: CreateDIBSection failed" ); + } + + if ( pbmiDIB->bmiHeader.biHeight > 0 ) { + // bottom up + win.buffer = sww.pixels + ( win.rc.height - 1 ) * win.rc.width; + win.pitch = -win.rc.width; + } else { + // top down + win.buffer = sww.pixels; + win.pitch = win.rc.width; + } + + // clear the DIB memory buffer + memset( sww.pixels, 0xff, win.rc.width * win.rc.height ); + + sww.prevobj = SelectObject( sww.dibdc, sww.dibsect ); + if( !sww.prevobj ) { + Com_Error( ERR_FATAL, "DIB_Init: SelectObject failed\n" ); + } +} + + +/* +SWimp_Init + +This routine is responsible for initializing the implementation +specific stuff in a software rendering subsystem. +*/ +static qboolean SWimp_Init( void ) { + int i; + + // create the window + Win_Init(); + + // set display mode + Win_SetMode(); + + // figure out if we're running in an 8-bit display mode + if ( GetDeviceCaps( win.dc, RASTERCAPS ) & RC_PALETTE ) { + sww.palettized = qtrue; + for ( i = 0; i < NUM_SYS_COLORS; i++ ) + sww.oldsyscolors[i] = GetSysColor( s_syspalindices[i] ); + } else { + sww.palettized = qfalse; + } + + // create logical DC + sww.dibdc = CreateCompatibleDC( win.dc ); + if( !sww.dibdc ) { + Com_EPrintf( "DIB_Init: CreateCompatibleDC failed\n" ); + goto fail; + } + + // call SWimp_ModeChanged and friends + Win_ModeChanged(); + + return qtrue; + +fail: + Com_Printf( "GetLastError() = %#lx", GetLastError() ); + SWimp_Shutdown(); + return qfalse; +} + +static void SWimp_BeginFrame( void ) { +} + +/* +SWimp_EndFrame + +This does an implementation specific copy from the backbuffer to the +front buffer. In the Win32 case it uses BitBlt if we're using DIB sections/GDI. +*/ +static void SWimp_EndFrame( void ) { + BitBlt( win.dc, 0, 0, win.rc.width, win.rc.height, sww.dibdc, 0, 0, SRCCOPY ); +} + +/* +DIB_SetPalette + +Sets the color table in our DIB section, and also sets the system palette +into an identity mode if we're running in an 8-bit palettized display mode. + +The palette is expected to be 1024 bytes, in the format: + +R = offset 0 +G = offset 1 +B = offset 2 +A = offset 3 +*/ +static void SWimp_UpdatePalette( const byte *_pal ) { + const byte *pal = _pal; + RGBQUAD colors[256]; + int i; + + // set the DIB color table + if ( sww.dibdc ) { + for ( i = 0; i < 256; i++, pal += 4 ) { + colors[i].rgbRed = pal[0]; + colors[i].rgbGreen = pal[1]; + colors[i].rgbBlue = pal[2]; + colors[i].rgbReserved = 0; + } + + colors[0].rgbRed = 0; + colors[0].rgbGreen = 0; + colors[0].rgbBlue = 0; + + colors[255].rgbRed = 0xff; + colors[255].rgbGreen = 0xff; + colors[255].rgbBlue = 0xff; + + if ( SetDIBColorTable( sww.dibdc, 0, 256, colors ) == 0 ) { + Com_EPrintf( "DIB_SetPalette: SetDIBColorTable failed\n" ); + } + } + + // for 8-bit color desktop modes we set up the palette for maximum + // speed by going into an identity palette mode. + if ( sww.palettized ) { + int ret; + HPALETTE hpalOld; + identitypalette_t ipal; + LOGPALETTE *pLogPal = ( LOGPALETTE * )&ipal; + + if ( SetSystemPaletteUse( win.dc, SYSPAL_NOSTATIC ) == SYSPAL_ERROR ) { + Com_Error( ERR_FATAL, "DIB_SetPalette: SetSystemPaletteUse() failed\n" ); + } + + // destroy our old palette + if ( sww.pal ) { + DeleteObject( sww.pal ); + sww.pal = 0; + } + + // take up all physical palette entries to flush out anything that's + // currently in the palette + pLogPal->palVersion = 0x300; + pLogPal->palNumEntries = 256; + + for ( i = 0, pal = _pal; i < 256; i++, pal += 4 ) { + pLogPal->palPalEntry[i].peRed = pal[0]; + pLogPal->palPalEntry[i].peGreen = pal[1]; + pLogPal->palPalEntry[i].peBlue = pal[2]; + pLogPal->palPalEntry[i].peFlags = PC_RESERVED | PC_NOCOLLAPSE; + } + pLogPal->palPalEntry[0].peRed = 0; + pLogPal->palPalEntry[0].peGreen = 0; + pLogPal->palPalEntry[0].peBlue = 0; + pLogPal->palPalEntry[0].peFlags = 0; + pLogPal->palPalEntry[255].peRed = 0xff; + pLogPal->palPalEntry[255].peGreen = 0xff; + pLogPal->palPalEntry[255].peBlue = 0xff; + pLogPal->palPalEntry[255].peFlags = 0; + + if ( ( sww.pal = CreatePalette( pLogPal ) ) == NULL ) { + Com_Error( ERR_FATAL, "DIB_SetPalette: CreatePalette failed(%lx)\n", GetLastError() ); + } + + if ( ( hpalOld = SelectPalette( win.dc, sww.pal, FALSE ) ) == NULL ) { + Com_Error( ERR_FATAL, "DIB_SetPalette: SelectPalette failed(%lx)\n", GetLastError() ); + } + + if ( sww.oldpal == NULL ) + sww.oldpal = hpalOld; + + if ( ( ret = RealizePalette( win.dc ) ) != pLogPal->palNumEntries ) { + Com_Error( ERR_FATAL, "DIB_SetPalette: RealizePalette set %d entries\n", ret ); + } + } +} + +/* +@@@@@@@@@@@@ +SWimp_FillAPI +@@@@@@@@@@@@ +*/ +void Video_FillSWAPI( videoAPI_t *api ) { + api->Init = SWimp_Init; + api->Shutdown = SWimp_Shutdown; + api->UpdateGamma = Win_UpdateGamma; + api->UpdatePalette = SWimp_UpdatePalette; + api->GetProcAddr = NULL; + api->BeginFrame = SWimp_BeginFrame; + api->EndFrame = SWimp_EndFrame; +} + |