Quake-2

Quake 2 GPL Source Release
Log | Files | Refs

rw_dib.c (8664B)


      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_DIB.C
     22 **
     23 ** This handles DIB section management under Windows.
     24 **
     25 */
     26 #include "..\ref_soft\r_local.h"
     27 #include "rw_win.h"
     28 
     29 #ifndef _WIN32
     30 #  error You should not be trying to compile this file on this platform
     31 #endif
     32 
     33 static qboolean s_systemcolors_saved;
     34 
     35 static HGDIOBJ previously_selected_GDI_obj;
     36 
     37 static int s_syspalindices[] = 
     38 {
     39   COLOR_ACTIVEBORDER,
     40   COLOR_ACTIVECAPTION,
     41   COLOR_APPWORKSPACE,
     42   COLOR_BACKGROUND,
     43   COLOR_BTNFACE,
     44   COLOR_BTNSHADOW,
     45   COLOR_BTNTEXT,
     46   COLOR_CAPTIONTEXT,
     47   COLOR_GRAYTEXT,
     48   COLOR_HIGHLIGHT,
     49   COLOR_HIGHLIGHTTEXT,
     50   COLOR_INACTIVEBORDER,
     51 
     52   COLOR_INACTIVECAPTION,
     53   COLOR_MENU,
     54   COLOR_MENUTEXT,
     55   COLOR_SCROLLBAR,
     56   COLOR_WINDOW,
     57   COLOR_WINDOWFRAME,
     58   COLOR_WINDOWTEXT
     59 };
     60 
     61 #define NUM_SYS_COLORS ( sizeof( s_syspalindices ) / sizeof( int ) )
     62 
     63 static int s_oldsyscolors[NUM_SYS_COLORS];
     64 
     65 typedef struct dibinfo
     66 {
     67 	BITMAPINFOHEADER	header;
     68 	RGBQUAD				acolors[256];
     69 } dibinfo_t;
     70 
     71 typedef struct
     72 {
     73 	WORD palVersion;
     74 	WORD palNumEntries;
     75 	PALETTEENTRY palEntries[256];
     76 } identitypalette_t;
     77 
     78 static identitypalette_t s_ipal;
     79 
     80 static void DIB_SaveSystemColors( void );
     81 static void DIB_RestoreSystemColors( void );
     82 
     83 /*
     84 ** DIB_Init
     85 **
     86 ** Builds our DIB section
     87 */
     88 qboolean DIB_Init( unsigned char **ppbuffer, int *ppitch )
     89 {
     90 	dibinfo_t   dibheader;
     91 	BITMAPINFO *pbmiDIB = ( BITMAPINFO * ) &dibheader;
     92 	int i;
     93 
     94 	memset( &dibheader, 0, sizeof( dibheader ) );
     95 
     96 	/*
     97 	** grab a DC
     98 	*/
     99 	if ( !sww_state.hDC )
    100 	{
    101 		if ( ( sww_state.hDC = GetDC( sww_state.hWnd ) ) == NULL )
    102 			return false;
    103 	}
    104 
    105 	/*
    106 	** figure out if we're running in an 8-bit display mode
    107 	*/
    108  	if ( GetDeviceCaps( sww_state.hDC, RASTERCAPS ) & RC_PALETTE )
    109 	{
    110 		sww_state.palettized = true;
    111 
    112 		// save system colors
    113 		if ( !s_systemcolors_saved )
    114 		{
    115 			DIB_SaveSystemColors();
    116 			s_systemcolors_saved = true;
    117 		}
    118 	}
    119 	else
    120 	{
    121 		sww_state.palettized = false;
    122 	}
    123 
    124 	/*
    125 	** fill in the BITMAPINFO struct
    126 	*/
    127 	pbmiDIB->bmiHeader.biSize          = sizeof(BITMAPINFOHEADER);
    128 	pbmiDIB->bmiHeader.biWidth         = vid.width;
    129 	pbmiDIB->bmiHeader.biHeight        = vid.height;
    130 	pbmiDIB->bmiHeader.biPlanes        = 1;
    131 	pbmiDIB->bmiHeader.biBitCount      = 8;
    132 	pbmiDIB->bmiHeader.biCompression   = BI_RGB;
    133 	pbmiDIB->bmiHeader.biSizeImage     = 0;
    134 	pbmiDIB->bmiHeader.biXPelsPerMeter = 0;
    135 	pbmiDIB->bmiHeader.biYPelsPerMeter = 0;
    136 	pbmiDIB->bmiHeader.biClrUsed       = 256;
    137 	pbmiDIB->bmiHeader.biClrImportant  = 256;
    138 
    139 	/*
    140 	** fill in the palette
    141 	*/
    142 	for ( i = 0; i < 256; i++ )
    143 	{
    144 		dibheader.acolors[i].rgbRed   = ( d_8to24table[i] >> 0 )  & 0xff;
    145 		dibheader.acolors[i].rgbGreen = ( d_8to24table[i] >> 8 )  & 0xff;
    146 		dibheader.acolors[i].rgbBlue  = ( d_8to24table[i] >> 16 ) & 0xff;
    147 	}
    148 
    149 	/*
    150 	** create the DIB section
    151 	*/
    152 	sww_state.hDIBSection = CreateDIBSection( sww_state.hDC,
    153 		                                     pbmiDIB,
    154 											 DIB_RGB_COLORS,
    155 											 &sww_state.pDIBBase,
    156 											 NULL,
    157 											 0 );
    158 
    159 	if ( sww_state.hDIBSection == NULL )
    160 	{
    161 		ri.Con_Printf( PRINT_ALL, "DIB_Init() - CreateDIBSection failed\n" );
    162 		goto fail;
    163 	}
    164 
    165 	if ( pbmiDIB->bmiHeader.biHeight > 0 )
    166     {
    167 		// bottom up
    168 		*ppbuffer	= sww_state.pDIBBase + ( vid.height - 1 ) * vid.width;
    169 		*ppitch		= -vid.width;
    170     }
    171     else
    172     {
    173 		// top down
    174 		*ppbuffer	= sww_state.pDIBBase;
    175 		*ppitch		= vid.width;
    176     }
    177 
    178 	/*
    179 	** clear the DIB memory buffer
    180 	*/
    181 	memset( sww_state.pDIBBase, 0xff, vid.width * vid.height );
    182 
    183 	if ( ( sww_state.hdcDIBSection = CreateCompatibleDC( sww_state.hDC ) ) == NULL )
    184 	{
    185 		ri.Con_Printf( PRINT_ALL, "DIB_Init() - CreateCompatibleDC failed\n" );
    186 		goto fail;
    187 	}
    188 	if ( ( previously_selected_GDI_obj = SelectObject( sww_state.hdcDIBSection, sww_state.hDIBSection ) ) == NULL )
    189 	{
    190 		ri.Con_Printf( PRINT_ALL, "DIB_Init() - SelectObject failed\n" );
    191 		goto fail;
    192 	}
    193 
    194 	return true;
    195 
    196 fail:
    197 	DIB_Shutdown();
    198 	return false;
    199 	
    200 }
    201 
    202 /*
    203 ** DIB_SetPalette
    204 **
    205 ** Sets the color table in our DIB section, and also sets the system palette
    206 ** into an identity mode if we're running in an 8-bit palettized display mode.
    207 **
    208 ** The palette is expected to be 1024 bytes, in the format:
    209 **
    210 ** R = offset 0
    211 ** G = offset 1
    212 ** B = offset 2
    213 ** A = offset 3
    214 */
    215 void DIB_SetPalette( const unsigned char *_pal )
    216 {
    217 	const unsigned char *pal = _pal;
    218   	LOGPALETTE		*pLogPal = ( LOGPALETTE * ) &s_ipal;
    219 	RGBQUAD			colors[256];
    220 	int				i;
    221 	int				ret;
    222 	HDC				hDC = sww_state.hDC;
    223 
    224 	/*
    225 	** set the DIB color table
    226 	*/
    227 	if ( sww_state.hdcDIBSection )
    228 	{
    229 		for ( i = 0; i < 256; i++, pal += 4 )
    230 		{
    231 			colors[i].rgbRed   = pal[0];
    232 			colors[i].rgbGreen = pal[1];
    233 			colors[i].rgbBlue  = pal[2];
    234 			colors[i].rgbReserved = 0;
    235 		}
    236 
    237 		colors[0].rgbRed = 0;
    238 		colors[0].rgbGreen = 0;
    239 		colors[0].rgbBlue = 0;
    240 
    241 		colors[255].rgbRed = 0xff;
    242 		colors[255].rgbGreen = 0xff;
    243 		colors[255].rgbBlue = 0xff;
    244 
    245 		if ( SetDIBColorTable( sww_state.hdcDIBSection, 0, 256, colors ) == 0 )
    246 		{
    247 			ri.Con_Printf( PRINT_ALL, "DIB_SetPalette() - SetDIBColorTable failed\n" );
    248 		}
    249 	}
    250 
    251 	/*
    252 	** for 8-bit color desktop modes we set up the palette for maximum
    253 	** speed by going into an identity palette mode.
    254 	*/
    255 	if ( sww_state.palettized )
    256 	{
    257 		int i;
    258 		HPALETTE hpalOld;
    259 
    260 		if ( SetSystemPaletteUse( hDC, SYSPAL_NOSTATIC ) == SYSPAL_ERROR )
    261 		{
    262 			ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - SetSystemPaletteUse() failed\n" );
    263 		}
    264 
    265 		/*
    266 		** destroy our old palette
    267 		*/
    268 		if ( sww_state.hPal )
    269 		{
    270 			DeleteObject( sww_state.hPal );
    271 			sww_state.hPal = 0;
    272 		}
    273 
    274 		/*
    275 		** take up all physical palette entries to flush out anything that's currently
    276 		** in the palette
    277 		*/
    278 		pLogPal->palVersion		= 0x300;
    279 		pLogPal->palNumEntries	= 256;
    280 
    281 		for ( i = 0, pal = _pal; i < 256; i++, pal += 4 )
    282 		{
    283 			pLogPal->palPalEntry[i].peRed	= pal[0];
    284 			pLogPal->palPalEntry[i].peGreen	= pal[1];
    285 			pLogPal->palPalEntry[i].peBlue	= pal[2];
    286 			pLogPal->palPalEntry[i].peFlags	= PC_RESERVED | PC_NOCOLLAPSE;
    287 		}
    288 		pLogPal->palPalEntry[0].peRed		= 0;
    289 		pLogPal->palPalEntry[0].peGreen		= 0;
    290 		pLogPal->palPalEntry[0].peBlue		= 0;
    291 		pLogPal->palPalEntry[0].peFlags		= 0;
    292 		pLogPal->palPalEntry[255].peRed		= 0xff;
    293 		pLogPal->palPalEntry[255].peGreen	= 0xff;
    294 		pLogPal->palPalEntry[255].peBlue	= 0xff;
    295 		pLogPal->palPalEntry[255].peFlags	= 0;
    296 
    297 		if ( ( sww_state.hPal = CreatePalette( pLogPal ) ) == NULL )
    298 		{
    299 			ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - CreatePalette failed(%x)\n", GetLastError() );
    300 		}
    301 
    302 		if ( ( hpalOld = SelectPalette( hDC, sww_state.hPal, FALSE ) ) == NULL )
    303 		{
    304 			ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - SelectPalette failed(%x)\n",GetLastError() );
    305 		}
    306 
    307 		if ( sww_state.hpalOld == NULL )
    308 			sww_state.hpalOld = hpalOld;
    309 
    310 		if ( ( ret = RealizePalette( hDC ) ) != pLogPal->palNumEntries ) 
    311 		{
    312 			ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - RealizePalette set %d entries\n", ret );
    313 		}
    314 	}
    315 }
    316 
    317 /*
    318 ** DIB_Shutdown
    319 */
    320 void DIB_Shutdown( void )
    321 {
    322 	if ( sww_state.palettized && s_systemcolors_saved )
    323 		DIB_RestoreSystemColors();
    324 
    325 	if ( sww_state.hPal )
    326 	{
    327 		DeleteObject( sww_state.hPal );
    328 		sww_state.hPal = 0;
    329 	}
    330 
    331 	if ( sww_state.hpalOld )
    332 	{
    333 		SelectPalette( sww_state.hDC, sww_state.hpalOld, FALSE );
    334 		RealizePalette( sww_state.hDC );
    335 		sww_state.hpalOld = NULL;
    336 	}
    337 
    338 	if ( sww_state.hdcDIBSection )
    339 	{
    340 		SelectObject( sww_state.hdcDIBSection, previously_selected_GDI_obj );
    341 		DeleteDC( sww_state.hdcDIBSection );
    342 		sww_state.hdcDIBSection = NULL;
    343 	}
    344 
    345 	if ( sww_state.hDIBSection )
    346 	{
    347 		DeleteObject( sww_state.hDIBSection );
    348 		sww_state.hDIBSection = NULL;
    349 		sww_state.pDIBBase = NULL;
    350 	}
    351 
    352 	if ( sww_state.hDC )
    353 	{
    354 		ReleaseDC( sww_state.hWnd, sww_state.hDC );
    355 		sww_state.hDC = 0;
    356 	}
    357 }
    358 
    359 
    360 /*
    361 ** DIB_Save/RestoreSystemColors
    362 */
    363 static void DIB_RestoreSystemColors( void )
    364 {
    365     SetSystemPaletteUse( sww_state.hDC, SYSPAL_STATIC );
    366     SetSysColors( NUM_SYS_COLORS, s_syspalindices, s_oldsyscolors );
    367 }
    368 
    369 static void DIB_SaveSystemColors( void )
    370 {
    371 	int i;
    372 
    373 	for ( i = 0; i < NUM_SYS_COLORS; i++ )
    374 		s_oldsyscolors[i] = GetSysColor( s_syspalindices[i] );
    375 }