ref: c05151aa1b7ac81866cf937c973e7038035dfe53
dir: /win32/rw_dib.c/
/* 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_DIB.C ** ** This handles DIB section management under Windows. ** */ #include "..\ref_soft\r_local.h" #include "rw_win.h" #ifndef _WIN32 # error You should not be trying to compile this file on this platform #endif static qboolean s_systemcolors_saved; static HGDIOBJ previously_selected_GDI_obj; static 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 ) ) static int s_oldsyscolors[NUM_SYS_COLORS]; typedef struct dibinfo { BITMAPINFOHEADER header; RGBQUAD acolors[256]; } dibinfo_t; typedef struct { WORD palVersion; WORD palNumEntries; PALETTEENTRY palEntries[256]; } identitypalette_t; static identitypalette_t s_ipal; static void DIB_SaveSystemColors( void ); static void DIB_RestoreSystemColors( void ); /* ** DIB_Init ** ** Builds our DIB section */ qboolean DIB_Init( unsigned char **ppbuffer, int *ppitch ) { dibinfo_t dibheader; BITMAPINFO *pbmiDIB = ( BITMAPINFO * ) &dibheader; int i; memset( &dibheader, 0, sizeof( dibheader ) ); /* ** grab a DC */ if ( !sww_state.hDC ) { if ( ( sww_state.hDC = GetDC( sww_state.hWnd ) ) == NULL ) return false; } /* ** figure out if we're running in an 8-bit display mode */ if ( GetDeviceCaps( sww_state.hDC, RASTERCAPS ) & RC_PALETTE ) { sww_state.palettized = true; // save system colors if ( !s_systemcolors_saved ) { DIB_SaveSystemColors(); s_systemcolors_saved = true; } } else { sww_state.palettized = false; } /* ** fill in the BITMAPINFO struct */ pbmiDIB->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); pbmiDIB->bmiHeader.biWidth = vid.width; pbmiDIB->bmiHeader.biHeight = vid.height; pbmiDIB->bmiHeader.biPlanes = 1; pbmiDIB->bmiHeader.biBitCount = 8; pbmiDIB->bmiHeader.biCompression = BI_RGB; pbmiDIB->bmiHeader.biSizeImage = 0; pbmiDIB->bmiHeader.biXPelsPerMeter = 0; pbmiDIB->bmiHeader.biYPelsPerMeter = 0; pbmiDIB->bmiHeader.biClrUsed = 256; pbmiDIB->bmiHeader.biClrImportant = 256; /* ** fill in the palette */ for ( i = 0; i < 256; i++ ) { dibheader.acolors[i].rgbRed = ( d_8to24table[i] >> 0 ) & 0xff; dibheader.acolors[i].rgbGreen = ( d_8to24table[i] >> 8 ) & 0xff; dibheader.acolors[i].rgbBlue = ( d_8to24table[i] >> 16 ) & 0xff; } /* ** create the DIB section */ sww_state.hDIBSection = CreateDIBSection( sww_state.hDC, pbmiDIB, DIB_RGB_COLORS, &sww_state.pDIBBase, NULL, 0 ); if ( sww_state.hDIBSection == NULL ) { ri.Con_Printf( PRINT_ALL, "DIB_Init() - CreateDIBSection failed\n" ); goto fail; } if ( pbmiDIB->bmiHeader.biHeight > 0 ) { // bottom up *ppbuffer = sww_state.pDIBBase + ( vid.height - 1 ) * vid.width; *ppitch = -vid.width; } else { // top down *ppbuffer = sww_state.pDIBBase; *ppitch = vid.width; } /* ** clear the DIB memory buffer */ memset( sww_state.pDIBBase, 0xff, vid.width * vid.height ); if ( ( sww_state.hdcDIBSection = CreateCompatibleDC( sww_state.hDC ) ) == NULL ) { ri.Con_Printf( PRINT_ALL, "DIB_Init() - CreateCompatibleDC failed\n" ); goto fail; } if ( ( previously_selected_GDI_obj = SelectObject( sww_state.hdcDIBSection, sww_state.hDIBSection ) ) == NULL ) { ri.Con_Printf( PRINT_ALL, "DIB_Init() - SelectObject failed\n" ); goto fail; } return true; fail: DIB_Shutdown(); return false; } /* ** 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 */ void DIB_SetPalette( const unsigned char *_pal ) { const unsigned char *pal = _pal; LOGPALETTE *pLogPal = ( LOGPALETTE * ) &s_ipal; RGBQUAD colors[256]; int i; int ret; HDC hDC = sww_state.hDC; /* ** set the DIB color table */ if ( sww_state.hdcDIBSection ) { 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_state.hdcDIBSection, 0, 256, colors ) == 0 ) { ri.Con_Printf( PRINT_ALL, "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_state.palettized ) { int i; HPALETTE hpalOld; if ( SetSystemPaletteUse( hDC, SYSPAL_NOSTATIC ) == SYSPAL_ERROR ) { ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - SetSystemPaletteUse() failed\n" ); } /* ** destroy our old palette */ if ( sww_state.hPal ) { DeleteObject( sww_state.hPal ); sww_state.hPal = 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_state.hPal = CreatePalette( pLogPal ) ) == NULL ) { ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - CreatePalette failed(%x)\n", GetLastError() ); } if ( ( hpalOld = SelectPalette( hDC, sww_state.hPal, FALSE ) ) == NULL ) { ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - SelectPalette failed(%x)\n",GetLastError() ); } if ( sww_state.hpalOld == NULL ) sww_state.hpalOld = hpalOld; if ( ( ret = RealizePalette( hDC ) ) != pLogPal->palNumEntries ) { ri.Sys_Error( ERR_FATAL, "DIB_SetPalette() - RealizePalette set %d entries\n", ret ); } } } /* ** DIB_Shutdown */ void DIB_Shutdown( void ) { if ( sww_state.palettized && s_systemcolors_saved ) DIB_RestoreSystemColors(); if ( sww_state.hPal ) { DeleteObject( sww_state.hPal ); sww_state.hPal = 0; } if ( sww_state.hpalOld ) { SelectPalette( sww_state.hDC, sww_state.hpalOld, FALSE ); RealizePalette( sww_state.hDC ); sww_state.hpalOld = NULL; } if ( sww_state.hdcDIBSection ) { SelectObject( sww_state.hdcDIBSection, previously_selected_GDI_obj ); DeleteDC( sww_state.hdcDIBSection ); sww_state.hdcDIBSection = NULL; } if ( sww_state.hDIBSection ) { DeleteObject( sww_state.hDIBSection ); sww_state.hDIBSection = NULL; sww_state.pDIBBase = NULL; } if ( sww_state.hDC ) { ReleaseDC( sww_state.hWnd, sww_state.hDC ); sww_state.hDC = 0; } } /* ** DIB_Save/RestoreSystemColors */ static void DIB_RestoreSystemColors( void ) { SetSystemPaletteUse( sww_state.hDC, SYSPAL_STATIC ); SetSysColors( NUM_SYS_COLORS, s_syspalindices, s_oldsyscolors ); } static void DIB_SaveSystemColors( void ) { int i; for ( i = 0; i < NUM_SYS_COLORS; i++ ) s_oldsyscolors[i] = GetSysColor( s_syspalindices[i] ); }