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 */
DIB_Init(unsigned char ** ppbuffer,int * ppitch)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 */
DIB_SetPalette(const unsigned char * _pal)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 */
DIB_Shutdown(void)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 */
DIB_RestoreSystemColors(void)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
DIB_SaveSystemColors(void)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 }
376