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 }