1 // Emacs style mode select   -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // $Id: i_video_mac.c 1543 2020-08-22 02:36:35Z wesleyjohnson $
5 //
6 // Copyright (C) 1993-1996 by id Software, Inc.
7 // Portions Copyright (C) 1998-2000 by DooM Legacy Team.
8 //
9 // This program is free software; you can redistribute it and/or
10 // modify it under the terms of the GNU General Public License
11 // as published by the Free Software Foundation; either version 2
12 // of the License, or (at your option) any later version.
13 //
14 // This program is distributed in the hope that it will be useful,
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 // GNU General Public License for more details.
18 //
19 // DESCRIPTION:
20 //      DOOM graphics stuff for Mac
21 //
22 //-----------------------------------------------------------------------------
23 
24 #include <AGL/agl.h>
25 #include <AGL/gl.h>
26 #include <AGL/glu.h>
27 #include <Carbon/Carbon.h>
28 
29 #include "doomincl.h"
30 #include "doomstat.h"
31 #include "i_system.h"
32 #include "i_video.h"
33 #include "v_video.h"
34 #include "m_argv.h"
35 #include "m_menu.h"
36 #include "d_main.h"
37 #include "s_sound.h"
38 #include "g_input.h"
39 #include "st_stuff.h"
40 #include "g_game.h"
41   // cv_fullscreen, cv_gamma etc.
42 #include "console.h"
43 #include "command.h"
44 #include "z_zone.h"
45 #include "hw_main.h"
46 #include "hw_drv.h"
47 #include "hwsym_mac.h"
48   // For dynamic referencing of HW rendering functions
49 #include "r_opengl.h"
50 
51 
52 // public
53 byte  native_bitpp, native_bytepp;
54 
55 
56 
57 struct modeDescription
58 {
59     uint16_t  w, h;
60     int freq;
61 };
62 
63 RGBA_t  gamma_correction = {0x7F7F7F7F};
64 
65 
66 WindowRef mainWindow = NULL;
67 
68 // all modes, used for window modes or fullscreen modes
69 #define MAXVIDMODES  33
70 #define MAX_LEN_VIDMODENAME  32
71 char   vidModeName[MAXVIDMODES][MAX_LEN_VIDMODENAME];
72 struct modeDescription modeList[MAXVIDMODES];
73 static int nummodes = 0;
74 
75 #define MAXWINMODES 8
76 // windowed video modes from which to choose from.
77 static int windowedModes[MAXWINMODES+1][2] = {
78    // hidden from display
79     {INITIAL_WINDOW_WIDTH, INITIAL_WINDOW_HEIGHT},  // initial mode
80    // public  1..
81     {MAXVIDWIDTH /*1600*/, MAXVIDHEIGHT/*1200*/},
82     { 320,  200},
83     { 400,  300},
84     { 512,  384},
85     { 640,  480},
86     { 800,  600},
87     {1024,  768},
88     {1280, 1024},
89     {1600, 1200}
90 };
91 
I_UpdateNoBlit(void)92 void I_UpdateNoBlit(void){}
I_ReadScreen(byte * scr)93 void I_ReadScreen(byte* scr){}
94 
OglMacSetPalette(RGBA_t * palette,RGBA_t * gamma)95 void OglMacSetPalette(RGBA_t *palette, RGBA_t *gamma)
96 {
97     int i;
98 
99     for (i=0; i<256; i++)
100     {
101         myPaletteData[i].s.red   = MIN((palette->s.red   * gamma->s.red)  /127, 255);
102         myPaletteData[i].s.green = MIN((palette->s.green * gamma->s.green)/127, 255);
103         myPaletteData[i].s.blue  = MIN((palette->s.blue  * gamma->s.blue) /127, 255);
104         myPaletteData[i].s.alpha = 0xff; // opaque
105         palette++;
106     }
107 
108     Flush();
109 }
110 
111 //
112 // I_SetPalette
113 //
I_SetPalette(RGBA_t * palette)114 void I_SetPalette (RGBA_t* palette)
115 {
116     int i;
117 
118     for (i=0; i<256; i++) {
119         myPaletteData[i].s.red   = MIN((palette->s.red   * cv_grgammared.value)  /127, 255);
120         myPaletteData[i].s.green = MIN((palette->s.green * cv_grgammagreen.value)/127, 255);
121         myPaletteData[i].s.blue  = MIN((palette->s.blue  * cv_grgammablue.value) /127, 255);
122         myPaletteData[i].s.alpha = 0xff; // opaque
123         palette++;
124     }
125 
126     Flush();
127 
128     return;
129 }
130 
131 //------------------------------
132 //  VID_Pause
133 //  Used by macConfigureInput
134 //  Stops fullscreen mode to allow ISp dialog appear
135 //  newMode - new mode to switch to
136 //  returns - current mode (should switch back to this)
VID_Pause(boolean pause)137 void VID_Pause(boolean pause)
138 {
139     static int oldMode = -1;
140 
141     /*if (pause)
142     {
143         oldMode = vid.modenum;
144         VID_SetMode (3);
145     }
146     else if (oldMode>0)
147         {
148         VID_SetMode(oldMode);
149                 oldMode = -1;
150         }*/
151 }
152 
153 // modetype is of modetype_e
VID_ModeRange(byte modetype)154 range_t  VID_ModeRange( byte modetype )
155 {
156     range_t  mrange = { 1, 1 };  // first is always 1
157     mrange.last = nummodes;  // fullscreen and window
158     return mrange;
159 }
160 
161 //------------------------------
162 
VID_GetMode_Stat(modenum_t modenum)163 modestat_t  VID_GetMode_Stat( modenum_t modenum )
164 {
165     modestat_t  ms;
166 
167     // fullscreen and window modes  1..
168     if( modenum.index < nummodes )
169     {
170         ms.width = modeList[modenum.index].w;
171         ms.height = modeList[modenum.index].h;
172         ms.type = MODE_either;
173         ms.mark = "";
174     }
175     else
176     {
177         ms.type = MODE_NOP;
178         ms.width = ms.height = 0;
179         ms.mark = NULL;
180     }
181     return ms;
182 }
183 
184 // VID_GetModeName
185 // Used in the video mode menu
VID_GetModeName(modenum_t modenum)186 char * VID_GetModeName( modenum_t modenum )
187 {
188     snprintf(&vidModeName[modenum.index][0], MAX_LEN_VIDMODENAME, "%ix%i", modeList[modenum.index].w, modeList[modenum.index].h);
189     vidModeName[modenum.index][MAX_LEN_VIDMODENAME-1] = 0;
190 
191     return &vidModeName[modenum.index][0];
192 }
193 
194 // rmodetype is of modetype_e
195 // Returns MODE_NOP when none found
VID_GetModeForSize(int rw,int rh,byte rmodetype)196 modenum_t  VID_GetModeForSize( int rw, int rh, byte rmodetype )
197 {
198     modenum_t  modenum = { MODE_NOP, 0 };
199     int bestdist = INT_MAX;
200     int best, tdist, i;
201 
202     best = 5;  // default is mode (640x480)
203 
204     if( nummodes == 0 )  goto done;
205     for(i=1; i<nummodes; i++)   // skip INITIAL_WINDOW
206     {
207         tdist = abs(modeList[i]->w - rw) + abs(modeList[i]->h - rh);
208         // find closest dist
209         if( bestdist > tdist )
210         {
211             bestdist = tdist;
212             best = i;
213             if( tdist == 0 )  break;   // found exact match
214         }
215     }
216     modenum.index = best;  // 1..
217     modenum.modetype = rmodetype;
218 done:
219     return modenum;
220 }
221 
222 
223 static
VID_PrepareModeList(void)224 void VID_PrepareModeList(void)
225 {
226     int i;
227 
228     for (i=0;i<MAXWINMODES;i++)
229     {
230         modeList[i].w = windowedModes[i][0];
231         modeList[i].h = windowedModes[i][1];
232         modeList[i].freq = 0;
233     }
234 
235     nummodes = i;
236 }
237 
238 
239 //   request_drawmode : vid_drawmode_e
240 //   request_fullscreen : true if want fullscreen modes
241 //   request_bitpp : bits per pixel
242 // Return true if there are viable modes.
VID_Query_Modelist(byte request_drawmode,byte request_fullscreen,byte request_bitpp)243 boolean  VID_Query_Modelist( byte request_drawmode, byte request_fullscreen, byte request_bitpp )
244 {
245     if( request_drawmode == DRM_opengl )
246     {
247         return true;
248     }
249     return false;
250 }
251 
252 
SetDSpMode(int w,int h,boolean enable)253 void SetDSpMode(int w, int h, boolean enable)
254 {
255     static int lastw, lasth, last_enable = -1;
256 
257     if (mainWindow)
258     {
259         DisposeWindow(mainWindow);
260         mainWindow = NULL;
261     }
262 
263     if (enable)
264     {
265         HideCursor();
266         HideMenuBar();
267     }
268     else
269     {
270         ShowCursor();
271         ShowMenuBar();
272         DrawMenuBar();
273     }
274 
275     lastw = w;
276     lasth = h;
277     last_enable = enable;
278 }
279 
280 
281 // Returns FAIL_end, FAIL_create, of status_return_e, 1 on success;
VID_SetMode(modenum_t modenum)282 int VID_SetMode(modenum_t modenum)
283 {
284     boolean set_fullscreen = (modenum.modetype == MODE_fullscreen);
285 
286 #if 0
287     if( graphics_state == VGS_off )
288         req_bitpp = 16;                     // quick hack as config hasn't been parsed
289                                             // (don't want to assume 32 bit available)
290     if( req_bitpp < 16 )
291         req_bitpp = 16;                     // dont want 8-bit (?)
292 #else
293     if ( graphics_state == VGS_off )
294         cv_scr_depth.value = 16;            // quick hack as config hasn't been parsed
295                                             // (don't want to assume 32 bit available)
296     if (cv_scr_depth.value<16)
297         CV_Set(&cv_scr_depth,"16");         // dont want 8-bit (?)
298 #endif
299 
300     vid.draw_ready = 0;  // disable print reaching console
301 
302     vid.bitpp = 32;
303     vid.bytepp = 4;
304     vid.width = modeList[modenum.index].w;
305     vid.height = modeList[modenum.index].h;
306     vid.widthbytes = vid.width * vid.bytepp;
307 
308     GenPrintf( EMSG_info, "VID_SetMode(%s,%i) %dx%d\n",
309                modetype_string[modenum.modetype], modenum.index, vid.width, vid.height);
310 
311     // OpenGL only
312     vid.direct_rowbytes = 0;
313     vid.direct_size = 0;
314     vid.ybytes = 0;
315     vid.screen_size = 0;
316     vid.display = NULL;
317     vid.screen1 = NULL;
318 
319     SetDSpMode(vid.width, vid.height, set_fullscreen);
320 
321     if( rendermode = render_opengl )
322     {
323         // OpenGL only
324         vid.direct_rowbytes = 0;
325         vid.direct_size = 0;
326         vid.ybytes = 0;
327         vid.screen_size = 0;
328         vid.display = NULL;
329         vid.screen1 = NULL;
330         OglMacSurface(&mainWindow, vid.width, vid.height, set_fullscreen);
331     }
332     else
333     {
334         // NOT FINISHED ???
335     }
336 
337     vid.recalc = true;
338     vid.modenum = modenum;
339     vid.fullscreen = set_fullscreen;
340 
341     return 1;
342 }
343 
GetTextureMemoryUsed(void)344 int GetTextureMemoryUsed(void)
345 {
346     return 0;
347 }
348 
349 // NOT FINISHED
I_FinishUpdate(void)350 void I_FinishUpdate(void)
351 {
352     if(rendermode==render_soft)
353     {
354         // NOT FINISHED
355     }
356     else
357     {
358         HWD.pfnFinishUpdate();
359     }
360 }
361 
362 
363 // Initialize the graphics system, with a initial window.
I_StartupGraphics(void)364 void I_StartupGraphics( void )
365 {
366     modenum_t  initialmode = {MODE_window,0};  // the initial mode
367     // pre-init by V_Init_VideoControl
368 
369     graphics_state = VGS_startup;
370 
371     I_StartupMouse( false );
372 
373     native_drawmode = DRM_opengl;
374     // do not assume 32 bit available
375     native_bitpp = 32;
376     native_bytepp = 4;
377 
378     VID_PrepareModeList();
379 
380     if( Set_VidMode( initialmode ) < 0 )   goto abort_error
381 
382     graphics_state = VGS_active;
383     if( verbose )
384         GenPrintf(EMSG_ver, "StartupGraphics completed\n" );
385     return;
386 
387 abort_error:
388     // cannot return without a display screen
389     I_Error("StartupGraphics Abort\n");
390 }
391 
392 
393 // Setup HWR calls according to rendermode.
I_Rendermode_setup(void)394 int I_Rendermode_setup( void )
395 {
396     HWD.pfnInit             = hwSym("Init");
397     HWD.pfnFinishUpdate     = hwSym("FinishUpdate");
398     HWD.pfnDraw2DLine       = hwSym("Draw2DLine");
399     HWD.pfnDrawPolygon      = hwSym("DrawPolygon");
400     HWD.pfnSetBlend         = hwSym("SetBlend");
401     HWD.pfnClearBuffer      = hwSym("ClearBuffer");
402     HWD.pfnSetTexture       = hwSym("SetTexture");
403     HWD.pfnReadRect         = hwSym("ReadRect");
404     HWD.pfnGClipRect        = hwSym("GClipRect");
405     HWD.pfnClearMipMapCache = hwSym("ClearMipMapCache");
406     HWD.pfnSetSpecialState  = hwSym("SetSpecialState");
407     HWD.pfnSetTransform     = hwSym("SetTransform");
408     HWD.pfnDrawMD2          = hwSym("DrawMD2");
409     HWD.pfnSetPalette       = OglMacSetPalette;
410     HWD.pfnGetTextureUsed   = GetTextureMemoryUsed;
411     return 1;
412 }
413 
414 
415 // Called to start rendering graphic screen according to the request switches.
416 // Fullscreen modes are possible.
417 // param: req_drawmode, req_bitpp, req_alt_bitpp, req_width, req_height.
418 // Returns FAIL_select, FAIL_end, FAIL_create, of status_return_e, 1 on success;
I_RequestFullGraphics(byte select_fullscreen)419 int I_RequestFullGraphics( byte select_fullscreen )
420 {
421     modenum_t  initialmode;  // the initial mode
422     byte  select_bitpp = 32;  // to select modes
423     byte  select_fullscreen_mode;
424     int  ret_value;
425 
426     // Seems to be OpenGL only.
427     switch( req_drawmode )
428     {
429       case DRM_opengl:
430 #if 0
431         select_bitpp = req_bitpp;
432 #else
433         select_bitpp = cv_scr_depth.EV;
434 #endif
435 //        select_bitpp = native_bitpp;
436         break;
437 #if 0
438       case DRM_native;
439         select_bitpp = native_bitpp;
440         // NOT FINISHED
441         break;
442 #endif
443       default:
444         goto no_modes;
445     }
446 
447     I_Rendermode_setup();
448 
449     textureformatGL = GL_RGBA;
450 //    rendermode = render_opengl;  // rendermode is set by v_switch_drawmode
451 
452     if( nummodes == 0 )
453         goto no_modes;
454 
455     vid.width = req_width;
456     vid.height = req_height;
457 
458     select_fullscreen_mode = vid_mode_table[select_fullscreen];
459     initialmode = VID_GetModeForSize( req_width, req_height, select_fullscreen_mode );
460     ret_value = VID_SetMode( initialmode );
461     if( ret_value < 0 )
462         return ret_value;
463 
464     graphics_state = VGS_fullactive;
465 
466     if( verbose )
467         GenPrintf(EMSG_ver, "RequestFullGraphics completed\n" );
468     return ret_value;
469 
470 no_modes:
471     return FAIL_select;
472 }
473 
474 
I_ShutdownGraphics(void)475 void I_ShutdownGraphics(void)
476 {
477     if( graphics_state <= VGS_shutdown )
478         return;
479 
480     graphics_state = VGS_shutdown;  // to catch some repeats due to errors
481 
482     CONS_Printf("I_ShutdownGraphics\n");
483     OglMacShutdown();
484     DisposeWindow(mainWindow);
485     ShowCursor();
486 
487     graphics_state = VGS_off;
488 }
489