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