2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
8 * $Source: r:/t2repos/thief2/src/render/scrnman.c,v $
11 * $Date: 2000/02/19 12:35:36 $
48 #include <dbmem.h> // must be last header!
54 BOOL g_table_fog_toggle
= TRUE
;
56 BOOL g_zbuffer_toggle
= TRUE
;
58 BOOL g_null_raster
= FALSE
;
60 static ScrnMode _cur_res
= -1;
62 static ScrnCallBack _curback
= NULL
;
64 static grs_canvas
*_off_screen
= NULL
;
65 static grs_canvas
*_draw_canv
= NULL
;
66 static bool _in_frame
= FALSE
;
68 ScrnMode
ScrnFindModeFlags(short w
, short h
, ubyte depth
,ulong flags
)
71 i
=gr_find_mode_flags(w
,h
,depth
,flags
|GRM_IS_SUPPORTED
);
80 static int _in_shell
= 0;
82 void _start_shell(void)
85 IGameShell_BeginFrame (pGameShell
);
93 IGameShell_EndFrame (pGameShell
);
98 #define _start_shell()
102 #define GET_KIND(p, a, b, c) COMCall3(p, GetKind2, a, b, c)
103 #define SET_KIND(p, a, b, c) COMCall3(p, SetKind2, a, b, c)
104 #define SET_FLIP(p, a) COMCall1(p, SetFlip, a)
106 static BOOL try_flip
= FALSE
;
108 int ScrnSetDisplay(int kind
, int flags
, GUID
*DD
)
110 int dispKind
, dispFlags
;
113 IDisplayDevice
*pDispDev
= AppGetObj(IDisplayDevice
);
114 BOOL different_dd
= FALSE
;
115 EXTERN BOOL g_no_dx6
;
116 BOOL last_flip
= try_flip
;
118 GET_KIND(pDispDev
, (eDisplayDeviceKind
*)&dispKind
, &dispFlags
, &curDD
);
120 if (DD
&& IsEqualGUID(DD
,&SCRNMAN_PRESERVE_DDRAW
))
123 different_dd
= DD
!= curDD
;
125 // If neither pointer is null, actually compare the guids
126 if (different_dd
&& DD
&& curDD
)
127 different_dd
= !IsEqualGUID(DD
,curDD
);
132 flags
&= kDispStrictMonitors
;
136 try_flip
= flags
& kDispAttemptFlippable
;
138 // Always attempt flippable! set flipping for real after setting mode!
139 flags
|= kDispAttemptFlippable
;
141 if (!different_dd
&& kind
== dispKind
)
142 // add attempt3d if is was there before...
143 flags
|= (kDispAttempt3D
& dispFlags
);
145 if (different_dd
|| kind
!= dispKind
|| flags
!= dispFlags
)
147 ConfigSpew("set_display_spew", ("Changing display to %d flags 0x%X\n", kind
, flags
));
150 SET_KIND(pDispDev
, kind
, flags
, DD
);
155 changed
= last_flip
!= try_flip
;
157 SafeRelease(pDispDev
);
160 // return old diplay kind
165 int scrn_mode_table
[] =
174 static BOOL g_page_flip
= FALSE
;
176 static void make_draw_canvas(void)
178 IDisplayDevice
* pDisp
= AppGetObj(IDisplayDevice
);
179 int disp_kind
, disp_flags
;
181 GET_KIND(pDisp
, &disp_kind
, &disp_flags
, NULL
);
183 // This would happen in gr_set_screen(), but we may not have called it.
184 gr_set_canvas(grd_back_canvas
);
186 if (_off_screen
!= NULL
)
188 gr_free_canvas(_off_screen
);
192 if (!g_page_flip
&& (disp_kind
== kDispFullScreen
))
193 { // FullScreen, not page flipping...
194 _off_screen
= gr_alloc_canvas(grd_bm
.type
,grd_bm
.w
,grd_bm
.h
); // Was always BMT_FLAT8
195 _draw_canv
= _off_screen
;
197 else // windowed or page flipping, no backing canvas
200 _draw_canv
= grd_visible_canvas
;
202 if (_draw_canv
->ytab
== NULL
)
203 gr_alloc_ytab(_draw_canv
);
208 void ScrnLockDrawCanvas(void)
210 IDisplayDevice
* pDisp
;
212 if (_off_screen
!=NULL
)
215 pDisp
= AppGetObj(IDisplayDevice
);
216 IDisplayDevice_Lock(pDisp
);
217 if (g_lgd3d
&& (!g_null_raster
))
222 void ScrnUnlockDrawCanvas(void)
224 IDisplayDevice
* pDisp
;
226 if (_off_screen
!=NULL
)
229 pDisp
= AppGetObj(IDisplayDevice
);
230 IDisplayDevice_Unlock(pDisp
);
231 if (g_lgd3d
&& (!g_null_raster
))
232 if (!pDisp
->lpVtbl
->IsLocked(pDisp
))
237 static BOOL
doMiscSetResStuff(int new_mode
, ulong flags
)
240 info
= gr_mode_info_from_mode(new_mode
);
242 if (grd_screen
== NULL
)
244 grs_screen
* screen
= gr_alloc_screen(info
->w
,info
->h
);
245 gr_set_screen(screen
);
249 // ScrnInit3d() has to happen before palmgr_recompute_all().
250 if (ScrnInit3d()==FALSE
) {
251 Warning(("ScrnInit3d failed!\n"));
256 palmgr_recompute_all();
258 if (flags
& kScrnPreservePal
)
266 gr_set_canvas(_draw_canv
);
273 // set a new screen mode. Preserve the previous
276 BOOL
ScrnSetRes(ScrnMode mode
,ulong flags
)
278 IDisplayDevice
*pDispDev
= AppGetObj(IDisplayDevice
);
280 static int last_mode
= -1;
285 Warning(("ScrnSetRes: Trying to set res inside frame\n"));
289 new_mode
= ScrnModeToGrMode(mode
);
291 ConfigSpew("set_res_spew",
292 ("setting screen mode %i. last_mode %i, grd_mode %i\n", new_mode
, last_mode
, grd_mode
));
294 // note that grd_mode is the mode we _would_ get if we set last_mode
295 // we really want to know if we'd end up with the same mode,
296 // so we compare against both!
297 // This will break horribly if we ever gr_set_mode() elsewhere...
299 if (grd_mode
!= -1) // make sure we haven't closed display device...
300 if ((last_mode
== new_mode
) || (grd_mode
== new_mode
)) {
302 if (try_flip
== g_page_flip
)
306 // OK, try to set page flipping correctly on the fly!
307 g_page_flip
= SET_FLIP(pDispDev
, try_flip
);
308 if (g_page_flip
== try_flip
)
309 // Success! Now we just need to make the draw canvas, etc.
312 // Couldn't do it, fall through to old way...
317 ConfigSpew("set_res_spew",
318 ("calling gr_set_mode with mode %i, flags %i\n", new_mode
, flags
&0xff));
319 if (gr_set_mode(new_mode
,flags
& 0xFF) == -1) // failure
322 // we want to save last_mode, not grd_mode, so we can compare later
323 last_mode
= new_mode
;
325 // g_page_flip needs to be set correctly before we try to make the draw canvas.
328 g_page_flip
= SET_FLIP(pDispDev
, TRUE
);
335 g_page_flip
= SET_FLIP(pDispDev
, FALSE
);
336 AssertMsg(g_page_flip
==FALSE
, "Kevin can't code for shit.");
341 retval
= doMiscSetResStuff(new_mode
, flags
);
344 SafeRelease(pDispDev
);
348 void ScrnUnsetRes(void)
350 ConfigSpew("set_res_spew", ("unsetting res...\n"));
351 if (grd_screen
!= NULL
)
353 gr_free_screen(grd_screen
);
357 if (_off_screen
!= NULL
)
359 gr_free_canvas(_off_screen
);
368 // returns -1 if not yet set
369 ScrnMode
ScrnGetRes(void)
375 EXTERN BOOL g_null_raster
;
376 EXTERN BOOL portal_multitexture
;
377 EXTERN
void portal_setup_light_masks(void);
379 int g_lgd3d_device_index
;
384 // Init/Term 3d accelleration
386 #ifdef USE_HARDWARE3D
388 BOOL
ScrnInit3d(void)
393 int num_devices
= lgd3d_enumerate_devices();
394 lgd3ds_device_info
* info
;
398 if (num_devices
<= 0) {
399 Warning(("No direct 3d devices available."));
403 if( (g_lgd3d_device_index
> num_devices
) || (g_lgd3d_device_index
< 0) )
404 g_lgd3d_device_index
= num_devices
-1;
406 info
= lgd3d_get_device_info(g_lgd3d_device_index
);
408 info
->request_flags
= LG3D_CF_DITHER
| LG3D_SHADER_MODULATE_ALPHA
;
409 info
->required_flags
= LG3D_SHADER_MULTITEX_COLOR
;
411 if( info
->caps
& LG3D_CF_SP_MULTI_TEX
)
412 info
->request_flags
|= LG3D_CF_SP_2LEV_TEX
;
414 if( g_zbuffer_toggle
) // that's a joke, right?
415 info
->required_flags
|= LG3D_CF_Z_BUFFER
;
420 config_get_int("lgd3d_spew", &spew
);
423 info
->request_flags
|= LG3D_SPEW
;
426 if (config_is_defined("fail_lgd3d_init"))
429 if( config_is_defined("lg3d_cache_alpha") )
430 info
->request_flags
|= LG3D_CF_RND_ALPHA_LAST
;
432 if( config_is_defined("force_two_passes") )
433 info
->request_flags
&= ~LG3D_CF_SP_2LEV_TEX
;
437 if( FAILED( lgd3d_init( info
, &set_flags
) ) )
440 // make sure our lightmap method is confirmed.
441 if( !(set_flags
& LG3D_SHADER_MULTITEX_COLOR
) )
444 // set error message?
448 lgd3d_set_chromakey(255, 0, 255);
450 portal_multitexture
= g_multitexture
= (set_flags
& LG3D_CF_SP_MULTI_TEX
) != 0;
451 g_zbuffer
= (set_flags
& LG3D_CF_Z_BUFFER
) != 0;
453 if( !g_zbuffer
&& g_zbuffer_toggle
)
455 Warning(("Couldn't create zbuffer.\n"));
463 portal_setup_light_masks();
468 #else # !USE_HARDWARE3D
469 BOOL
ScrnInit3d(void)
473 int num_devices
= lgd3d_enumerate_devices();
474 lgd3ds_device_info
*info
;
476 if (num_devices
<= 0) {
477 Warning(("No direct 3d devices available."));
481 if ((g_lgd3d_device_index
> num_devices
)||(g_lgd3d_device_index
< 0))
482 g_lgd3d_device_index
= num_devices
-1;
484 info
= lgd3d_get_device_info(g_lgd3d_device_index
);
486 // see if we can single pass multitexture
487 if (info
->flags
& LGD3DF_CAN_DO_SINGLE_PASS_MT
)
488 info
->flags
|= LGD3DF_MULTI_TEXTURING
;
490 info
->flags
&= ~LGD3DF_MULTI_TEXTURING
;
492 // check our lightmap method.
493 info
->flags
|= LGD3DF_MULTITEXTURE_COLOR
;
495 // try to do zbuffering if the user turned it on
496 if (g_zbuffer_toggle
)
497 info
->flags
|= LGD3DF_ZBUFFER
;
499 info
->flags
&= ~LGD3DF_ZBUFFER
;
501 if (g_table_fog_toggle
)
502 info
->flags
|= LGD3DF_TABLE_FOG
;
504 info
->flags
&= ~LGD3DF_TABLE_FOG
;
509 config_get_int("lgd3d_spew", &spew
);
512 info
->flags
|= LGD3DF_SPEW
;
514 info
->flags
&= ~LGD3DF_SPEW
;
518 if (config_is_defined("fail_lgd3d_init"))
521 if( config_is_defined("force_two_passes") )
522 info
->flags
&= ~LGD3DF_MULTI_TEXTURING
;
525 info
->flags
|= LGD3DF_DITHER
| LGD3DF_MODULATEALPHA
; //zb :
533 b_SS2_UseSageTexManager
= (config_is_defined("safe_texture_manager"));
539 // note that flags may be changed during this call, so we check afterwards
540 if (lgd3d_init(info
) == FALSE
)
543 // make sure our lightmap method is confirmed.
544 if (!(info
->flags
& LGD3DF_MULTITEXTURE_COLOR
))
547 // set error message?
551 lgd3d_set_chromakey(255, 0, 255);
553 portal_multitexture
= g_multitexture
= (info
->flags
& LGD3DF_MULTI_TEXTURING
) != 0;
554 g_zbuffer
= (info
->flags
& LGD3DF_ZBUFFER
) != 0;
556 if (!g_zbuffer
&& g_zbuffer_toggle
)
559 Warning(("Couldn't create zbuffer.\n"));
563 g_table_fog
= (info
->flags
& LGD3DF_TABLE_FOG
) != 0;
569 portal_setup_light_masks();
577 void ScrnTerm3d(void)
587 // background drawer callback function, takes data,
588 // takes effect next start frame. Should call it outside
589 // of a frame. Only one can be installed at a time
590 // no chaining. Maybe later if you ever need it
591 typedef void (*ScrnCallBack
)(int data
);
593 void ScrnInstallBackground(ScrnCallBack cb
,int data
)
596 if (_curback
!= NULL
) {
597 Warning(("ScrnInstallBackground: trying to install background over existing one\n"));
607 BOOL have_canv
= grd_visible_canvas
!= NULL
;
608 IDisplayDevice
* pDisp
= NULL
;
610 if (grd_mode
< 0 || _cur_res
< 0)
616 pDisp
= AppGetObj(IDisplayDevice
);
617 IDisplayDevice_Lock(pDisp
);
618 gr_push_canvas(grd_visible_canvas
);
623 if (_off_screen
!= 0)
625 gr_push_canvas(_off_screen
);
631 IDisplayDevice_Unlock(pDisp
);
632 IDisplayDevice_Flush(pDisp
);
637 // clear the screen to black and blacken the palette
638 // note that this works great, 8 or 16 bit as a prelude
639 // to loading a new screen
640 // Note that this works in or out of a frame
641 void ScrnBlacken(void)
644 BOOL have_canv
= grd_visible_canvas
!= NULL
;
645 IDisplayDevice
* pDisp
= NULL
;
649 pDisp
= AppGetObj(IDisplayDevice
);
650 IDisplayDevice_Lock(pDisp
);
653 // we don't want to change the palette, because we want to remember
655 ScrnNewBlackPalette();
657 // gr clear the visible canvas, so new palette set
658 // does not get garbage
659 // Zero is the universal black.
662 gr_push_canvas(grd_visible_canvas
);
666 if (_off_screen
!= 0)
668 gr_push_canvas(_off_screen
);
675 IDisplayDevice_Unlock(pDisp
);
676 IDisplayDevice_Flush(pDisp
);
682 // call the background callback if present
683 // otherwise just start the frame and go
684 void ScrnStartFrame(void)
690 if (_curback
!= NULL
) {
697 // compose cursor onto/off of back canvas
699 void compose_cursor(int cmd
)
701 if (LastCursor
!= NULL
)
703 grs_canvas
*save_canvas
= CursorCanvas
;
704 CursorCanvas
= _draw_canv
;
705 LastCursor
->func(cmd
,NULL
,LastCursor
,LastCursorPos
);
706 CursorCanvas
= save_canvas
;
711 // blit or page flip, transparently, woo woo.
712 void ScrnEndFrame(void)
720 // blit or page flip right now dammit
721 void ScrnForceUpdate(void)
723 Rect r
= { { 0, 0}, };
724 r
.lr
.x
= grd_visible_canvas
->bm
.w
;
725 r
.lr
.y
= grd_visible_canvas
->bm
.h
;
726 ScrnForceUpdateRect(&r
);
729 void ScrnForceUpdateRect(Rect
*r
)
731 IDisplayDevice
*disp
;
732 // BOOL frame = _in_frame;
738 disp
= AppGetObj(IDisplayDevice
);
743 IDisplayDevice_Lock(disp
);
746 compose_cursor(CURSOR_DRAW
);
748 gr_push_canvas(grd_visible_canvas
);
751 gr_safe_set_cliprect(r
->ul
.x
, r
->ul
.y
, r
->lr
.x
, r
->lr
.y
);
752 gr_bitmap(&(_off_screen
->bm
),0,0);
757 compose_cursor(CURSOR_UNDRAW
);
760 IDisplayDevice_Unlock(disp
);
765 IDisplayDevice_FlushRect(disp
, r
->ul
.x
, r
->ul
.y
, r
->lr
.x
, r
->lr
.y
);
774 // set the current canvas to be the visible screen
775 // the idea is you're not page flipping or blitting
776 // in fact, if you do an end_frame in this mode, you get
777 // an error. Can we do this under gameshell?
778 // THis is probably bad, since you need it locked
780 // unless we say you always have to be
783 void ScrnSetVisible(void)
785 gr_set_canvas(grd_visible_canvas
);
788 // set the current canvas to be the offscreen canvas(default)
789 void ScrnSetOffscreen(void)
791 gr_set_canvas(_draw_canv
);
794 grs_canvas
*ScrnGetDrawCanvas(void)
799 static void set_palette(void)
801 palmgr_update_pal_slot(0);
802 grd_ipal
= palmgr_get_ipal(0);
805 static void build_palette(uchar
* pal
,int start
,int size
)
807 palmgr_set_pal_slot_passively(0, 256, pal
, 0);
810 // load and use this palette
811 void ScrnNewPalette(uchar
* pal
,int start
,int size
)
814 if (start
< 0 || start
>255 || (start
+size
)>256 || size
< 0 ) {
815 Warning(("ScrnNewPalette: start is %d and size is %d, illegal\n",start
,size
));
819 build_palette(pal
,start
,size
);
824 // make the current palette black and use it
825 void ScrnNewBlackPalette(void)
829 build_palette(pal
,0,256);
834 // load but do not set this palette
835 void ScrnLoadPalette(uchar
*pal
,int start
,int size
)
838 if (start
< 0 || start
>255 || (start
+size
)>256 || size
< 0 ) {
839 Warning(("ScrnLoadPalette: start is %d and size is %d, illegal\n",start
,size
));
843 build_palette(pal
,start
,size
);
846 // Use the currently loaded palette
847 void ScrnUsePalette(void)
852 grd_pal
= palmgr_get_pal(0);
855 // return pointer to loaded palette. Beware, don't mess with it.
856 const uchar
*ScrnGetPalette(void)
858 return palmgr_get_pal(0);
861 ////////////////////////////////////////
862 const uchar
* ScrnGetInvPalette(void)
864 return palmgr_get_ipal(0);
867 int ScrnInvPaletteSize(void)