dxx-rebirth/arch/ogl/wgl.c
2006-03-20 17:12:09 +00:00

534 lines
13 KiB
C
Executable file

/* $Id: wgl.c,v 1.1.1.1 2006/03/17 19:53:36 zicodxx Exp $ */
/*
*
* opengl platform specific functions for WGL - added by Peter Hawkins
* fullscreen example code courtesy of Jeff Slutter
* everything merged together and cleaned up by Matt Mueller
* (with some win32 help from Nirvana)
*
*
*/
#ifdef HAVE_CONFIG_H
#include <conf.h>
#endif
#include <windows.h>
#include <mmsystem.h>
#include "internal.h"
#include "vers_id.h"
#include "error.h"
#include "key.h"
#include "joy.h"
#include "mouse.h"
#include "digi.h"
#include "args.h"
#include "resource.h"
/*#include "event.h"*/
#include <stdio.h>
//not defined in cygwin, needed to keep windows from resizing everything to fit the fullscreen res.
#ifndef CDS_FULLSCREEN
#define CDS_FULLSCREEN 0x4
#endif
DEVMODE devmode;//global so the activate proc can reset the screen mode.
HINSTANCE hInst=NULL;
HWND g_hWnd=NULL;
extern int Inferno_verbose;
static int mouse_hidden=0;
//extern unsigned int key_wparam, key_lparam, key_msg;
void keyboard_handler();
extern int WMKey_Handler_Ready;
HDC hDC;
static int GLPREF_width,GLPREF_height;
static int GLSTATE_width,GLSTATE_height;
static bool GLPREF_windowed;
static HGLRC GL_ResourceContext=NULL;
static WORD Saved_gamma_values[256 * 3];
static WORD gammaramp[256 * 3];
bool OpenGL_Initialize(void);
void OpenGL_Shutdown(void);
void PumpMessages(void)
{
MSG msg;
while (PeekMessage(&msg,NULL,0,0,PM_REMOVE|PM_NOYIELD))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
static void finiObjects()
{
// ogl_close();
// if(mouse_hidden){
// ShowCursor(TRUE);
// mouse_hidden=0;
// }
// DisableOpenGL( g_hWnd, hDC, hRC );
}
int vid_susp=0;
int wgl_game_activate(int active,int min){
int i=0;//do_game_activate(active,min);
if (!gl_initialized) return -1;
// printf("****** wgl_game_activate: %i %i,%i %i *******\n",GLPREF_windowed,active,min,vid_susp);
if (!active){
mouse_close();
if (!GLPREF_windowed)
if (!vid_susp){
ChangeDisplaySettings(NULL,0);
vid_susp=1;
}
}else{
mouse_init(0);
if (!GLPREF_windowed)
if (vid_susp){
ChangeDisplaySettings(&devmode,CDS_FULLSCREEN);
ShowWindow(g_hWnd,SW_SHOWNORMAL);
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
UpdateWindow(g_hWnd);
wglMakeCurrent(NULL, NULL);
wglMakeCurrent(hDC,GL_ResourceContext);//this seems to fix some glitches that appear when you alt-tab back in.
vid_susp=0;
}
}
// printf("****** -----------------: %i %i,%i %i *******\n",GLPREF_windowed,active,min,vid_susp);
return i;
}
long PASCAL DescentWndProc(HWND hWnd,UINT message,
WPARAM wParam,LPARAM lParam )
{
switch(message)
{
case WM_KEYDOWN:
case WM_KEYUP:
if (WMKey_Handler_Ready) {
// key_wparam=wParam; key_lparam=lParam; key_msg=message;
keyboard_handler();
}
break;
case WM_MOUSEMOVE:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_NCMOUSEMOVE:
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONUP:
case WM_NCRBUTTONDOWN:
case WM_NCRBUTTONUP:
break;
case WM_PALETTECHANGED:
case WM_PALETTEISCHANGING:
return 0;
case WM_KILLFOCUS:
if (!GLPREF_windowed)
ShowWindow(g_hWnd, SW_SHOWMINNOACTIVE);//this minimizes the game after you alt-tab out.
break;
case WM_ACTIVATE:
wgl_game_activate((!(LOWORD(wParam) == WA_INACTIVE)),(BOOL) HIWORD(wParam));
break;
case WM_ACTIVATEAPP:
// Win32_Key_Hook(wParam);
// DPH: This doesn't work... no idea why not...
break;
case WM_DESTROY:
finiObjects();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,message,wParam,lParam);
}
return 1;
}
int ogl_setbrightness_internal(void)
{
int i;
for (i = 0; i < 256; ++i)
{
gammaramp[i] = min((i + ogl_brightness_r * 4) * 256, 0xffff);
gammaramp[i + 256] = min((i + ogl_brightness_g * 4) * 256, 0xffff);
gammaramp[i + 512] = min((i + ogl_brightness_b * 4) * 256, 0xffff);
}
return SetDeviceGammaRamp(hDC, (LPVOID)gammaramp) ? 0 : -1;
}
void ogl_swap_buffers_internal(void){
SwapBuffers( hDC );
}
int get_win_x_bs(void){
// return GetSystemMetrics(SM_CXBORDER)*2
return GetSystemMetrics(SM_CXFIXEDFRAME)*2;
}
int get_win_y_bs(void){
// return GetSystemMetrics(SM_CYBORDER)*2+GetSystemMetrics(SM_CYCAPTION);
return GetSystemMetrics(SM_CYFIXEDFRAME)*2+GetSystemMetrics(SM_CYCAPTION);
}
void win32_create_window(int x,int y)
{
int flags;
WNDCLASS wcDescentClass;
if (!hInst)
Error("hInst=NULL\n");
wcDescentClass.lpszClassName = "WinD1X";
wcDescentClass.hInstance = hInst;
wcDescentClass.lpfnWndProc = DescentWndProc;
wcDescentClass.hCursor = LoadCursor(NULL, IDC_ARROW);
//wcDescentClass.hIcon = LoadIcon(NULL, IDI_WINLOGO);
wcDescentClass.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_MAIN_ICON));
wcDescentClass.lpszMenuName = NULL;
wcDescentClass.hbrBackground = NULL;
wcDescentClass.style = CS_OWNDC;
wcDescentClass.cbClsExtra = 0;
wcDescentClass.cbWndExtra = 0;
// Register the class
if (!RegisterClass(&wcDescentClass)){
// printf("RegisterClass==0?\n");
//always seems to return 0 after the first time, yet if you remove the call, it crashes. Heh.
}
if (ogl_fullscreen)
flags=WS_POPUP;//uh.. don't remember if removing sysmenu did anything or not.. but it works.
//flags=WS_POPUP | WS_SYSMENU;
else
flags=WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;//let us minimize it.
//flags=WS_OVERLAPPED | WS_BORDER | WS_CLIPCHILDREN | WS_CLIPSIBLINGS;
if (!ogl_fullscreen){
x+=get_win_x_bs();y+=get_win_y_bs();
}else{
if (FindArg("-gl_test2")){
x=GetSystemMetrics(SM_CXSCREEN);
y=GetSystemMetrics(SM_CYSCREEN);
}
}
g_hWnd = CreateWindowEx(0,
"WinD1X",
"Descent",
flags,
0, 0,
x,y,
NULL,
NULL,
hInst,
NULL
);
if (!g_hWnd) Error("no window?\n");
ShowWindow(g_hWnd,SW_SHOWNORMAL);
UpdateWindow(g_hWnd);
OpenGL_Initialize();
if (ogl_fullscreen){
ShowCursor(FALSE);
mouse_hidden = 1;
}
key_init();
mouse_init(0);
joy_init(JOYSTICKID1);
if (!FindArg( "-nosound" ))
digi_init();
// printf("arch_init successfully completed\n");
gl_initialized=1;
}
void ogl_destroy_window(void){
if (gl_initialized){
ogl_smash_texture_list_internal();
if (mouse_hidden){
ShowCursor(TRUE);
mouse_hidden = 0;
}
if (g_hWnd){
key_close();
mouse_close();
joy_close();
if (!FindArg( "-nosound" ))
digi_close();
OpenGL_Shutdown();
DestroyWindow(g_hWnd);
}else
Error("ogl_destroy_window: no g_hWnd?\n");
gl_initialized=0;
}
return;
}
void ogl_do_fullscreen_internal(void){
if (GLPREF_windowed==ogl_fullscreen){
ogl_destroy_window();
win32_create_window(GLPREF_width,GLPREF_height);
ogl_vivify_texture_list_internal();
}
}
int ogl_init_window(int x, int y){
GLPREF_width=x;
GLPREF_height=y;
if (gl_initialized){
if (GLSTATE_width==GLPREF_width && GLSTATE_height==GLPREF_height && GLPREF_windowed!=ogl_fullscreen)
return 0;//we are already in the right mode, don't do anything.
if (!ogl_fullscreen && GLPREF_windowed){
SetWindowPos(g_hWnd,0,0,0,x+get_win_x_bs(),y+get_win_y_bs(),SWP_NOMOVE);
}else{
ogl_destroy_window();
win32_create_window(x,y);
ogl_vivify_texture_list_internal();
}
}else {
win32_create_window(x,y);
}
return 0;
}
void ogl_init(void){
hInst=GetModuleHandle (NULL);
}
void ogl_close(void){
ogl_destroy_window();
}
//windows opengl fullscreen changing - courtesy of Jeff Slutter
/*
Windows Full Screen Setup
===========================================================================
*/
// Entering this function, the following values must be valid
// GLPREF_width,GLPREF_height: preferred width and height
// GLPREF_windowed: do we want windowed or full screen mode
// g_hWnd: handle to the window created for OpenGL
// On exit from this function (if returned true) the following values will be set
// GLSTATE_width,GLSTATE_height: real width and height of screen
// hDC: device context of the window
// GL_ResourceContext: OpenGL resource context
// Saved_gamma_values: Initial gamma values
bool OpenGL_Initialize(void)
{
char *errstr="";
int width,height;
int pf;
PIXELFORMATDESCRIPTOR pfd;//, pfd_copy;
GLPREF_windowed=!ogl_fullscreen;
if (FindArg("-gl_test1")){
GLSTATE_width = GLPREF_width;
GLSTATE_height = GLPREF_height;
}else{
if(!GLPREF_windowed)
{
// First set our display mode
// Create direct draw surface
int retval;
devmode.dmSize=sizeof(devmode);
devmode.dmBitsPerPel = FindArg("-gl_16bpp") ? 16 : 32;
devmode.dmPelsWidth=GLPREF_width;
devmode.dmPelsHeight=GLPREF_height;
devmode.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
if ((retval=FindArg("-gl_refresh"))){
devmode.dmDisplayFrequency=atoi(Args[retval+1]);
if (devmode.dmDisplayFrequency>=60)//uhh, I hope no one actually wants a refresh lower than 60.. gag.
devmode.dmFields|=DM_DISPLAYFREQUENCY;
printf("trying refresh %li hz\n", devmode.dmDisplayFrequency);
}
retval=ChangeDisplaySettings(&devmode,CDS_FULLSCREEN);
if (retval!=DISP_CHANGE_SUCCESSFUL)
{
// we couldn't switch to the desired screen mode
// fall back to 640x480
retval=-1;
devmode.dmBitsPerPel=16;
devmode.dmPelsWidth=640;
devmode.dmPelsHeight=480;
devmode.dmFields=DM_BITSPERPEL|DM_PELSWIDTH|DM_PELSHEIGHT;
retval=ChangeDisplaySettings(&devmode,CDS_FULLSCREEN);
if (retval!=DISP_CHANGE_SUCCESSFUL)
{
errstr="ChangeDisplaySettings";
// we couldn't even switch to 640x480, we're out of here
// restore screen mode to default
ChangeDisplaySettings(NULL,0);
goto OpenGLError;
}else
{
// successful, change our global settings to reflect what
// mode we are at
GLPREF_width=640;
GLPREF_height=480;
}
}else
{
// success at changing the video mode
}
}
if(GLPREF_windowed)
{
// we want windowed mode, figure out how big the window is
RECT rect;
GetWindowRect(g_hWnd,&rect);
width=abs(rect.right-rect.left);
height=abs(rect.bottom-rect.top);
}else
{
RECT rect;
// full screen mode, we want the window to be on top of everything
SetWindowPos(g_hWnd,HWND_TOPMOST,0,0,GLPREF_width,GLPREF_height,SWP_FRAMECHANGED);
width=GLPREF_width;
height=GLPREF_height;
GetWindowRect(g_hWnd,&rect);
}
GLSTATE_width = width;
GLSTATE_height = height;
}
hDC = GetDC(g_hWnd);
// Now we finally setup OpenGL
// If OpenGL is to be dynamically loaded, do this now (if the DLL isn't already
// loaded)
// remove the following error when you figure out what you want to do
// it's put here to make sure you notice this
#ifdef OGL_RUNTIME_LOAD
ogl_init_load_library();
#endif
// Setup our pixel format
memset(&pfd,0,sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
// pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER | PFD_GENERIC_ACCELERATED;
pfd.iPixelType = PFD_TYPE_RGBA;
//let the ogl driver decide. (fixes no hw accel in 16bit mode in w2k with tnt2)
// pfd.cColorBits = 16;
// pfd.cAlphaBits = 8;
// pfd.cDepthBits = 0;
// pfd.cAccumBits = 0;
// pfd.cStencilBits = 0;
pfd.iLayerType = PFD_MAIN_PLANE;
pfd.dwLayerMask = PFD_MAIN_PLANE;
// Find the user's "best match" PFD
pf = ChoosePixelFormat(hDC,&pfd);
if(pf == 0)
{
errstr="ChoosePixelFormat";
// no pixel format closely matches
goto OpenGLError;
}
// Set the new PFD
if(SetPixelFormat(hDC,pf,&pfd)==FALSE)
{
errstr="SetPixelFormat";
// unable to set the pixel format
goto OpenGLError;
}
// Now retrieve the PFD, we need to check some things
/* if(DescribePixelFormat(hDC,pf,sizeof(PIXELFORMATDESCRIPTOR),&pfd_copy)==0)
{
errstr="DescribePixelFormat";
// unable to get the PFD
goto OpenGLError;
}
// Make sure we are hardware accelerated
if((pfd_copy.dwFlags&PFD_GENERIC_ACCELERATED)==0&&(pfd_copy.dwFlags&PFD_GENERIC_FORMAT)!=0)
{
// we are not hardware accelerated!
goto OpenGLError;
}*/
// Finally, create our OpenGL context and make it current
GL_ResourceContext = wglCreateContext(hDC);
if(GL_ResourceContext==NULL)
{
errstr="wglCreateContext";
// we couldn't create a context!
goto OpenGLError;
}
// Make the context current
wglMakeCurrent(hDC,GL_ResourceContext);
// Save our gamma values because we'll probably be changing them,
// this way we can restore them on exit
GetDeviceGammaRamp(hDC, (LPVOID)Saved_gamma_values);
return true;
OpenGLError:
// Shutdown OpenGL
OpenGL_Shutdown();
Error("opengl init error: %s\n",errstr);
return false;
}
void OpenGL_Shutdown(void)
{
// Do any needed OpenGL shutdown here
// Now do Window specific shutdown
if(wglMakeCurrent)//check to make sure the function is valid (dyanmic loaded OpenGL)
wglMakeCurrent(NULL, NULL);
if(wglDeleteContext)//check to make sure the function is valid (dyanmic loaded OpenGL)
wglDeleteContext(GL_ResourceContext);
// Restore back to user screen settings
if(!GLPREF_windowed)
ChangeDisplaySettings(NULL,0);
// Restore gamma values
SetDeviceGammaRamp(hDC, (LPVOID)Saved_gamma_values);
ReleaseDC(g_hWnd,hDC);
}