2 * $Logfile: /Freespace2/code/Graphics/GrDirectDraw.cpp $
7 * Code for software 8-bpp rendering using DirectDraw
10 * Revision 1.1 2002/05/03 03:28:09 root
14 * 9 7/14/99 9:42a Dave
15 * Put in clear_color debug function. Put in base for 3dnow stuff / P3
18 * 8 6/29/99 10:35a Dave
19 * Interface polygon bitmaps! Whee!
21 * 7 2/03/99 11:44a Dave
22 * Fixed d3d transparent textures.
24 * 6 1/24/99 11:37p Dave
25 * First full rev of beam weapons. Very customizable. Removed some bogus
26 * Int3()'s in low level net code.
28 * 5 12/18/98 1:13a Dave
29 * Rough 1024x768 support for Direct3D. Proper detection and usage through
32 * 4 12/06/98 2:36p Dave
33 * Drastically improved nebula fogging.
35 * 3 11/30/98 1:07p Dave
36 * 16 bit conversion, first run.
38 * 2 10/07/98 10:52a Dave
41 * 1 10/07/98 10:49a Dave
43 * 17 5/22/98 10:28p John
44 * Made software movies not click your monitor when switching to 16-bpp.
45 * Total hack around my restrictive code, but at this point...
47 * 16 5/20/98 9:45p John
48 * added code so the places in code that change half the palette don't
49 * have to clear the screen.
51 * 15 5/17/98 5:03p John
52 * Fixed some bugs that make the taskbar interfere with the DEBUG-only
55 * 14 5/16/98 1:18p John
56 * Made softtware DirectDraw reset palette after Alt+TAB.
58 * 13 5/15/98 9:34p John
59 * Removed the initial ugly little cursor part that drew right at program
62 * 12 5/14/98 5:42p John
63 * Revamped the whole window position/mouse code for the graphics windows.
65 * 11 5/12/98 8:15a John
66 * Made dd code not print out rgb surface info.
68 * 10 5/07/98 6:58p Hoffoss
69 * Made changes to mouse code to fix a number of problems.
71 * 9 5/06/98 5:30p John
72 * Removed unused cfilearchiver. Removed/replaced some unused/little used
73 * graphics functions, namely gradient_h and _v and pixel_sp. Put in new
74 * DirectX header files and libs that fixed the Direct3D alpha blending
77 * 8 4/23/98 8:24a John
78 * Changed the way palette effect works so that:
79 * 1. If gr_flash isn't called this frame, screen shows no flash.
80 * 2. With hardware, only 3d portion of screen gets flashed.
82 * 7 4/21/98 5:22p John
83 * Fixed all the &^#@$ cursor bugs with popups. For Glide, had problem
84 * with mouse restoring assuming back buffer was same buffer last frame,
85 * for software, problems with half drawn new frames, then mouse got
86 * restored on top of that with old data.
88 * 6 4/17/98 3:56p Mike
89 * Fix palette trashing on MK's computer when he Alt-Tabs out of FreeSpace
90 * in software. At John's suggestion.
92 * 5 4/14/98 12:15p John
93 * Made 16-bpp movies work.
95 * 4 4/13/98 8:08p John
96 * Made surface restoration also restore the palette.
98 * 3 4/09/98 6:56p John
99 * Put in better code to restore surfaces when restoring them. Worth a
100 * try for an Interplay QA bug I can't find.
102 * 2 4/09/98 11:05a John
103 * Removed all traces of Direct3D out of the demo version of Freespace and
106 * 1 3/25/98 8:07p John
107 * Split software renderer into Win32 and DirectX
114 #include <windowsx.h>
122 #include "floating.h"
125 #include "grinternal.h"
127 // Headers for 2d functions
135 #include "gradient.h"
136 #include "pcxutils.h"
143 #include "grzbuffer.h"
145 static LPDIRECTDRAW lpDD = NULL;
146 static LPDIRECTDRAWSURFACE lpBackBuffer = NULL;
147 static LPDIRECTDRAWSURFACE lpFrontBuffer = NULL;
148 static LPDIRECTDRAWCLIPPER lpClipper = NULL;
149 static LPDIRECTDRAWPALETTE lpPalette = NULL;
151 void gr_directdraw_unlock();
152 void gr_directdraw_set_palette_internal( ubyte * new_pal );
154 void directdraw_clear_all_vram()
156 #ifndef HARDWARE_ONLY
159 LPDIRECTDRAWSURFACE buffer[16];
163 for (i=0; i<16; i++ ) {
164 memset( &ddsd, 0, sizeof( ddsd ) );
166 ddsd.dwSize = sizeof( ddsd );
167 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
168 ddsd.dwWidth = gr_screen.max_w;
169 ddsd.dwHeight = gr_screen.max_h;
170 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN | DDSCAPS_VIDEOMEMORY;
172 // create the back buffer
173 ddrval = lpDD->CreateSurface( &ddsd, &buffer[i], NULL );
174 if ( ddrval == DD_OK ) {
178 memset(&ddBltFx, 0, sizeof(DDBLTFX));
179 ddBltFx.dwSize = sizeof(DDBLTFX);
180 ddBltFx.dwFillColor = 0;
182 buffer[i]->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddBltFx);
191 for (i=0; i<num_buffers; i++ ) {
192 buffer[i]->Release();
199 LPDIRECTDRAW gr_directdraw_start_mve()
201 #ifndef HARDWARE_ONLY
203 memset( tmp_pal, 0, 768 );
205 gr_directdraw_set_palette_internal(tmp_pal);
207 // clear both buffers
216 gr_directdraw_unlock();
218 // Clear all of VRAM...
219 directdraw_clear_all_vram();
222 lpPalette->Release();
227 lpFrontBuffer->Release();
228 lpFrontBuffer = NULL;
240 void gr_directdraw_stop_mve()
242 #ifndef HARDWARE_ONLY
246 memset( &ddsd, 0, sizeof( ddsd ) );
248 ddsd.dwSize = sizeof( ddsd );
249 ddsd.dwFlags = DDSD_CAPS;
250 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
252 ddrval = lpDD->CreateSurface( &ddsd, &lpFrontBuffer, NULL );
253 if ( ddrval != DD_OK ) {
254 mprintf(( "GR_SOFT_INIT: CreateSurface (Front) failed.\n" ));
260 PALETTEENTRY pe[256];
261 for (i=0; i<256; i++ ) {
262 pe[i].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
263 pe[i].peRed = gr_palette[i*3+0];
264 pe[i].peGreen = gr_palette[i*3+1];
265 pe[i].peBlue = gr_palette[i*3+2];
268 ddrval = lpDD->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &lpPalette, NULL);
269 if (ddrval != DD_OK) {
270 mprintf(( "Error creating palette\n" ));
273 ddrval = lpFrontBuffer->SetPalette( lpPalette );
274 if (ddrval != DD_OK) {
275 mprintf(( "Error setting palette in gr_directdraw_set_palette\n" ));
288 static int Locked = 0;
290 uint gr_directdraw_lock()
292 #ifndef HARDWARE_ONLY
298 memset( &ddsd, 0, sizeof( ddsd ) );
299 ddsd.dwSize = sizeof( ddsd );
301 ddrval = lpBackBuffer->Lock( NULL, &ddsd, DDLOCK_WAIT, NULL );
302 if ( ddrval != DD_OK ) {
303 mprintf(( "Error locking surface in gr_d3d_lock\n" ));
304 gr_screen.offscreen_buffer_base = NULL; //(void *)fake_vram;
305 gr_screen.rowsize = 0;
306 gr_screen.offscreen_buffer = gr_screen.offscreen_buffer_base;
308 gr_screen.offscreen_buffer_base = (void *)ddsd.lpSurface;
309 gr_screen.rowsize = ddsd.lPitch;
310 gr_screen.offscreen_buffer = gr_screen.offscreen_buffer_base;
322 void gr_directdraw_unlock()
324 #ifndef HARDWARE_ONLY
326 // Unlock the back buffer
327 lpBackBuffer->Unlock( NULL );
335 void gr_directdraw_unlock_fake()
340 static int Palette_flashed = 0;
341 static int Palette_flashed_last_frame = 0;
344 static volatile int Gr_dd_activated = 0;
346 void gr_dd_activate(int active)
348 #ifndef HARDWARE_ONLY
358 void gr_directdraw_flip()
360 #ifndef HARDWARE_ONLY
361 if ( Gr_dd_activated || ((!Palette_flashed) && (Palette_flashed_last_frame)) ) {
363 gr_directdraw_set_palette_internal( gr_palette );
367 Palette_flashed_last_frame = Palette_flashed;
374 Grx_mouse_saved = 0; // assume not saved
377 if ( mouse_is_visible() ) {
379 mouse_get_pos( &mx, &my );
380 grx_save_mouse_area(mx,my,32,32);
381 if ( Gr_cursor == -1 ) {
382 gr_set_color(255,255,255);
383 gr_line( mx, my, mx+7, my + 7 );
384 gr_line( mx, my, mx+5, my );
385 gr_line( mx, my, mx, my+5 );
387 gr_set_bitmap(Gr_cursor);
392 gr_directdraw_unlock();
397 if ( lpFrontBuffer->IsLost() == DDERR_SURFACELOST ) {
398 lpFrontBuffer->Restore();
399 ddrval = lpFrontBuffer->SetPalette( lpPalette );
400 if (ddrval != DD_OK) {
401 mprintf(( "Error setting palette after restore\n" ));
404 if ( lpBackBuffer->IsLost() == DDERR_SURFACELOST ) {
405 lpBackBuffer->Restore();
408 HRESULT ddrval = lpFrontBuffer->Flip( NULL, DDFLIP_WAIT );
409 if ( ddrval == DDERR_SURFACELOST ) {
410 mprintf(( "Front surface lost... attempting to restore...\n" ));
411 os_sleep(1000); // Wait a second
413 } else if (ddrval != DD_OK ) {
414 mprintf(( "Fullscreen flip failed!\n" ));
418 RECT src_rect, dst_rect;
422 HWND hWnd = (HWND)os_get_window();
425 // src_rect is relative to offscreen buffer
426 GetClientRect( hWnd, &src_rect );
428 // dst_rect is relative to screen space so needs translation
430 ClientToScreen( hWnd, &pt );
432 dst_rect.left += pt.x;
433 dst_rect.right += pt.x;
434 dst_rect.top += pt.y;
435 dst_rect.bottom += pt.y;
437 // perform the blit from backbuffer to primary, using
438 // src_rect and dst_rect
441 if ( lpFrontBuffer->IsLost() == DDERR_SURFACELOST ) {
442 lpFrontBuffer->Restore();
444 /* ddrval = lpFrontBuffer->SetPalette( lpPalette );
445 if (ddrval != DD_OK) {
446 mprintf(( "Error setting palette after restore\n" ));
449 if ( lpBackBuffer->IsLost() == DDERR_SURFACELOST ) {
450 lpBackBuffer->Restore();
452 ddrval = lpFrontBuffer->Blt( &dst_rect, lpBackBuffer, &src_rect, DDBLT_WAIT, 0 );
453 if ( ddrval == DDERR_SURFACELOST ) {
454 mprintf(( "Front surface lost... attempting to restore...\n" ));
455 os_sleep(1000); // Wait a second
457 } else if (ddrval != DD_OK ) {
458 mprintf(( "Flip failed! $%x\n", ddrval ));
463 if ( Grx_mouse_saved ) {
464 grx_restore_mouse_area();
471 void gr_directdraw_flip_window(uint _hdc, int x, int y, int w, int h )
475 void gr_directdraw_start_frame()
480 void gr_directdraw_stop_frame()
485 void gr_directdraw_set_palette_internal( ubyte * new_pal )
487 #ifndef HARDWARE_ONLY
488 PALETTEENTRY pe[256];
490 gr_directdraw_unlock();
493 for (i=0; i<256; i++ ) {
494 pe[i].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
495 pe[i].peRed = new_pal[i*3+0];
496 pe[i].peGreen = new_pal[i*3+1];
497 pe[i].peBlue = new_pal[i*3+2];
501 ddrval = lpPalette->SetEntries( 0, 0, 256, pe );
502 if ( ddrval != DD_OK ) {
503 mprintf(( "Error setting palette\n" ));
512 void gr_directdraw_set_palette( ubyte * new_pal, int restrict_alphacolor )
514 #ifndef HARDWARE_ONLY
515 if ( !restrict_alphacolor ) {
523 // Make sure color 0 is black
524 if ( (new_pal[0]!=0) || (new_pal[1]!=0) || (new_pal[2]!=0) ) {
525 // color 0 isn't black!! switch it!
527 int black_index = -1;
529 for (i=1; i<256; i++ ) {
530 if ( (new_pal[i*3+0]==0) && (new_pal[i*3+1]==0) && (new_pal[i*3+2]==0) ) {
535 if ( black_index > -1 ) {
536 // swap black and color 0, so color 0 is black
538 tmp[0] = new_pal[black_index*3+0];
539 tmp[1] = new_pal[black_index*3+1];
540 tmp[2] = new_pal[black_index*3+2];
542 new_pal[black_index*3+0] = new_pal[0];
543 new_pal[black_index*3+1] = new_pal[1];
544 new_pal[black_index*3+2] = new_pal[2];
550 // no black in palette, force color 0 to be black.
557 gr_directdraw_set_palette_internal( new_pal );
563 void gr_directdraw_flash( int r, int g, int b )
565 #ifndef HARDWARE_ONLY
569 if ( (r==0) && (b==0) && (g==0) ) {
575 for (i=0; i<256; i++ ) {
576 t = gr_palette[i*3+0] + r;
577 if ( t < 0 ) t = 0; else if (t>255) t = 255;
578 new_pal[i*3+0] = (ubyte)t;
580 t = gr_palette[i*3+1] + g;
581 if ( t < 0 ) t = 0; else if (t>255) t = 255;
582 new_pal[i*3+1] = (ubyte)t;
584 t = gr_palette[i*3+2] + b;
585 if ( t < 0 ) t = 0; else if (t>255) t = 255;
586 new_pal[i*3+2] = (ubyte)t;
589 gr_directdraw_set_palette_internal( new_pal );
596 static int gr_palette_faded_out = 0;
598 #define FADE_TIME (F1_0/4) // How long to fade out
600 void gr_directdraw_fade_out(int instantaneous)
602 #ifndef HARDWARE_ONLY
606 if (!gr_palette_faded_out) {
608 if ( !instantaneous ) {
611 fix start_time, stop_time, t1;
613 start_time = timer_get_fixed_seconds();
617 for (i=0; i<768; i++ ) {
618 int c = (gr_palette[i]*(FADE_TIME-t1))/FADE_TIME;
624 new_pal[i] = (ubyte)c;
626 gr_directdraw_set_palette_internal( new_pal );
629 t1 = timer_get_fixed_seconds() - start_time;
631 } while ( (t1 < FADE_TIME) && (t1>=0) ); // Loop as long as time not up and timer hasn't rolled
633 stop_time = timer_get_fixed_seconds();
635 mprintf(( "Took %d frames (and %.1f secs) to fade out\n", count, f2fl(stop_time-start_time) ));
638 gr_palette_faded_out = 1;
641 memset( new_pal, 0, 768 );
642 gr_directdraw_set_palette_internal( new_pal );
649 void gr_directdraw_fade_in(int instantaneous)
651 #ifndef HARDWARE_ONLY
655 if (gr_palette_faded_out) {
657 if ( !instantaneous ) {
659 fix start_time, stop_time, t1;
661 start_time = timer_get_fixed_seconds();
665 for (i=0; i<768; i++ ) {
666 int c = (gr_palette[i]*t1)/FADE_TIME;
672 new_pal[i] = (ubyte)c;
674 gr_directdraw_set_palette_internal( new_pal );
677 t1 = timer_get_fixed_seconds() - start_time;
679 } while ( (t1 < FADE_TIME) && (t1>=0) ); // Loop as long as time not up and timer hasn't rolled
681 stop_time = timer_get_fixed_seconds();
683 mprintf(( "Took %d frames (and %.1f secs) to fade in\n", count, f2fl(stop_time-start_time) ));
685 gr_palette_faded_out = 0;
688 memcpy( new_pal, gr_palette, 768 );
689 gr_directdraw_set_palette_internal( new_pal );
695 void gr_directdraw_get_region(int front, int w, int h, ubyte *data)
699 // sets the clipping region & offset
700 void gr_directdraw_set_clip(int x,int y,int w,int h)
702 #ifndef HARDWARE_ONLY
703 gr_screen.offset_x = x;
704 gr_screen.offset_y = y;
706 gr_screen.clip_left = 0;
707 gr_screen.clip_right = w-1;
709 gr_screen.clip_top = 0;
710 gr_screen.clip_bottom = h-1;
712 // check for sanity of parameters
713 if ( gr_screen.clip_left+x < 0 ) {
714 gr_screen.clip_left = -x;
715 } else if ( gr_screen.clip_left+x > gr_screen.max_w-1 ) {
716 gr_screen.clip_left = gr_screen.max_w-1-x;
718 if ( gr_screen.clip_right+x < 0 ) {
719 gr_screen.clip_right = -x;
720 } else if ( gr_screen.clip_right+x >= gr_screen.max_w-1 ) {
721 gr_screen.clip_right = gr_screen.max_w-1-x;
724 if ( gr_screen.clip_top+y < 0 ) {
725 gr_screen.clip_top = -y;
726 } else if ( gr_screen.clip_top+y > gr_screen.max_h-1 ) {
727 gr_screen.clip_top = gr_screen.max_h-1-y;
730 if ( gr_screen.clip_bottom+y < 0 ) {
731 gr_screen.clip_bottom = -y;
732 } else if ( gr_screen.clip_bottom+y > gr_screen.max_h-1 ) {
733 gr_screen.clip_bottom = gr_screen.max_h-1-y;
736 gr_screen.clip_width = gr_screen.clip_right - gr_screen.clip_left + 1;
737 gr_screen.clip_height = gr_screen.clip_bottom - gr_screen.clip_top + 1;
743 // resolution checking
744 int gr_directdraw_supports_res_ingame(int res)
749 int gr_directdraw_supports_res_interface(int res)
754 void gr_directdraw_set_cull(int cull)
758 // resets the clipping region to entire screen
760 // should call this before gr_surface_flip() if you clipped some portion of the screen but still
761 // want a full-screen display
762 void gr_directdraw_reset_clip()
764 #ifndef HARDWARE_ONLY
765 gr_screen.offset_x = 0;
766 gr_screen.offset_y = 0;
767 gr_screen.clip_left = 0;
768 gr_screen.clip_top = 0;
769 gr_screen.clip_right = gr_screen.max_w - 1;
770 gr_screen.clip_bottom = gr_screen.max_h - 1;
771 gr_screen.clip_width = gr_screen.max_w;
772 gr_screen.clip_height = gr_screen.max_h;
779 // Sets the current bitmap
780 void gr_directdraw_set_bitmap( int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha, int sx, int sy )
782 #ifndef HARDWARE_ONLY
783 gr_screen.current_alpha = alpha;
784 gr_screen.current_alphablend_mode = alphablend_mode;
785 gr_screen.current_bitblt_mode = bitblt_mode;
786 gr_screen.current_bitmap = bitmap_num;
787 gr_screen.current_bitmap_sx = sx;
788 gr_screen.current_bitmap_sy = sy;
794 // clears entire clipping region to black.
795 void gr_directdraw_clear()
797 #ifndef HARDWARE_ONLY
800 gr_directdraw_unlock();
804 ddBltFx.dwSize = sizeof(DDBLTFX);
805 ddBltFx.dwFillColor = 0;
808 lpBackBuffer->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddBltFx);
809 // ddBltFx.dwROP = BLACKNESS;
810 // lpBackBuffer->Blt(NULL, NULL, NULL, DDBLT_ROP, &ddBltFx);
820 w = gr_screen.clip_right-gr_screen.clip_left+1;
821 for (i=gr_screen.clip_top; i<=gr_screen.clip_bottom; i++) {
822 pDestBits = GR_SCREEN_PTR(ubyte,gr_screen.clip_left,i);
823 memset( pDestBits, 0, w );
826 gr_directdraw_unlock();
833 void gr_directdraw_force_windowed()
835 #ifndef HARDWARE_ONLY
836 gr_directdraw_unlock();
838 HWND hwnd = (HWND)os_get_window();
841 PostMessage(hwnd,WM_SYSKEYUP, 0x9, 0xa00f0001 );
842 PostMessage(hwnd,WM_SYSKEYUP, 0x12, 0xc0380001 );
844 // Wait a second to give things a change to settle down.
851 void gr_directdraw_cleanup()
853 #ifndef HARDWARE_ONLY
854 HWND hwnd = (HWND)os_get_window();
856 gr_directdraw_unlock();
859 lpPalette->Release();
864 lpClipper->Release();
869 lpBackBuffer->Release();
874 lpFrontBuffer->Release();
875 lpFrontBuffer = NULL;
879 // JAS: I took this out because my taskbar seems to get screwed up
880 // if I leave this in. Doesn't make sense, hence this comment.
881 HRESULT ddrval = lpDD->RestoreDisplayMode();
882 if( ddrval != DD_OK ) {
883 mprintf(( "WIN_DD32: RestoreDisplayMode failed (0x%x)\n", ddrval ));
885 ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_NORMAL );
886 if( ddrval != DD_OK ) {
887 mprintf(( "WIN_DD32: SetCooperativeLevel W Failed (0x%x)\n", ddrval ));
901 void dd_get_shift_masks( DDSURFACEDESC *ddsd )
905 int r, red_shift, red_scale, red_mask;
906 int g, green_shift, green_scale, green_mask;
907 int b, blue_shift, blue_scale, blue_mask;
908 int a, alpha_shift, alpha_scale, alpha_mask;
910 if (gr_screen.bits_per_pixel == 8 ) {
914 Gr_red.mask = 0xff0000;
919 Gr_green.mask = 0xff00;
928 // Determine the red, green and blue masks' shift and scale.
929 for (s = 0, m = ddsd->ddpfPixelFormat.dwRBitMask; !(m & 1); s++, m >>= 1);
930 for (r = 0; m & 1; r++, m >>= 1);
932 red_scale = 255 / (ddsd->ddpfPixelFormat.dwRBitMask >> s);
933 red_mask = ddsd->ddpfPixelFormat.dwRBitMask;
935 for (s = 0, m = ddsd->ddpfPixelFormat.dwGBitMask; !(m & 1); s++, m >>= 1);
936 for (g = 0; m & 1; g++, m >>= 1);
938 green_scale = 255 / (ddsd->ddpfPixelFormat.dwGBitMask >> s);
939 green_mask = ddsd->ddpfPixelFormat.dwGBitMask;
941 for (s = 0, m = ddsd->ddpfPixelFormat.dwBBitMask; !(m & 1); s++, m >>= 1);
942 for (b = 0; m & 1; b++, m >>= 1);
944 blue_scale = 255 / (ddsd->ddpfPixelFormat.dwBBitMask >> s);
945 blue_mask = ddsd->ddpfPixelFormat.dwBBitMask;
947 if ( ddsd->ddpfPixelFormat.dwFlags & DDPF_ALPHAPIXELS ) {
948 for (s = 0, m = ddsd->ddpfPixelFormat.dwRGBAlphaBitMask; !(m & 1); s++, m >>= 1);
949 for (a = 0; m & 1; a++, m >>= 1);
951 alpha_scale = 255 / (ddsd->ddpfPixelFormat.dwRGBAlphaBitMask >> s);
952 alpha_mask = ddsd->ddpfPixelFormat.dwRGBAlphaBitMask;
954 alpha_shift = a = alpha_scale = alpha_mask = 0;
957 // mprintf(( "Red Bits:%2d, Shift:%2d, Scale:%3d, Mask:$%08x\n", r, red_shift, red_scale, red_mask ));
958 // mprintf(( "Green Bits:%2d, Shift:%2d, Scale:%3d, Mask:$%08x\n", g, green_shift, green_scale, green_mask ));
959 // mprintf(( "Blue Bits:%2d, Shift:%2d, Scale:%3d, Mask:$%08x\n", b, blue_shift, blue_scale, blue_mask ));
960 // mprintf(( "Alpha Bits:%2d, Shift:%2d, Scale:%3d, Mask:$%08x\n", a, alpha_shift, alpha_scale, alpha_mask ));
962 // we need to set stuff up so that the high bit is always an alpha bit.
965 Gr_red.shift = red_shift;
966 Gr_red.scale = red_scale;
967 Gr_red.mask = red_mask;
970 Gr_green.shift = green_shift;
971 Gr_green.scale = green_scale;
972 Gr_green.mask = green_mask;
975 Gr_blue.shift = blue_shift;
976 Gr_blue.scale = blue_scale;
977 Gr_blue.mask = blue_mask;
981 void gr_directdraw_cross_fade(int bmap1, int bmap2, int x1, int y1, int x2, int y2, float pct)
984 gr_set_bitmap(bmap1);
987 gr_set_bitmap(bmap2);
993 void gr_directdraw_filter_set(int filter)
998 void gr_directdraw_set_clear_color(int r, int g, int b)
1002 void gr_directdraw_init()
1004 #ifndef HARDWARE_ONLY
1008 Palette_flashed = 0;
1009 Palette_flashed_last_frame = 0;
1011 gr_screen.bits_per_pixel = 8;
1012 gr_screen.bytes_per_pixel = 1;
1014 Gr_dd_activated = 0;
1016 HWND hwnd = (HWND)os_get_window();
1019 mprintf(( "GR_SOFT_INIT: No window handle.\n" ));
1023 // Prepare the window to go full screen
1025 mprintf(( "Window in debugging mode... mouse clicking may cause problems!\n" ));
1026 SetWindowLong( hwnd, GWL_EXSTYLE, 0 );
1027 SetWindowLong( hwnd, GWL_STYLE, WS_POPUP );
1028 ShowWindow(hwnd, SW_SHOWNORMAL );
1030 SystemParametersInfo( SPI_GETWORKAREA, 0, &work_rect, 0 );
1031 SetWindowPos( hwnd, HWND_NOTOPMOST, work_rect.left, work_rect.top, gr_screen.max_w, gr_screen.max_h, 0 );
1032 SetActiveWindow(hwnd);
1033 SetForegroundWindow(hwnd);
1035 SetWindowLong( hwnd, GWL_EXSTYLE, 0 );
1036 SetWindowLong( hwnd, GWL_STYLE, WS_POPUP );
1037 ShowWindow(hwnd, SW_SHOWNORMAL );
1038 SetWindowPos( hwnd, HWND_TOPMOST, 0, 0, GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ), 0 );
1039 SetActiveWindow(hwnd);
1040 SetForegroundWindow(hwnd);
1044 ddrval = DirectDrawCreate( NULL, &lpDD, NULL );
1046 if ( ddrval != DD_OK ) {
1047 mprintf(( "GR_SOFT_INIT: DirectDrawCreate failed.\n" ));
1053 ddrval = lpDD->SetCooperativeLevel( hwnd, DDSCL_EXCLUSIVE | DDSCL_FULLSCREEN );
1054 if ( ddrval != DD_OK ) {
1055 mprintf(( "GR_SOFT_INIT: SetCooperativeLevel EXCLUSIVE failed.\n" ));
1060 // Go to full screen!
1062 ddrval = lpDD->SetDisplayMode( gr_screen.max_w, gr_screen.max_h, gr_screen.bits_per_pixel );
1064 if ( ddrval != DD_OK ) {
1065 mprintf(( "GR_SOFT_INIT: SetDisplayMode failed.\n" ));
1076 memset( &ddsd, 0, sizeof( ddsd ));
1078 ddsd.dwSize = sizeof( ddsd );
1079 ddsd.dwFlags = DDSD_CAPS | DDSD_BACKBUFFERCOUNT;
1080 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE | DDSCAPS_FLIP | DDSCAPS_COMPLEX;
1081 ddsd.dwBackBufferCount = 2;
1083 ddrval = lpDD->CreateSurface( &ddsd, &lpFrontBuffer, NULL );
1084 if ( ddrval != DD_OK ) {
1085 mprintf(( "GR_SOFT_INIT: CreateSurface (Front) failed.\n" ));
1090 ddscaps.dwCaps = DDSCAPS_BACKBUFFER;
1092 ddrval = lpFrontBuffer->GetAttachedSurface( &ddscaps, &lpBackBuffer );
1093 if ( ddrval != DD_OK ) {
1094 mprintf(( "GR_SOFT_INIT: GetAttachedSurface (Back) failed.\n" ));
1102 memset( &ddsd, 0, sizeof( ddsd ) );
1104 ddsd.dwSize = sizeof( ddsd );
1105 ddsd.dwFlags = DDSD_CAPS;
1106 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
1108 ddrval = lpDD->CreateSurface( &ddsd, &lpFrontBuffer, NULL );
1109 if ( ddrval != DD_OK ) {
1110 mprintf(( "GR_SOFT_INIT: CreateSurface (Front) failed.\n" ));
1115 ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
1116 ddsd.dwWidth = gr_screen.max_w;
1117 ddsd.dwHeight = gr_screen.max_h;
1118 ddsd.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
1120 // If debugging we have to create our surfaces in system memory
1121 // so that our debugger isn't hosed when locking surfaces.
1123 //ddsd.ddsCaps.dwCaps |= DDSCAPS_NONLOCALVIDMEM;
1124 ddsd.ddsCaps.dwCaps |= DDSCAPS_SYSTEMMEMORY;
1126 // create the back buffer
1127 ddrval = lpDD->CreateSurface( &ddsd, &lpBackBuffer , NULL );
1128 if ( ddrval != DD_OK ) {
1129 mprintf(( "GR_SOFT_INIT: CreateSurface (Back) failed.\n" ));
1133 // create a clipper and attach it to our window
1134 ddrval = lpDD->CreateClipper( 0, &lpClipper, NULL );
1135 if ( ddrval != DD_OK ) {
1136 mprintf(( "GR_SOFT_INIT: CreateClipper failed.\n" ));
1141 ddrval = lpClipper->SetHWnd( 0, hwnd );
1142 if ( ddrval != DD_OK ) {
1143 mprintf(( "GR_SOFT_INIT: SetHWnd failed.\n" ));
1148 ddrval = lpFrontBuffer->SetClipper( lpClipper );
1149 if ( ddrval != DD_OK ) {
1150 mprintf(( "GR_SOFT_INIT: SetClipper failed.\n" ));
1156 PALETTEENTRY pe[256];
1157 for (i=0; i<256; i++ ) {
1158 pe[i].peFlags = PC_NOCOLLAPSE|PC_RESERVED;
1163 ddrval = lpDD->CreatePalette( DDPCAPS_8BIT | DDPCAPS_ALLOW256, pe, &lpPalette, NULL);
1164 if (ddrval != DD_OK) {
1165 mprintf(( "Error creating palette\n" ));
1169 ddrval = lpFrontBuffer->SetPalette( lpPalette );
1170 if (ddrval != DD_OK) {
1171 mprintf(( "Error setting palette in gr_directdraw_set_palette\n" ));
1175 memset( &ddsd, 0, sizeof( ddsd ) );
1176 ddsd.dwSize = sizeof(ddsd);
1177 lpFrontBuffer->GetSurfaceDesc(&ddsd);
1178 dd_get_shift_masks( &ddsd );
1180 mprintf(( "Surfaces created...\n" ));
1192 grx_init_alphacolors();
1194 gr_screen.gf_flip = gr_directdraw_flip;
1195 gr_screen.gf_flip_window = gr_directdraw_flip_window;
1196 gr_screen.gf_set_clip = gr_directdraw_set_clip;
1197 gr_screen.gf_reset_clip = gr_directdraw_reset_clip;
1198 gr_screen.gf_set_font = grx_set_font;
1199 gr_screen.gf_set_color = grx_set_color;
1200 gr_screen.gf_set_bitmap = gr_directdraw_set_bitmap;
1201 gr_screen.gf_create_shader = grx_create_shader;
1202 gr_screen.gf_set_shader = grx_set_shader;
1203 gr_screen.gf_clear = gr_directdraw_clear;
1204 // gr_screen.gf_bitmap = grx_bitmap;
1205 // gr_screen.gf_bitmap_ex = grx_bitmap_ex;
1207 gr_screen.gf_aabitmap = grx_aabitmap;
1208 gr_screen.gf_aabitmap_ex = grx_aabitmap_ex;
1210 gr_screen.gf_rect = grx_rect;
1211 gr_screen.gf_shade = gr8_shade;
1212 gr_screen.gf_string = gr8_string;
1213 gr_screen.gf_circle = gr8_circle;
1215 gr_screen.gf_line = gr8_line;
1216 gr_screen.gf_aaline = gr8_aaline;
1217 gr_screen.gf_pixel = gr8_pixel;
1218 gr_screen.gf_scaler = gr8_scaler;
1219 gr_screen.gf_aascaler = gr8_aascaler;
1220 gr_screen.gf_tmapper = grx_tmapper;
1222 gr_screen.gf_gradient = gr8_gradient;
1224 gr_screen.gf_set_palette = gr_directdraw_set_palette;
1225 gr_screen.gf_get_color = grx_get_color;
1226 gr_screen.gf_init_color = grx_init_color;
1227 gr_screen.gf_init_alphacolor = grx_init_alphacolor;
1228 gr_screen.gf_set_color_fast = grx_set_color_fast;
1229 gr_screen.gf_print_screen = grx_print_screen;
1231 gr_screen.gf_start_frame = gr_directdraw_start_frame;
1232 gr_screen.gf_stop_frame = gr_directdraw_stop_frame;
1234 gr_screen.gf_fade_in = gr_directdraw_fade_in;
1235 gr_screen.gf_fade_out = gr_directdraw_fade_out;
1236 gr_screen.gf_flash = gr_directdraw_flash;
1238 // Retrieves the zbuffer mode.
1239 gr_screen.gf_zbuffer_get = gr8_zbuffer_get;
1240 gr_screen.gf_zbuffer_set = gr8_zbuffer_set;
1241 gr_screen.gf_zbuffer_clear = gr8_zbuffer_clear;
1243 gr_screen.gf_save_screen = gr8_save_screen;
1244 gr_screen.gf_restore_screen = gr8_restore_screen;
1245 gr_screen.gf_free_screen = gr8_free_screen;
1247 // Screen dumping stuff
1248 gr_screen.gf_dump_frame_start = gr8_dump_frame_start;
1249 gr_screen.gf_dump_frame_stop = gr8_dump_frame_stop;
1250 gr_screen.gf_dump_frame = gr8_dump_frame;
1253 gr_screen.gf_set_gamma = gr8_set_gamma;
1255 // Lock/unlock stuff
1256 gr_screen.gf_lock = gr_directdraw_lock;
1257 gr_screen.gf_unlock = gr_directdraw_unlock_fake;
1260 gr_screen.gf_get_region = gr_directdraw_get_region;
1263 gr_screen.gf_set_cull = gr_directdraw_set_cull;
1266 gr_screen.gf_cross_fade = gr_directdraw_cross_fade;
1269 gr_screen.gf_filter_set = gr_directdraw_filter_set;
1272 gr_screen.gf_set_clear_color = gr_directdraw_set_clear_color;
1276 mprintf(( "Surfaces locked...\n" ));