convert line ends
[canaan.git] / prj / cam / src / render / scrnman.c
blobb60e0ea0f19f4d5ec51c6aea2e8ae4534057975c
1 /*
2 @Copyright Looking Glass Studios, Inc.
3 1996,1997,1998,1999,2000 Unpublished Work.
4 */
7 /*
8 * $Source: r:/t2repos/thief2/src/render/scrnman.c,v $
9 * $Revision: 1.65 $
10 * $Author: toml $
11 * $Date: 2000/02/19 12:35:36 $
13 * Screen Manager
16 #include <string.h>
17 #include <scrnman.h>
18 #include <lg.h>
19 #include <2d.h>
20 #include <gameinfo.h>
21 #include <cursors.h>
22 #include <curdat.h>
23 #include <lgd3d.h>
24 #include <r3d.h>
26 #include <appagg.h>
27 #include <comtools.h>
28 #include <gshelapi.h>
29 #include <dispapi.h>
30 #include <rand.h>
32 #include <config.h>
33 #include <cfgdbg.h>
35 #include <palmgr.h>
37 // Include this last
38 #include <initguid.h>
39 #include <scrnguid.h>
45 //zb SS2 patch only!
46 #include <lgSS2P.h>
47 #include <memall.h>
48 #include <dbmem.h> // must be last header!
53 BOOL g_table_fog;
54 BOOL g_table_fog_toggle = TRUE;
55 BOOL g_zbuffer;
56 BOOL g_zbuffer_toggle = TRUE;
57 EXTERN BOOL g_lgd3d;
58 BOOL g_null_raster = FALSE;
60 static ScrnMode _cur_res = -1;
62 static ScrnCallBack _curback = NULL;
63 static int _data = 0;
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)
70 int i;
71 i=gr_find_mode_flags(w,h,depth,flags|GRM_IS_SUPPORTED);
72 if (i!=-1)
73 return i;
75 return SCR_NOMODE;
79 #ifdef DO_GAME_SHELL
80 static int _in_shell = 0;
82 void _start_shell(void)
84 if (_in_shell==0) {
85 IGameShell_BeginFrame (pGameShell);
87 _in_shell++;
90 void _end_shell(void)
92 if (_in_shell==1) {
93 IGameShell_EndFrame (pGameShell);
95 _in_shell--;
97 #else
98 #define _start_shell()
99 #define _end_shell()
100 #endif
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;
111 int changed;
112 GUID *curDD;
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))
121 DD = curDD;
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);
129 if (g_no_dx6) {
130 kind = kDispDebug;
131 DD = NULL;
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));
148 ScrnUnsetRes();
149 gr_close();
150 SET_KIND(pDispDev, kind, flags, DD);
151 gr_init();
152 grd_mode = -1;
153 changed = TRUE;
154 } else
155 changed = last_flip != try_flip;
157 SafeRelease(pDispDev);
160 // return old diplay kind
161 return changed;
165 int scrn_mode_table[] =
167 GRM_320x200x8,
168 GRM_320x400x8,
169 GRM_640x400x8,
170 GRM_640x480x8,
171 GRM_1024x768x8,
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);
189 _off_screen = NULL;
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
199 _off_screen = NULL;
200 _draw_canv = grd_visible_canvas;
202 if (_draw_canv->ytab == NULL)
203 gr_alloc_ytab(_draw_canv);
205 SafeRelease(pDisp);
208 void ScrnLockDrawCanvas(void)
210 IDisplayDevice* pDisp;
212 if (_off_screen!=NULL)
213 return;
215 pDisp = AppGetObj(IDisplayDevice);
216 IDisplayDevice_Lock(pDisp);
217 if (g_lgd3d && (!g_null_raster))
218 r3_use_g2();
219 SafeRelease(pDisp);
222 void ScrnUnlockDrawCanvas(void)
224 IDisplayDevice* pDisp;
226 if (_off_screen!=NULL)
227 return;
229 pDisp = AppGetObj(IDisplayDevice);
230 IDisplayDevice_Unlock(pDisp);
231 if (g_lgd3d && (!g_null_raster))
232 if (!pDisp->lpVtbl->IsLocked(pDisp))
233 r3_use_lgd3d();
234 SafeRelease(pDisp);
237 static BOOL doMiscSetResStuff(int new_mode, ulong flags)
239 grs_mode_info* info;
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);
247 make_draw_canvas();
249 // ScrnInit3d() has to happen before palmgr_recompute_all().
250 if (ScrnInit3d()==FALSE) {
251 Warning(("ScrnInit3d failed!\n"));
252 ScrnUnsetRes();
253 return FALSE;
256 palmgr_recompute_all();
258 if (flags & kScrnPreservePal)
260 ScrnUsePalette();
261 ScrnClear();
263 else
264 ScrnBlacken();
266 gr_set_canvas(_draw_canv);
268 _cur_res = new_mode;
270 return TRUE;
273 // set a new screen mode. Preserve the previous
274 // palette or not
275 // TRUE for success.
276 BOOL ScrnSetRes(ScrnMode mode,ulong flags)
278 IDisplayDevice *pDispDev = AppGetObj(IDisplayDevice);
279 int new_mode;
280 static int last_mode = -1;
281 int retval = FALSE;
283 #ifdef DBG_ON
284 if (_in_frame) {
285 Warning(("ScrnSetRes: Trying to set res inside frame\n"));
287 #endif
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)
303 goto ScrnSetResMisc;
304 // we're all set!
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.
310 goto ScrnSetResMisc;
312 // Couldn't do it, fall through to old way...
315 ScrnUnsetRes();
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
320 goto ScrnSetResDone;
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.
326 if (try_flip)
328 g_page_flip = SET_FLIP(pDispDev, TRUE);
329 if (!g_page_flip)
330 // fail!
331 goto ScrnSetResDone;
333 else
335 g_page_flip = SET_FLIP(pDispDev, FALSE);
336 AssertMsg(g_page_flip==FALSE, "Kevin can't code for shit.");
340 ScrnSetResMisc:
341 retval = doMiscSetResStuff(new_mode, flags);
343 ScrnSetResDone:
344 SafeRelease(pDispDev);
345 return retval;
348 void ScrnUnsetRes(void)
350 ConfigSpew("set_res_spew", ("unsetting res...\n"));
351 if (grd_screen != NULL)
353 gr_free_screen(grd_screen);
354 grd_screen = NULL;
357 if (_off_screen != NULL)
359 gr_free_canvas(_off_screen);
360 _off_screen = NULL;
362 _draw_canv = NULL;
364 _cur_res = -1;
368 // returns -1 if not yet set
369 ScrnMode ScrnGetRes(void)
371 return _cur_res;
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;
380 bool g_multitexture;
384 // Init/Term 3d accelleration
386 #ifdef USE_HARDWARE3D
388 BOOL ScrnInit3d(void)
391 if( g_lgd3d )
393 int num_devices = lgd3d_enumerate_devices();
394 lgd3ds_device_info* info;
395 ulong set_flags;
398 if (num_devices <= 0) {
399 Warning(("No direct 3d devices available."));
400 return FALSE;
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;
417 #ifndef SHIP
419 int spew = 0;
420 config_get_int("lgd3d_spew", &spew);
422 if( spew )
423 info->request_flags |= LG3D_SPEW;
426 if (config_is_defined("fail_lgd3d_init"))
427 return FALSE;
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;
435 #endif
437 if( FAILED( lgd3d_init( info, &set_flags ) ) )
438 return FALSE;
440 // make sure our lightmap method is confirmed.
441 if( !(set_flags & LG3D_SHADER_MULTITEX_COLOR) )
443 lgd3d_shutdown();
444 // set error message?
445 return FALSE;
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"));
458 if( !g_null_raster )
459 r3_use_lgd3d();
462 #ifdef RGB_LIGHTING
463 portal_setup_light_masks();
464 #endif
465 return TRUE;
468 #else # !USE_HARDWARE3D
469 BOOL ScrnInit3d(void)
471 if (g_lgd3d)
473 int num_devices = lgd3d_enumerate_devices();
474 lgd3ds_device_info *info;
476 if (num_devices <= 0) {
477 Warning(("No direct 3d devices available."));
478 return FALSE;
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;
489 else
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;
498 else
499 info->flags &= ~LGD3DF_ZBUFFER;
501 if (g_table_fog_toggle)
502 info->flags |= LGD3DF_TABLE_FOG;
503 else
504 info->flags &= ~LGD3DF_TABLE_FOG;
506 #ifndef SHIP
508 int spew = 0;
509 config_get_int("lgd3d_spew", &spew);
511 if (spew)
512 info->flags |= LGD3DF_SPEW;
513 else
514 info->flags &= ~LGD3DF_SPEW;
518 if (config_is_defined("fail_lgd3d_init"))
519 return FALSE;
521 if( config_is_defined("force_two_passes") )
522 info->flags &= ~LGD3DF_MULTI_TEXTURING;
523 #endif
525 info->flags |= LGD3DF_DITHER | LGD3DF_MODULATEALPHA; //zb :
532 //zb SS2 patch only!
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)
541 return FALSE;
543 // make sure our lightmap method is confirmed.
544 if (!(info->flags & LGD3DF_MULTITEXTURE_COLOR))
546 lgd3d_shutdown();
547 // set error message?
548 return FALSE;
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)
558 lgd3d_shutdown();
559 Warning(("Couldn't create zbuffer.\n"));
560 return FALSE;
563 g_table_fog = (info->flags & LGD3DF_TABLE_FOG) != 0;
565 if (!g_null_raster)
566 r3_use_lgd3d();
568 #ifdef RGB_LIGHTING
569 portal_setup_light_masks();
570 #endif
571 return TRUE;
574 #endif
577 void ScrnTerm3d(void)
579 if (g_lgd3d)
581 if (!g_null_raster)
582 r3_use_g2();
583 lgd3d_shutdown();
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)
595 #ifdef DBG_ON
596 if (_curback != NULL) {
597 Warning(("ScrnInstallBackground: trying to install background over existing one\n"));
599 #endif
601 _data = data;
602 _curback = cb;
605 void ScrnClear(void)
607 BOOL have_canv = grd_visible_canvas != NULL;
608 IDisplayDevice* pDisp = NULL;
610 if (grd_mode < 0 || _cur_res < 0)
611 return;
614 if (have_canv)
616 pDisp = AppGetObj(IDisplayDevice);
617 IDisplayDevice_Lock(pDisp);
618 gr_push_canvas(grd_visible_canvas);
619 gr_clear(0);
620 gr_pop_canvas();
623 if (_off_screen != 0)
625 gr_push_canvas(_off_screen);
626 gr_clear(0);
627 gr_pop_canvas();
629 if (have_canv)
631 IDisplayDevice_Unlock(pDisp);
632 IDisplayDevice_Flush(pDisp);
633 SafeRelease(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;
647 if (have_canv)
649 pDisp = AppGetObj(IDisplayDevice);
650 IDisplayDevice_Lock(pDisp);
653 // we don't want to change the palette, because we want to remember
654 // what it is.
655 ScrnNewBlackPalette();
657 // gr clear the visible canvas, so new palette set
658 // does not get garbage
659 // Zero is the universal black.
660 if (have_canv)
662 gr_push_canvas(grd_visible_canvas);
663 gr_clear(0);
664 gr_pop_canvas();
666 if (_off_screen != 0)
668 gr_push_canvas(_off_screen);
669 gr_clear(0);
670 gr_pop_canvas();
673 if (have_canv)
675 IDisplayDevice_Unlock(pDisp);
676 IDisplayDevice_Flush(pDisp);
677 SafeRelease(pDisp);
682 // call the background callback if present
683 // otherwise just start the frame and go
684 void ScrnStartFrame(void)
686 _start_shell();
688 ScrnSetOffscreen();
690 if (_curback != NULL) {
691 _curback(_data);
692 _curback = NULL;
694 _in_frame = TRUE;
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)
714 ScrnForceUpdate();
716 _in_frame = FALSE;
717 _end_shell();
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;
733 grs_clip clip;
735 if (g_page_flip)
736 return;
738 disp = AppGetObj(IDisplayDevice);
741 if (_off_screen)
743 IDisplayDevice_Lock(disp);
745 MouseLock++;
746 compose_cursor(CURSOR_DRAW);
748 gr_push_canvas(grd_visible_canvas);
749 clip = grd_gc.clip;
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);
754 grd_gc.clip = clip;
755 gr_pop_canvas();
757 compose_cursor(CURSOR_UNDRAW);
758 MouseLock--;
760 IDisplayDevice_Unlock(disp);
765 IDisplayDevice_FlushRect(disp, r->ul.x, r->ul.y, r->lr.x, r->lr.y);
769 SafeRelease(disp);
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
781 // in a frame
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)
796 return _draw_canv;
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)
813 #ifdef DBG_ON
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));
817 #endif
819 build_palette(pal,start,size);
820 ScrnUsePalette();
824 // make the current palette black and use it
825 void ScrnNewBlackPalette(void)
827 uchar pal[768];
828 memset(pal,0,768);
829 build_palette(pal,0,256);
830 ScrnUsePalette();
834 // load but do not set this palette
835 void ScrnLoadPalette(uchar *pal,int start,int size)
837 #ifdef DBG_ON
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));
841 #endif
843 build_palette(pal,start,size);
846 // Use the currently loaded palette
847 void ScrnUsePalette(void)
849 if (_cur_res > 0)
850 set_palette();
851 else
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)
869 return 32768;