2 * $Logfile: /Freespace2/code/Graphics/GrDirectDraw.cpp $
7 * Code for software 8-bpp rendering using DirectDraw
10 * Revision 1.2 2002/05/07 03:16:45 theoddone33
11 * The Great Newline Fix
13 * Revision 1.1.1.1 2002/05/03 03:28:09 root
17 * 9 7/14/99 9:42a Dave
18 * Put in clear_color debug function. Put in base for 3dnow stuff / P3
21 * 8 6/29/99 10:35a Dave
22 * Interface polygon bitmaps! Whee!
24 * 7 2/03/99 11:44a Dave
25 * Fixed d3d transparent textures.
27 * 6 1/24/99 11:37p Dave
28 * First full rev of beam weapons. Very customizable. Removed some bogus
29 * Int3()'s in low level net code.
31 * 5 12/18/98 1:13a Dave
32 * Rough 1024x768 support for Direct3D. Proper detection and usage through
35 * 4 12/06/98 2:36p Dave
36 * Drastically improved nebula fogging.
38 * 3 11/30/98 1:07p Dave
39 * 16 bit conversion, first run.
41 * 2 10/07/98 10:52a Dave
44 * 1 10/07/98 10:49a Dave
46 * 17 5/22/98 10:28p John
47 * Made software movies not click your monitor when switching to 16-bpp.
48 * Total hack around my restrictive code, but at this point...
50 * 16 5/20/98 9:45p John
51 * added code so the places in code that change half the palette don't
52 * have to clear the screen.
54 * 15 5/17/98 5:03p John
55 * Fixed some bugs that make the taskbar interfere with the DEBUG-only
58 * 14 5/16/98 1:18p John
59 * Made softtware DirectDraw reset palette after Alt+TAB.
61 * 13 5/15/98 9:34p John
62 * Removed the initial ugly little cursor part that drew right at program
65 * 12 5/14/98 5:42p John
66 * Revamped the whole window position/mouse code for the graphics windows.
68 * 11 5/12/98 8:15a John
69 * Made dd code not print out rgb surface info.
71 * 10 5/07/98 6:58p Hoffoss
72 * Made changes to mouse code to fix a number of problems.
74 * 9 5/06/98 5:30p John
75 * Removed unused cfilearchiver. Removed/replaced some unused/little used
76 * graphics functions, namely gradient_h and _v and pixel_sp. Put in new
77 * DirectX header files and libs that fixed the Direct3D alpha blending
80 * 8 4/23/98 8:24a John
81 * Changed the way palette effect works so that:
82 * 1. If gr_flash isn't called this frame, screen shows no flash.
83 * 2. With hardware, only 3d portion of screen gets flashed.
85 * 7 4/21/98 5:22p John
86 * Fixed all the &^#@$ cursor bugs with popups. For Glide, had problem
87 * with mouse restoring assuming back buffer was same buffer last frame,
88 * for software, problems with half drawn new frames, then mouse got
89 * restored on top of that with old data.
91 * 6 4/17/98 3:56p Mike
92 * Fix palette trashing on MK's computer when he Alt-Tabs out of FreeSpace
93 * in software. At John's suggestion.
95 * 5 4/14/98 12:15p John
96 * Made 16-bpp movies work.
98 * 4 4/13/98 8:08p John
99 * Made surface restoration also restore the palette.
101 * 3 4/09/98 6:56p John
102 * Put in better code to restore surfaces when restoring them. Worth a
103 * try for an Interplay QA bug I can't find.
105 * 2 4/09/98 11:05a John
106 * Removed all traces of Direct3D out of the demo version of Freespace and
109 * 1 3/25/98 8:07p John
110 * Split software renderer into Win32 and DirectX
117 #include <windowsx.h>
125 #include "floating.h"
128 #include "grinternal.h"
130 // Headers for 2d functions
138 #include "gradient.h"
139 #include "pcxutils.h"
146 #include "grzbuffer.h"
148 static LPDIRECTDRAW lpDD = NULL;
149 static LPDIRECTDRAWSURFACE lpBackBuffer = NULL;
150 static LPDIRECTDRAWSURFACE lpFrontBuffer = NULL;
151 static LPDIRECTDRAWCLIPPER lpClipper = NULL;
152 static LPDIRECTDRAWPALETTE lpPalette = NULL;
154 void gr_directdraw_unlock();
155 void gr_directdraw_set_palette_internal( ubyte * new_pal );
157 void directdraw_clear_all_vram()
159 #ifndef HARDWARE_ONLY
162 LPDIRECTDRAWSURFACE buffer[16];
166 for (i=0; i<16; i++ ) {
167 memset( &ddsd, 0, sizeof( ddsd ) );
169 ddsd.dwSize = sizeof( ddsd );
170 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
171 ddsd.dwWidth = gr_screen.max_w;
172 ddsd.dwHeight = gr_screen.max_h;
173 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
175 // create the back buffer
176 ddrval = lpDD->CreateSurface( &ddsd, &buffer[i], NULL );
177 if ( ddrval == DD_OK ) {
181 memset(&ddBltFx, 0, sizeof(DDBLTFX));
182 ddBltFx.dwSize = sizeof(DDBLTFX);
183 ddBltFx.dwFillColor = 0;
185 buffer[i]->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddBltFx);
194 for (i=0; i<num_buffers; i++ ) {
195 buffer[i]->Release();
202 LPDIRECTDRAW gr_directdraw_start_mve()
204 #ifndef HARDWARE_ONLY
206 memset( tmp_pal, 0, 768 );
208 gr_directdraw_set_palette_internal(tmp_pal);
210 // clear both buffers
219 gr_directdraw_unlock();
221 // Clear all of VRAM...
222 directdraw_clear_all_vram();
225 lpPalette->Release();
230 lpFrontBuffer->Release();
231 lpFrontBuffer = NULL;
243 void gr_directdraw_stop_mve()
245 #ifndef HARDWARE_ONLY
249 memset( &ddsd, 0, sizeof( ddsd ) );
251 ddsd.dwSize = sizeof( ddsd );
252 ddsd.dwFlags = DDSD_CAPS;
253 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
255 ddrval = lpDD->CreateSurface( &ddsd, &lpFrontBuffer, NULL );
256 if ( ddrval != DD_OK ) {
257 mprintf(( "GR_SOFT_INIT: CreateSurface (Front) failed.\n" ));
263 PALETTEENTRY pe[256];
264 for (i=0; i<256; i++ ) {
265 pe[i].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
266 pe[i].peRed = gr_palette[i*3+0];
267 pe[i].peGreen = gr_palette[i*3+1];
268 pe[i].peBlue = gr_palette[i*3+2];
271 ddrval = lpDD->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &lpPalette, NULL);
272 if (ddrval != DD_OK) {
273 mprintf(( "Error creating palette\n" ));
276 ddrval = lpFrontBuffer->SetPalette( lpPalette );
277 if (ddrval != DD_OK) {
278 mprintf(( "Error setting palette in gr_directdraw_set_palette\n" ));
291 static int Locked = 0;
293 uint gr_directdraw_lock()
295 #ifndef HARDWARE_ONLY
301 memset( &ddsd, 0, sizeof( ddsd ) );
302 ddsd.dwSize = sizeof( ddsd );
304 ddrval = lpBackBuffer->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
305 if ( ddrval != DD_OK ) {
306 mprintf(( "Error locking surface in gr_d3d_lock\n" ));
307 gr_screen.offscreen_buffer_base = NULL; //(void *)fake_vram;
308 gr_screen.rowsize = 0;
309 gr_screen.offscreen_buffer = gr_screen.offscreen_buffer_base;
311 gr_screen.offscreen_buffer_base = (void *)ddsd.lpSurface;
312 gr_screen.rowsize = ddsd.lPitch;
313 gr_screen.offscreen_buffer = gr_screen.offscreen_buffer_base;
325 void gr_directdraw_unlock()
327 #ifndef HARDWARE_ONLY
329 // Unlock the back buffer
330 lpBackBuffer->Unlock( NULL );
338 void gr_directdraw_unlock_fake()
343 static int Palette_flashed = 0;
344 static int Palette_flashed_last_frame = 0;
347 static volatile int Gr_dd_activated = 0;
349 void gr_dd_activate(int active)
351 #ifndef HARDWARE_ONLY
361 void gr_directdraw_flip()
363 #ifndef HARDWARE_ONLY
364 if ( Gr_dd_activated || ((!Palette_flashed) && (Palette_flashed_last_frame)) ) {
366 gr_directdraw_set_palette_internal( gr_palette );
370 Palette_flashed_last_frame = Palette_flashed;
377 Grx_mouse_saved = 0; // assume not saved
380 if ( mouse_is_visible() ) {
382 mouse_get_pos( &mx, &my );
383 grx_save_mouse_area(mx,my,32,32);
384 if ( Gr_cursor == -1 ) {
385 gr_set_color(255,255,255);
386 gr_line( mx, my, mx+7, my + 7 );
387 gr_line( mx, my, mx+5, my );
388 gr_line( mx, my, mx, my+5 );
390 gr_set_bitmap(Gr_cursor);
395 gr_directdraw_unlock();
400 if ( lpFrontBuffer->IsLost() == DDERR_SURFACELOST ) {
401 lpFrontBuffer->Restore();
402 ddrval = lpFrontBuffer->SetPalette( lpPalette );
403 if (ddrval != DD_OK) {
404 mprintf(( "Error setting palette after restore\n" ));
407 if ( lpBackBuffer->IsLost() == DDERR_SURFACELOST ) {
408 lpBackBuffer->Restore();
411 HRESULT ddrval = lpFrontBuffer->Flip( NULL, DDFLIP_WAIT );
412 if ( ddrval == DDERR_SURFACELOST ) {
413 mprintf(( "Front surface lost... attempting to restore...\n" ));
414 os_sleep(1000); // Wait a second
416 } else if (ddrval != DD_OK ) {
417 mprintf(( "Fullscreen flip failed!\n" ));
421 RECT src_rect, dst_rect;
425 HWND hWnd = (HWND)os_get_window();
428 // src_rect is relative to offscreen buffer
429 GetClientRect( hWnd, &src_rect );
431 // dst_rect is relative to screen space so needs translation
433 ClientToScreen( hWnd, &pt );
435 dst_rect.left += pt.x;
436 dst_rect.right += pt.x;
437 dst_rect.top += pt.y;
438 dst_rect.bottom += pt.y;
440 // perform the blit from backbuffer to primary, using
441 // src_rect and dst_rect
444 if ( lpFrontBuffer->IsLost() == DDERR_SURFACELOST ) {
445 lpFrontBuffer->Restore();
447 /* ddrval = lpFrontBuffer->SetPalette( lpPalette );
448 if (ddrval != DD_OK) {
449 mprintf(( "Error setting palette after restore\n" ));
452 if ( lpBackBuffer->IsLost() == DDERR_SURFACELOST ) {
453 lpBackBuffer->Restore();
455 ddrval = lpFrontBuffer->Blt( &dst_rect, lpBackBuffer, &src_rect, DDBLT_WAIT, 0 );
456 if ( ddrval == DDERR_SURFACELOST ) {
457 mprintf(( "Front surface lost... attempting to restore...\n" ));
458 os_sleep(1000); // Wait a second
460 } else if (ddrval != DD_OK ) {
461 mprintf(( "Flip failed! $%x\n", ddrval ));
466 if ( Grx_mouse_saved ) {
467 grx_restore_mouse_area();
474 void gr_directdraw_flip_window(uint _hdc, int x, int y, int w, int h )
478 void gr_directdraw_start_frame()
483 void gr_directdraw_stop_frame()
488 void gr_directdraw_set_palette_internal( ubyte * new_pal )
490 #ifndef HARDWARE_ONLY
491 PALETTEENTRY pe[256];
493 gr_directdraw_unlock();
496 for (i=0; i<256; i++ ) {
497 pe[i].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
498 pe[i].peRed = new_pal[i*3+0];
499 pe[i].peGreen = new_pal[i*3+1];
500 pe[i].peBlue = new_pal[i*3+2];
504 ddrval = lpPalette->SetEntries( 0, 0, 256, pe );
505 if ( ddrval != DD_OK ) {
506 mprintf(( "Error setting palette\n" ));
515 void gr_directdraw_set_palette( ubyte * new_pal, int restrict_alphacolor )
517 #ifndef HARDWARE_ONLY
518 if ( !restrict_alphacolor ) {
526 // Make sure color 0 is black
527 if ( (new_pal[0]!=0) || (new_pal[1]!=0) || (new_pal[2]!=0) ) {
528 // color 0 isn't black!! switch it!
530 int black_index = -1;
532 for (i=1; i<256; i++ ) {
533 if ( (new_pal[i*3+0]==0) && (new_pal[i*3+1]==0) && (new_pal[i*3+2]==0) ) {
538 if ( black_index > -1 ) {
539 // swap black and color 0, so color 0 is black
541 tmp[0] = new_pal[black_index*3+0];
542 tmp[1] = new_pal[black_index*3+1];
543 tmp[2] = new_pal[black_index*3+2];
545 new_pal[black_index*3+0] = new_pal[0];
546 new_pal[black_index*3+1] = new_pal[1];
547 new_pal[black_index*3+2] = new_pal[2];
553 // no black in palette, force color 0 to be black.
560 gr_directdraw_set_palette_internal( new_pal );
566 void gr_directdraw_flash( int r, int g, int b )
568 #ifndef HARDWARE_ONLY
572 if ( (r==0) && (b==0) && (g==0) ) {
578 for (i=0; i<256; i++ ) {
579 t = gr_palette[i*3+0] + r;
580 if ( t < 0 ) t = 0; else if (t>255) t = 255;
581 new_pal[i*3+0] = (ubyte)t;
583 t = gr_palette[i*3+1] + g;
584 if ( t < 0 ) t = 0; else if (t>255) t = 255;
585 new_pal[i*3+1] = (ubyte)t;
587 t = gr_palette[i*3+2] + b;
588 if ( t < 0 ) t = 0; else if (t>255) t = 255;
589 new_pal[i*3+2] = (ubyte)t;
592 gr_directdraw_set_palette_internal( new_pal );
599 static int gr_palette_faded_out = 0;
601 #define FADE_TIME (F1_0/4) // How long to fade out
603 void gr_directdraw_fade_out(int instantaneous)
605 #ifndef HARDWARE_ONLY
609 if (!gr_palette_faded_out) {
611 if ( !instantaneous ) {
614 fix start_time, stop_time, t1;
616 start_time = timer_get_fixed_seconds();
620 for (i=0; i<768; i++ ) {
621 int c = (gr_palette[i]*(FADE_TIME-t1))/FADE_TIME;
627 new_pal[i] = (ubyte)c;
629 gr_directdraw_set_palette_internal( new_pal );
632 t1 = timer_get_fixed_seconds() - start_time;
634 } while ( (t1 < FADE_TIME) && (t1>=0) ); // Loop as long as time not up and timer hasn't rolled
636 stop_time = timer_get_fixed_seconds();
638 mprintf(( "Took %d frames (and %.1f secs) to fade out\n", count, f2fl(stop_time-start_time) ));
641 gr_palette_faded_out = 1;
644 memset( new_pal, 0, 768 );
645 gr_directdraw_set_palette_internal( new_pal );
652 void gr_directdraw_fade_in(int instantaneous)
654 #ifndef HARDWARE_ONLY
658 if (gr_palette_faded_out) {
660 if ( !instantaneous ) {
662 fix start_time, stop_time, t1;
664 start_time = timer_get_fixed_seconds();
668 for (i=0; i<768; i++ ) {
669 int c = (gr_palette[i]*t1)/FADE_TIME;
675 new_pal[i] = (ubyte)c;
677 gr_directdraw_set_palette_internal( new_pal );
680 t1 = timer_get_fixed_seconds() - start_time;
682 } while ( (t1 < FADE_TIME) && (t1>=0) ); // Loop as long as time not up and timer hasn't rolled
684 stop_time = timer_get_fixed_seconds();
686 mprintf(( "Took %d frames (and %.1f secs) to fade in\n", count, f2fl(stop_time-start_time) ));
688 gr_palette_faded_out = 0;
691 memcpy( new_pal, gr_palette, 768 );
692 gr_directdraw_set_palette_internal( new_pal );
698 void gr_directdraw_get_region(int front, int w, int h, ubyte *data)
702 // sets the clipping region & offset
703 void gr_directdraw_set_clip(int x,int y,int w,int h)
705 #ifndef HARDWARE_ONLY
706 gr_screen.offset_x = x;
707 gr_screen.offset_y = y;
709 gr_screen.clip_left = 0;
710 gr_screen.clip_right = w-1;
712 gr_screen.clip_top = 0;
713 gr_screen.clip_bottom = h-1;
715 // check for sanity of parameters
716 if ( gr_screen.clip_left+x < 0 ) {
717 gr_screen.clip_left = -x;
718 } else if ( gr_screen.clip_left+x > gr_screen.max_w-1 ) {
719 gr_screen.clip_left = gr_screen.max_w-1-x;
721 if ( gr_screen.clip_right+x < 0 ) {
722 gr_screen.clip_right = -x;
723 } else if ( gr_screen.clip_right+x >= gr_screen.max_w-1 ) {
724 gr_screen.clip_right = gr_screen.max_w-1-x;
727 if ( gr_screen.clip_top+y < 0 ) {
728 gr_screen.clip_top = -y;
729 } else if ( gr_screen.clip_top+y > gr_screen.max_h-1 ) {
730 gr_screen.clip_top = gr_screen.max_h-1-y;
733 if ( gr_screen.clip_bottom+y < 0 ) {
734 gr_screen.clip_bottom = -y;
735 } else if ( gr_screen.clip_bottom+y > gr_screen.max_h-1 ) {
736 gr_screen.clip_bottom = gr_screen.max_h-1-y;
739 gr_screen.clip_width = gr_screen.clip_right - gr_screen.clip_left + 1;
740 gr_screen.clip_height = gr_screen.clip_bottom - gr_screen.clip_top + 1;
746 // resolution checking
747 int gr_directdraw_supports_res_ingame(int res)
752 int gr_directdraw_supports_res_interface(int res)
757 void gr_directdraw_set_cull(int cull)
761 // resets the clipping region to entire screen
763 // should call this before gr_surface_flip() if you clipped some portion of the screen but still
764 // want a full-screen display
765 void gr_directdraw_reset_clip()
767 #ifndef HARDWARE_ONLY
768 gr_screen.offset_x = 0;
769 gr_screen.offset_y = 0;
770 gr_screen.clip_left = 0;
771 gr_screen.clip_top = 0;
772 gr_screen.clip_right = gr_screen.max_w - 1;
773 gr_screen.clip_bottom = gr_screen.max_h - 1;
774 gr_screen.clip_width = gr_screen.max_w;
775 gr_screen.clip_height = gr_screen.max_h;
782 // Sets the current bitmap
783 void gr_directdraw_set_bitmap( int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha, int sx, int sy )
785 #ifndef HARDWARE_ONLY
786 gr_screen.current_alpha = alpha;
787 gr_screen.current_alphablend_mode = alphablend_mode;
788 gr_screen.current_bitblt_mode = bitblt_mode;
789 gr_screen.current_bitmap = bitmap_num;
790 gr_screen.current_bitmap_sx = sx;
791 gr_screen.current_bitmap_sy = sy;
797 // clears entire clipping region to black.
798 void gr_directdraw_clear()
800 #ifndef HARDWARE_ONLY
803 gr_directdraw_unlock();
807 ddBltFx.dwSize = sizeof(DDBLTFX);
808 ddBltFx.dwFillColor = 0;
811 lpBackBuffer->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddBltFx);
812 // ddBltFx.dwROP = BLACKNESS;
813 // lpBackBuffer->Blt(NULL, NULL, NULL, DDBLT_ROP, &ddBltFx);
823 w = gr_screen.clip_right-gr_screen.clip_left+1;
824 for (i=gr_screen.clip_top; i<=gr_screen.clip_bottom; i++) {
825 pDestBits = GR_SCREEN_PTR(ubyte,gr_screen.clip_left,i);
826 memset( pDestBits, 0, w );
829 gr_directdraw_unlock();
836 void gr_directdraw_force_windowed()
838 #ifndef HARDWARE_ONLY
839 gr_directdraw_unlock();
841 HWND hwnd = (HWND)os_get_window();
844 PostMessage(hwnd,WM_SYSKEYUP, 0x9, 0xa00f0001 );
845 PostMessage(hwnd,WM_SYSKEYUP, 0x12, 0xc0380001 );
847 // Wait a second to give things a change to settle down.
854 void gr_directdraw_cleanup()
856 #ifndef HARDWARE_ONLY
857 HWND hwnd = (HWND)os_get_window();
859 gr_directdraw_unlock();
862 lpPalette->Release();
867 lpClipper->Release();
872 lpBackBuffer->Release();
877 lpFrontBuffer->Release();
878 lpFrontBuffer = NULL;
882 // JAS: I took this out because my taskbar seems to get screwed up
883 // if I leave this in. Doesn't make sense, hence this comment.
884 HRESULT ddrval = lpDD->RestoreDisplayMode();
885 if( ddrval != DD_OK ) {
886 mprintf(( "WIN_DD32: RestoreDisplayMode failed (0x%x)\n", ddrval ));
888 ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL );
889 if( ddrval != DD_OK ) {
890 mprintf(( "WIN_DD32: SetCooperativeLevel W Failed (0x%x)\n", ddrval ));
904 void dd_get_shift_masks( DDSURFACEDESC *ddsd )
908 int r, red_shift, red_scale, red_mask;
909 int g, green_shift, green_scale, green_mask;
910 int b, blue_shift, blue_scale, blue_mask;
911 int a, alpha_shift, alpha_scale, alpha_mask;
913 if (gr_screen.bits_per_pixel == 8 ) {
917 Gr_red.mask = 0xff0000;
922 Gr_green.mask = 0xff00;
931 // Determine the red, green and blue masks' shift and scale.
932 for (s = 0, m = ddsd->ddpfPixelFormat.dwRBitMask; !(m & 1); s++, m >>= 1);
933 for (r = 0; m & 1; r++, m >>= 1);
935 red_scale = 255 / (ddsd->ddpfPixelFormat.dwRBitMask >> s);
936 red_mask = ddsd->ddpfPixelFormat.dwRBitMask;
938 for (s = 0, m = ddsd->ddpfPixelFormat.dwGBitMask; !(m & 1); s++, m >>= 1);
939 for (g = 0; m & 1; g++, m >>= 1);
941 green_scale = 255 / (ddsd->ddpfPixelFormat.dwGBitMask >> s);
942 green_mask = ddsd->ddpfPixelFormat.dwGBitMask;
944 for (s = 0, m = ddsd->ddpfPixelFormat.dwBBitMask; !(m & 1); s++, m >>= 1);
945 for (b = 0; m & 1; b++, m >>= 1);
947 blue_scale = 255 / (ddsd->ddpfPixelFormat.dwBBitMask >> s);
948 blue_mask = ddsd->ddpfPixelFormat.dwBBitMask;
950 if ( ddsd->ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS ) {
951 for (s = 0, m = ddsd->ddpfPixelFormat.dwRGBAlphaBitMask; !(m & 1); s++, m >>= 1);
952 for (a = 0; m & 1; a++, m >>= 1);
954 alpha_scale = 255 / (ddsd->ddpfPixelFormat.dwRGBAlphaBitMask >> s);
955 alpha_mask = ddsd->ddpfPixelFormat.dwRGBAlphaBitMask;
957 alpha_shift = a = alpha_scale = alpha_mask = 0;
960 // mprintf(( "Red Bits:%2d, Shift:%2d, Scale:%3d, Mask:$%08x\n", r, red_shift, red_scale, red_mask ));
961 // mprintf(( "Green Bits:%2d, Shift:%2d, Scale:%3d, Mask:$%08x\n", g, green_shift, green_scale, green_mask ));
962 // mprintf(( "Blue Bits:%2d, Shift:%2d, Scale:%3d, Mask:$%08x\n", b, blue_shift, blue_scale, blue_mask ));
963 // mprintf(( "Alpha Bits:%2d, Shift:%2d, Scale:%3d, Mask:$%08x\n", a, alpha_shift, alpha_scale, alpha_mask ));
965 // we need to set stuff up so that the high bit is always an alpha bit.
968 Gr_red.shift = red_shift;
969 Gr_red.scale = red_scale;
970 Gr_red.mask = red_mask;
973 Gr_green.shift = green_shift;
974 Gr_green.scale = green_scale;
975 Gr_green.mask = green_mask;
978 Gr_blue.shift = blue_shift;
979 Gr_blue.scale = blue_scale;
980 Gr_blue.mask = blue_mask;
984 void gr_directdraw_cross_fade(int bmap1, int bmap2, int x1, int y1, int x2, int y2, float pct)
987 gr_set_bitmap(bmap1);
990 gr_set_bitmap(bmap2);
996 void gr_directdraw_filter_set(int filter)
1001 void gr_directdraw_set_clear_color(int r, int g, int b)
1005 void gr_directdraw_init()
1007 #ifndef HARDWARE_ONLY
1011 Palette_flashed = 0;
1012 Palette_flashed_last_frame = 0;
1014 gr_screen.bits_per_pixel = 8;
1015 gr_screen.bytes_per_pixel = 1;
1017 Gr_dd_activated = 0;
1019 HWND hwnd = (HWND)os_get_window();
1022 mprintf(( "GR_SOFT_INIT: No window handle.\n" ));
1026 // Prepare the window to go full screen
1028 mprintf(( "Window in debugging mode... mouse clicking may cause problems!\n" ));
1029 SetWindowLong( hwnd, GWL_EXSTYLE, 0 );
1030 SetWindowLong( hwnd, GWL_STYLE, WS_POPUP );
1031 ShowWindow(hwnd, SW_SHOWNORMAL );
1033 SystemParametersInfo( SPI_GETWORKAREA, 0, &work_rect, 0 );
1034 SetWindowPos( hwnd, HWND_NOTOPMOST, work_rect.left, work_rect.top, gr_screen.max_w, gr_screen.max_h, 0 );
1035 SetActiveWindow(hwnd);
1036 SetForegroundWindow(hwnd);
1038 SetWindowLong( hwnd, GWL_EXSTYLE, 0 );
1039 SetWindowLong( hwnd, GWL_STYLE, WS_POPUP );
1040 ShowWindow(hwnd, SW_SHOWNORMAL );
1041 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ), 0 );
1042 SetActiveWindow(hwnd);
1043 SetForegroundWindow(hwnd);
1047 ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
1049 if ( ddrval != DD_OK ) {
1050 mprintf(( "GR_SOFT_INIT: DirectDrawCreate failed.\n" ));
1056 ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
1057 if ( ddrval != DD_OK ) {
1058 mprintf(( "GR_SOFT_INIT: SetCooperativeLevel EXCLUSIVE failed.\n" ));
1063 // Go to full screen!
1065 ddrval = lpDD->SetDisplayMode( gr_screen.max_w, gr_screen.max_h, gr_screen.bits_per_pixel );
1067 if ( ddrval != DD_OK ) {
1068 mprintf(( "GR_SOFT_INIT: SetDisplayMode failed.\n" ));
1079 memset( &ddsd, 0, sizeof( ddsd ));
1081 ddsd.dwSize = sizeof( ddsd );
1082 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1083 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
1084 ddsd.dwBackBufferCount = 2;
1086 ddrval = lpDD->CreateSurface( &ddsd, &lpFrontBuffer, NULL );
1087 if ( ddrval != DD_OK ) {
1088 mprintf(( "GR_SOFT_INIT: CreateSurface (Front) failed.\n" ));
1093 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
1095 ddrval = lpFrontBuffer->GetAttachedSurface( &ddscaps, &lpBackBuffer );
1096 if ( ddrval != DD_OK ) {
1097 mprintf(( "GR_SOFT_INIT: GetAttachedSurface (Back) failed.\n" ));
1105 memset( &ddsd, 0, sizeof( ddsd ) );
1107 ddsd.dwSize = sizeof( ddsd );
1108 ddsd.dwFlags = DDSD_CAPS;
1109 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1111 ddrval = lpDD->CreateSurface( &ddsd, &lpFrontBuffer, NULL );
1112 if ( ddrval != DD_OK ) {
1113 mprintf(( "GR_SOFT_INIT: CreateSurface (Front) failed.\n" ));
1118 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
1119 ddsd.dwWidth = gr_screen.max_w;
1120 ddsd.dwHeight = gr_screen.max_h;
1121 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1123 // If debugging we have to create our surfaces in system memory
1124 // so that our debugger isn't hosed when locking surfaces.
1126 //ddsd.ddsCaps.dwCaps |= DDSCAPS_NONLOCALVIDMEM;
1127 ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
1129 // create the back buffer
1130 ddrval = lpDD->CreateSurface( &ddsd, &lpBackBuffer , NULL );
1131 if ( ddrval != DD_OK ) {
1132 mprintf(( "GR_SOFT_INIT: CreateSurface (Back) failed.\n" ));
1136 // create a clipper and attach it to our window
1137 ddrval = lpDD->CreateClipper( 0, &lpClipper, NULL );
1138 if ( ddrval != DD_OK ) {
1139 mprintf(( "GR_SOFT_INIT: CreateClipper failed.\n" ));
1144 ddrval = lpClipper->SetHWnd( 0, hwnd );
1145 if ( ddrval != DD_OK ) {
1146 mprintf(( "GR_SOFT_INIT: SetHWnd failed.\n" ));
1151 ddrval = lpFrontBuffer->SetClipper( lpClipper );
1152 if ( ddrval != DD_OK ) {
1153 mprintf(( "GR_SOFT_INIT: SetClipper failed.\n" ));
1159 PALETTEENTRY pe[256];
1160 for (i=0; i<256; i++ ) {
1161 pe[i].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
1166 ddrval = lpDD->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &lpPalette, NULL);
1167 if (ddrval != DD_OK) {
1168 mprintf(( "Error creating palette\n" ));
1172 ddrval = lpFrontBuffer->SetPalette( lpPalette );
1173 if (ddrval != DD_OK) {
1174 mprintf(( "Error setting palette in gr_directdraw_set_palette\n" ));
1178 memset( &ddsd, 0, sizeof( ddsd ) );
1179 ddsd.dwSize = sizeof(ddsd);
1180 lpFrontBuffer->GetSurfaceDesc(&ddsd);
1181 dd_get_shift_masks( &ddsd );
1183 mprintf(( "Surfaces created...\n" ));
1195 grx_init_alphacolors();
1197 gr_screen.gf_flip = gr_directdraw_flip;
1198 gr_screen.gf_flip_window = gr_directdraw_flip_window;
1199 gr_screen.gf_set_clip = gr_directdraw_set_clip;
1200 gr_screen.gf_reset_clip = gr_directdraw_reset_clip;
1201 gr_screen.gf_set_font = grx_set_font;
1202 gr_screen.gf_set_color = grx_set_color;
1203 gr_screen.gf_set_bitmap = gr_directdraw_set_bitmap;
1204 gr_screen.gf_create_shader = grx_create_shader;
1205 gr_screen.gf_set_shader = grx_set_shader;
1206 gr_screen.gf_clear = gr_directdraw_clear;
1207 // gr_screen.gf_bitmap = grx_bitmap;
1208 // gr_screen.gf_bitmap_ex = grx_bitmap_ex;
1210 gr_screen.gf_aabitmap = grx_aabitmap;
1211 gr_screen.gf_aabitmap_ex = grx_aabitmap_ex;
1213 gr_screen.gf_rect = grx_rect;
1214 gr_screen.gf_shade = gr8_shade;
1215 gr_screen.gf_string = gr8_string;
1216 gr_screen.gf_circle = gr8_circle;
1218 gr_screen.gf_line = gr8_line;
1219 gr_screen.gf_aaline = gr8_aaline;
1220 gr_screen.gf_pixel = gr8_pixel;
1221 gr_screen.gf_scaler = gr8_scaler;
1222 gr_screen.gf_aascaler = gr8_aascaler;
1223 gr_screen.gf_tmapper = grx_tmapper;
1225 gr_screen.gf_gradient = gr8_gradient;
1227 gr_screen.gf_set_palette = gr_directdraw_set_palette;
1228 gr_screen.gf_get_color = grx_get_color;
1229 gr_screen.gf_init_color = grx_init_color;
1230 gr_screen.gf_init_alphacolor = grx_init_alphacolor;
1231 gr_screen.gf_set_color_fast = grx_set_color_fast;
1232 gr_screen.gf_print_screen = grx_print_screen;
1234 gr_screen.gf_start_frame = gr_directdraw_start_frame;
1235 gr_screen.gf_stop_frame = gr_directdraw_stop_frame;
1237 gr_screen.gf_fade_in = gr_directdraw_fade_in;
1238 gr_screen.gf_fade_out = gr_directdraw_fade_out;
1239 gr_screen.gf_flash = gr_directdraw_flash;
1241 // Retrieves the zbuffer mode.
1242 gr_screen.gf_zbuffer_get = gr8_zbuffer_get;
1243 gr_screen.gf_zbuffer_set = gr8_zbuffer_set;
1244 gr_screen.gf_zbuffer_clear = gr8_zbuffer_clear;
1246 gr_screen.gf_save_screen = gr8_save_screen;
1247 gr_screen.gf_restore_screen = gr8_restore_screen;
1248 gr_screen.gf_free_screen = gr8_free_screen;
1250 // Screen dumping stuff
1251 gr_screen.gf_dump_frame_start = gr8_dump_frame_start;
1252 gr_screen.gf_dump_frame_stop = gr8_dump_frame_stop;
1253 gr_screen.gf_dump_frame = gr8_dump_frame;
1256 gr_screen.gf_set_gamma = gr8_set_gamma;
1258 // Lock/unlock stuff
1259 gr_screen.gf_lock = gr_directdraw_lock;
1260 gr_screen.gf_unlock = gr_directdraw_unlock_fake;
1263 gr_screen.gf_get_region = gr_directdraw_get_region;
1266 gr_screen.gf_set_cull = gr_directdraw_set_cull;
1269 gr_screen.gf_cross_fade = gr_directdraw_cross_fade;
1272 gr_screen.gf_filter_set = gr_directdraw_filter_set;
1275 gr_screen.gf_set_clear_color = gr_directdraw_set_clear_color;
1279 mprintf(( "Surfaces locked...\n" ));