gl_vidnt.c
来自「quake1 dos源代码最新版本」· C语言 代码 · 共 1,980 行 · 第 1/4 页
C
1,980 行
/*
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// gl_vidnt.c -- NT GL vid component
#include "quakedef.h"
#include "winquake.h"
#include "resource.h"
#include <commctrl.h>
#define MAX_MODE_LIST 30
#define VID_ROW_SIZE 3
#define WARP_WIDTH 320
#define WARP_HEIGHT 200
#define MAXWIDTH 10000
#define MAXHEIGHT 10000
#define BASEWIDTH 320
#define BASEHEIGHT 200
#define MODE_WINDOWED 0
#define NO_MODE (MODE_WINDOWED - 1)
#define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 1)
typedef struct {
modestate_t type;
int width;
int height;
int modenum;
int dib;
int fullscreen;
int bpp;
int halfscreen;
char modedesc[17];
} vmode_t;
typedef struct {
int width;
int height;
} lmode_t;
lmode_t lowresmodes[] = {
{320, 200},
{320, 240},
{400, 300},
{512, 384},
};
const char *gl_vendor;
const char *gl_renderer;
const char *gl_version;
const char *gl_extensions;
qboolean DDActive;
qboolean scr_skipupdate;
static vmode_t modelist[MAX_MODE_LIST];
static int nummodes;
static vmode_t *pcurrentmode;
static vmode_t badmode;
static DEVMODE gdevmode;
static qboolean vid_initialized = false;
static qboolean windowed, leavecurrentmode;
static qboolean vid_canalttab = false;
static qboolean vid_wassuspended = false;
static int windowed_mouse;
extern qboolean mouseactive; // from in_win.c
static HICON hIcon;
int DIBWidth, DIBHeight;
RECT WindowRect;
DWORD WindowStyle, ExWindowStyle;
HWND mainwindow, dibwindow;
int vid_modenum = NO_MODE;
int vid_realmode;
int vid_default = MODE_WINDOWED;
static int windowed_default;
unsigned char vid_curpal[256*3];
static qboolean fullsbardraw = false;
static float vid_gamma = 1.0;
HGLRC baseRC;
HDC maindc;
glvert_t glv;
cvar_t *gl_ztrick;
HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow);
viddef_t vid; // global video state
unsigned short d_8to16table[256];
unsigned d_8to24table[256];
unsigned char d_15to8table[65536];
float gldepthmin, gldepthmax;
modestate_t modestate = MS_UNINIT;
void VID_MenuDraw (void);
void VID_MenuKey (int key);
LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void AppActivate(BOOL fActive, BOOL minimize);
char *VID_GetModeDescription (int mode);
void ClearAllStates (void);
void VID_UpdateWindowStatus (void);
void GL_Init (void);
PROC glArrayElementEXT;
PROC glColorPointerEXT;
PROC glTexCoordPointerEXT;
PROC glVertexPointerEXT;
typedef void (APIENTRY *lp3DFXFUNC) (int, int, int, int, int, const void*);
lp3DFXFUNC glColorTableEXT;
qboolean is8bit = false;
qboolean isPermedia = false;
qboolean gl_mtexable = false;
//====================================
cvar_t *vid_mode;
// Note that 0 is MODE_WINDOWED
cvar_t *_vid_default_mode;
// Note that 3 is MODE_FULLSCREEN_DEFAULT
cvar_t *_vid_default_mode_win;
cvar_t *vid_wait;
cvar_t *vid_nopageflip;
cvar_t *_vid_wait_override;
cvar_t *vid_config_x;
cvar_t *vid_config_y;
cvar_t *vid_stretch_by_2;
cvar_t *_windowed_mouse;
int window_center_x, window_center_y, window_x, window_y, window_width, window_height;
RECT window_rect;
// direct draw software compatability stuff
void VID_HandlePause (qboolean pause)
{
}
void VID_ForceLockState (int lk)
{
}
void VID_LockBuffer (void)
{
}
void VID_UnlockBuffer (void)
{
}
int VID_ForceUnlockedAndReturnState (void)
{
return 0;
}
void D_BeginDirectRect (int x, int y, byte *pbitmap, int width, int height)
{
}
void D_EndDirectRect (int x, int y, int width, int height)
{
}
void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify)
{
RECT rect;
int CenterX, CenterY;
CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) / 2;
CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) / 2;
if (CenterX > CenterY*2)
CenterX >>= 1; // dual screens
CenterX = (CenterX < 0) ? 0: CenterX;
CenterY = (CenterY < 0) ? 0: CenterY;
SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0,
SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME);
}
qboolean VID_SetWindowedMode (int modenum)
{
HDC hdc;
int width, height; //lastmodestate, // 2001-12-10 Reduced compiler warnings by Jeff Ford
RECT rect;
// lastmodestate = modestate; // 2001-12-10 Reduced compiler warnings by Jeff Ford
WindowRect.top = WindowRect.left = 0;
WindowRect.right = modelist[modenum].width;
WindowRect.bottom = modelist[modenum].height;
DIBWidth = modelist[modenum].width;
DIBHeight = modelist[modenum].height;
WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU |
WS_MINIMIZEBOX;
ExWindowStyle = 0;
rect = WindowRect;
AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
width = rect.right - rect.left;
height = rect.bottom - rect.top;
// Create the DIB window
dibwindow = CreateWindowEx (
ExWindowStyle,
"WinQuake",
"GLQuake",
WindowStyle,
rect.left, rect.top,
width,
height,
NULL,
NULL,
global_hInstance,
NULL);
if (!dibwindow)
Sys_Error ("Couldn't create DIB window");
// Center and show the DIB window
CenterWindow(dibwindow, WindowRect.right - WindowRect.left,
WindowRect.bottom - WindowRect.top, false);
ShowWindow (dibwindow, SW_SHOWDEFAULT);
UpdateWindow (dibwindow);
modestate = MS_WINDOWED;
// because we have set the background brush for the window to NULL
// (to avoid flickering when re-sizing the window on the desktop),
// we clear the window to black when created, otherwise it will be
// empty while Quake starts up.
hdc = GetDC(dibwindow);
PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
ReleaseDC(dibwindow, hdc);
if (vid.conheight > modelist[modenum].height)
vid.conheight = modelist[modenum].height;
if (vid.conwidth > modelist[modenum].width)
vid.conwidth = modelist[modenum].width;
vid.width = vid.conwidth;
vid.height = vid.conheight;
vid.numpages = 2;
mainwindow = dibwindow;
SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
return true;
}
qboolean VID_SetFullDIBMode (int modenum)
{
HDC hdc;
int width, height; //lastmodestate, // 2001-12-10 Reduced compiler warnings by Jeff Ford
RECT rect;
if (!leavecurrentmode)
{
gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
gdevmode.dmBitsPerPel = modelist[modenum].bpp;
gdevmode.dmPelsWidth = modelist[modenum].width <<
modelist[modenum].halfscreen;
gdevmode.dmPelsHeight = modelist[modenum].height;
gdevmode.dmSize = sizeof (gdevmode);
if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
Sys_Error ("Couldn't set fullscreen DIB mode");
}
// lastmodestate = modestate; // 2001-12-10 Reduced compiler warnings by Jeff Ford
modestate = MS_FULLDIB;
WindowRect.top = WindowRect.left = 0;
WindowRect.right = modelist[modenum].width;
WindowRect.bottom = modelist[modenum].height;
DIBWidth = modelist[modenum].width;
DIBHeight = modelist[modenum].height;
WindowStyle = WS_POPUP;
ExWindowStyle = 0;
rect = WindowRect;
AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0);
width = rect.right - rect.left;
height = rect.bottom - rect.top;
// Create the DIB window
dibwindow = CreateWindowEx (
ExWindowStyle,
"WinQuake",
"GLQuake",
WindowStyle,
rect.left, rect.top,
width,
height,
NULL,
NULL,
global_hInstance,
NULL);
if (!dibwindow)
Sys_Error ("Couldn't create DIB window");
ShowWindow (dibwindow, SW_SHOWDEFAULT);
UpdateWindow (dibwindow);
// Because we have set the background brush for the window to NULL
// (to avoid flickering when re-sizing the window on the desktop), we
// clear the window to black when created, otherwise it will be
// empty while Quake starts up.
hdc = GetDC(dibwindow);
PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS);
ReleaseDC(dibwindow, hdc);
if (vid.conheight > modelist[modenum].height)
vid.conheight = modelist[modenum].height;
if (vid.conwidth > modelist[modenum].width)
vid.conwidth = modelist[modenum].width;
vid.width = vid.conwidth;
vid.height = vid.conheight;
vid.numpages = 2;
// needed because we're not getting WM_MOVE messages fullscreen on NT
window_x = 0;
window_y = 0;
mainwindow = dibwindow;
SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon);
SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon);
return true;
}
int VID_SetMode (int modenum, unsigned char *palette)
{
int original_mode, temp;
qboolean stat;
MSG msg;
HDC hdc;
if ((windowed && (modenum != 0)) ||
(!windowed && (modenum < 1)) ||
(!windowed && (modenum >= nummodes)))
{
Sys_Error ("Bad video mode\n");
}
// so Con_Printfs don't mess us up by forcing vid and snd updates
temp = scr_disabled_for_loading;
scr_disabled_for_loading = true;
CDAudio_Pause ();
// 2001-12-10 Reduced compiler warnings by Jeff Ford start
/*
if (vid_modenum == NO_MODE)
original_mode = windowed_default;
else
original_mode = vid_modenum;
*/
// 2001-12-10 Reduced compiler warnings by Jeff Ford end
// Set either the fullscreen or windowed mode
if (modelist[modenum].type == MS_WINDOWED)
{
if (_windowed_mouse->value && key_dest == key_game)
{
stat = VID_SetWindowedMode(modenum);
IN_ActivateMouse ();
IN_HideMouse ();
}
else
{
IN_DeactivateMouse ();
IN_ShowMouse ();
stat = VID_SetWindowedMode(modenum);
}
}
else if (modelist[modenum].type == MS_FULLDIB)
{
stat = VID_SetFullDIBMode(modenum);
IN_ActivateMouse ();
IN_HideMouse ();
}
else
{
Sys_Error ("VID_SetMode: Bad mode type in modelist");
}
window_width = DIBWidth;
window_height = DIBHeight;
VID_UpdateWindowStatus ();
CDAudio_Resume ();
scr_disabled_for_loading = temp;
if (!stat)
{
Sys_Error ("Couldn't set video mode");
}
// now we try to make sure we get the focus on the mode switch, because
// sometimes in some systems we don't. We grab the foreground, then
// finish setting up, pump all our messages, and sleep for a little while
// to let messages finish bouncing around the system, then we put
// ourselves at the top of the z order, then grab the foreground again,
// Who knows if it helps, but it probably doesn't hurt
SetForegroundWindow (mainwindow);
VID_SetPalette (palette);
vid_modenum = modenum;
Cvar_SetValue (vid_mode, (float)vid_modenum);
while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
}
Sleep (100);
SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0,
SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW |
SWP_NOCOPYBITS);
SetForegroundWindow (mainwindow);
// fix the leftover Alt from any Alt-Tab or the like that switched us away
ClearAllStates ();
if (!msg_suppress_1)
Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum));
VID_SetPalette (palette);
vid.recalc_refdef = 1;
return true;
}
/*
================
VID_UpdateWindowStatus
================
*/
void VID_UpdateWindowStatus (void)
{
window_rect.left = window_x;
window_rect.top = window_y;
window_rect.right = window_x + window_width;
window_rect.bottom = window_y + window_height;
window_center_x = (window_rect.left + window_rect.right) / 2;
window_center_y = (window_rect.top + window_rect.bottom) / 2;
IN_UpdateClipCursor ();
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?