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