2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/Graphics/GrDirectDraw.cpp $
15 * Code for software 8-bpp rendering using DirectDraw
18 * Revision 1.3 2002/06/09 04:41:17 relnev
19 * added copyright header
21 * Revision 1.2 2002/05/07 03:16:45 theoddone33
22 * The Great Newline Fix
24 * Revision 1.1.1.1 2002/05/03 03:28:09 root
28 * 9 7/14/99 9:42a Dave
29 * Put in clear_color debug function. Put in base for 3dnow stuff / P3
32 * 8 6/29/99 10:35a Dave
33 * Interface polygon bitmaps! Whee!
35 * 7 2/03/99 11:44a Dave
36 * Fixed d3d transparent textures.
38 * 6 1/24/99 11:37p Dave
39 * First full rev of beam weapons. Very customizable. Removed some bogus
40 * Int3()'s in low level net code.
42 * 5 12/18/98 1:13a Dave
43 * Rough 1024x768 support for Direct3D. Proper detection and usage through
46 * 4 12/06/98 2:36p Dave
47 * Drastically improved nebula fogging.
49 * 3 11/30/98 1:07p Dave
50 * 16 bit conversion, first run.
52 * 2 10/07/98 10:52a Dave
55 * 1 10/07/98 10:49a Dave
57 * 17 5/22/98 10:28p John
58 * Made software movies not click your monitor when switching to 16-bpp.
59 * Total hack around my restrictive code, but at this point...
61 * 16 5/20/98 9:45p John
62 * added code so the places in code that change half the palette don't
63 * have to clear the screen.
65 * 15 5/17/98 5:03p John
66 * Fixed some bugs that make the taskbar interfere with the DEBUG-only
69 * 14 5/16/98 1:18p John
70 * Made softtware DirectDraw reset palette after Alt+TAB.
72 * 13 5/15/98 9:34p John
73 * Removed the initial ugly little cursor part that drew right at program
76 * 12 5/14/98 5:42p John
77 * Revamped the whole window position/mouse code for the graphics windows.
79 * 11 5/12/98 8:15a John
80 * Made dd code not print out rgb surface info.
82 * 10 5/07/98 6:58p Hoffoss
83 * Made changes to mouse code to fix a number of problems.
85 * 9 5/06/98 5:30p John
86 * Removed unused cfilearchiver. Removed/replaced some unused/little used
87 * graphics functions, namely gradient_h and _v and pixel_sp. Put in new
88 * DirectX header files and libs that fixed the Direct3D alpha blending
91 * 8 4/23/98 8:24a John
92 * Changed the way palette effect works so that:
93 * 1. If gr_flash isn't called this frame, screen shows no flash.
94 * 2. With hardware, only 3d portion of screen gets flashed.
96 * 7 4/21/98 5:22p John
97 * Fixed all the &^#@$ cursor bugs with popups. For Glide, had problem
98 * with mouse restoring assuming back buffer was same buffer last frame,
99 * for software, problems with half drawn new frames, then mouse got
100 * restored on top of that with old data.
102 * 6 4/17/98 3:56p Mike
103 * Fix palette trashing on MK's computer when he Alt-Tabs out of FreeSpace
104 * in software. At John's suggestion.
106 * 5 4/14/98 12:15p John
107 * Made 16-bpp movies work.
109 * 4 4/13/98 8:08p John
110 * Made surface restoration also restore the palette.
112 * 3 4/09/98 6:56p John
113 * Put in better code to restore surfaces when restoring them. Worth a
114 * try for an Interplay QA bug I can't find.
116 * 2 4/09/98 11:05a John
117 * Removed all traces of Direct3D out of the demo version of Freespace and
120 * 1 3/25/98 8:07p John
121 * Split software renderer into Win32 and DirectX
128 #include <windowsx.h>
136 #include "floating.h"
139 #include "grinternal.h"
141 // Headers for 2d functions
149 #include "gradient.h"
150 #include "pcxutils.h"
157 #include "grzbuffer.h"
159 static LPDIRECTDRAW lpDD = NULL;
160 static LPDIRECTDRAWSURFACE lpBackBuffer = NULL;
161 static LPDIRECTDRAWSURFACE lpFrontBuffer = NULL;
162 static LPDIRECTDRAWCLIPPER lpClipper = NULL;
163 static LPDIRECTDRAWPALETTE lpPalette = NULL;
165 void gr_directdraw_unlock();
166 void gr_directdraw_set_palette_internal( ubyte * new_pal );
168 void directdraw_clear_all_vram()
170 #ifndef HARDWARE_ONLY
173 LPDIRECTDRAWSURFACE buffer[16];
177 for (i=0; i<16; i++ ) {
178 memset( &ddsd, 0, sizeof( ddsd ) );
180 ddsd.dwSize = sizeof( ddsd );
181 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
182 ddsd.dwWidth = gr_screen.max_w;
183 ddsd.dwHeight = gr_screen.max_h;
184 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
186 // create the back buffer
187 ddrval = lpDD->CreateSurface( &ddsd, &buffer[i], NULL );
188 if ( ddrval == DD_OK ) {
192 memset(&ddBltFx, 0, sizeof(DDBLTFX));
193 ddBltFx.dwSize = sizeof(DDBLTFX);
194 ddBltFx.dwFillColor = 0;
196 buffer[i]->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddBltFx);
205 for (i=0; i<num_buffers; i++ ) {
206 buffer[i]->Release();
213 LPDIRECTDRAW gr_directdraw_start_mve()
215 #ifndef HARDWARE_ONLY
217 memset( tmp_pal, 0, 768 );
219 gr_directdraw_set_palette_internal(tmp_pal);
221 // clear both buffers
230 gr_directdraw_unlock();
232 // Clear all of VRAM...
233 directdraw_clear_all_vram();
236 lpPalette->Release();
241 lpFrontBuffer->Release();
242 lpFrontBuffer = NULL;
254 void gr_directdraw_stop_mve()
256 #ifndef HARDWARE_ONLY
260 memset( &ddsd, 0, sizeof( ddsd ) );
262 ddsd.dwSize = sizeof( ddsd );
263 ddsd.dwFlags = DDSD_CAPS;
264 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
266 ddrval = lpDD->CreateSurface( &ddsd, &lpFrontBuffer, NULL );
267 if ( ddrval != DD_OK ) {
268 mprintf(( "GR_SOFT_INIT: CreateSurface (Front) failed.\n" ));
274 PALETTEENTRY pe[256];
275 for (i=0; i<256; i++ ) {
276 pe[i].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
277 pe[i].peRed = gr_palette[i*3+0];
278 pe[i].peGreen = gr_palette[i*3+1];
279 pe[i].peBlue = gr_palette[i*3+2];
282 ddrval = lpDD->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &lpPalette, NULL);
283 if (ddrval != DD_OK) {
284 mprintf(( "Error creating palette\n" ));
287 ddrval = lpFrontBuffer->SetPalette( lpPalette );
288 if (ddrval != DD_OK) {
289 mprintf(( "Error setting palette in gr_directdraw_set_palette\n" ));
302 static int Locked = 0;
304 uint gr_directdraw_lock()
306 #ifndef HARDWARE_ONLY
312 memset( &ddsd, 0, sizeof( ddsd ) );
313 ddsd.dwSize = sizeof( ddsd );
315 ddrval = lpBackBuffer->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
316 if ( ddrval != DD_OK ) {
317 mprintf(( "Error locking surface in gr_d3d_lock\n" ));
318 gr_screen.offscreen_buffer_base = NULL; //(void *)fake_vram;
319 gr_screen.rowsize = 0;
320 gr_screen.offscreen_buffer = gr_screen.offscreen_buffer_base;
322 gr_screen.offscreen_buffer_base = (void *)ddsd.lpSurface;
323 gr_screen.rowsize = ddsd.lPitch;
324 gr_screen.offscreen_buffer = gr_screen.offscreen_buffer_base;
336 void gr_directdraw_unlock()
338 #ifndef HARDWARE_ONLY
340 // Unlock the back buffer
341 lpBackBuffer->Unlock( NULL );
349 void gr_directdraw_unlock_fake()
354 static int Palette_flashed = 0;
355 static int Palette_flashed_last_frame = 0;
358 static volatile int Gr_dd_activated = 0;
360 void gr_dd_activate(int active)
362 #ifndef HARDWARE_ONLY
372 void gr_directdraw_flip()
374 #ifndef HARDWARE_ONLY
375 if ( Gr_dd_activated || ((!Palette_flashed) && (Palette_flashed_last_frame)) ) {
377 gr_directdraw_set_palette_internal( gr_palette );
381 Palette_flashed_last_frame = Palette_flashed;
388 Grx_mouse_saved = 0; // assume not saved
391 if ( mouse_is_visible() ) {
393 mouse_get_pos( &mx, &my );
394 grx_save_mouse_area(mx,my,32,32);
395 if ( Gr_cursor == -1 ) {
396 gr_set_color(255,255,255);
397 gr_line( mx, my, mx+7, my + 7 );
398 gr_line( mx, my, mx+5, my );
399 gr_line( mx, my, mx, my+5 );
401 gr_set_bitmap(Gr_cursor);
406 gr_directdraw_unlock();
411 if ( lpFrontBuffer->IsLost() == DDERR_SURFACELOST ) {
412 lpFrontBuffer->Restore();
413 ddrval = lpFrontBuffer->SetPalette( lpPalette );
414 if (ddrval != DD_OK) {
415 mprintf(( "Error setting palette after restore\n" ));
418 if ( lpBackBuffer->IsLost() == DDERR_SURFACELOST ) {
419 lpBackBuffer->Restore();
422 HRESULT ddrval = lpFrontBuffer->Flip( NULL, DDFLIP_WAIT );
423 if ( ddrval == DDERR_SURFACELOST ) {
424 mprintf(( "Front surface lost... attempting to restore...\n" ));
425 os_sleep(1000); // Wait a second
427 } else if (ddrval != DD_OK ) {
428 mprintf(( "Fullscreen flip failed!\n" ));
432 RECT src_rect, dst_rect;
436 HWND hWnd = (HWND)os_get_window();
439 // src_rect is relative to offscreen buffer
440 GetClientRect( hWnd, &src_rect );
442 // dst_rect is relative to screen space so needs translation
444 ClientToScreen( hWnd, &pt );
446 dst_rect.left += pt.x;
447 dst_rect.right += pt.x;
448 dst_rect.top += pt.y;
449 dst_rect.bottom += pt.y;
451 // perform the blit from backbuffer to primary, using
452 // src_rect and dst_rect
455 if ( lpFrontBuffer->IsLost() == DDERR_SURFACELOST ) {
456 lpFrontBuffer->Restore();
458 /* ddrval = lpFrontBuffer->SetPalette( lpPalette );
459 if (ddrval != DD_OK) {
460 mprintf(( "Error setting palette after restore\n" ));
463 if ( lpBackBuffer->IsLost() == DDERR_SURFACELOST ) {
464 lpBackBuffer->Restore();
466 ddrval = lpFrontBuffer->Blt( &dst_rect, lpBackBuffer, &src_rect, DDBLT_WAIT, 0 );
467 if ( ddrval == DDERR_SURFACELOST ) {
468 mprintf(( "Front surface lost... attempting to restore...\n" ));
469 os_sleep(1000); // Wait a second
471 } else if (ddrval != DD_OK ) {
472 mprintf(( "Flip failed! $%x\n", ddrval ));
477 if ( Grx_mouse_saved ) {
478 grx_restore_mouse_area();
485 void gr_directdraw_flip_window(uint _hdc, int x, int y, int w, int h )
489 void gr_directdraw_start_frame()
494 void gr_directdraw_stop_frame()
499 void gr_directdraw_set_palette_internal( ubyte * new_pal )
501 #ifndef HARDWARE_ONLY
502 PALETTEENTRY pe[256];
504 gr_directdraw_unlock();
507 for (i=0; i<256; i++ ) {
508 pe[i].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
509 pe[i].peRed = new_pal[i*3+0];
510 pe[i].peGreen = new_pal[i*3+1];
511 pe[i].peBlue = new_pal[i*3+2];
515 ddrval = lpPalette->SetEntries( 0, 0, 256, pe );
516 if ( ddrval != DD_OK ) {
517 mprintf(( "Error setting palette\n" ));
526 void gr_directdraw_set_palette( ubyte * new_pal, int restrict_alphacolor )
528 #ifndef HARDWARE_ONLY
529 if ( !restrict_alphacolor ) {
537 // Make sure color 0 is black
538 if ( (new_pal[0]!=0) || (new_pal[1]!=0) || (new_pal[2]!=0) ) {
539 // color 0 isn't black!! switch it!
541 int black_index = -1;
543 for (i=1; i<256; i++ ) {
544 if ( (new_pal[i*3+0]==0) && (new_pal[i*3+1]==0) && (new_pal[i*3+2]==0) ) {
549 if ( black_index > -1 ) {
550 // swap black and color 0, so color 0 is black
552 tmp[0] = new_pal[black_index*3+0];
553 tmp[1] = new_pal[black_index*3+1];
554 tmp[2] = new_pal[black_index*3+2];
556 new_pal[black_index*3+0] = new_pal[0];
557 new_pal[black_index*3+1] = new_pal[1];
558 new_pal[black_index*3+2] = new_pal[2];
564 // no black in palette, force color 0 to be black.
571 gr_directdraw_set_palette_internal( new_pal );
577 void gr_directdraw_flash( int r, int g, int b )
579 #ifndef HARDWARE_ONLY
583 if ( (r==0) && (b==0) && (g==0) ) {
589 for (i=0; i<256; i++ ) {
590 t = gr_palette[i*3+0] + r;
591 if ( t < 0 ) t = 0; else if (t>255) t = 255;
592 new_pal[i*3+0] = (ubyte)t;
594 t = gr_palette[i*3+1] + g;
595 if ( t < 0 ) t = 0; else if (t>255) t = 255;
596 new_pal[i*3+1] = (ubyte)t;
598 t = gr_palette[i*3+2] + b;
599 if ( t < 0 ) t = 0; else if (t>255) t = 255;
600 new_pal[i*3+2] = (ubyte)t;
603 gr_directdraw_set_palette_internal( new_pal );
610 static int gr_palette_faded_out = 0;
612 #define FADE_TIME (F1_0/4) // How long to fade out
614 void gr_directdraw_fade_out(int instantaneous)
616 #ifndef HARDWARE_ONLY
620 if (!gr_palette_faded_out) {
622 if ( !instantaneous ) {
625 fix start_time, stop_time, t1;
627 start_time = timer_get_fixed_seconds();
631 for (i=0; i<768; i++ ) {
632 int c = (gr_palette[i]*(FADE_TIME-t1))/FADE_TIME;
638 new_pal[i] = (ubyte)c;
640 gr_directdraw_set_palette_internal( new_pal );
643 t1 = timer_get_fixed_seconds() - start_time;
645 } while ( (t1 < FADE_TIME) && (t1>=0) ); // Loop as long as time not up and timer hasn't rolled
647 stop_time = timer_get_fixed_seconds();
649 mprintf(( "Took %d frames (and %.1f secs) to fade out\n", count, f2fl(stop_time-start_time) ));
652 gr_palette_faded_out = 1;
655 memset( new_pal, 0, 768 );
656 gr_directdraw_set_palette_internal( new_pal );
663 void gr_directdraw_fade_in(int instantaneous)
665 #ifndef HARDWARE_ONLY
669 if (gr_palette_faded_out) {
671 if ( !instantaneous ) {
673 fix start_time, stop_time, t1;
675 start_time = timer_get_fixed_seconds();
679 for (i=0; i<768; i++ ) {
680 int c = (gr_palette[i]*t1)/FADE_TIME;
686 new_pal[i] = (ubyte)c;
688 gr_directdraw_set_palette_internal( new_pal );
691 t1 = timer_get_fixed_seconds() - start_time;
693 } while ( (t1 < FADE_TIME) && (t1>=0) ); // Loop as long as time not up and timer hasn't rolled
695 stop_time = timer_get_fixed_seconds();
697 mprintf(( "Took %d frames (and %.1f secs) to fade in\n", count, f2fl(stop_time-start_time) ));
699 gr_palette_faded_out = 0;
702 memcpy( new_pal, gr_palette, 768 );
703 gr_directdraw_set_palette_internal( new_pal );
709 void gr_directdraw_get_region(int front, int w, int h, ubyte *data)
713 // sets the clipping region & offset
714 void gr_directdraw_set_clip(int x,int y,int w,int h)
716 #ifndef HARDWARE_ONLY
717 gr_screen.offset_x = x;
718 gr_screen.offset_y = y;
720 gr_screen.clip_left = 0;
721 gr_screen.clip_right = w-1;
723 gr_screen.clip_top = 0;
724 gr_screen.clip_bottom = h-1;
726 // check for sanity of parameters
727 if ( gr_screen.clip_left+x < 0 ) {
728 gr_screen.clip_left = -x;
729 } else if ( gr_screen.clip_left+x > gr_screen.max_w-1 ) {
730 gr_screen.clip_left = gr_screen.max_w-1-x;
732 if ( gr_screen.clip_right+x < 0 ) {
733 gr_screen.clip_right = -x;
734 } else if ( gr_screen.clip_right+x >= gr_screen.max_w-1 ) {
735 gr_screen.clip_right = gr_screen.max_w-1-x;
738 if ( gr_screen.clip_top+y < 0 ) {
739 gr_screen.clip_top = -y;
740 } else if ( gr_screen.clip_top+y > gr_screen.max_h-1 ) {
741 gr_screen.clip_top = gr_screen.max_h-1-y;
744 if ( gr_screen.clip_bottom+y < 0 ) {
745 gr_screen.clip_bottom = -y;
746 } else if ( gr_screen.clip_bottom+y > gr_screen.max_h-1 ) {
747 gr_screen.clip_bottom = gr_screen.max_h-1-y;
750 gr_screen.clip_width = gr_screen.clip_right - gr_screen.clip_left + 1;
751 gr_screen.clip_height = gr_screen.clip_bottom - gr_screen.clip_top + 1;
757 // resolution checking
758 int gr_directdraw_supports_res_ingame(int res)
763 int gr_directdraw_supports_res_interface(int res)
768 void gr_directdraw_set_cull(int cull)
772 // resets the clipping region to entire screen
774 // should call this before gr_surface_flip() if you clipped some portion of the screen but still
775 // want a full-screen display
776 void gr_directdraw_reset_clip()
778 #ifndef HARDWARE_ONLY
779 gr_screen.offset_x = 0;
780 gr_screen.offset_y = 0;
781 gr_screen.clip_left = 0;
782 gr_screen.clip_top = 0;
783 gr_screen.clip_right = gr_screen.max_w - 1;
784 gr_screen.clip_bottom = gr_screen.max_h - 1;
785 gr_screen.clip_width = gr_screen.max_w;
786 gr_screen.clip_height = gr_screen.max_h;
793 // Sets the current bitmap
794 void gr_directdraw_set_bitmap( int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha, int sx, int sy )
796 #ifndef HARDWARE_ONLY
797 gr_screen.current_alpha = alpha;
798 gr_screen.current_alphablend_mode = alphablend_mode;
799 gr_screen.current_bitblt_mode = bitblt_mode;
800 gr_screen.current_bitmap = bitmap_num;
801 gr_screen.current_bitmap_sx = sx;
802 gr_screen.current_bitmap_sy = sy;
808 // clears entire clipping region to black.
809 void gr_directdraw_clear()
811 #ifndef HARDWARE_ONLY
814 gr_directdraw_unlock();
818 ddBltFx.dwSize = sizeof(DDBLTFX);
819 ddBltFx.dwFillColor = 0;
822 lpBackBuffer->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddBltFx);
823 // ddBltFx.dwROP = BLACKNESS;
824 // lpBackBuffer->Blt(NULL, NULL, NULL, DDBLT_ROP, &ddBltFx);
834 w = gr_screen.clip_right-gr_screen.clip_left+1;
835 for (i=gr_screen.clip_top; i<=gr_screen.clip_bottom; i++) {
836 pDestBits = GR_SCREEN_PTR(ubyte,gr_screen.clip_left,i);
837 memset( pDestBits, 0, w );
840 gr_directdraw_unlock();
847 void gr_directdraw_force_windowed()
849 #ifndef HARDWARE_ONLY
850 gr_directdraw_unlock();
852 HWND hwnd = (HWND)os_get_window();
855 PostMessage(hwnd,WM_SYSKEYUP, 0x9, 0xa00f0001 );
856 PostMessage(hwnd,WM_SYSKEYUP, 0x12, 0xc0380001 );
858 // Wait a second to give things a change to settle down.
865 void gr_directdraw_cleanup()
867 #ifndef HARDWARE_ONLY
868 HWND hwnd = (HWND)os_get_window();
870 gr_directdraw_unlock();
873 lpPalette->Release();
878 lpClipper->Release();
883 lpBackBuffer->Release();
888 lpFrontBuffer->Release();
889 lpFrontBuffer = NULL;
893 // JAS: I took this out because my taskbar seems to get screwed up
894 // if I leave this in. Doesn't make sense, hence this comment.
895 HRESULT ddrval = lpDD->RestoreDisplayMode();
896 if( ddrval != DD_OK ) {
897 mprintf(( "WIN_DD32: RestoreDisplayMode failed (0x%x)\n", ddrval ));
899 ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL );
900 if( ddrval != DD_OK ) {
901 mprintf(( "WIN_DD32: SetCooperativeLevel W Failed (0x%x)\n", ddrval ));
915 void dd_get_shift_masks( DDSURFACEDESC *ddsd )
919 int r, red_shift, red_scale, red_mask;
920 int g, green_shift, green_scale, green_mask;
921 int b, blue_shift, blue_scale, blue_mask;
922 int a, alpha_shift, alpha_scale, alpha_mask;
924 if (gr_screen.bits_per_pixel == 8 ) {
928 Gr_red.mask = 0xff0000;
933 Gr_green.mask = 0xff00;
942 // Determine the red, green and blue masks' shift and scale.
943 for (s = 0, m = ddsd->ddpfPixelFormat.dwRBitMask; !(m & 1); s++, m >>= 1);
944 for (r = 0; m & 1; r++, m >>= 1);
946 red_scale = 255 / (ddsd->ddpfPixelFormat.dwRBitMask >> s);
947 red_mask = ddsd->ddpfPixelFormat.dwRBitMask;
949 for (s = 0, m = ddsd->ddpfPixelFormat.dwGBitMask; !(m & 1); s++, m >>= 1);
950 for (g = 0; m & 1; g++, m >>= 1);
952 green_scale = 255 / (ddsd->ddpfPixelFormat.dwGBitMask >> s);
953 green_mask = ddsd->ddpfPixelFormat.dwGBitMask;
955 for (s = 0, m = ddsd->ddpfPixelFormat.dwBBitMask; !(m & 1); s++, m >>= 1);
956 for (b = 0; m & 1; b++, m >>= 1);
958 blue_scale = 255 / (ddsd->ddpfPixelFormat.dwBBitMask >> s);
959 blue_mask = ddsd->ddpfPixelFormat.dwBBitMask;
961 if ( ddsd->ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS ) {
962 for (s = 0, m = ddsd->ddpfPixelFormat.dwRGBAlphaBitMask; !(m & 1); s++, m >>= 1);
963 for (a = 0; m & 1; a++, m >>= 1);
965 alpha_scale = 255 / (ddsd->ddpfPixelFormat.dwRGBAlphaBitMask >> s);
966 alpha_mask = ddsd->ddpfPixelFormat.dwRGBAlphaBitMask;
968 alpha_shift = a = alpha_scale = alpha_mask = 0;
971 // mprintf(( "Red Bits:%2d, Shift:%2d, Scale:%3d, Mask:$%08x\n", r, red_shift, red_scale, red_mask ));
972 // mprintf(( "Green Bits:%2d, Shift:%2d, Scale:%3d, Mask:$%08x\n", g, green_shift, green_scale, green_mask ));
973 // mprintf(( "Blue Bits:%2d, Shift:%2d, Scale:%3d, Mask:$%08x\n", b, blue_shift, blue_scale, blue_mask ));
974 // mprintf(( "Alpha Bits:%2d, Shift:%2d, Scale:%3d, Mask:$%08x\n", a, alpha_shift, alpha_scale, alpha_mask ));
976 // we need to set stuff up so that the high bit is always an alpha bit.
979 Gr_red.shift = red_shift;
980 Gr_red.scale = red_scale;
981 Gr_red.mask = red_mask;
984 Gr_green.shift = green_shift;
985 Gr_green.scale = green_scale;
986 Gr_green.mask = green_mask;
989 Gr_blue.shift = blue_shift;
990 Gr_blue.scale = blue_scale;
991 Gr_blue.mask = blue_mask;
995 void gr_directdraw_cross_fade(int bmap1, int bmap2, int x1, int y1, int x2, int y2, float pct)
998 gr_set_bitmap(bmap1);
1001 gr_set_bitmap(bmap2);
1007 void gr_directdraw_filter_set(int filter)
1012 void gr_directdraw_set_clear_color(int r, int g, int b)
1016 void gr_directdraw_init()
1018 #ifndef HARDWARE_ONLY
1022 Palette_flashed = 0;
1023 Palette_flashed_last_frame = 0;
1025 gr_screen.bits_per_pixel = 8;
1026 gr_screen.bytes_per_pixel = 1;
1028 Gr_dd_activated = 0;
1030 HWND hwnd = (HWND)os_get_window();
1033 mprintf(( "GR_SOFT_INIT: No window handle.\n" ));
1037 // Prepare the window to go full screen
1039 mprintf(( "Window in debugging mode... mouse clicking may cause problems!\n" ));
1040 SetWindowLong( hwnd, GWL_EXSTYLE, 0 );
1041 SetWindowLong( hwnd, GWL_STYLE, WS_POPUP );
1042 ShowWindow(hwnd, SW_SHOWNORMAL );
1044 SystemParametersInfo( SPI_GETWORKAREA, 0, &work_rect, 0 );
1045 SetWindowPos( hwnd, HWND_NOTOPMOST, work_rect.left, work_rect.top, gr_screen.max_w, gr_screen.max_h, 0 );
1046 SetActiveWindow(hwnd);
1047 SetForegroundWindow(hwnd);
1049 SetWindowLong( hwnd, GWL_EXSTYLE, 0 );
1050 SetWindowLong( hwnd, GWL_STYLE, WS_POPUP );
1051 ShowWindow(hwnd, SW_SHOWNORMAL );
1052 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ), 0 );
1053 SetActiveWindow(hwnd);
1054 SetForegroundWindow(hwnd);
1058 ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
1060 if ( ddrval != DD_OK ) {
1061 mprintf(( "GR_SOFT_INIT: DirectDrawCreate failed.\n" ));
1067 ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
1068 if ( ddrval != DD_OK ) {
1069 mprintf(( "GR_SOFT_INIT: SetCooperativeLevel EXCLUSIVE failed.\n" ));
1074 // Go to full screen!
1076 ddrval = lpDD->SetDisplayMode( gr_screen.max_w, gr_screen.max_h, gr_screen.bits_per_pixel );
1078 if ( ddrval != DD_OK ) {
1079 mprintf(( "GR_SOFT_INIT: SetDisplayMode failed.\n" ));
1090 memset( &ddsd, 0, sizeof( ddsd ));
1092 ddsd.dwSize = sizeof( ddsd );
1093 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1094 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
1095 ddsd.dwBackBufferCount = 2;
1097 ddrval = lpDD->CreateSurface( &ddsd, &lpFrontBuffer, NULL );
1098 if ( ddrval != DD_OK ) {
1099 mprintf(( "GR_SOFT_INIT: CreateSurface (Front) failed.\n" ));
1104 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
1106 ddrval = lpFrontBuffer->GetAttachedSurface( &ddscaps, &lpBackBuffer );
1107 if ( ddrval != DD_OK ) {
1108 mprintf(( "GR_SOFT_INIT: GetAttachedSurface (Back) failed.\n" ));
1116 memset( &ddsd, 0, sizeof( ddsd ) );
1118 ddsd.dwSize = sizeof( ddsd );
1119 ddsd.dwFlags = DDSD_CAPS;
1120 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1122 ddrval = lpDD->CreateSurface( &ddsd, &lpFrontBuffer, NULL );
1123 if ( ddrval != DD_OK ) {
1124 mprintf(( "GR_SOFT_INIT: CreateSurface (Front) failed.\n" ));
1129 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
1130 ddsd.dwWidth = gr_screen.max_w;
1131 ddsd.dwHeight = gr_screen.max_h;
1132 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1134 // If debugging we have to create our surfaces in system memory
1135 // so that our debugger isn't hosed when locking surfaces.
1137 //ddsd.ddsCaps.dwCaps |= DDSCAPS_NONLOCALVIDMEM;
1138 ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
1140 // create the back buffer
1141 ddrval = lpDD->CreateSurface( &ddsd, &lpBackBuffer , NULL );
1142 if ( ddrval != DD_OK ) {
1143 mprintf(( "GR_SOFT_INIT: CreateSurface (Back) failed.\n" ));
1147 // create a clipper and attach it to our window
1148 ddrval = lpDD->CreateClipper( 0, &lpClipper, NULL );
1149 if ( ddrval != DD_OK ) {
1150 mprintf(( "GR_SOFT_INIT: CreateClipper failed.\n" ));
1155 ddrval = lpClipper->SetHWnd( 0, hwnd );
1156 if ( ddrval != DD_OK ) {
1157 mprintf(( "GR_SOFT_INIT: SetHWnd failed.\n" ));
1162 ddrval = lpFrontBuffer->SetClipper( lpClipper );
1163 if ( ddrval != DD_OK ) {
1164 mprintf(( "GR_SOFT_INIT: SetClipper failed.\n" ));
1170 PALETTEENTRY pe[256];
1171 for (i=0; i<256; i++ ) {
1172 pe[i].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
1177 ddrval = lpDD->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &lpPalette, NULL);
1178 if (ddrval != DD_OK) {
1179 mprintf(( "Error creating palette\n" ));
1183 ddrval = lpFrontBuffer->SetPalette( lpPalette );
1184 if (ddrval != DD_OK) {
1185 mprintf(( "Error setting palette in gr_directdraw_set_palette\n" ));
1189 memset( &ddsd, 0, sizeof( ddsd ) );
1190 ddsd.dwSize = sizeof(ddsd);
1191 lpFrontBuffer->GetSurfaceDesc(&ddsd);
1192 dd_get_shift_masks( &ddsd );
1194 mprintf(( "Surfaces created...\n" ));
1206 grx_init_alphacolors();
1208 gr_screen.gf_flip = gr_directdraw_flip;
1209 gr_screen.gf_flip_window = gr_directdraw_flip_window;
1210 gr_screen.gf_set_clip = gr_directdraw_set_clip;
1211 gr_screen.gf_reset_clip = gr_directdraw_reset_clip;
1212 gr_screen.gf_set_font = grx_set_font;
1213 gr_screen.gf_set_color = grx_set_color;
1214 gr_screen.gf_set_bitmap = gr_directdraw_set_bitmap;
1215 gr_screen.gf_create_shader = grx_create_shader;
1216 gr_screen.gf_set_shader = grx_set_shader;
1217 gr_screen.gf_clear = gr_directdraw_clear;
1218 // gr_screen.gf_bitmap = grx_bitmap;
1219 // gr_screen.gf_bitmap_ex = grx_bitmap_ex;
1221 gr_screen.gf_aabitmap = grx_aabitmap;
1222 gr_screen.gf_aabitmap_ex = grx_aabitmap_ex;
1224 gr_screen.gf_rect = grx_rect;
1225 gr_screen.gf_shade = gr8_shade;
1226 gr_screen.gf_string = gr8_string;
1227 gr_screen.gf_circle = gr8_circle;
1229 gr_screen.gf_line = gr8_line;
1230 gr_screen.gf_aaline = gr8_aaline;
1231 gr_screen.gf_pixel = gr8_pixel;
1232 gr_screen.gf_scaler = gr8_scaler;
1233 gr_screen.gf_aascaler = gr8_aascaler;
1234 gr_screen.gf_tmapper = grx_tmapper;
1236 gr_screen.gf_gradient = gr8_gradient;
1238 gr_screen.gf_set_palette = gr_directdraw_set_palette;
1239 gr_screen.gf_get_color = grx_get_color;
1240 gr_screen.gf_init_color = grx_init_color;
1241 gr_screen.gf_init_alphacolor = grx_init_alphacolor;
1242 gr_screen.gf_set_color_fast = grx_set_color_fast;
1243 gr_screen.gf_print_screen = grx_print_screen;
1245 gr_screen.gf_start_frame = gr_directdraw_start_frame;
1246 gr_screen.gf_stop_frame = gr_directdraw_stop_frame;
1248 gr_screen.gf_fade_in = gr_directdraw_fade_in;
1249 gr_screen.gf_fade_out = gr_directdraw_fade_out;
1250 gr_screen.gf_flash = gr_directdraw_flash;
1252 // Retrieves the zbuffer mode.
1253 gr_screen.gf_zbuffer_get = gr8_zbuffer_get;
1254 gr_screen.gf_zbuffer_set = gr8_zbuffer_set;
1255 gr_screen.gf_zbuffer_clear = gr8_zbuffer_clear;
1257 gr_screen.gf_save_screen = gr8_save_screen;
1258 gr_screen.gf_restore_screen = gr8_restore_screen;
1259 gr_screen.gf_free_screen = gr8_free_screen;
1261 // Screen dumping stuff
1262 gr_screen.gf_dump_frame_start = gr8_dump_frame_start;
1263 gr_screen.gf_dump_frame_stop = gr8_dump_frame_stop;
1264 gr_screen.gf_dump_frame = gr8_dump_frame;
1267 gr_screen.gf_set_gamma = gr8_set_gamma;
1269 // Lock/unlock stuff
1270 gr_screen.gf_lock = gr_directdraw_lock;
1271 gr_screen.gf_unlock = gr_directdraw_unlock_fake;
1274 gr_screen.gf_get_region = gr_directdraw_get_region;
1277 gr_screen.gf_set_cull = gr_directdraw_set_cull;
1280 gr_screen.gf_cross_fade = gr_directdraw_cross_fade;
1283 gr_screen.gf_filter_set = gr_directdraw_filter_set;
1286 gr_screen.gf_set_clear_color = gr_directdraw_set_clear_color;
1290 mprintf(( "Surfaces locked...\n" ));