- fixed all undefined symbols except OpenGLFrameBuffer.

This commit is contained in:
Christoph Oelckers 2019-12-23 10:53:58 +01:00
parent 10683e9123
commit 6e9631f2d8
29 changed files with 2397 additions and 652 deletions

View file

@ -831,12 +831,16 @@ set (PCH_SOURCES
common/menu/menuinput.cpp
common/menu/messagebox.cpp
common/menu/optionmenu.cpp
common/menu/resolutionmenu.cpp
common/input/i_gui.cpp
common/input/i_joystick.cpp
common/input/i_input.cpp
#common/input/i_joystick.cpp
#common/input/i_input.cpp
common/input/m_joy.cpp
common/input/input.cpp
common/rendering/v_video.cpp
common/rendering/v_framebuffer.cpp
common/rendering/r_videoscale.cpp
)
if( MSVC )

View file

@ -128,23 +128,23 @@ extern int32_t qsetmode;
#define in3dmode() (qsetmode==200)
int32_t initsystem(void);
void uninitsystem(void);
void system_getcvars(void);
extern int32_t g_logFlushWindow;
int32_t handleevents(void);
void I_GetEvent();
inline int32_t handleevents(void)
{
I_GetEvent();
return 0;
}
int32_t handleevents_peekkeys(void);
int32_t initinput(void);
void uninitinput(void);
void joySetCallback(void (*callback)(int32_t,int32_t));
const char *joyGetName(int32_t what, int32_t num); // what: 0=axis, 1=button, 2=hat
void joyScanDevices(void);
void mouseInit(void);
void mouseUninit(void);
void mouseGrabInput(bool grab);
void mouseLockToWindow(bool a);
void mouseMoveToCenter(void);

View file

@ -12,15 +12,6 @@
#include "d_event.h"
#include "../../glbackend/glbackend.h"
// video
#ifdef _WIN32
extern "C"
{
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 0x00000001;
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
}
#endif // _WIN32
int32_t g_borderless=2;
int GUICapture = false;

View file

@ -8100,8 +8100,6 @@ void engineUnInit(void)
Bmemset(basepaltable, 0, sizeof(basepaltable));
basepaltable[0] = palette;
uninitsystem();
for (bssize_t i = 0; i < num_usermaphacks; i++)
{
Xfree(usermaphacks[i].mhkfile);

View file

@ -76,7 +76,6 @@ static SDL_version linked;
double g_beforeSwapTime;
GameInterface* gi;
FArgs* Args;
void buildkeytranslationtable();;
@ -156,72 +155,6 @@ uint16_t joydead[9], joysatur[9];
#define MAX_ERRORTEXT 4096
//==========================================================================
//
// CalculateCPUSpeed
//
// Make a decent guess at how much time elapses between TSC steps. This can
// vary over runtime depending on power management settings, so should not
// be used anywhere that truely accurate timing actually matters.
//
//==========================================================================
double PerfToSec, PerfToMillisec;
#include "stats.h"
static void CalculateCPUSpeed()
{
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
if (freq.QuadPart != 0)
{
LARGE_INTEGER count1, count2;
cycle_t ClockCalibration;
DWORD min_diff;
ClockCalibration.Reset();
// Count cycles for at least 55 milliseconds.
// The performance counter may be very low resolution compared to CPU
// speeds today, so the longer we count, the more accurate our estimate.
// On the other hand, we don't want to count too long, because we don't
// want the user to notice us spend time here, since most users will
// probably never use the performance statistics.
min_diff = freq.LowPart * 11 / 200;
// Minimize the chance of task switching during the testing by going very
// high priority. This is another reason to avoid timing for too long.
SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
// Make sure we start timing on a counter boundary.
QueryPerformanceCounter(&count1);
do
{
QueryPerformanceCounter(&count2);
} while (count1.QuadPart == count2.QuadPart);
// Do the timing loop.
ClockCalibration.Clock();
do
{
QueryPerformanceCounter(&count1);
} while ((count1.QuadPart - count2.QuadPart) < min_diff);
ClockCalibration.Unclock();
SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS);
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
PerfToSec = double(count1.QuadPart - count2.QuadPart) / (double(ClockCalibration.GetRawCounter()) * freq.QuadPart);
PerfToMillisec = PerfToSec * 1000.0;
}
}
//==========================================================================
//
// I_Error
@ -578,6 +511,7 @@ static void sighandler(int signum)
int GameMain();
#if 0
#ifdef _WIN32
int WINAPI WinMain(HINSTANCE , HINSTANCE , LPSTR , int )
@ -585,59 +519,8 @@ int WINAPI WinMain(HINSTANCE , HINSTANCE , LPSTR , int )
int main(int argc, char *argv[])
#endif
{
#ifdef _WIN32
char* argvbuf;
int32_t buildargc = win_buildargs(&argvbuf);
const char** buildargv = (const char**)Xmalloc(sizeof(char*) * (buildargc + 1));
char* wp = argvbuf;
for (bssize_t i = 0; i < buildargc; i++, wp++)
{
buildargv[i] = wp;
while (*wp) wp++;
}
buildargv[buildargc] = NULL;
#else
auto buildargc = argc;
auto buildargv = argv;
#endif
Args = new FArgs(buildargc, buildargv);
#if defined _WIN32 && defined SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING
// Thread naming interferes with debugging using MinGW-w64's GDB.
SDL_SetHint(SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING, "1");
#endif
int32_t r;
#ifndef _WIN32
setenv("__GL_THREADED_OPTIMIZATIONS", "1", 0);
#endif
CalculateCPUSpeed();
buildkeytranslationtable();
#ifndef _WIN32 // catching signals is not really helpful on Windows.
signal(SIGSEGV, sighandler);
signal(SIGILL, sighandler); /* clang -fcatch-undefined-behavior uses an ill. insn */
signal(SIGABRT, sighandler);
signal(SIGFPE, sighandler);
#endif
#if defined(HAVE_GTK2)
// Pre-initialize SDL video system in order to make sure XInitThreads() is called
// before GTK starts talking to X11.
uint32_t inited = SDL_WasInit(SDL_INIT_VIDEO);
if (inited == 0)
SDL_Init(SDL_INIT_VIDEO);
else if (!(inited & SDL_INIT_VIDEO))
SDL_InitSubSystem(SDL_INIT_VIDEO);
gtkbuild_init(&argc, &argv);
#endif
if (initsystem()) Bexit(9);
SDL_StartTextInput();
@ -648,6 +531,7 @@ int main(int argc, char *argv[])
#endif
return r;
}
#endif
// The resourge manager in cache1d is far too broken to add some arbitrary file without some adjustment.
// For now, keep this file here, until the resource management can be redone in a more workable fashion.
@ -696,117 +580,6 @@ int32_t videoSetVsync(int32_t newSync)
}
#endif
int32_t sdlayer_checkversion(void);
#if SDL_MAJOR_VERSION != 1
int32_t sdlayer_checkversion(void)
{
#if 0
SDL_version compiled;
SDL_GetVersion(&linked);
SDL_VERSION(&compiled);
if (!Bmemcmp(&compiled, &linked, sizeof(SDL_version)))
initprintf("Initializing SDL %d.%d.%d\n",
compiled.major, compiled.minor, compiled.patch);
else
initprintf("Initializing SDL %d.%d.%d"
" (built against SDL version %d.%d.%d)\n",
linked.major, linked.minor, linked.patch, compiled.major, compiled.minor, compiled.patch);
if (SDL_VERSIONNUM(linked.major, linked.minor, linked.patch) < SDL_REQUIREDVERSION)
{
/*reject running under SDL versions older than what is stated in sdl_inc.h */
initprintf("You need at least v%d.%d.%d of SDL to run this game\n",SDL_MIN_X,SDL_MIN_Y,SDL_MIN_Z);
return -1;
}
#endif
return 0;
}
//
// initsystem() -- init SDL systems
//
int32_t initsystem(void)
{
const int sdlinitflags = SDL_INIT_VIDEO;
if (sdlayer_checkversion())
return -1;
int32_t err = 0;
uint32_t inited = SDL_WasInit(sdlinitflags);
if (inited == 0)
err = SDL_Init(sdlinitflags);
else if ((inited & sdlinitflags) != sdlinitflags)
err = SDL_InitSubSystem(sdlinitflags & ~inited);
if (err)
{
initprintf("Initialization failed! (%s)\nNon-interactive mode enabled\n", SDL_GetError());
novideo = 1;
#ifdef USE_OPENGL
nogl = 1;
#endif
}
#if SDL_MAJOR_VERSION > 1
SDL_StopTextInput();
#endif
atexit(uninitsystem);
frameplace = 0;
lockcount = 0;
if (!novideo)
{
#ifdef USE_OPENGL
if (SDL_GL_LoadLibrary(0))
{
initprintf("Failed loading OpenGL Driver. GL modes will be unavailable. Error: %s\n", SDL_GetError());
nogl = 1;
}
#endif
#ifndef _WIN32
const char *drvname = SDL_GetVideoDriver(0);
if (drvname)
initprintf("Using \"%s\" video driver\n", drvname);
#endif
}
return 0;
}
#endif
//
// uninitsystem() -- uninit SDL systems
//
void uninitsystem(void)
{
uninitinput();
timerUninit();
if (appicon)
{
SDL_FreeSurface(appicon);
appicon = NULL;
}
SDL_Quit();
#ifdef USE_OPENGL
# if SDL_MAJOR_VERSION!=1
SDL_GL_UnloadLibrary();
# endif
#endif
}
//
// system_getcvars() -- propagate any cvars that are read post-initialization
//
@ -1007,8 +780,6 @@ int32_t initinput(void)
//
void uninitinput(void)
{
mouseUninit();
if (controller)
{
SDL_GameControllerClose(controller);

View file

@ -178,19 +178,3 @@ struct Va_List
va_list list;
};
int CheckRatio (int width, int height, int *trueratio=NULL);
static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); }
inline bool IsRatioWidescreen(int ratio) { return (ratio & 3) != 0; }
float ActiveRatio (int width, int height, float *trueratio = NULL);
static inline double ActiveRatio (double width, double height) { return ActiveRatio(int(width), int(height)); }
int AspectBaseWidth(float aspect);
int AspectBaseHeight(float aspect);
double AspectPspriteOffset(float aspect);
int AspectMultiplier(float aspect);
bool AspectTallerThanWide(float aspect);
void ScaleWithAspect(int &w, int &h, int Width, int Height);
int GetUIScale(int altval);
int GetConScale(int altval);

View file

@ -39,8 +39,7 @@
#include "drawparms.h"
#include "templates.h"
#include "v_draw.h"
ScreenDummy* screen;
#include "v_video.h"
CUSTOM_CVAR(Int, uiscale, 0, CVAR_ARCHIVE | CVAR_NOINITCALL)
{
@ -52,8 +51,6 @@ CUSTOM_CVAR(Int, uiscale, 0, CVAR_ARCHIVE | CVAR_NOINITCALL)
//setsizeneeded = true;
}
CVAR(Int, vid_aspect, 0, 0)
int GetUIScale(int altval)
{
int scaleval;
@ -107,36 +104,6 @@ int CleanWidth, CleanHeight;
int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1;
void V_UpdateModeSize(int width, int height)
{
// This calculates the menu scale.
// The optimal scale will always be to fit a virtual 640 pixel wide display onto the screen.
// Exceptions are made for a few ranges where the available virtual width is > 480.
// This reference size is being used so that on 800x450 (small 16:9) a scale of 2 gets used.
CleanXfac = std::max(std::min(screen->GetWidth() / 400, screen->GetHeight() / 240), 1);
if (CleanXfac >= 4) CleanXfac--; // Otherwise we do not have enough space for the episode/skill menus in some languages.
CleanYfac = CleanXfac;
CleanWidth = screen->GetWidth() / CleanXfac;
CleanHeight = screen->GetHeight() / CleanYfac;
int w = screen->GetWidth();
int factor;
if (w < 640) factor = 1;
else if (w >= 1024 && w < 1280) factor = 2;
else if (w >= 1600 && w < 1920) factor = 3;
else factor = w / 640;
if (w < 1360) factor = 1;
else if (w < 1920) factor = 2;
else factor = int(factor * 0.7);
CleanYfac_1 = CleanXfac_1 = factor;// MAX(1, int(factor * 0.7));
CleanWidth_1 = width / CleanXfac_1;
CleanHeight_1 = height / CleanYfac_1;
}
//==========================================================================
//
// Draw parameter parsing
@ -749,156 +716,3 @@ void VirtualToRealCoords(double &x, double &y, double &w, double &h,
}
}
// Helper for ActiveRatio and CheckRatio. Returns the forced ratio type, or -1 if none.
int ActiveFakeRatio(int width, int height)
{
int fakeratio = -1;
if ((vid_aspect >= 1) && (vid_aspect <= 6))
{
// [SP] User wants to force aspect ratio; let them.
fakeratio = int(vid_aspect);
if (fakeratio == 3)
{
fakeratio = 0;
}
else if (fakeratio == 5)
{
fakeratio = 3;
}
}
else if (vid_aspect == 0)// && ViewportIsScaled43())
{
fakeratio = 0;
}
return fakeratio;
}
// Active screen ratio based on cvars and size
float ActiveRatio(int width, int height, float* trueratio)
{
static float forcedRatioTypes[] =
{
4 / 3.0f,
16 / 9.0f,
16 / 10.0f,
17 / 10.0f,
5 / 4.0f,
17 / 10.0f,
21 / 9.0f
};
float ratio = width / (float)height;
int fakeratio = ActiveFakeRatio(width, height);
if (trueratio)
*trueratio = ratio;
return (fakeratio != -1) ? forcedRatioTypes[fakeratio] : ratio;
}
// Tries to guess the physical dimensions of the screen based on the
// screen's pixel dimensions. Can return:
// 0: 4:3
// 1: 16:9
// 2: 16:10
// 3: 17:10
// 4: 5:4
// 5: 17:10 (redundant, never returned)
// 6: 21:9
int CheckRatio(int width, int height, int* trueratio)
{
float aspect = width / (float)height;
static std::pair<float, int> ratioTypes[] =
{
{ 21 / 9.0f , 6 },
{ 16 / 9.0f , 1 },
{ 17 / 10.0f , 3 },
{ 16 / 10.0f , 2 },
{ 4 / 3.0f , 0 },
{ 5 / 4.0f , 4 },
{ 0.0f, 0 }
};
int ratio = ratioTypes[0].second;
float distance = fabs(ratioTypes[0].first - aspect);
for (int i = 1; ratioTypes[i].first != 0.0f; i++)
{
float d = fabs(ratioTypes[i].first - aspect);
if (d < distance)
{
ratio = ratioTypes[i].second;
distance = d;
}
}
int fakeratio = ActiveFakeRatio(width, height);
if (fakeratio == -1)
fakeratio = ratio;
if (trueratio)
*trueratio = ratio;
return fakeratio;
}
int AspectBaseWidth(float aspect)
{
return (int)round(240.0f * aspect * 3.0f);
}
int AspectBaseHeight(float aspect)
{
if (!AspectTallerThanWide(aspect))
return (int)round(200.0f * (320.0f / (AspectBaseWidth(aspect) / 3.0f)) * 3.0f);
else
return (int)round((200.0f * (4.0f / 3.0f)) / aspect * 3.0f);
}
double AspectPspriteOffset(float aspect)
{
if (!AspectTallerThanWide(aspect))
return 0.0;
else
return ((4.0 / 3.0) / aspect - 1.0) * 97.5;
}
int AspectMultiplier(float aspect)
{
if (!AspectTallerThanWide(aspect))
return (int)round(320.0f / (AspectBaseWidth(aspect) / 3.0f) * 48.0f);
else
return (int)round(200.0f / (AspectBaseHeight(aspect) / 3.0f) * 48.0f);
}
bool AspectTallerThanWide(float aspect)
{
return aspect < 1.333f;
}
void ScaleWithAspect(int& w, int& h, int Width, int Height)
{
int resRatio = CheckRatio(Width, Height);
int screenRatio;
CheckRatio(w, h, &screenRatio);
if (resRatio == screenRatio)
return;
double yratio;
switch (resRatio)
{
case 0: yratio = 4. / 3.; break;
case 1: yratio = 16. / 9.; break;
case 2: yratio = 16. / 10.; break;
case 3: yratio = 17. / 10.; break;
case 4: yratio = 5. / 4.; break;
case 6: yratio = 21. / 9.; break;
default: return;
}
double y = w / yratio;
if (y > h)
w = static_cast<int>(h * yratio);
else
h = static_cast<int>(y);
}

View file

@ -2,18 +2,13 @@
#include "drawparms.h"
#include "c_cvars.h"
#include "v_video.h"
// Undo Windows's forced #defines
#ifdef DrawText
#undef DrawText
#endif
extern int32_t xdim, ydim;
struct ScreenDummy
{
static int GetWidth() { return xdim; }
static int GetHeight() { return ydim; }
};
extern ScreenDummy* screen;
int GetUIScale(int altval);
int GetConScale(int altval);
@ -33,7 +28,7 @@ extern int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1;
bool SetTextureParms(DrawParms *parms, FTexture *img, double xx, double yy);
bool ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t tag, Va_List& tags, DrawParms *parms, bool fortext);
void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom, bool handleaspect);
int ActiveFakeRatio(int width, int height);
//int ActiveFakeRatio(int width, int height);
float ActiveRatio(int width, int height, float* trueratio);
int CheckRatio(int width, int height, int* trueratio);
int AspectBaseWidth(float aspect);;
@ -53,13 +48,3 @@ void DrawFrame(F2DDrawer* twod, PalEntry color, int left, int top, int width, in
EXTERN_CVAR(Int, con_scaletext) // Scale notify text at high resolutions?
EXTERN_CVAR(Int, con_scale)
inline int active_con_scaletext(bool newconfont = false)
{
return newconfont ? GetConScale(con_scaletext) : GetUIScale(con_scaletext);
}
inline int active_con_scale()
{
return GetConScale(con_scale);
}

View file

@ -304,7 +304,7 @@ int V_GetColor(const char* cstr)
{
val[0] = cstr[1 + i * 2];
val[1] = cstr[2 + i * 2];
c[i] = ParseHex(val);
c[i] = ParseHex(val, nullptr);
}
}
else if (len == 4)
@ -313,7 +313,7 @@ int V_GetColor(const char* cstr)
for (i = 0; i < 3; ++i)
{
val[1] = val[0] = cstr[1 + i];
c[i] = ParseHex(val);
c[i] = ParseHex(val, nullptr);
}
}
else
@ -366,7 +366,7 @@ int V_GetColor(const char* cstr)
{
val[1] = val[0];
}
c[i] = ParseHex(val);
c[i] = ParseHex(val, nullptr);
}
}
}

View file

@ -286,8 +286,8 @@ int GameMain()
C_InitConsole(1024, 768, true);
FStringf logpath("logfile %sdemolition.log", M_GetDocumentsPath().GetChars());
C_DoCommand(logpath);
I_StartupJoysticks();
mouseInit();
//I_StartupJoysticks();
//mouseInit();
#ifndef NETCODE_DISABLE
gHaveNetworking = !enet_initialize();

View file

@ -948,6 +948,22 @@ void M_MenuSound(EMenuSounds snd)
//
//=============================================================================
void M_PreviousMenu()
{
if (DMenu::CurrentMenu != nullptr)
{
DMenu* parent = DMenu::CurrentMenu->mParentMenu;
DMenu::CurrentMenu->Destroy();
DMenu::CurrentMenu = parent;
}
}
//=============================================================================
//
//
//
//=============================================================================
void M_Init (void)
{
RegisterDukeMenus();

View file

@ -765,6 +765,7 @@ void M_EnableMenu (bool on) ;
bool M_Responder (event_t *ev);
void M_Ticker (void);
void M_Drawer (void);
void M_PreviousMenu();
void M_Init (void);
void M_CreateMenus();
void M_ActivateMenu(DMenu *menu);

View file

@ -1,8 +1,9 @@
/*
** i_gui.cpp
** resolutionmenu.cpp
** Basic Custom Resolution Selector for the Menu
**
**---------------------------------------------------------------------------
** Copyright 2008 Randy Heit
** Copyright 2018 Rachael Alexanderson
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
@ -31,57 +32,61 @@
**
*/
#include <string.h>
#include "c_dispatch.h"
#include "c_cvars.h"
#include "v_video.h"
#include "menu/menu.h"
#include <SDL.h>
CVAR(Int, menu_resolution_custom_width, 640, 0)
CVAR(Int, menu_resolution_custom_height, 480, 0)
#include "bitmap.h"
//#include "v_palette.h"
#include "textures.h"
EXTERN_CVAR(Bool, vid_fullscreen)
EXTERN_CVAR(Bool, win_maximized)
EXTERN_CVAR(Bool, vid_scale_customlinear)
EXTERN_CVAR(Bool, vid_scale_customstretched)
EXTERN_CVAR(Int, vid_scale_customwidth)
EXTERN_CVAR(Int, vid_scale_customheight)
EXTERN_CVAR(Int, vid_scalemode)
EXTERN_CVAR(Float, vid_scalefactor)
bool I_SetCursor(FTexture *cursorpic)
CCMD (menu_resolution_set_custom)
{
static SDL_Cursor *cursor;
static SDL_Surface *cursorSurface;
if (cursorpic != NULL)
if (argv.argc() > 2)
{
auto src = cursorpic->GetBgraBitmap(nullptr);
// Must be no larger than 32x32.
if (src.GetWidth() > 32 || src.GetHeight() > 32)
{
return false;
}
if (cursorSurface == NULL)
cursorSurface = SDL_CreateRGBSurface (0, 32, 32, 32, MAKEARGB(0,255,0,0), MAKEARGB(0,0,255,0), MAKEARGB(0,0,0,255), MAKEARGB(255,0,0,0));
SDL_LockSurface(cursorSurface);
uint8_t buffer[32*32*4];
memset(buffer, 0, 32*32*4);
FBitmap bmp(buffer, 32*4, 32, 32);
bmp.Blit(0, 0, src); // expand to 32*32
memcpy(cursorSurface->pixels, bmp.GetPixels(), 32*32*4);
SDL_UnlockSurface(cursorSurface);
if (cursor)
SDL_FreeCursor (cursor);
cursor = SDL_CreateColorCursor (cursorSurface, 0, 0);
SDL_SetCursor (cursor);
menu_resolution_custom_width = atoi(argv[1]);
menu_resolution_custom_height = atoi(argv[2]);
}
else
{
if (cursor)
{
SDL_SetCursor (NULL);
SDL_FreeCursor (cursor);
cursor = NULL;
Printf("This command is not meant to be used outside the menu! But if you want to use it, please specify <x> and <y>.\n");
}
if (cursorSurface != NULL)
{
SDL_FreeSurface(cursorSurface);
cursorSurface = NULL;
}
}
return true;
M_PreviousMenu();
}
CCMD (menu_resolution_commit_changes)
{
int do_fullscreen = fullscreen;
if (argv.argc() > 1)
{
do_fullscreen = atoi(argv[1]);
}
if (do_fullscreen == false)
{
vid_scalemode = vid_scale_customlinear;
vid_scalefactor = 1.;
screen->SetWindowSize(menu_resolution_custom_width, menu_resolution_custom_height);
V_OutputResized(screen->GetClientWidth(), screen->GetClientHeight());
}
else
{
fullscreen = true;
vid_scalemode = 5;
vid_scalefactor = 1.;
vid_scale_customwidth = menu_resolution_custom_width;
vid_scale_customheight = menu_resolution_custom_height;
vid_scale_customstretched = false;
}
}

View file

@ -0,0 +1,38 @@
#ifndef __I_VIDEO_H__
#define __I_VIDEO_H__
#include <cstdint>
class DFrameBuffer;
class IVideo
{
public:
virtual ~IVideo() {}
virtual DFrameBuffer *CreateFrameBuffer() = 0;
bool SetResolution();
virtual void DumpAdapters();
};
void I_InitGraphics();
void I_ShutdownGraphics();
extern IVideo *Video;
void I_PolyPresentInit();
uint8_t *I_PolyPresentLock(int w, int h, bool vsync, int &pitch);
void I_PolyPresentUnlock(int x, int y, int w, int h);
void I_PolyPresentDeinit();
// Pause a bit.
// [RH] Despite the name, it apparently never waited for the VBL, even in
// the original DOS version (if the Heretic/Hexen source is any indicator).
void I_WaitVBL(int count);
#endif // __I_VIDEO_H__

View file

@ -0,0 +1,261 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2017 Magnus Norddahl
// Copyright(C) 2018 Rachael Alexanderson
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
#include <math.h>
#include "c_dispatch.h"
#include "c_cvars.h"
#include "v_video.h"
#include "templates.h"
#include "printf.h"
#define NUMSCALEMODES 7
bool setsizeneeded;
EXTERN_CVAR(Int, vid_aspect)
CUSTOM_CVAR(Int, vid_scale_customwidth, VID_MIN_WIDTH, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < VID_MIN_WIDTH)
self = VID_MIN_WIDTH;
setsizeneeded = true;
}
CUSTOM_CVAR(Int, vid_scale_customheight, VID_MIN_HEIGHT, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (self < VID_MIN_HEIGHT)
self = VID_MIN_HEIGHT;
setsizeneeded = true;
}
CVAR(Bool, vid_scale_customlinear, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CUSTOM_CVAR(Bool, vid_scale_customstretched, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
setsizeneeded = true;
}
namespace
{
struct v_ScaleTable
{
bool isValid;
bool isLinear;
uint32_t(*GetScaledWidth)(uint32_t Width, uint32_t Height);
uint32_t(*GetScaledHeight)(uint32_t Width, uint32_t Height);
bool isScaled43;
bool isCustom;
};
float v_MinimumToFill(uint32_t inwidth, uint32_t inheight)
{
// sx = screen x dimension, sy = same for y
float sx = (float)inwidth, sy = (float)inheight;
static float lastsx = 0., lastsy = 0., result = 0.;
if (lastsx != sx || lastsy != sy)
{
if (sx <= 0. || sy <= 0.)
return 1.; // prevent x/0 error
// set absolute minimum scale to fill the entire screen but get as close to 640x400 as possible
float ssx = (float)(VID_MIN_WIDTH) / sx, ssy = (float)(VID_MIN_HEIGHT) / sy;
result = (ssx < ssy) ? ssy : ssx;
lastsx = sx;
lastsy = sy;
}
return result;
}
inline uint32_t v_mfillX(uint32_t inwidth, uint32_t inheight)
{
return (uint32_t)((float)inwidth * v_MinimumToFill(inwidth, inheight));
}
inline uint32_t v_mfillY(uint32_t inwidth, uint32_t inheight)
{
return (uint32_t)((float)inheight * v_MinimumToFill(inwidth, inheight));
}
v_ScaleTable vScaleTable[NUMSCALEMODES] =
{
// isValid, isLinear, GetScaledWidth(), GetScaledHeight(), isScaled43, isCustom
{ true, false, [](uint32_t Width, uint32_t Height)->uint32_t { return Width; }, [](uint32_t Width, uint32_t Height)->uint32_t { return Height; }, false, false }, // 0 - Native
{ true, true, [](uint32_t Width, uint32_t Height)->uint32_t { return Width; }, [](uint32_t Width, uint32_t Height)->uint32_t { return Height; }, false, false }, // 1 - Native (Linear)
{ true, false, [](uint32_t Width, uint32_t Height)->uint32_t { return 640; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 400; }, true, false }, // 2 - 640x400 (formerly 320x200)
{ true, true, [](uint32_t Width, uint32_t Height)->uint32_t { return 960; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 600; }, true, false }, // 3 - 960x600 (formerly 640x400)
{ true, true, [](uint32_t Width, uint32_t Height)->uint32_t { return 1280; }, [](uint32_t Width, uint32_t Height)->uint32_t { return 800; }, true, false }, // 4 - 1280x800
{ true, true, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customwidth; }, [](uint32_t Width, uint32_t Height)->uint32_t { return vid_scale_customheight; }, true, true }, // 5 - Custom
{ true, true, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillX(Width, Height); }, [](uint32_t Width, uint32_t Height)->uint32_t { return v_mfillY(Width, Height); }, false, false }, // 6 - Minimum Scale to Fill Entire Screen
};
bool isOutOfBounds(int x)
{
return (x < 0 || x >= NUMSCALEMODES || vScaleTable[x].isValid == false);
}
}
void R_ShowCurrentScaling();
CUSTOM_CVAR(Float, vid_scalefactor, 1.0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
setsizeneeded = true;
if (self < 0.05 || self > 2.0)
self = 1.0;
if (self != 1.0)
R_ShowCurrentScaling();
}
CUSTOM_CVAR(Int, vid_scalemode, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
setsizeneeded = true;
if (isOutOfBounds(self))
self = 0;
}
CUSTOM_CVAR(Bool, vid_cropaspect, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
setsizeneeded = true;
}
bool ViewportLinearScale()
{
if (isOutOfBounds(vid_scalemode))
vid_scalemode = 0;
// hack - use custom scaling if in "custom" mode
if (vScaleTable[vid_scalemode].isCustom)
return vid_scale_customlinear;
// vid_scalefactor > 1 == forced linear scale
return (vid_scalefactor > 1.0) ? true : vScaleTable[vid_scalemode].isLinear;
}
int ViewportScaledWidth(int width, int height)
{
if (isOutOfBounds(vid_scalemode))
vid_scalemode = 0;
if (vid_cropaspect && height > 0)
{
width = ((float)width/height > ActiveRatio(width, height)) ? (int)(height * ActiveRatio(width, height)) : width;
height = ((float)width/height < ActiveRatio(width, height)) ? (int)(width / ActiveRatio(width, height)) : height;
}
return (int)std::max((int32_t)VID_MIN_WIDTH, (int32_t)(vid_scalefactor * vScaleTable[vid_scalemode].GetScaledWidth(width, height)));
}
int ViewportScaledHeight(int width, int height)
{
if (isOutOfBounds(vid_scalemode))
vid_scalemode = 0;
if (vid_cropaspect && height > 0)
{
height = ((float)width/height < ActiveRatio(width, height)) ? (int)(width / ActiveRatio(width, height)) : height;
width = ((float)width/height > ActiveRatio(width, height)) ? (int)(height * ActiveRatio(width, height)) : width;
}
return (int)std::max((int32_t)VID_MIN_HEIGHT, (int32_t)(vid_scalefactor * vScaleTable[vid_scalemode].GetScaledHeight(width, height)));
}
bool ViewportIsScaled43()
{
if (isOutOfBounds(vid_scalemode))
vid_scalemode = 0;
// hack - use custom scaling if in "custom" mode
if (vScaleTable[vid_scalemode].isCustom)
return vid_scale_customstretched;
return vScaleTable[vid_scalemode].isScaled43;
}
void R_ShowCurrentScaling()
{
int x1 = screen->GetClientWidth(), y1 = screen->GetClientHeight(), x2 = ViewportScaledWidth(x1, y1), y2 = ViewportScaledHeight(x1, y1);
Printf("Current vid_scalefactor: %f\n", (float)(vid_scalefactor));
Printf("Real resolution: %i x %i\nEmulated resolution: %i x %i\n", x1, y1, x2, y2);
}
CCMD (vid_showcurrentscaling)
{
R_ShowCurrentScaling();
}
CCMD (vid_scaletowidth)
{
if (argv.argc() > 1)
{
// the following enables the use of ViewportScaledWidth to get the proper dimensions in custom scale modes
vid_scalefactor = 1;
vid_scalefactor = (float)((double)atof(argv[1]) / ViewportScaledWidth(screen->GetClientWidth(), screen->GetClientHeight()));
}
}
CCMD (vid_scaletoheight)
{
if (argv.argc() > 1)
{
vid_scalefactor = 1;
vid_scalefactor = (float)((double)atof(argv[1]) / ViewportScaledHeight(screen->GetClientWidth(), screen->GetClientHeight()));
}
}
inline bool atob(char* I)
{
if (stricmp (I, "true") == 0 || stricmp (I, "1") == 0)
return true;
return false;
}
CCMD (vid_setscale)
{
if (argv.argc() > 2)
{
vid_scale_customwidth = atoi(argv[1]);
vid_scale_customheight = atoi(argv[2]);
if (argv.argc() > 3)
{
vid_scale_customlinear = atob(argv[3]);
if (argv.argc() > 4)
{
vid_scale_customstretched = atob(argv[4]);
}
}
vid_scalemode = 5;
vid_scalefactor = 1.0;
}
else
{
Printf("Usage: vid_setscale <x> <y> [bool linear] [bool long-pixel-shape]\nThis command will create a custom viewport scaling mode.\n");
}
}
CCMD (vid_scaletolowest)
{
uint32_t method = 0;
if (argv.argc() > 1)
method = atoi(argv[1]);
switch (method)
{
case 1: // Method 1: set a custom video scaling
vid_scalemode = 5;
vid_scalefactor = 1.0;
vid_scale_customlinear = 1;
vid_scale_customstretched = 0;
vid_scale_customwidth = v_mfillX(screen->GetClientWidth(), screen->GetClientHeight());
vid_scale_customheight = v_mfillY(screen->GetClientWidth(), screen->GetClientHeight());
break;
case 2: // Method 2: use the actual downscaling mode directly
vid_scalemode = 6;
vid_scalefactor = 1.0;
break;
default: // Default method: use vid_scalefactor to achieve the result on a default scaling mode
vid_scalemode = 1;
vid_scalefactor = v_MinimumToFill(screen->GetClientWidth(), screen->GetClientHeight());
break;
}
}

View file

@ -0,0 +1,31 @@
//
//---------------------------------------------------------------------------
//
// Copyright(C) 2017 Magnus Norddahl
// Copyright(C) 2017 Rachael Alexanderson
// All rights reserved.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with this program. If not, see http://www.gnu.org/licenses/
//
//--------------------------------------------------------------------------
//
#ifndef __VIDEOSCALE_H__
#define __VIDEOSCALE_H__
EXTERN_CVAR (Int, vid_scalemode)
bool ViewportLinearScale();
int ViewportScaledWidth(int width, int height);
int ViewportScaledHeight(int width, int height);
bool ViewportIsScaled43();
#endif //__VIDEOSCALE_H__

View file

@ -0,0 +1,389 @@
/*
** The base framebuffer class
**
**---------------------------------------------------------------------------
** Copyright 1999-2016 Randy Heit
** Copyright 2005-2018 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include <stdio.h>
#include "v_video.h"
#include "c_dispatch.h"
#include "hardware.h"
#include "r_videoscale.h"
#include "i_time.h"
#include "v_font.h"
#include "v_draw.h"
#include "i_time.h"
#include "v_2ddrawer.h"
/*
#include "hwrenderer/scene/hw_portal.h"
#include "hwrenderer/utility/hw_clock.h"
#include "hwrenderer/data/flatvertices.h"
*/
#include <chrono>
#include <thread>
CVAR(Bool, gl_scale_viewport, true, CVAR_ARCHIVE);
CVAR(Bool, vid_fps, false, 0)
CVAR(Int, vid_showpalette, 0, 0)
EXTERN_CVAR(Bool, ticker)
EXTERN_CVAR(Float, vid_brightness)
EXTERN_CVAR(Float, vid_contrast)
EXTERN_CVAR(Int, vid_maxfps)
EXTERN_CVAR(Bool, cl_capfps)
EXTERN_CVAR(Int, screenblocks)
//==========================================================================
//
// DCanvas :: CalcGamma
//
//==========================================================================
void DFrameBuffer::CalcGamma (float gamma, uint8_t gammalookup[256])
{
// I found this formula on the web at
// <http://panda.mostang.com/sane/sane-gamma.html>,
// but that page no longer exits.
double invgamma = 1.f / gamma;
int i;
for (i = 0; i < 256; i++)
{
gammalookup[i] = (uint8_t)(255.0 * pow (i / 255.0, invgamma) + 0.5);
}
}
//==========================================================================
//
// DFrameBuffer Constructor
//
// A frame buffer canvas is the most common and represents the image that
// gets drawn to the screen.
//
//==========================================================================
DFrameBuffer::DFrameBuffer (int width, int height)
{
SetSize(width, height);
//mPortalState = new FPortalSceneState;
}
DFrameBuffer::~DFrameBuffer()
{
//delete mPortalState;
}
void DFrameBuffer::SetSize(int width, int height)
{
Width = ViewportScaledWidth(width, height);
Height = ViewportScaledHeight(width, height);
}
//==========================================================================
//
// DFrameBuffer :: DrawRateStuff
//
// Draws the fps counter, dot ticker, and palette debug.
//
//==========================================================================
void DFrameBuffer::DrawRateStuff ()
{
// Draws frame time and cumulative fps
if (vid_fps)
{
uint64_t ms = screen->FrameTime;
uint64_t howlong = ms - LastMS;
if ((signed)howlong >= 0)
{
char fpsbuff[40];
int chars;
int rate_x;
int textScale = active_con_scale();
chars = snprintf (fpsbuff, countof(fpsbuff), "%2llu ms (%3llu fps)", (unsigned long long)howlong, (unsigned long long)LastCount);
rate_x = Width / textScale - NewConsoleFont->StringWidth(&fpsbuff[0]);
twod.AddColorOnlyQuad(rate_x * textScale, 0, Width, NewConsoleFont->GetHeight() * textScale, 0);
DrawText (&twod, NewConsoleFont, CR_WHITE, rate_x, 0, (char *)&fpsbuff[0],
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
uint32_t thisSec = (uint32_t)(ms/1000);
if (LastSec < thisSec)
{
LastCount = FrameCount / (thisSec - LastSec);
LastSec = thisSec;
FrameCount = 0;
}
FrameCount++;
}
LastMS = ms;
}
}
//==========================================================================
//
// Palette stuff.
//
//==========================================================================
void DFrameBuffer::Update()
{
//CheckBench();
int initialWidth = GetClientWidth();
int initialHeight = GetClientHeight();
int clientWidth = ViewportScaledWidth(initialWidth, initialHeight);
int clientHeight = ViewportScaledHeight(initialWidth, initialHeight);
if (clientWidth < VID_MIN_WIDTH) clientWidth = VID_MIN_WIDTH;
if (clientHeight < VID_MIN_HEIGHT) clientHeight = VID_MIN_HEIGHT;
if (clientWidth > 0 && clientHeight > 0 && (GetWidth() != clientWidth || GetHeight() != clientHeight))
{
SetVirtualSize(clientWidth, clientHeight);
V_OutputResized(clientWidth, clientHeight);
//mVertexData->OutputResized(clientWidth, clientHeight);
}
}
//==========================================================================
//
// DFrameBuffer :: SetVSync
//
// Turns vertical sync on and off, if supported.
//
//==========================================================================
void DFrameBuffer::SetVSync (bool vsync)
{
}
//==========================================================================
//
// DFrameBuffer :: WipeStartScreen
//
// Grabs a copy of the screen currently displayed to serve as the initial
// frame of a screen wipe. Also determines which screenwipe will be
// performed.
//
//==========================================================================
FTexture *DFrameBuffer::WipeStartScreen()
{
return nullptr;
}
//==========================================================================
//
// DFrameBuffer :: WipeEndScreen
//
// Grabs a copy of the most-recently drawn, but not yet displayed, screen
// to serve as the final frame of a screen wipe.
//
//==========================================================================
FTexture *DFrameBuffer::WipeEndScreen()
{
return nullptr;
}
//==========================================================================
//
// DFrameBuffer :: GetCaps
//
//==========================================================================
EXTERN_CVAR(Bool, r_drawvoxels)
void DFrameBuffer::WriteSavePic(player_t *player, FileWriter *file, int width, int height)
{
//SWRenderer->WriteSavePic(player, file, width, height);
}
//==========================================================================
//
// Calculates the viewport values needed for 2D and 3D operations
//
//==========================================================================
void DFrameBuffer::SetViewportRects(IntRect *bounds)
{
if (bounds)
{
//mSceneViewport = *bounds;
mScreenViewport = *bounds;
mOutputLetterbox = *bounds;
return;
}
#if 0
// Special handling so the view with a visible status bar displays properly
int height, width;
if (screenblocks >= 10)
{
height = GetHeight();
width = GetWidth();
}
else
{
height = (screenblocks*GetHeight() / 10) & ~7;
width = (screenblocks*GetWidth() / 10);
}
#endif
// Back buffer letterbox for the final output
int clientWidth = GetClientWidth();
int clientHeight = GetClientHeight();
if (clientWidth == 0 || clientHeight == 0)
{
// When window is minimized there may not be any client area.
// Pretend to the rest of the render code that we just have a very small window.
clientWidth = 160;
clientHeight = 120;
}
int screenWidth = GetWidth();
int screenHeight = GetHeight();
float scaleX, scaleY;
if (ViewportIsScaled43())
{
scaleX = std::min(clientWidth / (float)screenWidth, clientHeight / (screenHeight * 1.2f));
scaleY = scaleX * 1.2f;
}
else
{
scaleX = std::min(clientWidth / (float)screenWidth, clientHeight / (float)screenHeight);
scaleY = scaleX;
}
mOutputLetterbox.width = (int)round(screenWidth * scaleX);
mOutputLetterbox.height = (int)round(screenHeight * scaleY);
mOutputLetterbox.left = (clientWidth - mOutputLetterbox.width) / 2;
mOutputLetterbox.top = (clientHeight - mOutputLetterbox.height) / 2;
// The entire renderable area, including the 2D HUD
mScreenViewport.left = 0;
mScreenViewport.top = 0;
mScreenViewport.width = screenWidth;
mScreenViewport.height = screenHeight;
#if 0
// Viewport for the 3D scene
mSceneViewport.left = viewwindowx;
mSceneViewport.top = screenHeight - (height + viewwindowy - ((height - viewheight) / 2));
mSceneViewport.width = viewwidth;
mSceneViewport.height = height;
#endif
// Scale viewports to fit letterbox
bool notScaled = ((mScreenViewport.width == ViewportScaledWidth(mScreenViewport.width, mScreenViewport.height)) &&
(mScreenViewport.width == ViewportScaledHeight(mScreenViewport.width, mScreenViewport.height)) &&
!ViewportIsScaled43());
if (gl_scale_viewport && !IsFullscreen() && notScaled)
{
mScreenViewport.width = mOutputLetterbox.width;
mScreenViewport.height = mOutputLetterbox.height;
#if 0
mSceneViewport.left = (int)round(mSceneViewport.left * scaleX);
mSceneViewport.top = (int)round(mSceneViewport.top * scaleY);
mSceneViewport.width = (int)round(mSceneViewport.width * scaleX);
mSceneViewport.height = (int)round(mSceneViewport.height * scaleY);
#endif
}
}
//===========================================================================
//
// Calculates the OpenGL window coordinates for a zdoom screen position
//
//===========================================================================
int DFrameBuffer::ScreenToWindowX(int x)
{
return mScreenViewport.left + (int)round(x * mScreenViewport.width / (float)GetWidth());
}
int DFrameBuffer::ScreenToWindowY(int y)
{
return mScreenViewport.top + mScreenViewport.height - (int)round(y * mScreenViewport.height / (float)GetHeight());
}
void DFrameBuffer::ScaleCoordsFromWindow(int16_t &x, int16_t &y)
{
int letterboxX = mOutputLetterbox.left;
int letterboxY = mOutputLetterbox.top;
int letterboxWidth = mOutputLetterbox.width;
int letterboxHeight = mOutputLetterbox.height;
x = int16_t((x - letterboxX) * Width / letterboxWidth);
y = int16_t((y - letterboxY) * Height / letterboxHeight);
}
void DFrameBuffer::FPSLimit()
{
#if 0 // This doesn't work with Build games.
using namespace std::chrono;
using namespace std::this_thread;
if (vid_maxfps <= 0 || cl_capfps)
return;
uint64_t targetWakeTime = fpsLimitTime + 1'000'000 / vid_maxfps;
while (true)
{
fpsLimitTime = duration_cast<microseconds>(steady_clock::now().time_since_epoch()).count();
int64_t timeToWait = targetWakeTime - fpsLimitTime;
if (timeToWait > 1'000'000 || timeToWait <= 0)
{
break;
}
if (timeToWait <= 2'000)
{
// We are too close to the deadline. OS sleep is not precise enough to wake us before it elapses.
// Yield execution and check time again.
sleep_for(nanoseconds(0));
}
else
{
// Sleep, but try to wake before deadline.
sleep_for(microseconds(timeToWait - 2'000));
}
}
#endif
}

View file

@ -0,0 +1,806 @@
/*
** Video basics and init code.
**
**---------------------------------------------------------------------------
** Copyright 1999-2016 Randy Heit
** Copyright 2005-2016 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#include <stdio.h>
#include "i_system.h"
#include "c_cvars.h"
#include "i_video.h"
#include "c_console.h"
#include "m_argv.h"
#include "v_video.h"
#include "v_text.h"
#include "sc_man.h"
#include "c_dispatch.h"
#include "cmdlib.h"
#include "hardware.h"
#include "m_png.h"
#include "menu/menu.h"
#include "r_videoscale.h"
#include "i_time.h"
#include "version.h"
#include "filesystem.h"
EXTERN_CVAR(Int, menu_resolution_custom_width)
EXTERN_CVAR(Int, menu_resolution_custom_height)
CVAR(Int, vid_aspect, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR(Int, win_x, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Int, win_y, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Int, win_w, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Int, win_h, -1, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
CVAR(Bool, win_maximized, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
#if 0
CUSTOM_CVAR(Int, vid_maxfps, 200, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
{
if (vid_maxfps < TICRATE && vid_maxfps != 0)
{
vid_maxfps = TICRATE;
}
else if (vid_maxfps > 1000)
{
vid_maxfps = 1000;
}
}
#endif
CUSTOM_CVAR(Int, vid_rendermode, 4, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
if (self < 0 || self > 4)
{
self = 4;
}
#if 0
if (usergame)
{
// [SP] Update pitch limits to the netgame/gamesim.
players[consoleplayer].SendPitchLimits();
}
#endif
screen->SetTextureFilterMode();
// No further checks needed. All this changes now is which scene drawer the render backend calls.
}
CUSTOM_CVAR(Int, vid_preferbackend, 0, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
// [SP] This may seem pointless - but I don't want to implement live switching just
// yet - I'm pretty sure it's going to require a lot of reinits and destructions to
// do it right without memory leaks
switch(self)
{
case 2:
Printf("Selecting SoftPoly backend...\n");
break;
#ifdef HAVE_VULKAN
case 1:
Printf("Selecting Vulkan backend...\n");
break;
#endif
default:
Printf("Selecting OpenGL backend...\n");
}
Printf("Changing the video backend requires a restart for " GAMENAME ".\n");
}
CVAR(Int, vid_renderer, 1, 0) // for some stupid mods which threw caution out of the window...
EXTERN_CVAR(Bool, r_blendmethod)
int active_con_scale();
#define DBGBREAK assert(0)
class DDummyFrameBuffer : public DFrameBuffer
{
typedef DFrameBuffer Super;
public:
DDummyFrameBuffer (int width, int height)
: DFrameBuffer (0, 0)
{
SetVirtualSize(width, height);
}
// These methods should never be called.
void Update() { DBGBREAK; }
bool IsFullscreen() { DBGBREAK; return 0; }
int GetClientWidth() { DBGBREAK; return 0; }
int GetClientHeight() { DBGBREAK; return 0; }
void InitializeState() override {}
float Gamma;
};
int DisplayWidth, DisplayHeight;
// [RH] The framebuffer is no longer a mere byte array.
// There's also only one, not four.
DFrameBuffer *screen;
CVAR (Int, vid_defwidth, 640, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Int, vid_defheight, 480, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CVAR (Bool, ticker, false, 0)
CUSTOM_CVAR (Bool, vid_vsync, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{
if (screen != NULL)
{
screen->SetVSync (*self);
}
}
// [RH] Set true when vid_setmode command has been executed
bool setmodeneeded = false;
//==========================================================================
//
// DCanvas Constructor
//
//==========================================================================
DCanvas::DCanvas (int _width, int _height, bool _bgra)
{
// Init member vars
Width = _width;
Height = _height;
Bgra = _bgra;
Resize(_width, _height);
}
//==========================================================================
//
// DCanvas Destructor
//
//==========================================================================
DCanvas::~DCanvas ()
{
}
//==========================================================================
//
//
//
//==========================================================================
void DCanvas::Resize(int width, int height, bool optimizepitch)
{
Width = width;
Height = height;
// Making the pitch a power of 2 is very bad for performance
// Try to maximize the number of cache lines that can be filled
// for each column drawing operation by making the pitch slightly
// longer than the width. The values used here are all based on
// empirical evidence.
if (width <= 640 || !optimizepitch)
{
// For low resolutions, just keep the pitch the same as the width.
// Some speedup can be seen using the technique below, but the speedup
// is so marginal that I don't consider it worthwhile.
Pitch = width;
}
else
{
#if 0
// If we couldn't figure out the CPU's L1 cache line size, assume
// it's 32 bytes wide.
if (CPU.DataL1LineSize == 0)
{
CPU.DataL1LineSize = 32;
}
// The Athlon and P3 have very different caches, apparently.
// I am going to generalize the Athlon's performance to all AMD
// processors and the P3's to all non-AMD processors. I don't know
// how smart that is, but I don't have a vast plethora of
// processors to test with.
if (CPU.bIsAMD)
{
Pitch = width + CPU.DataL1LineSize;
}
else
{
Pitch = width + MAX(0, CPU.DataL1LineSize - 8);
}
#endif
}
int bytes_per_pixel = Bgra ? 4 : 1;
Pixels.Resize(Pitch * height * bytes_per_pixel);
memset (Pixels.Data(), 0, Pixels.Size());
}
//==========================================================================
//
// V_GetColorFromString
//
// Passed a string of the form "#RGB", "#RRGGBB", "R G B", or "RR GG BB",
// returns a number representing that color. If palette is non-NULL, the
// index of the best match in the palette is returned, otherwise the
// RRGGBB value is returned directly.
//
//==========================================================================
int V_GetColorFromString (const uint32_t *palette, const char *cstr, FScriptPosition *sc)
{
int c[3], i, p;
char val[3];
val[2] = '\0';
// Check for HTML-style #RRGGBB or #RGB color string
if (cstr[0] == '#')
{
size_t len = strlen (cstr);
if (len == 7)
{
// Extract each eight-bit component into c[].
for (i = 0; i < 3; ++i)
{
val[0] = cstr[1 + i*2];
val[1] = cstr[2 + i*2];
c[i] = ParseHex (val, sc);
}
}
else if (len == 4)
{
// Extract each four-bit component into c[], expanding to eight bits.
for (i = 0; i < 3; ++i)
{
val[1] = val[0] = cstr[1 + i];
c[i] = ParseHex (val, sc);
}
}
else
{
// Bad HTML-style; pretend it's black.
c[2] = c[1] = c[0] = 0;
}
}
else
{
if (strlen(cstr) == 6)
{
char *p;
int color = strtol(cstr, &p, 16);
if (*p == 0)
{
// RRGGBB string
c[0] = (color & 0xff0000) >> 16;
c[1] = (color & 0xff00) >> 8;
c[2] = (color & 0xff);
}
else goto normal;
}
else
{
normal:
// Treat it as a space-delimited hexadecimal string
for (i = 0; i < 3; ++i)
{
// Skip leading whitespace
while (*cstr <= ' ' && *cstr != '\0')
{
cstr++;
}
// Extract a component and convert it to eight-bit
for (p = 0; *cstr > ' '; ++p, ++cstr)
{
if (p < 2)
{
val[p] = *cstr;
}
}
if (p == 0)
{
c[i] = 0;
}
else
{
if (p == 1)
{
val[1] = val[0];
}
c[i] = ParseHex (val, sc);
}
}
}
}
return MAKERGB(c[0], c[1], c[2]);
}
//==========================================================================
//
// V_GetColorStringByName
//
// Searches for the given color name in x11r6rgb.txt and returns an
// HTML-ish "#RRGGBB" string for it if found or the empty string if not.
//
//==========================================================================
FString V_GetColorStringByName (const char *name, FScriptPosition *sc)
{
char *rgbEnd;
char *rgb, *endp;
int rgblump;
int c[3], step;
size_t namelen;
if (fileSystem.GetNumEntries()==0) return FString();
rgblump = fileSystem.FindFile ("demolition/X11R6RGB.txt");
if (rgblump == -1)
{
if (!sc) Printf ("X11R6RGB lump not found\n");
else sc->Message(MSG_WARNING, "X11R6RGB lump not found");
return FString();
}
rgb = (char*)fileSystem.Lock(rgblump);
rgbEnd = rgb + fileSystem.FileLength (rgblump);
step = 0;
namelen = strlen (name);
while (rgb < rgbEnd)
{
// Skip white space
if (*rgb <= ' ')
{
do
{
rgb++;
} while (rgb < rgbEnd && *rgb <= ' ');
}
else if (step == 0 && *rgb == '!')
{ // skip comment lines
do
{
rgb++;
} while (rgb < rgbEnd && *rgb != '\n');
}
else if (step < 3)
{ // collect RGB values
c[step++] = strtoul (rgb, &endp, 10);
if (endp == rgb)
{
break;
}
rgb = endp;
}
else
{ // Check color name
endp = rgb;
// Find the end of the line
while (endp < rgbEnd && *endp != '\n')
endp++;
// Back up over any whitespace
while (endp > rgb && *endp <= ' ')
endp--;
if (endp == rgb)
{
break;
}
size_t checklen = ++endp - rgb;
if (checklen == namelen && strnicmp (rgb, name, checklen) == 0)
{
FString descr;
descr.Format ("#%02x%02x%02x", c[0], c[1], c[2]);
return descr;
}
rgb = endp;
step = 0;
}
}
if (rgb < rgbEnd)
{
if (!sc) Printf ("X11R6RGB lump is corrupt\n");
else sc->Message(MSG_WARNING, "X11R6RGB lump is corrupt");
}
return FString();
}
//==========================================================================
//
// V_GetColor
//
// Works like V_GetColorFromString(), but also understands X11 color names.
//
//==========================================================================
int V_GetColor (const uint32_t *palette, const char *str, FScriptPosition *sc)
{
FString string = V_GetColorStringByName (str, sc);
int res;
if (!string.IsEmpty())
{
res = V_GetColorFromString (palette, string, sc);
}
else
{
res = V_GetColorFromString (palette, str, sc);
}
return res;
}
int V_GetColor(const uint32_t *palette, FScanner &sc)
{
FScriptPosition scc = sc;
return V_GetColor(palette, sc.String, &scc);
}
CCMD(clean)
{
Printf ("CleanXfac: %d\nCleanYfac: %d\n", CleanXfac, CleanYfac);
}
void V_UpdateModeSize (int width, int height)
{
// This calculates the menu scale.
// The optimal scale will always be to fit a virtual 640 pixel wide display onto the screen.
// Exceptions are made for a few ranges where the available virtual width is > 480.
// This reference size is being used so that on 800x450 (small 16:9) a scale of 2 gets used.
CleanXfac = std::max(std::min(screen->GetWidth() / 400, screen->GetHeight() / 240), 1);
if (CleanXfac >= 4) CleanXfac--; // Otherwise we do not have enough space for the episode/skill menus in some languages.
CleanYfac = CleanXfac;
CleanWidth = screen->GetWidth() / CleanXfac;
CleanHeight = screen->GetHeight() / CleanYfac;
int w = screen->GetWidth();
int factor;
if (w < 640) factor = 1;
else if (w >= 1024 && w < 1280) factor = 2;
else if (w >= 1600 && w < 1920) factor = 3;
else factor = w / 640;
if (w < 1360) factor = 1;
else if (w < 1920) factor = 2;
else factor = int(factor * 0.7);
CleanYfac_1 = CleanXfac_1 = factor;// MAX(1, int(factor * 0.7));
CleanWidth_1 = width / CleanXfac_1;
CleanHeight_1 = height / CleanYfac_1;
DisplayWidth = width;
DisplayHeight = height;
}
void V_OutputResized (int width, int height)
{
V_UpdateModeSize(width, height);
// setsizeneeded = true;
C_NewModeAdjust();
}
void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *_cx1, int *_cx2)
{
if (designheight < 240 && realheight >= 480) designheight = 240;
*cleanx = *cleany = std::min(realwidth / designwidth, realheight / designheight);
}
bool IVideo::SetResolution ()
{
DFrameBuffer *buff = CreateFrameBuffer();
if (buff == NULL) // this cannot really happen
{
return false;
}
screen = buff;
screen->InitializeState();
screen->SetGamma();
V_UpdateModeSize(screen->GetWidth(), screen->GetHeight());
return true;
}
//
// V_Init
//
void V_InitScreenSize ()
{
const char *i;
int width, height, bits;
width = height = bits = 0;
if ( (i = Args->CheckValue ("-width")) )
width = atoi (i);
if ( (i = Args->CheckValue ("-height")) )
height = atoi (i);
if (width == 0)
{
if (height == 0)
{
width = vid_defwidth;
height = vid_defheight;
}
else
{
width = (height * 8) / 6;
}
}
else if (height == 0)
{
height = (width * 6) / 8;
}
// Remember the passed arguments for the next time the game starts up windowed.
vid_defwidth = width;
vid_defheight = height;
}
void V_InitScreen()
{
screen = new DDummyFrameBuffer (vid_defwidth, vid_defheight);
}
void V_Init2()
{
float gamma = static_cast<DDummyFrameBuffer *>(screen)->Gamma;
{
DFrameBuffer *s = screen;
screen = NULL;
delete s;
}
UCVarValue val;
val.Bool = !!Args->CheckParm("-devparm");
ticker.SetGenericRepDefault(val, CVAR_Bool);
I_InitGraphics();
Video->SetResolution(); // this only fails via exceptions.
Printf ("Resolution: %d x %d\n", SCREENWIDTH, SCREENHEIGHT);
// init these for the scaling menu
menu_resolution_custom_width = SCREENWIDTH;
menu_resolution_custom_height = SCREENHEIGHT;
screen->SetVSync(vid_vsync);
screen->SetGamma ();
FBaseCVar::ResetColors ();
C_NewModeAdjust();
//setsizeneeded = true;
}
// Helper for ActiveRatio and CheckRatio. Returns the forced ratio type, or -1 if none.
static int ActiveFakeRatio(int width, int height)
{
int fakeratio = -1;
if ((vid_aspect >= 1) && (vid_aspect <= 6))
{
// [SP] User wants to force aspect ratio; let them.
fakeratio = int(vid_aspect);
if (fakeratio == 3)
{
fakeratio = 0;
}
else if (fakeratio == 5)
{
fakeratio = 3;
}
}
else if (vid_aspect == 0 && ViewportIsScaled43())
{
fakeratio = 0;
}
return fakeratio;
}
// Active screen ratio based on cvars and size
float ActiveRatio(int width, int height, float *trueratio)
{
static float forcedRatioTypes[] =
{
4 / 3.0f,
16 / 9.0f,
16 / 10.0f,
17 / 10.0f,
5 / 4.0f,
17 / 10.0f,
21 / 9.0f
};
float ratio = width / (float)height;
int fakeratio = ActiveFakeRatio(width, height);
if (trueratio)
*trueratio = ratio;
return (fakeratio != -1) ? forcedRatioTypes[fakeratio] : ratio;
}
// Tries to guess the physical dimensions of the screen based on the
// screen's pixel dimensions. Can return:
// 0: 4:3
// 1: 16:9
// 2: 16:10
// 3: 17:10
// 4: 5:4
// 5: 17:10 (redundant, never returned)
// 6: 21:9
int CheckRatio (int width, int height, int *trueratio)
{
float aspect = width / (float)height;
static std::pair<float, int> ratioTypes[] =
{
{ 21 / 9.0f , 6 },
{ 16 / 9.0f , 1 },
{ 17 / 10.0f , 3 },
{ 16 / 10.0f , 2 },
{ 4 / 3.0f , 0 },
{ 5 / 4.0f , 4 },
{ 0.0f, 0 }
};
int ratio = ratioTypes[0].second;
float distance = fabs(ratioTypes[0].first - aspect);
for (int i = 1; ratioTypes[i].first != 0.0f; i++)
{
float d = fabs(ratioTypes[i].first - aspect);
if (d < distance)
{
ratio = ratioTypes[i].second;
distance = d;
}
}
int fakeratio = ActiveFakeRatio(width, height);
if (fakeratio == -1)
fakeratio = ratio;
if (trueratio)
*trueratio = ratio;
return fakeratio;
}
int AspectBaseWidth(float aspect)
{
return (int)round(240.0f * aspect * 3.0f);
}
int AspectBaseHeight(float aspect)
{
if (!AspectTallerThanWide(aspect))
return (int)round(200.0f * (320.0f / (AspectBaseWidth(aspect) / 3.0f)) * 3.0f);
else
return (int)round((200.0f * (4.0f / 3.0f)) / aspect * 3.0f);
}
double AspectPspriteOffset(float aspect)
{
if (!AspectTallerThanWide(aspect))
return 0.0;
else
return ((4.0 / 3.0) / aspect - 1.0) * 97.5;
}
int AspectMultiplier(float aspect)
{
if (!AspectTallerThanWide(aspect))
return (int)round(320.0f / (AspectBaseWidth(aspect) / 3.0f) * 48.0f);
else
return (int)round(200.0f / (AspectBaseHeight(aspect) / 3.0f) * 48.0f);
}
bool AspectTallerThanWide(float aspect)
{
return aspect < 1.333f;
}
void ScaleWithAspect (int &w, int &h, int Width, int Height)
{
int resRatio = CheckRatio (Width, Height);
int screenRatio;
CheckRatio (w, h, &screenRatio);
if (resRatio == screenRatio)
return;
double yratio;
switch(resRatio)
{
case 0: yratio = 4./3.; break;
case 1: yratio = 16./9.; break;
case 2: yratio = 16./10.; break;
case 3: yratio = 17./10.; break;
case 4: yratio = 5./4.; break;
case 6: yratio = 21./9.; break;
default: return;
}
double y = w/yratio;
if (y > h)
w = static_cast<int>(h * yratio);
else
h = static_cast<int>(y);
}
CCMD(vid_setsize)
{
if (argv.argc() < 3)
{
Printf("Usage: vid_setsize width height\n");
}
else
{
screen->SetWindowSize((int)strtol(argv[1], nullptr, 0), (int)strtol(argv[2], nullptr, 0));
V_OutputResized(screen->GetClientWidth(), screen->GetClientHeight());
}
}
void IVideo::DumpAdapters ()
{
Printf("Multi-monitor support unavailable.\n");
}
CUSTOM_CVAR(Bool, vid_fullscreen, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
setmodeneeded = true;
}
CUSTOM_CVAR(Bool, vid_hdr, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
{
Printf("This won't take effect until " GAMENAME " is restarted.\n");
}
CCMD(vid_listadapters)
{
if (Video != NULL)
Video->DumpAdapters();
}
bool vid_hdr_active = false;

View file

@ -0,0 +1,465 @@
/*
** v_video.h
**
**---------------------------------------------------------------------------
** Copyright 1998-2008 Randy Heit
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
#ifndef __V_VIDEO_H__
#define __V_VIDEO_H__
#include <functional>
#include "basics.h"
#include "vectors.h"
#include "m_png.h"
//#include "doomdef.h"
//#include "dobject.h"
#include "renderstyle.h"
#include "c_cvars.h"
#include "v_2ddrawer.h"
#include "hwrenderer/dynlights/hw_shadowmap.h"
static const int VID_MIN_WIDTH = 640;
static const int VID_MIN_HEIGHT = 400;
struct sector_t;
class FTexture;
struct FPortalSceneState;
class FSkyVertexBuffer;
class IIndexBuffer;
class IVertexBuffer;
class IDataBuffer;
class FFlatVertexBuffer;
class HWViewpointBuffer;
class FLightBuffer;
struct HWDrawInfo;
enum EHWCaps
{
// [BB] Added texture compression flags.
RFL_TEXTURE_COMPRESSION = 1,
RFL_TEXTURE_COMPRESSION_S3TC = 2,
RFL_SHADER_STORAGE_BUFFER = 4,
RFL_BUFFER_STORAGE = 8,
RFL_NO_CLIP_PLANES = 32,
RFL_INVALIDATE_BUFFER = 64,
RFL_DEBUG = 128,
};
struct IntRect
{
int left, top;
int width, height;
void Offset(int xofs, int yofs)
{
left += xofs;
top += yofs;
}
void AddToRect(int x, int y)
{
if (x < left)
left = x;
if (x > left + width)
width = x - left;
if (y < top)
top = y;
if (y > top + height)
height = y - top;
}
};
extern int CleanWidth, CleanHeight, CleanXfac, CleanYfac;
extern int CleanWidth_1, CleanHeight_1, CleanXfac_1, CleanYfac_1;
extern int DisplayWidth, DisplayHeight;
void V_UpdateModeSize (int width, int height);
void V_OutputResized (int width, int height);
void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *cx1=NULL, int *cx2=NULL);
EXTERN_CVAR(Int, vid_rendermode)
EXTERN_CVAR(Bool, vid_fullscreen)
EXTERN_CVAR(Int, win_x)
EXTERN_CVAR(Int, win_y)
EXTERN_CVAR(Int, win_w)
EXTERN_CVAR(Int, win_h)
EXTERN_CVAR(Bool, win_maximized)
inline bool V_IsHardwareRenderer()
{
return vid_rendermode == 4;
}
inline bool V_IsSoftwareRenderer()
{
return vid_rendermode < 2;
}
inline bool V_IsPolyRenderer()
{
return vid_rendermode == 2 || vid_rendermode == 3;
}
inline bool V_IsTrueColor()
{
return vid_rendermode == 1 || vid_rendermode == 3 || vid_rendermode == 4;
}
class FTexture;
struct FColormap;
class FileWriter;
enum FTextureFormat : uint32_t;
class FModelRenderer;
struct SamplerUniform;
// TagItem definitions for DrawTexture. As far as I know, tag lists
// originated on the Amiga.
//
// Think of TagItems as an array of the following structure:
//
// struct TagItem {
// uint32_t ti_Tag;
// uint32_t ti_Data;
// };
#define TAG_DONE (0) /* Used to indicate the end of the Tag list */
#define TAG_END (0) /* Ditto */
/* list pointed to in ti_Data */
#define TAG_USER ((uint32_t)(1u<<30))
class FFont;
struct FRemapTable;
class player_t;
typedef uint32_t angle_t;
//
// VIDEO
//
//
class DCanvas
{
public:
DCanvas (int width, int height, bool bgra);
~DCanvas ();
void Resize(int width, int height, bool optimizepitch = true);
// Member variable access
inline uint8_t *GetPixels () const { return Pixels.Data(); }
inline int GetWidth () const { return Width; }
inline int GetHeight () const { return Height; }
inline int GetPitch () const { return Pitch; }
inline bool IsBgra() const { return Bgra; }
protected:
TArray<uint8_t> Pixels;
int Width;
int Height;
int Pitch;
bool Bgra;
};
class FUniquePalette;
class IHardwareTexture;
class FTexture;
class DFrameBuffer
{
protected:
void DrawTextureV(FTexture *img, double x, double y, uint32_t tag, va_list tags) = delete;
void DrawTextureParms(FTexture *img, DrawParms &parms);
template<class T>
bool ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, bool fortext) const;
template<class T>
void DrawTextCommon(FFont *font, int normalcolor, double x, double y, const T *string, DrawParms &parms);
F2DDrawer m2DDrawer;
private:
int Width = 0;
int Height = 0;
protected:
int clipleft = 0, cliptop = 0, clipwidth = -1, clipheight = -1;
public:
// Hardware render state that needs to be exposed to the API independent part of the renderer. For ease of access this is stored in the base class.
int hwcaps = 0; // Capability flags
float glslversion = 0; // This is here so that the differences between old OpenGL and new OpenGL/Vulkan can be handled by platform independent code.
int instack[2] = { 0,0 }; // this is globally maintained state for portal recursion avoidance.
int stencilValue = 0; // Global stencil test value
unsigned int uniformblockalignment = 256; // Hardware dependent uniform buffer alignment.
unsigned int maxuniformblock = 65536;
const char *vendorstring; // We have to account for some issues with particular vendors.
//FPortalSceneState *mPortalState; // global portal state.
//FSkyVertexBuffer *mSkyData = nullptr; // the sky vertex buffer
//FFlatVertexBuffer *mVertexData = nullptr; // Global vertex data
//HWViewpointBuffer *mViewpoints = nullptr; // Viewpoint render data.
//FLightBuffer *mLights = nullptr; // Dynamic lights
//IShadowMap mShadowMap;
IntRect mScreenViewport;
//IntRect mSceneViewport;
IntRect mOutputLetterbox;
float mSceneClearColor[4];
public:
DFrameBuffer (int width=1, int height=1);
virtual ~DFrameBuffer();
virtual void InitializeState() = 0; // For stuff that needs 'screen' set.
virtual bool IsVulkan() { return false; }
virtual bool IsPoly() { return false; }
virtual DCanvas* GetCanvas() { return nullptr; }
void SetSize(int width, int height);
void SetVirtualSize(int width, int height)
{
Width = width;
Height = height;
}
inline int GetWidth() const { return Width; }
inline int GetHeight() const { return Height; }
#if 0
FVector2 SceneScale() const
{
return { mSceneViewport.width / (float)mScreenViewport.width, mSceneViewport.height / (float)mScreenViewport.height };
}
FVector2 SceneOffset() const
{
return { mSceneViewport.left / (float)mScreenViewport.width, mSceneViewport.top / (float)mScreenViewport.height };
}
#endif
// Make the surface visible.
virtual void Update ();
// Stores the palette with flash blended in into 256 dwords
// Mark the palette as changed. It will be updated on the next Update().
virtual void UpdatePalette() {}
virtual void SetGamma() {}
// Returns true if running fullscreen.
virtual bool IsFullscreen () = 0;
virtual void ToggleFullscreen(bool yes) {}
// Changes the vsync setting, if supported by the device.
virtual void SetVSync (bool vsync);
// Delete any resources that need to be deleted after restarting with a different IWAD
virtual void CleanForRestart() {}
virtual void SetTextureFilterMode() {}
virtual IHardwareTexture *CreateHardwareTexture() { return nullptr; }
virtual void PrecacheMaterial(FMaterial *mat, int translation) {}
virtual FModelRenderer *CreateModelRenderer(int mli) { return nullptr; }
virtual void TextureFilterChanged() {}
virtual void BeginFrame() {}
virtual void SetWindowSize(int w, int h) {}
virtual void StartPrecaching() {}
virtual int GetClientWidth() = 0;
virtual int GetClientHeight() = 0;
virtual void BlurScene(float amount) {}
// Interface to hardware rendering resources
virtual IVertexBuffer *CreateVertexBuffer() { return nullptr; }
virtual IIndexBuffer *CreateIndexBuffer() { return nullptr; }
virtual IDataBuffer *CreateDataBuffer(int bindingpoint, bool ssbo, bool needsresize) { return nullptr; }
bool BuffersArePersistent() { return !!(hwcaps & RFL_BUFFER_STORAGE); }
// Begin/End 2D drawing operations.
void Begin2D() { isIn2D = true; }
void End2D() { isIn2D = false; }
void End2DAndUpdate()
{
DrawRateStuff();
End2D();
Update();
}
// Returns true if Begin2D has been called and 2D drawing is now active
bool HasBegun2D() { return isIn2D; }
// This is overridable in case Vulkan does it differently.
virtual bool RenderTextureIsFlipped() const
{
return true;
}
// Report a game restart
virtual int Backend() { return 0; }
virtual const char* DeviceName() const { return "Unknown"; }
virtual void WriteSavePic(player_t *player, FileWriter *file, int width, int height);
virtual sector_t *RenderView(player_t *player) { return nullptr; }
// Screen wiping
virtual FTexture *WipeStartScreen();
virtual FTexture *WipeEndScreen();
virtual void PostProcessScene(int fixedcm, const std::function<void()> &afterBloomDrawEndScene2D) { if (afterBloomDrawEndScene2D) afterBloomDrawEndScene2D(); }
void ScaleCoordsFromWindow(int16_t &x, int16_t &y);
uint64_t GetLastFPS() const { return LastCount; }
// 2D Texture drawing
void ClearClipRect() { clipleft = cliptop = 0; clipwidth = clipheight = -1; }
void SetClipRect(int x, int y, int w, int h);
void GetClipRect(int *x, int *y, int *w, int *h);
void VirtualToRealCoords(double &x, double &y, double &w, double &h, double vwidth, double vheight, bool vbottom = false, bool handleaspect = true) const;
// Code that uses these (i.e. SBARINFO) should probably be evaluated for using doubles all around instead.
void VirtualToRealCoordsInt(int &x, int &y, int &w, int &h, int vwidth, int vheight, bool vbottom = false, bool handleaspect = true) const;
// Text drawing functions -----------------------------------------------
// Calculate gamma table
void CalcGamma(float gamma, uint8_t gammalookup[256]);
virtual void SetViewportRects(IntRect *bounds);
int ScreenToWindowX(int x);
int ScreenToWindowY(int y);
void FPSLimit();
// Retrieves a buffer containing image data for a screenshot.
// Hint: Pitch can be negative for upside-down images, in which case buffer
// points to the last row in the buffer, which will be the first row output.
virtual TArray<uint8_t> GetScreenshotBuffer(int &pitch, ESSType &color_type, float &gamma) { return TArray<uint8_t>(); }
static float GetZNear() { return 5.f; }
static float GetZFar() { return 65536.f; }
// The original size of the framebuffer as selected in the video menu.
uint64_t FrameTime = 0;
protected:
void DrawRateStuff ();
private:
uint64_t fpsLimitTime = 0;
uint64_t LastMS = 0, LastSec = 0, FrameCount = 0, LastCount = 0, LastTic = 0;
bool isIn2D = false;
};
// This is the screen updated by I_FinishUpdate.
extern DFrameBuffer *screen;
#define SCREENWIDTH (screen->GetWidth ())
#define SCREENHEIGHT (screen->GetHeight ())
#define SCREENPITCH (screen->GetPitch ())
EXTERN_CVAR (Float, Gamma)
// Allocates buffer screens, call before R_Init.
void V_InitScreenSize();
void V_InitScreen();
// Initializes graphics mode for the first time.
void V_Init2 ();
void V_Shutdown ();
class FScanner;
struct FScriptPosition;
// Returns the closest color to the one desired. String
// should be of the form "rr gg bb".
int V_GetColorFromString (const uint32_t *palette, const char *colorstring, FScriptPosition *sc = nullptr);
// Scans through the X11R6RGB lump for a matching color
// and returns a color string suitable for V_GetColorFromString.
FString V_GetColorStringByName (const char *name, FScriptPosition *sc = nullptr);
// Tries to get color by name, then by string
int V_GetColor (const uint32_t *palette, const char *str, FScriptPosition *sc = nullptr);
int V_GetColor(const uint32_t *palette, FScanner &sc);
int CheckRatio (int width, int height, int *trueratio=NULL);
static inline int CheckRatio (double width, double height) { return CheckRatio(int(width), int(height)); }
inline bool IsRatioWidescreen(int ratio) { return (ratio & 3) != 0; }
float ActiveRatio (int width, int height, float *trueratio = NULL);
static inline double ActiveRatio (double width, double height) { return ActiveRatio(int(width), int(height)); }
int AspectBaseWidth(float aspect);
int AspectBaseHeight(float aspect);
double AspectPspriteOffset(float aspect);
int AspectMultiplier(float aspect);
bool AspectTallerThanWide(float aspect);
void ScaleWithAspect(int &w, int &h, int Width, int Height);
int GetUIScale(int altval);
int GetConScale(int altval);
EXTERN_CVAR(Int, uiscale);
EXTERN_CVAR(Int, con_scaletext);
EXTERN_CVAR(Int, con_scale);
inline int active_con_scaletext(bool newconfont = false)
{
return newconfont? GetConScale(con_scaletext) : GetUIScale(con_scaletext);
}
inline int active_con_scale()
{
return GetConScale(con_scale);
}
#endif // __V_VIDEO_H__

View file

@ -41,18 +41,22 @@ class FStartupScreen
public:
static FStartupScreen *CreateInstance(int max_progress);
FStartupScreen(int max_progress);
virtual ~FStartupScreen();
FStartupScreen(int max_progress)
{
MaxPos = max_progress;
CurPos = 0;
NotchPos = 0;
}
virtual void Progress();
virtual void LoadingStatus(const char *message, int colors); // Used by Heretic only
virtual void AppendStatusLine(const char *status); // Used by Heretic only
virtual ~FStartupScreen() = default;
virtual void NetInit(const char *message, int num_players);
virtual void NetProgress(int count);
virtual void NetMessage(const char *format, ...); // cover for printf
virtual void NetDone();
virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata);
virtual void Progress() {}
virtual void NetInit(const char *message, int num_players) {}
virtual void NetProgress(int count) {}
virtual void NetMessage(const char *format, ...) {} // cover for printf
virtual void NetDone() {}
virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata) { return false; }
protected:
int MaxPos, CurPos, NotchPos;
};
@ -74,17 +78,28 @@ protected:
int NetMaxPos, NetCurPos;
};
class FGraphicalStartupScreen : public FBasicStartupScreen
{
public:
FGraphicalStartupScreen(int max_progress);
~FGraphicalStartupScreen();
};
extern FStartupScreen *StartScreen;
void DeleteStartupScreen();
//===========================================================================
//
// DeleteStartupScreen
//
// Makes sure the startup screen has been deleted before quitting.
//
//===========================================================================
inline void DeleteStartupScreen()
{
if (StartScreen != nullptr)
{
delete StartScreen;
StartScreen = nullptr;
}
}
extern void ST_Endoom();
// The entire set of functions here uses native Windows types. These are recreations of those types so that the code doesn't need to be changed more than necessary

View file

@ -62,7 +62,6 @@ public:
operator const char *() const { return NameData.NameArray[Index].Text; }
FName &operator = (const char *text) { Index = NameData.FindName (text, false); return *this; }
FName &operator = (const FString &text);
FName &operator = (const FName &other) = default;
FName &operator = (ENamedName index) { Index = index; return *this; }

View file

@ -1,14 +1,39 @@
/* For code that originates from ZDoom the following applies:
**
**---------------------------------------------------------------------------
** Copyright 2005-2016 Randy Heit
** Copyright 2005-2016 Christoph Oelckers
** All rights reserved.
**
** Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions
** are met:
**
** 1. Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** 2. Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in the
** documentation and/or other materials provided with the distribution.
** 3. The name of the author may not be used to endorse or promote products
** derived from this software without specific prior written permission.
**
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**---------------------------------------------------------------------------
**
*/
//**************************************************************************
//**
//** sc_man.c : Heretic 2 : Raven Software, Corp.
//**
//** $RCSfile: sc_man.c,v $
//** $Revision: 1.3 $
//** $Date: 96/01/06 03:23:43 $
//** $Author: bgokey $
//**
//**************************************************************************
// HEADER FILES ------------------------------------------------------------
@ -240,11 +265,11 @@ void FScanner::PrepareScript ()
{
// The scanner requires the file to end with a '\n', so add one if
// it doesn't already.
if (ScriptBuffer.Len() == 0 || ScriptBuffer[ScriptBuffer.Len() - 1] != '\n')
if (ScriptBuffer.Len() == 0 || ScriptBuffer.Back() != '\n')
{
// If the last character in the buffer is a null character, change
// it to a newline. Otherwise, append a newline to the end.
if (ScriptBuffer.Len() > 0 && ScriptBuffer[ScriptBuffer.Len() - 1] == '\0')
if (ScriptBuffer.Len() > 0 && ScriptBuffer.Back() == '\0')
{
ScriptBuffer.LockBuffer()[ScriptBuffer.Len() - 1] = '\n';
ScriptBuffer.UnlockBuffer();
@ -873,6 +898,76 @@ bool FScanner::Compare (const char *text)
return (stricmp (text, String) == 0);
}
//==========================================================================
//
// Convenience helpers that parse an entire number including a leading minus or plus sign
//
//==========================================================================
bool FScanner::ScanValue(bool allowfloat)
{
bool neg = false;
if (!GetToken())
{
return false;
}
if (TokenType == '-' || TokenType == '+')
{
neg = TokenType == '-';
if (!GetToken())
{
return false;
}
}
if (TokenType != TK_IntConst && (TokenType != TK_FloatConst || !allowfloat))
{
return false;
}
if (neg)
{
Number = -Number;
Float = -Float;
}
return true;
}
bool FScanner::CheckValue(bool allowfloat)
{
auto savedstate = SavePos();
bool res = ScanValue(allowfloat);
if (!res) RestorePos(savedstate);
return res;
}
void FScanner::MustGetValue(bool allowfloat)
{
if (!ScanValue(allowfloat)) ScriptError(allowfloat ? "Numeric constant expected" : "Integer constant expected");
}
bool FScanner::CheckBoolToken()
{
if (CheckToken(TK_True))
{
Number = 1;
Float = 1;
return true;
}
if (CheckToken(TK_False))
{
Number = 0;
Float = 0;
return true;
}
return false;
}
void FScanner::MustGetBoolToken()
{
if (!CheckBoolToken())
ScriptError("Expected true or false");
}
//==========================================================================
//
// FScanner :: TokenName
@ -977,7 +1072,7 @@ void FScanner::ScriptMessage (const char *message, ...)
va_end (arglist);
}
Printf (TEXTCOLOR_RED "Script error, \"%s\" line %d:\n" TEXTCOLOR_RED "%s\n", ScriptName.GetChars(),
Printf (TEXTCOLOR_RED "Script error, \"%s\"" TEXTCOLOR_RED " line %d:\n" TEXTCOLOR_RED "%s\n", ScriptName.GetChars(),
AlreadyGot? AlreadyGotLine : Line, composed.GetChars());
}
@ -991,10 +1086,118 @@ void FScanner::CheckOpen()
{
if (ScriptOpen == false)
{
I_Error ("SC_ call before SC_Open().");
I_FatalError ("SC_ call before SC_Open().");
}
}
//==========================================================================
//
// a class that remembers a parser position
//
//==========================================================================
int FScriptPosition::ErrorCounter;
int FScriptPosition::WarnCounter;
bool FScriptPosition::StrictErrors; // makes all OPTERROR messages real errors.
bool FScriptPosition::errorout; // call I_Error instead of printing the error itself.
FScriptPosition::FScriptPosition(FString fname, int line)
{
FileName = fname.GetChars();
ScriptLine = line;
}
FScriptPosition::FScriptPosition(FScanner &sc)
{
FileName = sc.ScriptName;
ScriptLine = sc.GetMessageLine();
}
FScriptPosition &FScriptPosition::operator=(FScanner &sc)
{
FileName = sc.ScriptName;
ScriptLine = sc.GetMessageLine();
return *this;
}
//==========================================================================
//
// FScriptPosition::Message
//
//==========================================================================
void FScriptPosition::Message (int severity, const char *message, ...) const
{
FString composed;
#if 0
if (severity == MSG_DEBUGLOG && developer < DMSG_NOTIFY) return;
if (severity == MSG_DEBUGERROR && developer < DMSG_ERROR) return;
if (severity == MSG_DEBUGWARN && developer < DMSG_WARNING) return;
if (severity == MSG_DEBUGMSG && developer < DMSG_NOTIFY) return;
#endif
if (severity == MSG_OPTERROR)
{
severity = StrictErrors ? MSG_ERROR : MSG_WARNING;
}
// This is mainly for catching the error with an exception handler.
if (severity == MSG_ERROR && errorout) severity = MSG_FATAL;
if (message == NULL)
{
composed = "Bad syntax.";
}
else
{
va_list arglist;
va_start (arglist, message);
composed.VFormat (message, arglist);
va_end (arglist);
}
const char *type = "";
const char *color;
int level = PRINT_HIGH;
switch (severity)
{
default:
return;
case MSG_WARNING:
case MSG_DEBUGWARN:
case MSG_DEBUGERROR: // This is intentionally not being printed as an 'error', the difference to MSG_DEBUGWARN is only the severity level at which it gets triggered.
WarnCounter++;
type = "warning";
color = TEXTCOLOR_ORANGE;
break;
case MSG_ERROR:
ErrorCounter++;
type = "error";
color = TEXTCOLOR_RED;
break;
case MSG_MESSAGE:
case MSG_DEBUGMSG:
type = "message";
color = TEXTCOLOR_GREEN;
break;
case MSG_DEBUGLOG:
case MSG_LOG:
type = "message";
level = PRINT_LOG;
color = "";
break;
case MSG_FATAL:
I_Error ("Script error, \"%s\" line %d:\n%s\n",
FileName.GetChars(), ScriptLine, composed.GetChars());
return;
}
Printf (level, "%sScript %s, \"%s\" line %d:\n%s%s\n",
color, type, FileName.GetChars(), ScriptLine, color, composed.GetChars());
}
//==========================================================================
//
@ -1002,7 +1205,7 @@ void FScanner::CheckOpen()
//
//==========================================================================
int ParseHex(const char* hex)
int ParseHex(const char* hex, FScriptPosition* sc)
{
const char* str;
int num;
@ -1020,7 +1223,8 @@ int ParseHex(const char* hex)
else if (*str >= 'A' && *str <= 'F')
num += 10 + *str - 'A';
else {
Printf("Bad hex number: %s\n", hex);
if (sc) sc->Message(MSG_WARNING, "Bad hex number: %s", hex);
else Printf("Bad hex number: %s\n", hex);
return 0;
}
str++;

View file

@ -57,6 +57,12 @@ public:
void MustGetFloat();
bool CheckFloat();
// Token based variant
bool CheckValue(bool allowfloat);
void MustGetValue(bool allowfloat);
bool CheckBoolToken();
void MustGetBoolToken();
void UnGet();
bool Compare(const char *text);
@ -103,9 +109,12 @@ protected:
const char *LastGotPtr;
int LastGotLine;
bool CMode;
BYTE StateMode;
uint8_t StateMode;
bool StateOptions;
bool Escape;
bool ScanValue(bool allowfloat);
};
enum
@ -137,6 +146,40 @@ enum
MSG_MESSAGE
};
int ParseHex(const char* hex);
//==========================================================================
//
// a class that remembers a parser position
//
//==========================================================================
struct FScriptPosition
{
static int WarnCounter;
static int ErrorCounter;
static bool StrictErrors;
static bool errorout;
FName FileName;
int ScriptLine;
FScriptPosition()
{
FileName = NAME_None;
ScriptLine=0;
}
FScriptPosition(const FScriptPosition &other) = default;
FScriptPosition(FString fname, int line);
FScriptPosition(FScanner &sc);
FScriptPosition &operator=(const FScriptPosition &other) = default;
FScriptPosition &operator=(FScanner &sc);
void Message(int severity, const char *message,...) const GCCPRINTF(3,4);
static void ResetErrorCounter()
{
WarnCounter = 0;
ErrorCounter = 0;
}
};
int ParseHex(const char* hex, FScriptPosition* sc);
#endif //__SC_MAN_H__

View file

@ -791,7 +791,7 @@ nextdemo_nomenu:
// draw status
Demo_DisplayProfStatus();
if (handleevents_peekkeys())
if (I_GeneralTrigger())
Demo_StopProfiling();
}
else

View file

@ -131,8 +131,8 @@ static bool noidle = false;
LPDIRECTINPUT8 g_pdi;
LPDIRECTINPUT g_pdi3;
bool AppActive;
extern bool AppActive;
int SessionState = 0;
int BlockMouseMove;
@ -144,30 +144,6 @@ CVAR (Bool, k_allowfullscreentoggle, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
extern int chatmodeon;
static void I_CheckGUICapture ()
{
#if 0
bool wantCapt;
if (menuactive == MENU_Off)
{
wantCapt = ConsoleState == c_down || ConsoleState == c_falling || chatmodeon;
}
else
{
wantCapt = (menuactive == MENU_On || menuactive == MENU_OnNoPause);
}
if (wantCapt != GUICapture)
{
GUICapture = wantCapt;
if (wantCapt && Keyboard != NULL)
{
Keyboard->AllKeysUp();
}
}
#endif
}
void I_SetMouseCapture()
{
@ -762,9 +738,7 @@ void I_StartTic ()
{
BlockMouseMove--;
buttonMap.ResetButtonTriggers ();
I_CheckGUICapture ();
EventHandlerResultForNativeMouse = false;
I_CheckNativeMouse (false, EventHandlerResultForNativeMouse);
I_CheckNativeMouse (false, false);
I_GetEvent ();
}

View file

@ -40,6 +40,7 @@
#include "i_input.h"
#include "d_event.h"
#include "inputstate.h"
// MACROS ------------------------------------------------------------------
@ -90,7 +91,7 @@ protected:
extern HWND Window;
extern LPDIRECTINPUT8 g_pdi;
extern LPDIRECTINPUT g_pdi3;
extern bool GUICapture;
// PRIVATE DATA DEFINITIONS ------------------------------------------------

View file

@ -275,38 +275,16 @@ static bool CaptureMode_InGame()
//
//==========================================================================
static bool grab_mouse;
void mouseGrabInput(bool grab)
{
grab_mouse = grab;
}
void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult)
{
bool windowed = (screen == NULL) || !screen->IsFullscreen();
bool want_native;
if (!windowed)
{
// ungrab mouse when in the menu with mouse control on.
want_native = m_use_mouse && (menuactive == MENU_On || menuactive == MENU_OnNoPause);
}
else
{
if ((GetForegroundWindow() != Window) || preferNative || !use_mouse)
{
want_native = true;
}
else if (menuactive == MENU_WaitKey)
{
want_native = false;
}
else
{
want_native = ((!m_use_mouse || menuactive != MENU_WaitKey) &&
(!CaptureMode_InGame() || GUICapture /*|| paused || demoplayback*/));
}
}
if (!want_native && eventhandlerresult)
want_native = true;
//Printf ("%d %d %d\n", wantNative, preferNative, NativeMouse);
bool want_native = !grab_mouse || preferNative;
if (want_native != NativeMouse)
{
if (Mouse != NULL)

View file

@ -396,34 +396,6 @@ static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LP
return FALSE;
}
//==========================================================================
//
// FGraphicalStartupScreen Constructor
//
// This doesn't really do anything. The subclass is responsible for
// creating the resources that will be freed by this class's destructor.
//
//==========================================================================
FGraphicalStartupScreen::FGraphicalStartupScreen(int max_progress)
: FBasicStartupScreen(max_progress, false)
{
}
//==========================================================================
//
// FGraphicalStartupScreen Destructor
//
//==========================================================================
FGraphicalStartupScreen::~FGraphicalStartupScreen()
{
if (StartupScreen != NULL)
{
DestroyWindow (StartupScreen);
StartupScreen = NULL;
}
}
//==========================================================================
//

View file

@ -793,7 +793,7 @@ nextdemo_nomenu:
// draw status
Demo_DisplayProfStatus();
if (handleevents_peekkeys())
if (I_GeneralTrigger())
Demo_StopProfiling();
}
else