2bf193001b
remove MAX_MAP_LEAFS limit, although its still checked for sanity (just MUCH higher). You may need 64bit processes on account of the pvs+phs memory required. integrated my fork of frikdec into fteqccgui. Just associate .dat with fteqccgui and it'll decompile the progs (compiling will then embed the decompiled source into the resulting .dat to avoid repeated decompilation). Be sure to back up first... not tested as a 64bit process. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5114 fc73d0e0-1445-4013-8a0c-d673dee63da5
806 lines
17 KiB
C
806 lines
17 KiB
C
#include "quakedef.h"
|
|
#ifdef SWQUAKE
|
|
#include "sw.h"
|
|
|
|
#include "winquake.h"
|
|
/*Fixup outdated windows headers*/
|
|
#ifndef WM_XBUTTONDOWN
|
|
#define WM_XBUTTONDOWN 0x020B
|
|
#define WM_XBUTTONUP 0x020C
|
|
#endif
|
|
#ifndef MK_XBUTTON1
|
|
#define MK_XBUTTON1 0x0020
|
|
#endif
|
|
#ifndef MK_XBUTTON2
|
|
#define MK_XBUTTON2 0x0040
|
|
#endif
|
|
// copied from DarkPlaces in an attempt to grab more buttons
|
|
#ifndef MK_XBUTTON3
|
|
#define MK_XBUTTON3 0x0080
|
|
#endif
|
|
#ifndef MK_XBUTTON4
|
|
#define MK_XBUTTON4 0x0100
|
|
#endif
|
|
#ifndef MK_XBUTTON5
|
|
#define MK_XBUTTON5 0x0200
|
|
#endif
|
|
#ifndef MK_XBUTTON6
|
|
#define MK_XBUTTON6 0x0400
|
|
#endif
|
|
#ifndef MK_XBUTTON7
|
|
#define MK_XBUTTON7 0x0800
|
|
#endif
|
|
#ifndef WM_INPUT
|
|
#define WM_INPUT 255
|
|
#endif
|
|
|
|
|
|
|
|
typedef struct dibinfo
|
|
{
|
|
BITMAPINFOHEADER header;
|
|
RGBQUAD acolors[256];
|
|
} dibinfo_t;
|
|
|
|
//struct
|
|
//{
|
|
HBITMAP hDIBSection;
|
|
qbyte *pDIBBase;
|
|
|
|
HDC mainhDC;
|
|
HDC hdcDIBSection;
|
|
HGDIOBJ previously_selected_GDI_obj;
|
|
|
|
int framenumber;
|
|
void *screenbuffer;
|
|
qintptr_t screenpitch;
|
|
int window_x, window_y;
|
|
unsigned int *depthbuffer;
|
|
struct
|
|
{
|
|
qboolean isfullscreen;
|
|
} w32sw;
|
|
HWND mainwindow;
|
|
|
|
void DIB_Shutdown(void)
|
|
{
|
|
if (depthbuffer)
|
|
{
|
|
BZ_Free(depthbuffer);
|
|
depthbuffer = NULL;
|
|
}
|
|
|
|
if (hdcDIBSection)
|
|
{
|
|
SelectObject(hdcDIBSection, previously_selected_GDI_obj);
|
|
DeleteDC(hdcDIBSection);
|
|
hdcDIBSection = NULL;
|
|
}
|
|
|
|
if (hDIBSection)
|
|
{
|
|
DeleteObject(hDIBSection);
|
|
hDIBSection = NULL;
|
|
pDIBBase = NULL;
|
|
}
|
|
|
|
if (mainhDC)
|
|
{
|
|
ReleaseDC(mainwindow, mainhDC);
|
|
mainhDC = 0;
|
|
}
|
|
}
|
|
qboolean DIB_Init(void)
|
|
{
|
|
dibinfo_t dibheader;
|
|
BITMAPINFO *pbmiDIB = ( BITMAPINFO * ) &dibheader;
|
|
int i;
|
|
|
|
memset( &dibheader, 0, sizeof( dibheader ) );
|
|
|
|
/*
|
|
** grab a DC
|
|
*/
|
|
if ( !mainhDC )
|
|
{
|
|
if ( ( mainhDC = GetDC( mainwindow ) ) == NULL )
|
|
return false;
|
|
}
|
|
|
|
/*
|
|
** fill in the BITMAPINFO struct
|
|
*/
|
|
pbmiDIB->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
|
pbmiDIB->bmiHeader.biWidth = vid.pixelwidth;
|
|
pbmiDIB->bmiHeader.biHeight = vid.pixelheight;
|
|
pbmiDIB->bmiHeader.biPlanes = 1;
|
|
pbmiDIB->bmiHeader.biBitCount = 32;
|
|
pbmiDIB->bmiHeader.biCompression = BI_RGB;
|
|
pbmiDIB->bmiHeader.biSizeImage = 0;
|
|
pbmiDIB->bmiHeader.biXPelsPerMeter = 0;
|
|
pbmiDIB->bmiHeader.biYPelsPerMeter = 0;
|
|
pbmiDIB->bmiHeader.biClrUsed = 0;
|
|
pbmiDIB->bmiHeader.biClrImportant = 0;
|
|
|
|
/*
|
|
** fill in the palette
|
|
*/
|
|
for ( i = 0; i < 256; i++ )
|
|
{
|
|
dibheader.acolors[i].rgbRed = ( d_8to24rgbtable[i] >> 0 ) & 0xff;
|
|
dibheader.acolors[i].rgbGreen = ( d_8to24rgbtable[i] >> 8 ) & 0xff;
|
|
dibheader.acolors[i].rgbBlue = ( d_8to24rgbtable[i] >> 16 ) & 0xff;
|
|
}
|
|
|
|
/*
|
|
** create the DIB section
|
|
*/
|
|
hDIBSection = CreateDIBSection( mainhDC,
|
|
pbmiDIB,
|
|
DIB_RGB_COLORS,
|
|
(void**)&pDIBBase,
|
|
NULL,
|
|
0 );
|
|
|
|
if ( hDIBSection == NULL )
|
|
{
|
|
Con_Printf( "DIB_Init() - CreateDIBSection failed\n" );
|
|
goto fail;
|
|
}
|
|
|
|
if (pbmiDIB->bmiHeader.biHeight < 0)
|
|
{
|
|
// bottom up
|
|
screenbuffer = pDIBBase + ( vid.pixelheight - 1 ) * vid.pixelwidth * 4;
|
|
screenpitch = -(int)vid.pixelwidth;
|
|
}
|
|
else
|
|
{
|
|
// top down
|
|
screenbuffer = pDIBBase;
|
|
screenpitch = vid.pixelwidth;
|
|
}
|
|
|
|
/*
|
|
** clear the DIB memory buffer
|
|
*/
|
|
memset( pDIBBase, 0, vid.pixelwidth * vid.pixelheight * 4);
|
|
|
|
if ( ( hdcDIBSection = CreateCompatibleDC( mainhDC ) ) == NULL )
|
|
{
|
|
Con_Printf( "DIB_Init() - CreateCompatibleDC failed\n" );
|
|
goto fail;
|
|
}
|
|
if ( ( previously_selected_GDI_obj = SelectObject( hdcDIBSection, hDIBSection ) ) == NULL )
|
|
{
|
|
Con_Printf( "DIB_Init() - SelectObject failed\n" );
|
|
goto fail;
|
|
}
|
|
|
|
depthbuffer = BZ_Malloc(vid.pixelwidth * vid.pixelheight * sizeof(*depthbuffer));
|
|
if (depthbuffer)
|
|
return true;
|
|
|
|
fail:
|
|
DIB_Shutdown();
|
|
return false;
|
|
}
|
|
void DIB_SwapBuffers(void)
|
|
{
|
|
// extern float usingstretch;
|
|
|
|
// if (usingstretch == 1)
|
|
BitBlt( mainhDC,
|
|
0, 0,
|
|
vid.pixelwidth,
|
|
vid.pixelheight,
|
|
hdcDIBSection,
|
|
0, 0,
|
|
SRCCOPY );
|
|
/* else
|
|
StretchBlt( mainhDC, //Why is StretchBlt not optimised for a scale of 2? Surly that would be a frequently used quantity?
|
|
0, 0,
|
|
vid.width*usingstretch,
|
|
vid.height*usingstretch,
|
|
hdcDIBSection,
|
|
0, 0,
|
|
vid.width, vid.height,
|
|
SRCCOPY );
|
|
*/
|
|
}
|
|
|
|
static int window_width;
|
|
static int window_height;
|
|
void SWV_UpdateWindowStatus(void)
|
|
{
|
|
POINT p;
|
|
RECT nr;
|
|
RECT WindowRect;
|
|
GetClientRect(mainwindow, &nr);
|
|
|
|
//if its bad then we're probably minimised
|
|
if (nr.right <= nr.left)
|
|
return;
|
|
if (nr.bottom <= nr.top)
|
|
return;
|
|
|
|
WindowRect = nr;
|
|
p.x = 0;
|
|
p.y = 0;
|
|
ClientToScreen(mainwindow, &p);
|
|
window_x = p.x;
|
|
window_y = p.y;
|
|
window_width = WindowRect.right - WindowRect.left;
|
|
window_height = WindowRect.bottom - WindowRect.top;
|
|
|
|
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;
|
|
|
|
INS_UpdateClipCursor ();
|
|
}
|
|
|
|
|
|
qboolean SWAppActivate(BOOL fActive, BOOL minimize)
|
|
/****************************************************************************
|
|
*
|
|
* Function: AppActivate
|
|
* Parameters: fActive - True if app is activating
|
|
*
|
|
* Description: If the application is activating, then swap the system
|
|
* into SYSPAL_NOSTATIC mode so that our palettes will display
|
|
* correctly.
|
|
*
|
|
****************************************************************************/
|
|
{
|
|
static BOOL sound_active;
|
|
|
|
if (vid.activeapp == fActive && Minimized == minimize)
|
|
return false; //so windows doesn't crash us over and over again.
|
|
|
|
vid.activeapp = fActive;
|
|
Minimized = minimize;
|
|
|
|
// enable/disable sound on focus gain/loss
|
|
if (!vid.activeapp && sound_active)
|
|
{
|
|
S_BlockSound ();
|
|
sound_active = false;
|
|
}
|
|
else if (vid.activeapp && !sound_active)
|
|
{
|
|
S_UnblockSound ();
|
|
sound_active = true;
|
|
}
|
|
|
|
INS_UpdateGrabs(false, vid.activeapp);
|
|
|
|
/*
|
|
if (fActive)
|
|
{
|
|
if (modestate != MS_WINDOWED)
|
|
{
|
|
if (vid_canalttab && vid_wassuspended) {
|
|
vid_wassuspended = false;
|
|
ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN);
|
|
ShowWindow(mainwindow, SW_SHOWNORMAL);
|
|
}
|
|
}
|
|
}
|
|
if (!fActive)
|
|
{
|
|
if (modestate != MS_WINDOWED)
|
|
{
|
|
if (vid_canalttab) {
|
|
ChangeDisplaySettings (NULL, 0);
|
|
vid_wassuspended = true;
|
|
}
|
|
}
|
|
}
|
|
*/
|
|
return true;
|
|
}
|
|
|
|
LONG WINAPI MainWndProc (
|
|
HWND hWnd,
|
|
UINT uMsg,
|
|
WPARAM wParam,
|
|
LPARAM lParam)
|
|
{
|
|
LONG lRet = 0;
|
|
int fActive, fMinimized, temp;
|
|
HDC hdc;
|
|
PAINTSTRUCT ps;
|
|
extern unsigned int uiWheelMessage;
|
|
// static int recursiveflag;
|
|
|
|
if ( uMsg == uiWheelMessage ) {
|
|
uMsg = WM_MOUSEWHEEL;
|
|
wParam <<= 16;
|
|
}
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_CREATE:
|
|
break;
|
|
|
|
case WM_SYSCOMMAND:
|
|
|
|
// Check for maximize being hit
|
|
switch (wParam & ~0x0F)
|
|
{
|
|
case SC_MAXIMIZE:
|
|
Cbuf_AddText("vid_fullscreen 1;vid_restart\n", RESTRICT_LOCAL);
|
|
// if minimized, bring up as a window before going fullscreen,
|
|
// so MGL will have the right state to restore
|
|
/* if (Minimized)
|
|
{
|
|
force_mode_set = true;
|
|
VID_SetMode (vid_modenum, vid_curpal);
|
|
force_mode_set = false;
|
|
}
|
|
|
|
VID_SetMode ((int)vid_fullscreen_mode.value, vid_curpal);
|
|
*/ break;
|
|
|
|
case SC_SCREENSAVE:
|
|
case SC_MONITORPOWER:
|
|
if (w32sw.isfullscreen)
|
|
{
|
|
// don't call DefWindowProc() because we don't want to start
|
|
// the screen saver fullscreen
|
|
break;
|
|
}
|
|
|
|
// fall through windowed and allow the screen saver to start
|
|
|
|
default:
|
|
// if (!vid_initializing)
|
|
// {
|
|
// S_BlockSound ();
|
|
// }
|
|
|
|
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
|
|
|
|
// if (!vid_initializing)
|
|
// {
|
|
// S_UnblockSound ();
|
|
// }
|
|
}
|
|
break;
|
|
|
|
case WM_MOVE:
|
|
SWV_UpdateWindowStatus ();
|
|
|
|
// if ((modestate == MS_WINDOWED) && !in_mode_set && !Minimized)
|
|
// VID_RememberWindowPos ();
|
|
|
|
break;
|
|
|
|
case WM_SIZE:
|
|
SWV_UpdateWindowStatus ();
|
|
/* Minimized = false;
|
|
|
|
if (!(wParam & SIZE_RESTORED))
|
|
{
|
|
if (wParam & SIZE_MINIMIZED)
|
|
Minimized = true;
|
|
}
|
|
|
|
if (!Minimized && !w32sw.isfullscreen)
|
|
{
|
|
int nt, nl;
|
|
int nw, nh;
|
|
qboolean move = false;
|
|
RECT r;
|
|
GetClientRect (hWnd, &r);
|
|
nw = (int)(r.right - r.left)&~3;
|
|
nh = (int)(r.bottom - r.top)&~3;
|
|
|
|
window_width = nw;
|
|
window_height = nh;
|
|
VID2_UpdateWindowStatus();
|
|
|
|
if (nw < 320)
|
|
{
|
|
move = true;
|
|
nw = 320;
|
|
}
|
|
if (nh < 200)
|
|
{
|
|
move = true;
|
|
nh = 200;
|
|
}
|
|
if (nh > MAXHEIGHT)
|
|
{
|
|
move = true;
|
|
nh = MAXHEIGHT;
|
|
}
|
|
if ((r.right - r.left) & 3)
|
|
move = true;
|
|
if ((r.bottom - r.top) & 3)
|
|
move = true;
|
|
|
|
GetWindowRect (hWnd, &r);
|
|
nl = r.left;
|
|
nt = r.top;
|
|
r.left =0;
|
|
r.top = 0;
|
|
r.right = nw*usingstretch;
|
|
r.bottom = nh*usingstretch;
|
|
AdjustWindowRectEx(&r, WS_OVERLAPPEDWINDOW, FALSE, 0);
|
|
if (move)
|
|
MoveWindow(hWnd, nl, nt, r.right - r.left, r.bottom - r.top, true);
|
|
else
|
|
{
|
|
if (vid.width != nw || vid.height != nh)
|
|
{
|
|
M_RemoveAllMenus(); //can cause probs
|
|
DIB_Shutdown();
|
|
vid.conwidth = vid.width = nw;//vid_stretch.value;
|
|
vid.conheight = vid.height = nh;///vid_stretch.value;
|
|
|
|
DIB_Init( &vid.buffer, &vid.rowbytes );
|
|
vid.conbuffer = vid.buffer;
|
|
vid.conrowbytes = vid.rowbytes;
|
|
|
|
if (VID_AllocBuffers(vid.width, vid.height, r_pixbytes))
|
|
D_InitCaches (vid_surfcache, vid_surfcachesize);
|
|
|
|
SCR_UpdateWholeScreen();
|
|
}
|
|
else
|
|
SCR_UpdateWholeScreen();
|
|
}
|
|
|
|
}
|
|
*/
|
|
break;
|
|
|
|
case WM_SYSCHAR:
|
|
// keep Alt-Space from happening
|
|
break;
|
|
|
|
case WM_ACTIVATE:
|
|
fActive = LOWORD(wParam);
|
|
fMinimized = (BOOL) HIWORD(wParam);
|
|
SWAppActivate(!(fActive == WA_INACTIVE), fMinimized);
|
|
|
|
// fix the leftover Alt from any Alt-Tab or the like that switched us away
|
|
// ClearAllStates ();
|
|
|
|
break;
|
|
|
|
case WM_PAINT:
|
|
hdc = BeginPaint(hWnd, &ps);
|
|
|
|
// if (!in_mode_set && host_initialized)
|
|
// SCR_UpdateWholeScreen ();
|
|
|
|
EndPaint(hWnd, &ps);
|
|
break;
|
|
|
|
case WM_KEYDOWN:
|
|
case WM_SYSKEYDOWN:
|
|
// if (!vid_initializing)
|
|
INS_TranslateKeyEvent(wParam, lParam, true, 0, false);
|
|
break;
|
|
|
|
case WM_KEYUP:
|
|
case WM_SYSKEYUP:
|
|
// if (!vid_initializing)
|
|
INS_TranslateKeyEvent(wParam, lParam, false, 0, false);
|
|
break;
|
|
|
|
case WM_APPCOMMAND:
|
|
lRet = INS_AppCommand(lParam);
|
|
break;
|
|
|
|
// this is complicated because Win32 seems to pack multiple mouse events into
|
|
// one update sometimes, so we always check all states and look for events
|
|
case WM_LBUTTONDOWN:
|
|
case WM_LBUTTONUP:
|
|
case WM_RBUTTONDOWN:
|
|
case WM_RBUTTONUP:
|
|
case WM_MBUTTONDOWN:
|
|
case WM_MBUTTONUP:
|
|
case WM_MOUSEMOVE:
|
|
case WM_XBUTTONDOWN:
|
|
case WM_XBUTTONUP:
|
|
// if (!vid_initializing)
|
|
{
|
|
temp = 0;
|
|
|
|
if (wParam & MK_LBUTTON)
|
|
temp |= 1;
|
|
|
|
if (wParam & MK_RBUTTON)
|
|
temp |= 2;
|
|
|
|
if (wParam & MK_MBUTTON)
|
|
temp |= 4;
|
|
|
|
// extra buttons
|
|
if (wParam & MK_XBUTTON1)
|
|
temp |= 8;
|
|
|
|
if (wParam & MK_XBUTTON2)
|
|
temp |= 16;
|
|
|
|
if (wParam & MK_XBUTTON3)
|
|
temp |= 32;
|
|
|
|
if (wParam & MK_XBUTTON4)
|
|
temp |= 64;
|
|
|
|
if (wParam & MK_XBUTTON5)
|
|
temp |= 128;
|
|
|
|
if (wParam & MK_XBUTTON6)
|
|
temp |= 256;
|
|
|
|
if (wParam & MK_XBUTTON7)
|
|
temp |= 512;
|
|
|
|
INS_MouseEvent (temp);
|
|
}
|
|
break;
|
|
// JACK: This is the mouse wheel with the Intellimouse
|
|
// Its delta is either positive or neg, and we generate the proper
|
|
// Event.
|
|
case WM_MOUSEWHEEL:
|
|
{
|
|
if ((short) HIWORD(wParam) > 0)
|
|
{
|
|
Key_Event(0, K_MWHEELUP, 0, true);
|
|
Key_Event(0, K_MWHEELUP, 0, false);
|
|
}
|
|
else
|
|
{
|
|
Key_Event(0, K_MWHEELDOWN, 0, true);
|
|
Key_Event(0, K_MWHEELDOWN, 0, false);
|
|
}
|
|
}
|
|
break;
|
|
case WM_INPUT:
|
|
// raw input handling
|
|
INS_RawInput_Read((HANDLE)lParam);
|
|
break;
|
|
/* case WM_DISPLAYCHANGE:
|
|
if (!in_mode_set && (modestate == MS_WINDOWED) && !vid_fulldib_on_focus_mode)
|
|
{
|
|
force_mode_set = true;
|
|
VID_SetMode (vid_modenum, vid_curpal);
|
|
force_mode_set = false;
|
|
}
|
|
break;
|
|
*/
|
|
case WM_CLOSE:
|
|
// this causes Close in the right-click task bar menu not to work, but right
|
|
// now bad things happen if Close is handled in that case (garbage and a
|
|
// crash on Win95)
|
|
// if (!vid_initializing)
|
|
{
|
|
if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit",
|
|
MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES)
|
|
{
|
|
Cbuf_AddText("\nquit\n", RESTRICT_LOCAL);
|
|
}
|
|
}
|
|
break;
|
|
|
|
#ifdef HAVE_CDPLAYER
|
|
case MM_MCINOTIFY:
|
|
lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam);
|
|
break;
|
|
#endif
|
|
|
|
default:
|
|
/* pass all unhandled messages to DefWindowProc */
|
|
lRet = DefWindowProc (hWnd, uMsg, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
/* return 0 if handled message, 1 if not */
|
|
return lRet;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
** VID_CreateWindow
|
|
*/
|
|
#define WINDOW_CLASS_NAME FULLENGINENAME
|
|
#define WINDOW_TITLE_NAME FULLENGINENAME
|
|
|
|
|
|
void VID_CreateWindow(int width, int height, qboolean fullscreen)
|
|
{
|
|
WNDCLASS wc;
|
|
RECT r;
|
|
int x, y, w, h;
|
|
int exstyle;
|
|
int stylebits;
|
|
|
|
|
|
if (fullscreen)
|
|
{
|
|
exstyle = WS_EX_TOPMOST;
|
|
stylebits = WS_POPUP;
|
|
}
|
|
else
|
|
{
|
|
exstyle = 0;
|
|
stylebits = WS_OVERLAPPEDWINDOW;
|
|
}
|
|
|
|
/* Register the frame class */
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = (WNDPROC)MainWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = global_hInstance;
|
|
wc.hIcon = 0;
|
|
wc.hCursor = LoadCursor (NULL,IDC_ARROW);
|
|
wc.hbrBackground = (void *)COLOR_GRAYTEXT;
|
|
wc.lpszMenuName = 0;
|
|
wc.lpszClassName = WINDOW_CLASS_NAME;
|
|
|
|
RegisterClass(&wc);
|
|
|
|
r.left = 0;
|
|
r.top = 0;
|
|
r.right = width;
|
|
r.bottom = height;
|
|
|
|
AdjustWindowRectEx (&r, stylebits, FALSE, exstyle);
|
|
|
|
window_rect = r;
|
|
|
|
w = r.right - r.left;
|
|
h = r.bottom - r.top;
|
|
x = 0;//vid_xpos.value;
|
|
y = 0;//vid_ypos.value;
|
|
|
|
mainwindow = CreateWindowEx(
|
|
exstyle,
|
|
WINDOW_CLASS_NAME,
|
|
WINDOW_TITLE_NAME,
|
|
stylebits,
|
|
x, y, w, h,
|
|
NULL,
|
|
NULL,
|
|
global_hInstance,
|
|
NULL);
|
|
|
|
if (!mainwindow)
|
|
Sys_Error("Couldn't create window");
|
|
|
|
ShowWindow(mainwindow, SW_SHOWNORMAL);
|
|
UpdateWindow(mainwindow);
|
|
SetForegroundWindow(mainwindow);
|
|
SetFocus(mainwindow);
|
|
|
|
SWV_UpdateWindowStatus();
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void SW_VID_UpdateViewport(wqcom_t *com)
|
|
{
|
|
com->viewport.cbuf = screenbuffer;
|
|
com->viewport.dbuf = depthbuffer;
|
|
com->viewport.width = vid.pixelwidth;
|
|
com->viewport.height = vid.pixelheight;
|
|
com->viewport.stride = screenpitch;
|
|
com->viewport.framenum = framenumber;
|
|
}
|
|
|
|
void SW_VID_SwapBuffers(void)
|
|
{
|
|
extern cvar_t vid_conautoscale;
|
|
DIB_SwapBuffers();
|
|
framenumber++;
|
|
|
|
INS_UpdateGrabs(false, vid.activeapp);
|
|
|
|
// memset( pDIBBase, 0, vid.pixelwidth * vid.pixelheight * 4);
|
|
|
|
|
|
if (window_width != vid.pixelwidth || window_height != vid.pixelheight)
|
|
{
|
|
DIB_Shutdown();
|
|
vid.pixelwidth = window_width;
|
|
vid.pixelheight = window_height;
|
|
if (!DIB_Init())
|
|
Sys_Error("resize reinitialization error");
|
|
|
|
Cvar_ForceCallback(&vid_conautoscale);
|
|
}
|
|
}
|
|
|
|
qboolean SW_VID_Init(rendererstate_t *info, unsigned char *palette)
|
|
{
|
|
vid.pixelwidth = info->width;
|
|
vid.pixelheight = info->height;
|
|
|
|
if (info->fullscreen) //don't do this with d3d - d3d should set it's own video mode.
|
|
{ //make windows change res.
|
|
DEVMODE gdevmode;
|
|
gdevmode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
|
|
if (info->bpp)
|
|
gdevmode.dmFields |= DM_BITSPERPEL;
|
|
if (info->rate)
|
|
gdevmode.dmFields |= DM_DISPLAYFREQUENCY;
|
|
gdevmode.dmBitsPerPel = info->bpp;
|
|
if (info->bpp && (gdevmode.dmBitsPerPel < 15))
|
|
{
|
|
Con_Printf("Forcing at least 16bpp\n");
|
|
gdevmode.dmBitsPerPel = 16;
|
|
}
|
|
gdevmode.dmDisplayFrequency = info->rate;
|
|
gdevmode.dmPelsWidth = info->width;
|
|
gdevmode.dmPelsHeight = info->height;
|
|
gdevmode.dmSize = sizeof (gdevmode);
|
|
|
|
if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL)
|
|
{
|
|
Con_SafePrintf((gdevmode.dmFields&DM_DISPLAYFREQUENCY)?"Windows rejected mode %i*%i*%i*%i\n":"Windows rejected mode %i*%i*%i\n", (int)gdevmode.dmPelsWidth, (int)gdevmode.dmPelsHeight, (int)gdevmode.dmBitsPerPel, (int)gdevmode.dmDisplayFrequency);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
VID_CreateWindow(vid.pixelwidth, vid.pixelheight, info->fullscreen);
|
|
|
|
if (!DIB_Init())
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
void SW_VID_DeInit(void)
|
|
{
|
|
Image_Shutdown();
|
|
|
|
DIB_Shutdown();
|
|
DestroyWindow(mainwindow);
|
|
|
|
ChangeDisplaySettings (NULL, 0);
|
|
}
|
|
qboolean SW_VID_ApplyGammaRamps (unsigned int gammarampsize, unsigned short *ramps)
|
|
{
|
|
return false;
|
|
}
|
|
char *SW_VID_GetRGBInfo(int *bytestride, int *truevidwidth, int *truevidheight, enum uploadfmt *fmt)
|
|
{
|
|
char *buf = NULL;
|
|
char *src, *dst;
|
|
int w, h;
|
|
buf = BZ_Malloc((vid.pixelwidth * vid.pixelheight * 3));
|
|
dst = buf;
|
|
for (h = 0; h < vid.pixelheight; h++)
|
|
{
|
|
for (w = 0, src = (char*)screenbuffer + (h * vid.pixelwidth*4); w < vid.pixelwidth; w++, dst += 3, src += 4)
|
|
{
|
|
dst[0] = src[2];
|
|
dst[1] = src[1];
|
|
dst[2] = src[0];
|
|
}
|
|
}
|
|
*bytestride = vid.pixelwidth*3;
|
|
*truevidwidth = vid.pixelwidth;
|
|
*truevidheight = vid.pixelheight;
|
|
*fmt = TF_BGR24;
|
|
return buf;
|
|
}
|
|
void SW_VID_SetWindowCaption(const char *msg)
|
|
{
|
|
}
|
|
#endif
|