This commit was manufactured by cvs2svn to create tag 'd2x-0_1_2'.
[btb/d2x.git] / arch / ogl / wgl.c
1 /*
2  * $Source: /cvs/cvsroot/d2x/arch/ogl/wgl.c,v $
3  * $Revision: 1.2 $
4  * $Author: bradleyb $
5  * $Date: 2001-11-04 08:49:57 $
6  *
7  * opengl platform specific functions for WGL - added by Peter Hawkins
8  * fullscreen example code courtesy of Jeff Slutter
9  * everything merged together and cleaned up by Matt Mueller
10  *         (with some win32 help from Nirvana)
11  *
12  * $Log: not supported by cvs2svn $
13  * Revision 1.1  2001/10/25 08:25:34  bradleyb
14  * Finished moving stuff to arch/blah.  I know, it's ugly, but It'll be easier to sync with d1x.
15  *
16  * Revision 1.2  2001/01/29 13:47:52  bradleyb
17  * Fixed build, some minor cleanups.
18  *
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24
25 #include <windows.h>
26 #include <mmsystem.h>
27 #include "ogl_init.h"
28 #include "vers_id.h"
29 #include "error.h"
30 #include "key.h"
31 #include "joy.h"
32 #include "mouse.h"
33 #include "digi.h"
34 #include "args.h"
35 #include "resource.h"
36 /*#include "event.h"*/
37 #include <stdio.h>
38
39 //not defined in cygwin, needed to keep windows from resizing everything to fit the fullscreen res.
40 #ifndef CDS_FULLSCREEN
41 #define CDS_FULLSCREEN 0x4
42 #endif
43
44 DEVMODE devmode;//global so the activate proc can reset the screen mode.
45 HINSTANCE hInst=NULL;
46 HWND g_hWnd=NULL;
47
48 extern int Inferno_verbose;
49
50 static int mouse_hidden=0;
51
52
53 //extern unsigned int key_wparam, key_lparam, key_msg;
54 void keyboard_handler();
55 extern int WMKey_Handler_Ready;
56
57 HDC hDC;
58
59 static int GLPREF_width,GLPREF_height;
60 static int GLSTATE_width,GLSTATE_height;
61 static bool GLPREF_windowed;
62
63 static HGLRC GL_ResourceContext=NULL;
64 //static WORD Saved_gamma_values[256*3];
65 bool OpenGL_Initialize(void);
66 void OpenGL_Shutdown(void);
67
68
69 void PumpMessages(void)
70 {
71   MSG msg;
72
73   while (PeekMessage(&msg,NULL,0,0,PM_REMOVE|PM_NOYIELD))
74   {
75         TranslateMessage(&msg);
76         DispatchMessage(&msg);
77   }
78 }
79 static void finiObjects()
80 {
81 //      ogl_close();
82 //   if(mouse_hidden){
83 //    ShowCursor(TRUE);
84 //      mouse_hidden=0;
85 //   }
86
87  //  DisableOpenGL( g_hWnd, hDC, hRC );
88
89
90
91 int vid_susp=0;
92 int wgl_game_activate(int active,int min){
93         int i=0;//do_game_activate(active,min);
94         if (!gl_initialized) return -1;
95         //      printf("****** wgl_game_activate: %i %i,%i %i *******\n",GLPREF_windowed,active,min,vid_susp);
96         if (!active){
97                 mouse_close();
98                 if (!GLPREF_windowed)
99                         if (!vid_susp){
100                                 ChangeDisplaySettings(NULL,0);
101                                 vid_susp=1;
102                         }
103         }else{
104                 mouse_init(0);
105                 if (!GLPREF_windowed)
106                         if (vid_susp){
107                                 ChangeDisplaySettings(&devmode,CDS_FULLSCREEN);
108                                 ShowWindow(g_hWnd,SW_SHOWNORMAL);
109                                 SetWindowPos(g_hWnd,HWND_TOPMOST,0,0,GLPREF_width,GLPREF_height,SWP_FRAMECHANGED);//if you don't set the pos, it comes up half off the screen, or just shows the desktop
110                                 UpdateWindow(g_hWnd);
111                                 wglMakeCurrent(NULL, NULL);
112                                 wglMakeCurrent(hDC,GL_ResourceContext);//this seems to fix some glitches that appear when you alt-tab back in.
113                                 vid_susp=0;
114                         }
115         }
116         //      printf("****** -----------------: %i %i,%i %i *******\n",GLPREF_windowed,active,min,vid_susp);
117         return i;
118 }
119 long PASCAL DescentWndProc(HWND hWnd,UINT message,
120                                                    WPARAM wParam,LPARAM lParam )
121 {
122   switch(message)
123   {
124
125    case WM_KEYDOWN:
126    case WM_KEYUP:
127         if (WMKey_Handler_Ready) {
128 //      key_wparam=wParam; key_lparam=lParam; key_msg=message;
129           keyboard_handler();
130         }
131         break;
132    case WM_MOUSEMOVE:
133    case WM_LBUTTONDOWN:
134    case WM_LBUTTONUP:
135    case WM_RBUTTONDOWN:
136    case WM_RBUTTONUP:
137    case WM_NCMOUSEMOVE:
138    case WM_NCLBUTTONDOWN:
139    case WM_NCLBUTTONUP:
140    case WM_NCRBUTTONDOWN:
141    case WM_NCRBUTTONUP:
142          break;
143    case WM_PALETTECHANGED:
144    case WM_PALETTEISCHANGING:
145          return 0;
146    case WM_KILLFOCUS:
147          if (!GLPREF_windowed)
148                  ShowWindow(g_hWnd, SW_SHOWMINNOACTIVE);//this minimizes the game after you alt-tab out.
149          break;
150    case WM_ACTIVATE:
151          wgl_game_activate((!(LOWORD(wParam) == WA_INACTIVE)),(BOOL) HIWORD(wParam));
152          break;
153    case WM_ACTIVATEAPP:
154 //     Win32_Key_Hook(wParam);
155 // DPH: This doesn't work... no idea why not...
156          break;
157    case WM_DESTROY:
158          finiObjects();
159          PostQuitMessage(0);
160          break;
161    default:
162          return DefWindowProc(hWnd,message,wParam,lParam);
163   }
164   return 1;
165 }
166
167
168
169 void ogl_swap_buffers_internal(void){
170         SwapBuffers( hDC );
171 }
172
173 int get_win_x_bs(void){
174 //      return GetSystemMetrics(SM_CXBORDER)*2
175         return GetSystemMetrics(SM_CXFIXEDFRAME)*2;
176 }
177 int get_win_y_bs(void){
178 //      return GetSystemMetrics(SM_CYBORDER)*2+GetSystemMetrics(SM_CYCAPTION);
179         return GetSystemMetrics(SM_CYFIXEDFRAME)*2+GetSystemMetrics(SM_CYCAPTION);
180 }
181 void win32_create_window(int x,int y)
182 {
183         int flags;
184
185         WNDCLASS wcDescentClass;
186
187         if (!hInst)
188                 Error("hInst=NULL\n");
189
190
191         wcDescentClass.lpszClassName = "WinD1X";
192         wcDescentClass.hInstance     = hInst;
193         wcDescentClass.lpfnWndProc   = DescentWndProc;
194         wcDescentClass.hCursor       = LoadCursor(NULL, IDC_ARROW);
195         //wcDescentClass.hIcon         = LoadIcon(NULL, IDI_WINLOGO);
196         wcDescentClass.hIcon         = LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAIN_ICON));
197         wcDescentClass.lpszMenuName  = NULL;
198         wcDescentClass.hbrBackground = NULL;
199         wcDescentClass.style         = CS_OWNDC;
200         wcDescentClass.cbClsExtra    = 0;
201         wcDescentClass.cbWndExtra    = 0;
202                 
203         // Register the class
204         if (!RegisterClass(&wcDescentClass)){
205 //              printf("RegisterClass==0?\n");
206                 //always seems to return 0 after the first time, yet if you remove the call, it crashes. Heh.
207         }
208
209         if (ogl_fullscreen)
210                 flags=WS_POPUP;//uh.. don't remember if removing sysmenu did anything or not.. but it works.
211                 //flags=WS_POPUP | WS_SYSMENU;
212         else
213                 flags=WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;//let us minimize it.
214                 //flags=WS_OVERLAPPED | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
215
216         if (!ogl_fullscreen){
217                 x+=get_win_x_bs();y+=get_win_y_bs();
218         }else{
219                 if (FindArg("-gl_test2")){
220                         x=GetSystemMetrics(SM_CXSCREEN);
221                         y=GetSystemMetrics(SM_CYSCREEN);
222                 }
223         }
224         g_hWnd = CreateWindowEx(0,
225                         "WinD1X",
226                         "Descent",
227                         flags,
228                         0, 0,
229                         x,y,
230                         NULL,
231                         NULL,
232                         hInst,
233                         NULL
234                                                    );
235
236         if (!g_hWnd) Error("no window?\n");
237         ShowWindow(g_hWnd,SW_SHOWNORMAL);
238         UpdateWindow(g_hWnd);
239
240         OpenGL_Initialize();
241
242         if (ogl_fullscreen){
243         ShowCursor(FALSE);
244         mouse_hidden = 1;
245         }
246
247         key_init();
248         mouse_init(0);
249         joy_init(JOYSTICKID1);
250         if (!FindArg( "-nosound" ))
251                 digi_init();
252 //      printf("arch_init successfully completed\n");
253
254         gl_initialized=1;
255 }
256 void ogl_destroy_window(void){
257         if (gl_initialized){
258                 ogl_smash_texture_list_internal();
259                 if (mouse_hidden){
260                         ShowCursor(TRUE);
261                         mouse_hidden = 0;
262                 }
263                 if (g_hWnd){
264                         key_close();
265                         mouse_close();
266                         joy_close();
267                         if (!FindArg( "-nosound" ))
268                                 digi_close();
269                         OpenGL_Shutdown();
270                         DestroyWindow(g_hWnd);
271                 }else
272                         Error("ogl_destroy_window: no g_hWnd?\n");
273                 gl_initialized=0;
274         }
275         return;
276 }
277
278 void ogl_do_fullscreen_internal(void){
279         if (GLPREF_windowed==ogl_fullscreen){
280                 ogl_destroy_window();
281                 win32_create_window(GLPREF_width,GLPREF_height);
282                 ogl_vivify_texture_list_internal();
283         }
284 }
285
286
287 int ogl_init_window(int x, int y){
288         GLPREF_width=x;
289         GLPREF_height=y;
290         if (gl_initialized){
291                 if (GLSTATE_width==GLPREF_width && GLSTATE_height==GLPREF_height && GLPREF_windowed!=ogl_fullscreen)
292                         return 0;//we are already in the right mode, don't do anything.
293                 if (!ogl_fullscreen && GLPREF_windowed){
294                         SetWindowPos(g_hWnd,0,0,0,x+get_win_x_bs(),y+get_win_y_bs(),SWP_NOMOVE);
295                 }else{
296                         ogl_destroy_window();
297                         win32_create_window(x,y);
298                         ogl_vivify_texture_list_internal();
299                 }
300         }else {
301                 win32_create_window(x,y);
302         }
303         return 0;
304 }
305 void ogl_init(void){
306         hInst=GetModuleHandle (NULL);
307 }
308 void ogl_close(void){
309         ogl_destroy_window();
310 }
311
312
313 //windows opengl fullscreen changing - courtesy of Jeff Slutter
314
315 /*
316
317   Windows Full Screen Setup
318
319   ===========================================================================
320 */
321
322
323 // Entering this function, the following values must be valid
324 //              GLPREF_width,GLPREF_height: preferred width and height
325 //              GLPREF_windowed: do we want windowed or full screen mode
326 //              g_hWnd: handle to the window created for OpenGL
327 //      On exit from this function (if returned true) the following values will be set
328 //              GLSTATE_width,GLSTATE_height: real width and height of screen
329 //              hDC: device context of the window
330 //              GL_ResourceContext: OpenGL resource context
331 //              Saved_gamma_values: Initial gamma values
332 bool OpenGL_Initialize(void)
333 {
334         char *errstr="";
335         int width,height;
336         int pf;
337         PIXELFORMATDESCRIPTOR pfd;//, pfd_copy;
338
339         GLPREF_windowed=!ogl_fullscreen;
340         
341         if (FindArg("-gl_test1")){
342                 GLSTATE_width = GLPREF_width;
343                 GLSTATE_height = GLPREF_height;
344         }else{
345                 if(!GLPREF_windowed)
346                 {
347                         // First set our display mode
348                         // Create direct draw surface
349                         int retval;
350
351                         devmode.dmSize=sizeof(devmode);
352                         devmode.dmBitsPerPel=16;
353                         devmode.dmPelsWidth=GLPREF_width;
354                         devmode.dmPelsHeight=GLPREF_height;
355                         devmode.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
356                         if ((retval=FindArg("-gl_refresh"))){
357                                 devmode.dmDisplayFrequency=atoi(Args[retval+1]);
358                                 if (devmode.dmDisplayFrequency>=60)//uhh, I hope no one actually wants a refresh lower than 60.. gag.
359                                         devmode.dmFields|=DM_DISPLAYFREQUENCY;
360                                 printf("trying refresh %i hz\n",devmode.dmDisplayFrequency);
361                         }
362
363                         retval=ChangeDisplaySettings(&devmode,CDS_FULLSCREEN);
364
365                         if (retval!=DISP_CHANGE_SUCCESSFUL)
366                         {
367                                 // we couldn't switch to the desired screen mode
368                                 // fall back to 640x480
369                                 retval=-1;
370                                 devmode.dmBitsPerPel=16;
371                                 devmode.dmPelsWidth=640;
372                                 devmode.dmPelsHeight=480;
373                                 devmode.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
374
375                                 retval=ChangeDisplaySettings(&devmode,CDS_FULLSCREEN);
376                                 if (retval!=DISP_CHANGE_SUCCESSFUL)
377                                 {
378                                         errstr="ChangeDisplaySettings";
379                                         // we couldn't even switch to 640x480, we're out of here
380                                         // restore screen mode to default
381                                         ChangeDisplaySettings(NULL,0);
382                                         goto OpenGLError;
383                                 }else
384                                 {
385                                         // successful, change our global settings to reflect what 
386                                         // mode we are at
387                                         GLPREF_width=640;
388                                         GLPREF_height=480;
389                                 }
390                         }else
391                         {
392                                 // success at changing the video mode
393                         }
394                 }
395
396
397                 if(GLPREF_windowed)
398                 {
399                         // we want windowed mode, figure out how big the window is
400                         RECT rect;
401                         GetWindowRect(g_hWnd,&rect);
402                         width=abs(rect.right-rect.left);
403                         height=abs(rect.bottom-rect.top);
404                 }else
405                 {
406                         RECT rect;
407                         // full screen mode, we want the window to be on top of everything
408                         SetWindowPos(g_hWnd,HWND_TOPMOST,0,0,GLPREF_width,GLPREF_height,SWP_FRAMECHANGED);
409                         width=GLPREF_width;
410                         height=GLPREF_height;
411                         GetWindowRect(g_hWnd,&rect);
412                 }
413
414                 GLSTATE_width = width;
415                 GLSTATE_height = height;
416
417         }
418         
419         hDC = GetDC(g_hWnd);
420         
421         // Now we finally setup OpenGL
422         // If OpenGL is to be dynamically loaded, do this now (if the DLL isn't already
423         // loaded)
424         // remove the following error when you figure out what you want to do
425         // it's put here to make sure you notice this
426 #ifdef OGL_RUNTIME_LOAD
427         ogl_init_load_library();
428 #endif
429
430         // Setup our pixel format
431
432         memset(&pfd,0,sizeof(pfd));
433         pfd.nSize        = sizeof(pfd);
434         pfd.nVersion     = 1;
435         pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
436 //      pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_GENERIC_ACCELERATED;
437         pfd.iPixelType   = PFD_TYPE_RGBA;
438         //let the ogl driver decide. (fixes no hw accel in 16bit mode in w2k with tnt2)
439 //      pfd.cColorBits = 16;
440 //      pfd.cAlphaBits = 8;
441 //      pfd.cDepthBits = 0;
442 //      pfd.cAccumBits = 0;
443 //      pfd.cStencilBits = 0;
444         pfd.iLayerType = PFD_MAIN_PLANE;
445         pfd.dwLayerMask = PFD_MAIN_PLANE;
446
447
448         // Find the user's "best match" PFD 
449         pf = ChoosePixelFormat(hDC,&pfd);
450         if(pf == 0) 
451         {
452                 errstr="ChoosePixelFormat";
453                 // no pixel format closely matches      
454                 goto OpenGLError;
455         } 
456
457         // Set the new PFD
458         if(SetPixelFormat(hDC,pf,&pfd)==FALSE) 
459         {
460                 errstr="SetPixelFormat";
461                 // unable to set the pixel format
462                 goto OpenGLError;
463         }
464
465         // Now retrieve the PFD, we need to check some things
466 /*      if(DescribePixelFormat(hDC,pf,sizeof(PIXELFORMATDESCRIPTOR),&pfd_copy)==0)
467         {
468                 errstr="DescribePixelFormat";
469                 // unable to get the PFD
470                 goto OpenGLError;
471         }
472
473         // Make sure we are hardware accelerated
474         if((pfd_copy.dwFlags&PFD_GENERIC_ACCELERATED)==0&&(pfd_copy.dwFlags&PFD_GENERIC_FORMAT)!=0)
475         {
476                 // we are not hardware accelerated!
477                 goto OpenGLError;
478         }*/
479
480         // Finally, create our OpenGL context and make it current
481         GL_ResourceContext = wglCreateContext(hDC);
482         if(GL_ResourceContext==NULL)
483         {
484                 errstr="wglCreateContext";
485                 // we couldn't create a context!
486                 goto OpenGLError;
487         }
488
489         // Make the context current
490         wglMakeCurrent(hDC,GL_ResourceContext);
491
492         // Save our gamma values because we'll probably be changing them,
493         // this way we can restore them on exit
494
495 //      GetDeviceGammaRamp(hDC,(LPVOID)Saved_gamma_values);
496
497         return true;
498
499 OpenGLError:
500         // Shutdown OpenGL
501         OpenGL_Shutdown();
502         Error("opengl init error: %s\n",errstr);
503         return false;
504 }
505
506 void OpenGL_Shutdown(void)
507 {
508         // Do any needed OpenGL shutdown here
509
510
511         // Now do Window specific shutdown
512         if(wglMakeCurrent)//check to make sure the function is valid (dyanmic loaded OpenGL)
513                 wglMakeCurrent(NULL, NULL);
514
515         if(wglDeleteContext)//check to make sure the function is valid (dyanmic loaded OpenGL)
516                 wglDeleteContext(GL_ResourceContext);
517         
518         // Restore back to user screen settings
519         if(!GLPREF_windowed)
520                 ChangeDisplaySettings(NULL,0);
521
522         // Restore gamma values
523
524 //      SetDeviceGammaRamp(hDC,(LPVOID)Saved_gamma_values);
525         
526         ReleaseDC(g_hWnd,hDC);
527 }