2 * $Source: /cvs/cvsroot/d2x/arch/ogl/wgl.c,v $
5 * $Date: 2001-11-04 08:49:57 $
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)
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.
16 * Revision 1.2 2001/01/29 13:47:52 bradleyb
17 * Fixed build, some minor cleanups.
36 /*#include "event.h"*/
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
44 DEVMODE devmode;//global so the activate proc can reset the screen mode.
48 extern int Inferno_verbose;
50 static int mouse_hidden=0;
53 //extern unsigned int key_wparam, key_lparam, key_msg;
54 void keyboard_handler();
55 extern int WMKey_Handler_Ready;
59 static int GLPREF_width,GLPREF_height;
60 static int GLSTATE_width,GLSTATE_height;
61 static bool GLPREF_windowed;
63 static HGLRC GL_ResourceContext=NULL;
64 //static WORD Saved_gamma_values[256*3];
65 bool OpenGL_Initialize(void);
66 void OpenGL_Shutdown(void);
69 void PumpMessages(void)
73 while (PeekMessage(&msg,NULL,0,0,PM_REMOVE|PM_NOYIELD))
75 TranslateMessage(&msg);
76 DispatchMessage(&msg);
79 static void finiObjects()
87 // DisableOpenGL( g_hWnd, hDC, hRC );
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);
100 ChangeDisplaySettings(NULL,0);
105 if (!GLPREF_windowed)
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.
116 // printf("****** -----------------: %i %i,%i %i *******\n",GLPREF_windowed,active,min,vid_susp);
119 long PASCAL DescentWndProc(HWND hWnd,UINT message,
120 WPARAM wParam,LPARAM lParam )
127 if (WMKey_Handler_Ready) {
128 // key_wparam=wParam; key_lparam=lParam; key_msg=message;
138 case WM_NCLBUTTONDOWN:
140 case WM_NCRBUTTONDOWN:
143 case WM_PALETTECHANGED:
144 case WM_PALETTEISCHANGING:
147 if (!GLPREF_windowed)
148 ShowWindow(g_hWnd, SW_SHOWMINNOACTIVE);//this minimizes the game after you alt-tab out.
151 wgl_game_activate((!(LOWORD(wParam) == WA_INACTIVE)),(BOOL) HIWORD(wParam));
154 // Win32_Key_Hook(wParam);
155 // DPH: This doesn't work... no idea why not...
162 return DefWindowProc(hWnd,message,wParam,lParam);
169 void ogl_swap_buffers_internal(void){
173 int get_win_x_bs(void){
174 // return GetSystemMetrics(SM_CXBORDER)*2
175 return GetSystemMetrics(SM_CXFIXEDFRAME)*2;
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);
181 void win32_create_window(int x,int y)
185 WNDCLASS wcDescentClass;
188 Error("hInst=NULL\n");
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;
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.
210 flags=WS_POPUP;//uh.. don't remember if removing sysmenu did anything or not.. but it works.
211 //flags=WS_POPUP | WS_SYSMENU;
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;
216 if (!ogl_fullscreen){
217 x+=get_win_x_bs();y+=get_win_y_bs();
219 if (FindArg("-gl_test2")){
220 x=GetSystemMetrics(SM_CXSCREEN);
221 y=GetSystemMetrics(SM_CYSCREEN);
224 g_hWnd = CreateWindowEx(0,
236 if (!g_hWnd) Error("no window?\n");
237 ShowWindow(g_hWnd,SW_SHOWNORMAL);
238 UpdateWindow(g_hWnd);
249 joy_init(JOYSTICKID1);
250 if (!FindArg( "-nosound" ))
252 // printf("arch_init successfully completed\n");
256 void ogl_destroy_window(void){
258 ogl_smash_texture_list_internal();
267 if (!FindArg( "-nosound" ))
270 DestroyWindow(g_hWnd);
272 Error("ogl_destroy_window: no g_hWnd?\n");
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();
287 int ogl_init_window(int x, int y){
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);
296 ogl_destroy_window();
297 win32_create_window(x,y);
298 ogl_vivify_texture_list_internal();
301 win32_create_window(x,y);
306 hInst=GetModuleHandle (NULL);
308 void ogl_close(void){
309 ogl_destroy_window();
313 //windows opengl fullscreen changing - courtesy of Jeff Slutter
317 Windows Full Screen Setup
319 ===========================================================================
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)
337 PIXELFORMATDESCRIPTOR pfd;//, pfd_copy;
339 GLPREF_windowed=!ogl_fullscreen;
341 if (FindArg("-gl_test1")){
342 GLSTATE_width = GLPREF_width;
343 GLSTATE_height = GLPREF_height;
347 // First set our display mode
348 // Create direct draw surface
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);
363 retval=ChangeDisplaySettings(&devmode,CDS_FULLSCREEN);
365 if (retval!=DISP_CHANGE_SUCCESSFUL)
367 // we couldn't switch to the desired screen mode
368 // fall back to 640x480
370 devmode.dmBitsPerPel=16;
371 devmode.dmPelsWidth=640;
372 devmode.dmPelsHeight=480;
373 devmode.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
375 retval=ChangeDisplaySettings(&devmode,CDS_FULLSCREEN);
376 if (retval!=DISP_CHANGE_SUCCESSFUL)
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);
385 // successful, change our global settings to reflect what
392 // success at changing the video mode
399 // we want windowed mode, figure out how big the window is
401 GetWindowRect(g_hWnd,&rect);
402 width=abs(rect.right-rect.left);
403 height=abs(rect.bottom-rect.top);
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);
410 height=GLPREF_height;
411 GetWindowRect(g_hWnd,&rect);
414 GLSTATE_width = width;
415 GLSTATE_height = height;
421 // Now we finally setup OpenGL
422 // If OpenGL is to be dynamically loaded, do this now (if the DLL isn't already
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();
430 // Setup our pixel format
432 memset(&pfd,0,sizeof(pfd));
433 pfd.nSize = sizeof(pfd);
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;
448 // Find the user's "best match" PFD
449 pf = ChoosePixelFormat(hDC,&pfd);
452 errstr="ChoosePixelFormat";
453 // no pixel format closely matches
458 if(SetPixelFormat(hDC,pf,&pfd)==FALSE)
460 errstr="SetPixelFormat";
461 // unable to set the pixel format
465 // Now retrieve the PFD, we need to check some things
466 /* if(DescribePixelFormat(hDC,pf,sizeof(PIXELFORMATDESCRIPTOR),&pfd_copy)==0)
468 errstr="DescribePixelFormat";
469 // unable to get the PFD
473 // Make sure we are hardware accelerated
474 if((pfd_copy.dwFlags&PFD_GENERIC_ACCELERATED)==0&&(pfd_copy.dwFlags&PFD_GENERIC_FORMAT)!=0)
476 // we are not hardware accelerated!
480 // Finally, create our OpenGL context and make it current
481 GL_ResourceContext = wglCreateContext(hDC);
482 if(GL_ResourceContext==NULL)
484 errstr="wglCreateContext";
485 // we couldn't create a context!
489 // Make the context current
490 wglMakeCurrent(hDC,GL_ResourceContext);
492 // Save our gamma values because we'll probably be changing them,
493 // this way we can restore them on exit
495 // GetDeviceGammaRamp(hDC,(LPVOID)Saved_gamma_values);
502 Error("opengl init error: %s\n",errstr);
506 void OpenGL_Shutdown(void)
508 // Do any needed OpenGL shutdown here
511 // Now do Window specific shutdown
512 if(wglMakeCurrent)//check to make sure the function is valid (dyanmic loaded OpenGL)
513 wglMakeCurrent(NULL, NULL);
515 if(wglDeleteContext)//check to make sure the function is valid (dyanmic loaded OpenGL)
516 wglDeleteContext(GL_ResourceContext);
518 // Restore back to user screen settings
520 ChangeDisplaySettings(NULL,0);
522 // Restore gamma values
524 // SetDeviceGammaRamp(hDC,(LPVOID)Saved_gamma_values);
526 ReleaseDC(g_hWnd,hDC);