Merge remote-tracking branch 'upstream/master' into truecolor

# Conflicts:
#	src/v_video.cpp
This commit is contained in:
Magnus Norddahl 2016-09-19 23:55:15 +02:00
commit 77233f2f65
127 changed files with 4263 additions and 1663 deletions

View file

@ -65,6 +65,8 @@
#include "menu/menu.h"
#include "r_data/voxels.h"
int active_con_scale();
FRenderer *Renderer;
IMPLEMENT_ABSTRACT_CLASS (DCanvas)
@ -761,6 +763,21 @@ void DCanvas::CalcGamma (float gamma, BYTE gammalookup[256])
DSimpleCanvas::DSimpleCanvas (int width, int height, bool bgra)
: DCanvas (width, height, bgra)
{
MemBuffer = nullptr;
Resize(width, height);
}
void DSimpleCanvas::Resize(int width, int height)
{
Width = width;
Height = height;
if (MemBuffer != NULL)
{
delete[] MemBuffer;
MemBuffer = NULL;
}
// 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
@ -796,7 +813,7 @@ DSimpleCanvas::DSimpleCanvas (int width, int height, bool bgra)
Pitch = width + MAX(0, CPU.DataL1LineSize - 8);
}
}
int bytes_per_pixel = bgra ? 4 : 1;
int bytes_per_pixel = Bgra ? 4 : 1;
MemBuffer = new BYTE[Pitch * height * bytes_per_pixel];
memset (MemBuffer, 0, Pitch * height * bytes_per_pixel);
}
@ -872,6 +889,9 @@ DFrameBuffer::DFrameBuffer (int width, int height, bool bgra)
{
LastMS = LastSec = FrameCount = LastCount = LastTic = 0;
Accel2D = false;
VideoWidth = width;
VideoHeight = height;
}
//==========================================================================
@ -959,10 +979,20 @@ void DFrameBuffer::DrawRateStuff ()
int chars;
int rate_x;
int textScale = active_con_scale();
if (textScale == 0)
textScale = CleanXfac;
chars = mysnprintf (fpsbuff, countof(fpsbuff), "%2u ms (%3u fps)", howlong, LastCount);
rate_x = Width - ConFont->StringWidth(&fpsbuff[0]);
Clear (rate_x, 0, Width, ConFont->GetHeight(), GPalette.BlackIndex, 0);
DrawText (ConFont, CR_WHITE, rate_x, 0, (char *)&fpsbuff[0], TAG_DONE);
rate_x = Width / textScale - ConFont->StringWidth(&fpsbuff[0]);
Clear (rate_x * textScale, 0, Width, ConFont->GetHeight() * textScale, GPalette.BlackIndex, 0);
if (textScale == 1)
DrawText (ConFont, CR_WHITE, rate_x, 0, (char *)&fpsbuff[0], TAG_DONE);
else
DrawText (ConFont, CR_WHITE, rate_x, 0, (char *)&fpsbuff[0],
DTA_VirtualWidth, screen->GetWidth() / textScale,
DTA_VirtualHeight, screen->GetHeight() / textScale,
DTA_KeepRatio, true, TAG_DONE);
DWORD thisSec = ms/1000;
if (LastSec < thisSec)
@ -1020,11 +1050,12 @@ void DFrameBuffer::DrawRateStuff ()
// Drawing it as a texture does and continues to show how
// well the PalTex shader is working.
static FPaletteTester palette;
int size = screen->GetHeight() < 800 ? 16 * 7 : 16 * 7 * 2;
palette.SetTranslation(vid_showpalette);
DrawTexture(&palette, 0, 0,
DTA_DestWidth, 16*7,
DTA_DestHeight, 16*7,
DTA_DestWidth, size,
DTA_DestHeight, size,
DTA_Masked, false,
TAG_DONE);
}
@ -1350,7 +1381,6 @@ CCMD(clean)
bool V_DoModeSetup (int width, int height, int bits)
{
DFrameBuffer *buff = I_SetMode (width, height, screen);
int cx1, cx2;
if (buff == NULL)
{
@ -1365,6 +1395,17 @@ bool V_DoModeSetup (int width, int height, int bits)
// if D3DFB is being used for the display.
FFont::StaticPreloadFonts();
DisplayBits = bits;
V_UpdateModeSize(width, height);
M_RefreshModesList ();
return true;
}
void V_UpdateModeSize (int width, int height)
{
int cx1, cx2;
V_CalcCleanFacs(320, 200, width, height, &CleanXfac, &CleanYfac, &cx1, &cx2);
CleanWidth = width / CleanXfac;
@ -1405,32 +1446,38 @@ bool V_DoModeSetup (int width, int height, int bits)
DisplayWidth = width;
DisplayHeight = height;
DisplayBits = bits;
R_OldBlend = ~0;
Renderer->OnModeSet();
M_RefreshModesList ();
}
return true;
void V_OutputResized (int width, int height)
{
V_UpdateModeSize(width, height);
setsizeneeded = true;
if (StatusBar != NULL)
{
StatusBar->ScreenSizeChanged();
}
C_NewModeAdjust();
}
void V_CalcCleanFacs (int designwidth, int designheight, int realwidth, int realheight, int *cleanx, int *cleany, int *_cx1, int *_cx2)
{
int ratio;
float ratio;
int cwidth;
int cheight;
int cx1, cy1, cx2, cy2;
ratio = CheckRatio(realwidth, realheight);
if (Is54Aspect(ratio))
ratio = ActiveRatio(realwidth, realheight);
if (AspectTallerThanWide(ratio))
{
cwidth = realwidth;
cheight = realheight * BaseRatioSizes[ratio][3] / 48;
cheight = realheight * AspectMultiplier(ratio) / 48;
}
else
{
cwidth = realwidth * BaseRatioSizes[ratio][3] / 48;
cwidth = realwidth * AspectMultiplier(ratio) / 48;
cheight = realheight;
}
// Use whichever pair of cwidth/cheight or width/height that produces less difference
@ -1664,20 +1711,10 @@ CUSTOM_CVAR (Int, vid_aspect, 0, CVAR_GLOBALCONFIG|CVAR_ARCHIVE)
}
}
// 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)
// 6: 21:9
int CheckRatio (int width, int height, int *trueratio)
// Helper for ActiveRatio and CheckRatio. Returns the forced ratio type, or -1 if none.
int ActiveFakeRatio(int width, int height)
{
int fakeratio = -1;
int ratio;
if ((vid_aspect >= 1) && (vid_aspect <= 6))
{
// [SP] User wants to force aspect ratio; let them.
@ -1689,7 +1726,7 @@ int CheckRatio (int width, int height, int *trueratio)
else if (fakeratio == 5)
{
fakeratio = 3;
}
}
}
if (vid_nowidescreen)
{
@ -1699,74 +1736,112 @@ int CheckRatio (int width, int height, int *trueratio)
}
else
{
fakeratio = (height * 5/4 == width) ? 4 : 0;
fakeratio = (height * 5 / 4 == width) ? 4 : 0;
}
}
// If the size is approximately 16:9, consider it so.
if (abs (height * 16/9 - width) < 10)
{
ratio = 1;
}
// Consider 17:10 as well.
else if (abs (height * 17/10 - width) < 10)
{
ratio = 3;
}
// 16:10 has more variance in the pixel dimensions. Grr.
else if (abs (height * 16/10 - width) < 60)
{
// 320x200 and 640x400 are always 4:3, not 16:10
if ((width == 320 && height == 200) || (width == 640 && height == 400))
{
ratio = 0;
}
else
{
ratio = 2;
}
}
// Unless vid_tft is set, 1280x1024 is 4:3, not 5:4.
else if (height * 5/4 == width && vid_tft)
{
ratio = 4;
}
// test for 21:9 (actually 64:27, 21:9 is a semi-accurate ratio used in marketing)
else if (abs (height * 64/27 - width) < 30)
{
ratio = 6;
}
// Assume anything else is 4:3. (Which is probably wrong these days...)
else
{
ratio = 0;
}
if (trueratio != NULL)
{
*trueratio = ratio;
}
return (fakeratio >= 0) ? fakeratio : ratio;
return fakeratio;
}
// First column: Base width
// Second column: Base height (used for wall visibility multiplier)
// Third column: Psprite offset (needed for "tallscreen" modes)
// Fourth column: Width or height multiplier
// For widescreen aspect ratio x:y ...
// base_width = 240 * x / y
// multiplier = 320 / base_width
// base_height = 200 * multiplier
const int BaseRatioSizes[7][4] =
// Active screen ratio based on cvars and size
float ActiveRatio(int width, int height, float *trueratio)
{
{ 960, 600, 0, 48 }, // 4:3 320, 200, multiplied by three
{ 1280, 450, 0, 48*3/4 }, // 16:9 426.6667, 150, multiplied by three
{ 1152, 500, 0, 48*5/6 }, // 16:10 386, 166.6667, multiplied by three
{ 1224, 471, 0, 48*40/51 }, // 17:10 408, 156.8627, multiplied by three
{ 960, 640, (int)(6.5*FRACUNIT), 48*15/16 }, // 5:4 320, 213.3333, multiplied by three
{ 1224, 471, 0, 48*40/51 }, // 17:10 408, 156.8627, multiplied by three (REDUNDANT)
{ 1707, 338, 0, 48*9/16 } // 21:9 568.8889, 337.5, multiplied by three
};
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 IVideo::DumpAdapters ()
{