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