1 /* $Id: wgl.c,v 1.8 2004-05-20 07:49:21 btb Exp $ */
4 * opengl platform specific functions for WGL - added by Peter Hawkins
5 * fullscreen example code courtesy of Jeff Slutter
6 * everything merged together and cleaned up by Matt Mueller
7 * (with some win32 help from Nirvana)
28 /*#include "event.h"*/
31 //not defined in cygwin, needed to keep windows from resizing everything to fit the fullscreen res.
32 #ifndef CDS_FULLSCREEN
33 #define CDS_FULLSCREEN 0x4
36 DEVMODE devmode;//global so the activate proc can reset the screen mode.
40 extern int Inferno_verbose;
42 static int mouse_hidden=0;
45 //extern unsigned int key_wparam, key_lparam, key_msg;
46 void keyboard_handler();
47 extern int WMKey_Handler_Ready;
51 static int GLPREF_width,GLPREF_height;
52 static int GLSTATE_width,GLSTATE_height;
53 static bool GLPREF_windowed;
55 static HGLRC GL_ResourceContext=NULL;
56 static WORD Saved_gamma_values[256 * 3];
57 static WORD gammaramp[256 * 3];
58 bool OpenGL_Initialize(void);
59 void OpenGL_Shutdown(void);
62 void PumpMessages(void)
66 while (PeekMessage(&msg,NULL,0,0,PM_REMOVE|PM_NOYIELD))
68 TranslateMessage(&msg);
69 DispatchMessage(&msg);
72 static void finiObjects()
80 // DisableOpenGL( g_hWnd, hDC, hRC );
85 int wgl_game_activate(int active,int min){
86 int i=0;//do_game_activate(active,min);
87 if (!gl_initialized) return -1;
88 // printf("****** wgl_game_activate: %i %i,%i %i *******\n",GLPREF_windowed,active,min,vid_susp);
93 ChangeDisplaySettings(NULL,0);
100 ChangeDisplaySettings(&devmode,CDS_FULLSCREEN);
101 ShowWindow(g_hWnd,SW_SHOWNORMAL);
102 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
103 UpdateWindow(g_hWnd);
104 wglMakeCurrent(NULL, NULL);
105 wglMakeCurrent(hDC,GL_ResourceContext);//this seems to fix some glitches that appear when you alt-tab back in.
109 // printf("****** -----------------: %i %i,%i %i *******\n",GLPREF_windowed,active,min,vid_susp);
112 long PASCAL DescentWndProc(HWND hWnd,UINT message,
113 WPARAM wParam,LPARAM lParam )
120 if (WMKey_Handler_Ready) {
121 // key_wparam=wParam; key_lparam=lParam; key_msg=message;
131 case WM_NCLBUTTONDOWN:
133 case WM_NCRBUTTONDOWN:
136 case WM_PALETTECHANGED:
137 case WM_PALETTEISCHANGING:
140 if (!GLPREF_windowed)
141 ShowWindow(g_hWnd, SW_SHOWMINNOACTIVE);//this minimizes the game after you alt-tab out.
144 wgl_game_activate((!(LOWORD(wParam) == WA_INACTIVE)),(BOOL) HIWORD(wParam));
147 // Win32_Key_Hook(wParam);
148 // DPH: This doesn't work... no idea why not...
155 return DefWindowProc(hWnd,message,wParam,lParam);
161 int ogl_setbrightness_internal(void)
165 for (i = 0; i < 256; ++i)
167 gammaramp[i] = min((i + ogl_brightness_r * 4) * 256, 0xffff);
168 gammaramp[i + 256] = min((i + ogl_brightness_g * 4) * 256, 0xffff);
169 gammaramp[i + 512] = min((i + ogl_brightness_b * 4) * 256, 0xffff);
172 return SetDeviceGammaRamp(hDC, (LPVOID)gammaramp) ? 0 : -1;
175 void ogl_swap_buffers_internal(void){
179 int get_win_x_bs(void){
180 // return GetSystemMetrics(SM_CXBORDER)*2
181 return GetSystemMetrics(SM_CXFIXEDFRAME)*2;
183 int get_win_y_bs(void){
184 // return GetSystemMetrics(SM_CYBORDER)*2+GetSystemMetrics(SM_CYCAPTION);
185 return GetSystemMetrics(SM_CYFIXEDFRAME)*2+GetSystemMetrics(SM_CYCAPTION);
187 void win32_create_window(int x,int y)
191 WNDCLASS wcDescentClass;
194 Error("hInst=NULL\n");
197 wcDescentClass.lpszClassName = "WinD1X";
198 wcDescentClass.hInstance = hInst;
199 wcDescentClass.lpfnWndProc = DescentWndProc;
200 wcDescentClass.hCursor = LoadCursor(NULL, IDC_ARROW);
201 //wcDescentClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
202 wcDescentClass.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAIN_ICON));
203 wcDescentClass.lpszMenuName = NULL;
204 wcDescentClass.hbrBackground = NULL;
205 wcDescentClass.style = CS_OWNDC;
206 wcDescentClass.cbClsExtra = 0;
207 wcDescentClass.cbWndExtra = 0;
209 // Register the class
210 if (!RegisterClass(&wcDescentClass)){
211 // printf("RegisterClass==0?\n");
212 //always seems to return 0 after the first time, yet if you remove the call, it crashes. Heh.
216 flags=WS_POPUP;//uh.. don't remember if removing sysmenu did anything or not.. but it works.
217 //flags=WS_POPUP | WS_SYSMENU;
219 flags=WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;//let us minimize it.
220 //flags=WS_OVERLAPPED | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
222 if (!ogl_fullscreen){
223 x+=get_win_x_bs();y+=get_win_y_bs();
225 if (FindArg("-gl_test2")){
226 x=GetSystemMetrics(SM_CXSCREEN);
227 y=GetSystemMetrics(SM_CYSCREEN);
230 g_hWnd = CreateWindowEx(0,
242 if (!g_hWnd) Error("no window?\n");
243 ShowWindow(g_hWnd,SW_SHOWNORMAL);
244 UpdateWindow(g_hWnd);
255 joy_init(JOYSTICKID1);
256 if (!FindArg( "-nosound" ))
258 // printf("arch_init successfully completed\n");
262 void ogl_destroy_window(void){
264 ogl_smash_texture_list_internal();
273 if (!FindArg( "-nosound" ))
276 DestroyWindow(g_hWnd);
278 Error("ogl_destroy_window: no g_hWnd?\n");
284 void ogl_do_fullscreen_internal(void){
285 if (GLPREF_windowed==ogl_fullscreen){
286 ogl_destroy_window();
287 win32_create_window(GLPREF_width,GLPREF_height);
288 ogl_vivify_texture_list_internal();
293 int ogl_init_window(int x, int y){
297 if (GLSTATE_width==GLPREF_width && GLSTATE_height==GLPREF_height && GLPREF_windowed!=ogl_fullscreen)
298 return 0;//we are already in the right mode, don't do anything.
299 if (!ogl_fullscreen && GLPREF_windowed){
300 SetWindowPos(g_hWnd,0,0,0,x+get_win_x_bs(),y+get_win_y_bs(),SWP_NOMOVE);
302 ogl_destroy_window();
303 win32_create_window(x,y);
304 ogl_vivify_texture_list_internal();
307 win32_create_window(x,y);
312 hInst=GetModuleHandle (NULL);
314 void ogl_close(void){
315 ogl_destroy_window();
319 //windows opengl fullscreen changing - courtesy of Jeff Slutter
323 Windows Full Screen Setup
325 ===========================================================================
329 // Entering this function, the following values must be valid
330 // GLPREF_width,GLPREF_height: preferred width and height
331 // GLPREF_windowed: do we want windowed or full screen mode
332 // g_hWnd: handle to the window created for OpenGL
333 // On exit from this function (if returned true) the following values will be set
334 // GLSTATE_width,GLSTATE_height: real width and height of screen
335 // hDC: device context of the window
336 // GL_ResourceContext: OpenGL resource context
337 // Saved_gamma_values: Initial gamma values
338 bool OpenGL_Initialize(void)
343 PIXELFORMATDESCRIPTOR pfd;//, pfd_copy;
345 GLPREF_windowed=!ogl_fullscreen;
347 if (FindArg("-gl_test1")){
348 GLSTATE_width = GLPREF_width;
349 GLSTATE_height = GLPREF_height;
353 // First set our display mode
354 // Create direct draw surface
357 devmode.dmSize=sizeof(devmode);
358 devmode.dmBitsPerPel=16;
359 devmode.dmPelsWidth=GLPREF_width;
360 devmode.dmPelsHeight=GLPREF_height;
361 devmode.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
362 if ((retval=FindArg("-gl_refresh"))){
363 devmode.dmDisplayFrequency=atoi(Args[retval+1]);
364 if (devmode.dmDisplayFrequency>=60)//uhh, I hope no one actually wants a refresh lower than 60.. gag.
365 devmode.dmFields|=DM_DISPLAYFREQUENCY;
366 printf("trying refresh %li hz\n", devmode.dmDisplayFrequency);
369 retval=ChangeDisplaySettings(&devmode,CDS_FULLSCREEN);
371 if (retval!=DISP_CHANGE_SUCCESSFUL)
373 // we couldn't switch to the desired screen mode
374 // fall back to 640x480
376 devmode.dmBitsPerPel=16;
377 devmode.dmPelsWidth=640;
378 devmode.dmPelsHeight=480;
379 devmode.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
381 retval=ChangeDisplaySettings(&devmode,CDS_FULLSCREEN);
382 if (retval!=DISP_CHANGE_SUCCESSFUL)
384 errstr="ChangeDisplaySettings";
385 // we couldn't even switch to 640x480, we're out of here
386 // restore screen mode to default
387 ChangeDisplaySettings(NULL,0);
391 // successful, change our global settings to reflect what
398 // success at changing the video mode
405 // we want windowed mode, figure out how big the window is
407 GetWindowRect(g_hWnd,&rect);
408 width=abs(rect.right-rect.left);
409 height=abs(rect.bottom-rect.top);
413 // full screen mode, we want the window to be on top of everything
414 SetWindowPos(g_hWnd,HWND_TOPMOST,0,0,GLPREF_width,GLPREF_height,SWP_FRAMECHANGED);
416 height=GLPREF_height;
417 GetWindowRect(g_hWnd,&rect);
420 GLSTATE_width = width;
421 GLSTATE_height = height;
427 // Now we finally setup OpenGL
428 // If OpenGL is to be dynamically loaded, do this now (if the DLL isn't already
430 // remove the following error when you figure out what you want to do
431 // it's put here to make sure you notice this
432 #ifdef OGL_RUNTIME_LOAD
433 ogl_init_load_library();
436 // Setup our pixel format
438 memset(&pfd,0,sizeof(pfd));
439 pfd.nSize = sizeof(pfd);
441 pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
442 // pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_GENERIC_ACCELERATED;
443 pfd.iPixelType = PFD_TYPE_RGBA;
444 //let the ogl driver decide. (fixes no hw accel in 16bit mode in w2k with tnt2)
445 // pfd.cColorBits = 16;
446 // pfd.cAlphaBits = 8;
447 // pfd.cDepthBits = 0;
448 // pfd.cAccumBits = 0;
449 // pfd.cStencilBits = 0;
450 pfd.iLayerType = PFD_MAIN_PLANE;
451 pfd.dwLayerMask = PFD_MAIN_PLANE;
454 // Find the user's "best match" PFD
455 pf = ChoosePixelFormat(hDC,&pfd);
458 errstr="ChoosePixelFormat";
459 // no pixel format closely matches
464 if(SetPixelFormat(hDC,pf,&pfd)==FALSE)
466 errstr="SetPixelFormat";
467 // unable to set the pixel format
471 // Now retrieve the PFD, we need to check some things
472 /* if(DescribePixelFormat(hDC,pf,sizeof(PIXELFORMATDESCRIPTOR),&pfd_copy)==0)
474 errstr="DescribePixelFormat";
475 // unable to get the PFD
479 // Make sure we are hardware accelerated
480 if((pfd_copy.dwFlags&PFD_GENERIC_ACCELERATED)==0&&(pfd_copy.dwFlags&PFD_GENERIC_FORMAT)!=0)
482 // we are not hardware accelerated!
486 // Finally, create our OpenGL context and make it current
487 GL_ResourceContext = wglCreateContext(hDC);
488 if(GL_ResourceContext==NULL)
490 errstr="wglCreateContext";
491 // we couldn't create a context!
495 // Make the context current
496 wglMakeCurrent(hDC,GL_ResourceContext);
498 // Save our gamma values because we'll probably be changing them,
499 // this way we can restore them on exit
501 GetDeviceGammaRamp(hDC, (LPVOID)Saved_gamma_values);
508 Error("opengl init error: %s\n",errstr);
512 void OpenGL_Shutdown(void)
514 // Do any needed OpenGL shutdown here
517 // Now do Window specific shutdown
518 if(wglMakeCurrent)//check to make sure the function is valid (dyanmic loaded OpenGL)
519 wglMakeCurrent(NULL, NULL);
521 if(wglDeleteContext)//check to make sure the function is valid (dyanmic loaded OpenGL)
522 wglDeleteContext(GL_ResourceContext);
524 // Restore back to user screen settings
526 ChangeDisplaySettings(NULL,0);
528 // Restore gamma values
530 SetDeviceGammaRamp(hDC, (LPVOID)Saved_gamma_values);
532 ReleaseDC(g_hWnd,hDC);