icculus quake2 doxygen  1.0 dev
rw_dib.c
Go to the documentation of this file.
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 
34 
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 
64 
65 typedef struct dibinfo
66 {
67  BITMAPINFOHEADER header;
68  RGBQUAD acolors[256];
69 } dibinfo_t;
70 
71 typedef struct
72 {
73  WORD palVersion;
75  PALETTEENTRY palEntries[256];
77 
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  {
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,
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  }
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 {
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 );
336  }
337 
338  if ( sww_state.hdcDIBSection )
339  {
341  DeleteDC( sww_state.hdcDIBSection );
343  }
344 
345  if ( sww_state.hDIBSection )
346  {
347  DeleteObject( sww_state.hDIBSection );
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 );
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 }
DIB_Init
qboolean DIB_Init(unsigned char **ppbuffer, int *ppitch)
Definition: rw_dib.c:88
DIB_SetPalette
void DIB_SetPalette(const unsigned char *_pal)
Definition: rw_dib.c:215
rw_win.h
identitypalette_t::palNumEntries
WORD palNumEntries
Definition: rw_dib.c:74
dibinfo_t
struct dibinfo dibinfo_t
s_ipal
static identitypalette_t s_ipal
Definition: rw_dib.c:78
ri
refimport_t ri
Definition: r_main.c:25
qboolean
qboolean
Definition: q_shared.h:56
viddef_t::width
int width
Definition: vid.h:29
i
int i
Definition: q_shared.c:305
previously_selected_GDI_obj
static HGDIOBJ previously_selected_GDI_obj
Definition: rw_dib.c:35
swwstate_t::pDIBBase
unsigned char * pDIBBase
Definition: rw_win.h:35
viddef_t::height
int height
Definition: vid.h:29
identitypalette_t::palVersion
WORD palVersion
Definition: rw_dib.c:73
refimport_t::Con_Printf
void(* Con_Printf)(int print_level, char *str,...)
Definition: ref.h:228
PRINT_ALL
#define PRINT_ALL
Definition: qcommon.h:743
swwstate_t::hPal
HPALETTE hPal
Definition: rw_win.h:37
swwstate_t::palettized
qboolean palettized
Definition: rw_win.h:49
HDC
HDC(WINAPI *qwglGetCurrentDC)(VOID)
refimport_t::Sys_Error
void(* Sys_Error)(int err_level, char *str,...)
Definition: ref.h:220
DIB_SaveSystemColors
static void DIB_SaveSystemColors(void)
Definition: rw_dib.c:369
NULL
#define NULL
Definition: q_shared.h:60
DIB_Shutdown
void DIB_Shutdown(void)
Definition: rw_dib.c:320
DIB_RestoreSystemColors
static void DIB_RestoreSystemColors(void)
Definition: rw_dib.c:363
ERR_FATAL
#define ERR_FATAL
Definition: qcommon.h:735
dibinfo::acolors
RGBQUAD acolors[256]
Definition: rw_dib.c:68
d_8to24table
unsigned d_8to24table[256]
Definition: r_main.c:27
swwstate_t::hpalOld
HPALETTE hpalOld
Definition: rw_win.h:38
swwstate_t::hdcDIBSection
HDC hdcDIBSection
Definition: rw_win.h:33
s_syspalindices
static int s_syspalindices[]
Definition: rw_dib.c:37
dibinfo
Definition: rw_dib.c:65
dibinfo::header
BITMAPINFOHEADER header
Definition: rw_dib.c:67
sww_state
swwstate_t sww_state
Definition: rw_imp.c:38
swwstate_t::hWnd
HWND hWnd
Definition: rw_win.h:31
swwstate_t::hDC
HDC hDC
Definition: rw_win.h:30
NUM_SYS_COLORS
#define NUM_SYS_COLORS
Definition: rw_dib.c:61
s_systemcolors_saved
static qboolean s_systemcolors_saved
Definition: rw_dib.c:33
s_oldsyscolors
static int s_oldsyscolors[NUM_SYS_COLORS]
Definition: rw_dib.c:63
swwstate_t::hDIBSection
HBITMAP hDIBSection
Definition: rw_win.h:34
identitypalette_t
Definition: rw_dib.c:71
vid
viddef_t vid
Definition: r_main.c:24