534 lines
13 KiB
C
Executable file
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);
|
|
}
|