mirror of
https://github.com/ZDoom/raze-gles.git
synced 2024-12-24 18:50:47 +00:00
- fixed all undefined symbols except OpenGLFrameBuffer.
This commit is contained in:
parent
10683e9123
commit
6e9631f2d8
29 changed files with 2397 additions and 652 deletions
|
@ -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 )
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
if (cursorSurface != NULL)
|
||||
{
|
||||
SDL_FreeSurface(cursorSurface);
|
||||
cursorSurface = 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");
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
38
source/common/rendering/i_video.h
Normal file
38
source/common/rendering/i_video.h
Normal 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__
|
261
source/common/rendering/r_videoscale.cpp
Normal file
261
source/common/rendering/r_videoscale.cpp
Normal 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;
|
||||
}
|
||||
}
|
31
source/common/rendering/r_videoscale.h
Normal file
31
source/common/rendering/r_videoscale.h
Normal 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__
|
389
source/common/rendering/v_framebuffer.cpp
Normal file
389
source/common/rendering/v_framebuffer.cpp
Normal 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
|
||||
}
|
806
source/common/rendering/v_video.cpp
Normal file
806
source/common/rendering/v_video.cpp
Normal 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;
|
465
source/common/rendering/v_video.h
Normal file
465
source/common/rendering/v_video.h
Normal 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__
|
|
@ -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 ~FStartupScreen() = default;
|
||||
|
||||
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 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);
|
||||
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
|
||||
|
|
|
@ -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; }
|
||||
|
||||
|
|
|
@ -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,9 +1205,9 @@ void FScanner::CheckOpen()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
int ParseHex(const char* hex)
|
||||
int ParseHex(const char* hex, FScriptPosition* sc)
|
||||
{
|
||||
const char* str;
|
||||
const char* str;
|
||||
int num;
|
||||
|
||||
num = 0;
|
||||
|
@ -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++;
|
||||
|
@ -1029,4 +1233,4 @@ int ParseHex(const char* hex)
|
|||
return num;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -56,6 +56,12 @@ public:
|
|||
bool GetFloat();
|
||||
void MustGetFloat();
|
||||
bool CheckFloat();
|
||||
|
||||
// Token based variant
|
||||
bool CheckValue(bool allowfloat);
|
||||
void MustGetValue(bool allowfloat);
|
||||
bool CheckBoolToken();
|
||||
void MustGetBoolToken();
|
||||
|
||||
void UnGet();
|
||||
|
||||
|
@ -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__
|
||||
|
|
|
@ -791,7 +791,7 @@ nextdemo_nomenu:
|
|||
// draw status
|
||||
Demo_DisplayProfStatus();
|
||||
|
||||
if (handleevents_peekkeys())
|
||||
if (I_GeneralTrigger())
|
||||
Demo_StopProfiling();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -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 ();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 ------------------------------------------------
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -793,7 +793,7 @@ nextdemo_nomenu:
|
|||
// draw status
|
||||
Demo_DisplayProfStatus();
|
||||
|
||||
if (handleevents_peekkeys())
|
||||
if (I_GeneralTrigger())
|
||||
Demo_StopProfiling();
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in a new issue