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