summaryrefslogtreecommitdiff
path: root/source/win_swimp.c
diff options
context:
space:
mode:
Diffstat (limited to 'source/win_swimp.c')
-rw-r--r--source/win_swimp.c348
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;
+}
+