- stripped out the entire software 2D renderer and moved all 2D drawing functions to DFrameBuffer so that they cannot be used with software DSimpleCanvas anymore.

This commit is contained in:
Christoph Oelckers 2018-03-26 23:16:27 +02:00
parent e0039179cb
commit d650e37497
10 changed files with 283 additions and 765 deletions

View file

@ -833,7 +833,7 @@ void D_Display ()
}
if (!automapactive || viewactive)
{
V_RefreshViewBorder ();
screen->RefreshViewBorder ();
}
// for timing the statusbar code.

View file

@ -32,148 +32,6 @@
#include "templates.h"
#include "v_palette.h"
EXTERN_CVAR(Bool, r_blendmethod)
//
// SCREEN WIPE PACKAGE
//
static int CurrentWipeType;
static short *wipe_scr_start;
static short *wipe_scr_end;
static int *y;
// [RH] Fire Wipe
#define FIREWIDTH 64
#define FIREHEIGHT 64
static uint8_t *burnarray;
static int density;
static int burntime;
// [RH] Crossfade
static int fade;
// Melt -------------------------------------------------------------
// Match the strip sizes that oldschool Doom used on a 320x200 screen.
#define MELT_WIDTH 160
#define MELT_HEIGHT 200
void wipe_shittyColMajorXform (short *array)
{
int x, y;
short *dest;
int width = SCREENWIDTH / 2;
dest = new short[width*SCREENHEIGHT*2];
for(y = 0; y < SCREENHEIGHT; y++)
for(x = 0; x < width; x++)
dest[x*SCREENHEIGHT+y] = array[y*width+x];
memcpy(array, dest, SCREENWIDTH*SCREENHEIGHT);
delete[] dest;
}
bool wipe_initMelt (int ticks)
{
int i, r;
// copy start screen to main screen
screen->DrawBlock (0, 0, SCREENWIDTH, SCREENHEIGHT, (uint8_t *)wipe_scr_start);
// makes this wipe faster (in theory)
// to have stuff in column-major format
wipe_shittyColMajorXform (wipe_scr_start);
wipe_shittyColMajorXform (wipe_scr_end);
// setup initial column positions
// (y<0 => not ready to scroll yet)
y = new int[MELT_WIDTH];
y[0] = -(M_Random() & 15);
for (i = 1; i < MELT_WIDTH; i++)
{
r = (M_Random()%3) - 1;
y[i] = clamp(y[i-1] + r, -15, 0);
}
return 0;
}
bool wipe_doMelt (int ticks)
{
int i, j, dy, x;
const short *s;
short *d;
bool done = true;
while (ticks--)
{
done = true;
for (i = 0; i < MELT_WIDTH; i++)
{
if (y[i] < 0)
{
y[i]++;
done = false;
}
else if (y[i] < MELT_HEIGHT)
{
dy = (y[i] < 16) ? y[i]+1 : 8;
y[i] = MIN(y[i] + dy, MELT_HEIGHT);
done = false;
}
if (ticks == 0 && y[i] >= 0)
{ // Only draw for the final tick.
const int pitch = screen->GetPitch() / 2;
int sy = y[i] * SCREENHEIGHT / MELT_HEIGHT;
for (x = i * (SCREENWIDTH/2) / MELT_WIDTH; x < (i + 1) * (SCREENWIDTH/2) / MELT_WIDTH; ++x)
{
s = &wipe_scr_end[x*SCREENHEIGHT];
d = &((short *)screen->GetBuffer())[x];
for (j = sy; j != 0; --j)
{
*d = *(s++);
d += pitch;
}
s = &wipe_scr_start[x*SCREENHEIGHT];
for (j = SCREENHEIGHT - sy; j != 0; --j)
{
*d = *(s++);
d += pitch;
}
}
}
}
}
return done;
}
bool wipe_exitMelt (int ticks)
{
delete[] y;
return 0;
}
// Burn -------------------------------------------------------------
bool wipe_initBurn (int ticks)
{
burnarray = new uint8_t[FIREWIDTH * (FIREHEIGHT+5)];
memset (burnarray, 0, FIREWIDTH * (FIREHEIGHT+5));
density = 4;
burntime = 0;
return 0;
}
int wipe_CalcBurn (uint8_t *burnarray, int width, int height, int density)
{
// This is a modified version of the fire that was once used
@ -258,263 +116,3 @@ int wipe_CalcBurn (uint8_t *burnarray, int width, int height, int density)
return -1;
}
bool wipe_doBurn (int ticks)
{
bool done;
burntime += ticks;
ticks *= 2;
// Make the fire burn
done = false;
while (!done && ticks--)
{
density = wipe_CalcBurn(burnarray, FIREWIDTH, FIREHEIGHT, density);
done = (density < 0);
}
// Draw the screen
int xstep, ystep, firex, firey;
int x, y;
uint8_t *to, *fromold, *fromnew;
const int SHIFT = 16;
xstep = (FIREWIDTH << SHIFT) / SCREENWIDTH;
ystep = (FIREHEIGHT << SHIFT) / SCREENHEIGHT;
to = screen->GetBuffer();
fromold = (uint8_t *)wipe_scr_start;
fromnew = (uint8_t *)wipe_scr_end;
if (!r_blendmethod)
{
for (y = 0, firey = 0; y < SCREENHEIGHT; y++, firey += ystep)
{
for (x = 0, firex = 0; x < SCREENWIDTH; x++, firex += xstep)
{
int fglevel;
fglevel = burnarray[(firex>>SHIFT)+(firey>>SHIFT)*FIREWIDTH] / 2;
if (fglevel >= 63)
{
to[x] = fromnew[x];
}
else if (fglevel == 0)
{
to[x] = fromold[x];
done = false;
}
else
{
int bglevel = 64-fglevel;
uint32_t *fg2rgb = Col2RGB8[fglevel];
uint32_t *bg2rgb = Col2RGB8[bglevel];
uint32_t fg = fg2rgb[fromnew[x]];
uint32_t bg = bg2rgb[fromold[x]];
fg = (fg+bg) | 0x1f07c1f;
to[x] = RGB32k.All[fg & (fg>>15)];
done = false;
}
}
fromold += SCREENWIDTH;
fromnew += SCREENWIDTH;
to += SCREENPITCH;
}
}
else
{
for (y = 0, firey = 0; y < SCREENHEIGHT; y++, firey += ystep)
{
for (x = 0, firex = 0; x < SCREENWIDTH; x++, firex += xstep)
{
int fglevel;
fglevel = burnarray[(firex>>SHIFT)+(firey>>SHIFT)*FIREWIDTH] / 2;
if (fglevel >= 63)
{
to[x] = fromnew[x];
}
else if (fglevel == 0)
{
to[x] = fromold[x];
done = false;
}
else
{
int bglevel = 64-fglevel;
const PalEntry* pal = GPalette.BaseColors;
uint32_t fg = fromnew[x];
uint32_t bg = fromold[x];
int r = MIN((pal[fg].r * fglevel + pal[bg].r * bglevel) >> 8, 63);
int g = MIN((pal[fg].g * fglevel + pal[bg].g * bglevel) >> 8, 63);
int b = MIN((pal[fg].b * fglevel + pal[bg].b * bglevel) >> 8, 63);
to[x] = RGB256k.RGB[r][g][b];
done = false;
}
}
fromold += SCREENWIDTH;
fromnew += SCREENWIDTH;
to += SCREENPITCH;
}
}
return done || (burntime > 40);
}
bool wipe_exitBurn (int ticks)
{
delete[] burnarray;
return 0;
}
// Crossfade --------------------------------------------------------
bool wipe_initFade (int ticks)
{
fade = 0;
return 0;
}
bool wipe_doFade (int ticks)
{
fade += ticks * 2;
if (fade > 64)
{
screen->DrawBlock (0, 0, SCREENWIDTH, SCREENHEIGHT, (uint8_t *)wipe_scr_end);
return true;
}
else
{
int x, y;
int bglevel = 64 - fade;
uint32_t *fg2rgb = Col2RGB8[fade];
uint32_t *bg2rgb = Col2RGB8[bglevel];
uint8_t *fromnew = (uint8_t *)wipe_scr_end;
uint8_t *fromold = (uint8_t *)wipe_scr_start;
uint8_t *to = screen->GetBuffer();
const PalEntry *pal = GPalette.BaseColors;
if (!r_blendmethod)
{
for (y = 0; y < SCREENHEIGHT; y++)
{
for (x = 0; x < SCREENWIDTH; x++)
{
uint32_t fg = fg2rgb[fromnew[x]];
uint32_t bg = bg2rgb[fromold[x]];
fg = (fg+bg) | 0x1f07c1f;
to[x] = RGB32k.All[fg & (fg>>15)];
}
fromnew += SCREENWIDTH;
fromold += SCREENWIDTH;
to += SCREENPITCH;
}
}
else
{
for (y = 0; y < SCREENHEIGHT; y++)
{
for (x = 0; x < SCREENWIDTH; x++)
{
uint32_t fg = fromnew[x];
uint32_t bg = fromold[x];
int r = MIN((pal[fg].r * (64-bglevel) + pal[bg].r * bglevel) >> 8, 63);
int g = MIN((pal[fg].g * (64-bglevel) + pal[bg].g * bglevel) >> 8, 63);
int b = MIN((pal[fg].b * (64-bglevel) + pal[bg].b * bglevel) >> 8, 63);
to[x] = RGB256k.RGB[r][g][b];
}
fromnew += SCREENWIDTH;
fromold += SCREENWIDTH;
to += SCREENPITCH;
}
}
}
return false;
}
bool wipe_exitFade (int ticks)
{
return 0;
}
// General Wipe Functions -------------------------------------------
static bool (*wipes[])(int) =
{
wipe_initMelt, wipe_doMelt, wipe_exitMelt,
wipe_initBurn, wipe_doBurn, wipe_exitBurn,
wipe_initFade, wipe_doFade, wipe_exitFade
};
// Returns true if the wipe should be performed.
bool wipe_StartScreen (int type)
{
if (screen->IsBgra())
return false;
CurrentWipeType = clamp(type, 0, wipe_NUMWIPES - 1);
if (CurrentWipeType)
{
wipe_scr_start = new short[SCREENWIDTH * SCREENHEIGHT / 2];
screen->GetBlock (0, 0, SCREENWIDTH, SCREENHEIGHT, (uint8_t *)wipe_scr_start);
return true;
}
return false;
}
void wipe_EndScreen (void)
{
if (screen->IsBgra())
return;
if (CurrentWipeType)
{
wipe_scr_end = new short[SCREENWIDTH * SCREENHEIGHT / 2];
screen->GetBlock (0, 0, SCREENWIDTH, SCREENHEIGHT, (uint8_t *)wipe_scr_end);
screen->DrawBlock (0, 0, SCREENWIDTH, SCREENHEIGHT, (uint8_t *)wipe_scr_start); // restore start scr.
// Initialize the wipe
(*wipes[(CurrentWipeType-1)*3])(0);
}
}
// Returns true if the wipe is done.
bool wipe_ScreenWipe (int ticks)
{
bool rc;
if (screen->IsBgra())
return true;
if (CurrentWipeType == wipe_None)
return true;
// do a piece of wipe-in
rc = (*wipes[(CurrentWipeType-1)*3+1])(ticks);
return rc;
}
// Final things for the wipe
void wipe_Cleanup()
{
if (screen->IsBgra())
return;
if (wipe_scr_start != NULL)
{
delete[] wipe_scr_start;
wipe_scr_start = NULL;
}
if (wipe_scr_end != NULL)
{
delete[] wipe_scr_end;
wipe_scr_end = NULL;
}
if (CurrentWipeType > 0)
{
(*wipes[(CurrentWipeType-1)*3+2])(0);
}
}

View file

@ -30,6 +30,7 @@
// SCREEN WIPE PACKAGE
//
#if 0
bool wipe_StartScreen (int type);
void wipe_EndScreen (void);
bool wipe_ScreenWipe (int ticks);
@ -37,6 +38,7 @@ void wipe_Cleanup ();
// The buffer must have an additional 5 rows not included in height
// to use for a seeding area.
#endif
int wipe_CalcBurn(uint8_t *buffer, int width, int height, int density);
enum

View file

@ -835,8 +835,8 @@ void DBaseStatusBar::RefreshBackground () const
{
if(y < SCREENHEIGHT)
{
V_DrawBorder (x+1, y, SCREENWIDTH, y+1);
V_DrawBorder (x+1, SCREENHEIGHT-1, SCREENWIDTH, SCREENHEIGHT);
screen->DrawBorder (x+1, y, SCREENWIDTH, y+1);
screen->DrawBorder (x+1, SCREENHEIGHT-1, SCREENWIDTH, SCREENHEIGHT);
}
}
else
@ -855,8 +855,8 @@ void DBaseStatusBar::RefreshBackground () const
x2 = SCREENWIDTH;
}
V_DrawBorder (0, y, x+1, SCREENHEIGHT);
V_DrawBorder (x2-1, y, SCREENWIDTH, SCREENHEIGHT);
screen->DrawBorder (0, y, x+1, SCREENHEIGHT);
screen->DrawBorder (x2-1, y, SCREENWIDTH, SCREENHEIGHT);
if (setblocks >= 10)
{

View file

@ -1,22 +0,0 @@
#pragma once
#include "v_video.h"
#include "r_data/colormaps.h"
class SWCanvas
{
public:
static void DrawTexture(DCanvas *canvas, FTexture *img, DrawParms &parms);
static void FillSimplePoly(DCanvas *canvas, FTexture *tex, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley, DAngle rotation,
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
static void DrawLine(DCanvas *canvas, int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor);
static void DrawPixel(DCanvas *canvas, int x, int y, int palColor, uint32_t realcolor);
static void Clear(DCanvas *canvas, int left, int top, int right, int bottom, int palcolor, uint32_t color);
static void Dim(DCanvas *canvas, PalEntry color, float damount, int x1, int y1, int w, int h);
private:
static void PUTTRANSDOT(DCanvas *canvas, int xx, int yy, int basecolor, int level);
static int PalFromRGB(uint32_t rgb);
};

View file

@ -69,7 +69,9 @@
#include "swrenderer/r_renderthread.h"
CVAR(Int, r_portal_recursions, 4, CVAR_ARCHIVE)
CVAR(Bool, r_highlight_portals, false, CVAR_ARCHIVE)
#if 0
CVAR(Bool, r_highlight_portals, false, 0)
#endif
CVAR(Bool, r_skyboxes, true, 0)
// Avoid infinite recursion with stacked sectors by limiting them.
@ -321,8 +323,10 @@ namespace swrenderer
}
}
#if 0
if (r_highlight_portals)
RenderLinePortalHighlight(pds);
#endif
return;
}
@ -462,9 +466,11 @@ namespace swrenderer
Thread->Clip3D->LeaveSkybox(); // pop 3D floor height map
CurrentPortalUniq = prevuniq2;
#if 0
// draw a red line around a portal if it's being highlighted
if (r_highlight_portals)
RenderLinePortalHighlight(pds);
#endif
CurrentPortal = prevpds;
MirrorFlags = prevmf;
@ -474,6 +480,7 @@ namespace swrenderer
viewpoint.Path[1] = savedpath[1];
}
#if 0
void RenderPortal::RenderLinePortalHighlight(PortalDrawseg* pds)
{
// [ZZ] NO OVERFLOW CHECKS HERE
@ -515,6 +522,7 @@ namespace swrenderer
else *(pixels + Ybottom * viewport->RenderTarget->GetPitch() + x) = color;
}
}
#endif
void RenderPortal::CopyStackedViewParameters()
{

View file

@ -32,8 +32,6 @@
**
*/
// #define NO_SWRENDER // set this if you want to exclude the software renderer. Without the software renderer software canvas drawing does nothing.
#include <stdio.h>
#include <stdarg.h>
@ -43,9 +41,6 @@
#include "r_defs.h"
#include "r_utility.h"
#include "r_renderer.h"
#ifndef NO_SWRENDER
#include "swrenderer/r_swcanvas.h"
#endif
#include "r_data/r_translate.h"
#include "doomstat.h"
#include "v_palette.h"
@ -64,6 +59,19 @@
#include "textures.h"
#include "vm.h"
CUSTOM_CVAR(Float, dimamount, -1.f, CVAR_ARCHIVE)
{
if (self < 0.f && self != -1.f)
{
self = -1.f;
}
else if (self > 1.f)
{
self = 1.f;
}
}
CVAR(Color, dimcolor, 0xffd700, CVAR_ARCHIVE)
CUSTOM_CVAR(Int, uiscale, 0, CVAR_ARCHIVE | CVAR_NOINITCALL)
{
if (self < 0)
@ -109,6 +117,12 @@ int CleanWidth, CleanHeight;
int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1;
//==========================================================================
//
// ZScript wrappers for inlines
//
//==========================================================================
DEFINE_ACTION_FUNCTION(_Screen, GetWidth)
{
PARAM_PROLOGUE;
@ -130,7 +144,13 @@ DEFINE_ACTION_FUNCTION(_Screen, PaletteColor)
ACTION_RETURN_INT(index);
}
void DCanvas::DrawTexture (FTexture *img, double x, double y, int tags_first, ...)
//==========================================================================
//
// Internal texture drawing function
//
//==========================================================================
void DFrameBuffer::DrawTexture (FTexture *img, double x, double y, int tags_first, ...)
{
Va_List tags;
va_start(tags.list, tags_first);
@ -145,9 +165,15 @@ void DCanvas::DrawTexture (FTexture *img, double x, double y, int tags_first, ..
DrawTextureParms(img, parms);
}
//==========================================================================
//
// ZScript texture drawing function
//
//==========================================================================
int ListGetInt(VMVa_List &tags);
void DCanvas::DrawTexture(FTexture *img, double x, double y, VMVa_List &args)
void DFrameBuffer::DrawTexture(FTexture *img, double x, double y, VMVa_List &args)
{
DrawParms parms;
uint32_t tag = ListGetInt(args);
@ -172,19 +198,23 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawTexture)
return 0;
}
void DCanvas::DrawTextureParms(FTexture *img, DrawParms &parms)
{
#ifndef NO_SWRENDER
SWCanvas::DrawTexture(this, img, parms);
#endif
//==========================================================================
//
// common drawing function
//
//==========================================================================
if (ticdup != 0 && menuactive == MENU_Off)
void DFrameBuffer::DrawTextureParms(FTexture *img, DrawParms &parms)
{
NetUpdate();
}
}
void DCanvas::SetClipRect(int x, int y, int w, int h)
//==========================================================================
//
// Clipping rect
//
//==========================================================================
void DFrameBuffer::SetClipRect(int x, int y, int w, int h)
{
clipleft = clamp(x, 0, GetWidth());
clipwidth = clamp(w, -1, GetWidth() - x);
@ -210,7 +240,7 @@ DEFINE_ACTION_FUNCTION(_Screen, ClearClipRect)
return 0;
}
void DCanvas::GetClipRect(int *x, int *y, int *w, int *h)
void DFrameBuffer::GetClipRect(int *x, int *y, int *w, int *h)
{
if (x) *x = clipleft;
if (y) *y = cliptop;
@ -240,7 +270,13 @@ DEFINE_ACTION_FUNCTION(_Screen, GetViewWindow)
return MIN(numret, 4);
}
bool DCanvas::SetTextureParms(DrawParms *parms, FTexture *img, double xx, double yy) const
//==========================================================================
//
// Draw parameter parsing
//
//==========================================================================
bool DFrameBuffer::SetTextureParms(DrawParms *parms, FTexture *img, double xx, double yy) const
{
if (img != NULL)
{
@ -322,6 +358,12 @@ bool DCanvas::SetTextureParms(DrawParms *parms, FTexture *img, double xx, double
return false;
}
//==========================================================================
//
// template helpers
//
//==========================================================================
static void ListEnd(Va_List &tags)
{
va_end(tags.list);
@ -387,8 +429,14 @@ static inline FColormapStyle * ListGetColormapStyle(VMVa_List &tags)
return nullptr;
}
//==========================================================================
//
// Main taglist parsing
//
//==========================================================================
template<class T>
bool DCanvas::ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, bool fortext) const
bool DFrameBuffer::ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t tag, T& tags, DrawParms *parms, bool fortext) const
{
INTBOOL boolval;
int intval;
@ -836,10 +884,16 @@ bool DCanvas::ParseDrawTextureTags(FTexture *img, double x, double y, uint32_t t
}
// explicitly instantiate both versions for v_text.cpp.
template bool DCanvas::ParseDrawTextureTags<Va_List>(FTexture *img, double x, double y, uint32_t tag, Va_List& tags, DrawParms *parms, bool fortext) const;
template bool DCanvas::ParseDrawTextureTags<VMVa_List>(FTexture *img, double x, double y, uint32_t tag, VMVa_List& tags, DrawParms *parms, bool fortext) const;
template bool DFrameBuffer::ParseDrawTextureTags<Va_List>(FTexture *img, double x, double y, uint32_t tag, Va_List& tags, DrawParms *parms, bool fortext) const;
template bool DFrameBuffer::ParseDrawTextureTags<VMVa_List>(FTexture *img, double x, double y, uint32_t tag, VMVa_List& tags, DrawParms *parms, bool fortext) const;
void DCanvas::VirtualToRealCoords(double &x, double &y, double &w, double &h,
//==========================================================================
//
// Coordinate conversion
//
//==========================================================================
void DFrameBuffer::VirtualToRealCoords(double &x, double &y, double &w, double &h,
double vwidth, double vheight, bool vbottom, bool handleaspect) const
{
float myratio = handleaspect ? ActiveRatio (Width, Height) : (4.0f / 3.0f);
@ -899,7 +953,7 @@ DEFINE_ACTION_FUNCTION(_Screen, VirtualToRealCoords)
return MIN(numret, 2);
}
void DCanvas::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h,
void DFrameBuffer::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h,
int vwidth, int vheight, bool vbottom, bool handleaspect) const
{
double dx, dy, dw, dh;
@ -915,7 +969,13 @@ void DCanvas::VirtualToRealCoordsInt(int &x, int &y, int &w, int &h,
h = int(dy + dh + 0.5) - y;
}
void DCanvas::FillBorder (FTexture *img)
//==========================================================================
//
//
//
//==========================================================================
void DFrameBuffer::FillBorder (FTexture *img)
{
float myratio = ActiveRatio (Width, Height);
@ -961,11 +1021,14 @@ void DCanvas::FillBorder (FTexture *img)
}
}
void DCanvas::DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor)
//==========================================================================
//
// Draw a line
//
//==========================================================================
void DFrameBuffer::DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor)
{
#ifndef NO_SWRENDER
SWCanvas::DrawLine(this, x0, y0, x1, y1, palColor, realcolor);
#endif
}
DEFINE_ACTION_FUNCTION(_Screen, DrawLine)
@ -981,11 +1044,14 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawLine)
return 0;
}
void DCanvas::DrawPixel(int x, int y, int palColor, uint32_t realcolor)
//==========================================================================
//
// Draw a single pixel
//
//==========================================================================
void DFrameBuffer::DrawPixel(int x, int y, int palColor, uint32_t realcolor)
{
#ifndef NO_SWRENDER
SWCanvas::DrawPixel(this, x, y, palColor, realcolor);
#endif
}
//==========================================================================
@ -996,21 +1062,11 @@ void DCanvas::DrawPixel(int x, int y, int palColor, uint32_t realcolor)
//
//==========================================================================
void DCanvas::DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color)
void DFrameBuffer::DoClear (int left, int top, int right, int bottom, int palcolor, uint32_t color)
{
#ifndef NO_SWRENDER
if (palcolor < 0 && APART(color) != 255)
{
Dim(color, APART(color) / 255.f, left, top, right - left, bottom - top);
}
else
{
SWCanvas::Clear(this, left, top, right, bottom, palcolor, color);
}
#endif
}
void DCanvas::Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color)
void DFrameBuffer::Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color)
{
if (clipwidth >= 0 && clipheight >= 0)
{
@ -1059,14 +1115,11 @@ DEFINE_ACTION_FUNCTION(_Screen, Clear)
//
//==========================================================================
void DCanvas::DoDim(PalEntry color, float damount, int x1, int y1, int w, int h)
void DFrameBuffer::DoDim(PalEntry color, float damount, int x1, int y1, int w, int h)
{
#ifndef NO_SWRENDER
SWCanvas::Dim(this, color, damount, x1, y1, w, h);
#endif
}
void DCanvas::Dim(PalEntry color, float damount, int x1, int y1, int w, int h)
void DFrameBuffer::Dim(PalEntry color, float damount, int x1, int y1, int w, int h)
{
if (clipwidth >= 0 && clipheight >= 0)
{
@ -1118,113 +1171,85 @@ DEFINE_ACTION_FUNCTION(_Screen, Dim)
//
//==========================================================================
void DCanvas::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
void DFrameBuffer::FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley, DAngle rotation,
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip)
{
#ifndef NO_SWRENDER
SWCanvas::FillSimplePoly(this, tex, points, npoints, originx, originy, scalex, scaley, rotation, colormap, flatcolor, lightlevel, bottomclip);
#endif
}
/********************************/
/* */
/* Other miscellaneous routines */
/* */
/********************************/
//==========================================================================
//
// V_DrawBlock
// Draw a linear block of pixels into the view buffer.
// DCanvas :: FlatFill
//
void DCanvas::DrawBlock (int x, int y, int _width, int _height, const uint8_t *src) const
{
if (IsBgra())
return;
int srcpitch = _width;
int destpitch;
uint8_t *dest;
if (ClipBox (x, y, _width, _height, src, srcpitch))
{
return; // Nothing to draw
}
destpitch = Pitch;
dest = Buffer + y*Pitch + x;
do
{
memcpy (dest, src, _width);
src += srcpitch;
dest += destpitch;
} while (--_height);
}
// Fill an area with a texture. If local_origin is false, then the origin
// used for the wrapping is (0,0). Otherwise, (left,right) is used.
//
// V_GetBlock
// Gets a linear block of pixels from the view buffer.
//==========================================================================
void DFrameBuffer::FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin)
{
int w = src->GetWidth();
int h = src->GetHeight();
// Repeatedly draw the texture, left-to-right, top-to-bottom.
for (int y = local_origin ? top : (top / h * h); y < bottom; y += h)
{
for (int x = local_origin ? left : (left / w * w); x < right; x += w)
{
DrawTexture(src, x, y,
DTA_ClipLeft, left,
DTA_ClipRight, right,
DTA_ClipTop, top,
DTA_ClipBottom, bottom,
DTA_TopOffset, 0,
DTA_LeftOffset, 0,
TAG_DONE);
}
}
}
//==========================================================================
//
void DCanvas::GetBlock (int x, int y, int _width, int _height, uint8_t *dest) const
{
if (IsBgra())
return;
// DCanvas :: Dim
//
// Applies a colored overlay to the entire screen, with the opacity
// determined by the dimamount cvar.
//
//==========================================================================
const uint8_t *src;
#ifdef RANGECHECK
if (x<0
||x+_width > Width
|| y<0
|| y+_height>Height)
void DFrameBuffer::Dim(PalEntry color)
{
I_Error ("Bad V_GetBlock");
PalEntry dimmer;
float amount;
if (dimamount >= 0)
{
dimmer = PalEntry(dimcolor);
amount = dimamount;
}
#endif
src = Buffer + y*Pitch + x;
while (_height--)
else
{
memcpy (dest, src, _width);
src += Pitch;
dest += _width;
}
dimmer = gameinfo.dimcolor;
amount = gameinfo.dimamount;
}
// Returns true if the box was completely clipped. False otherwise.
bool DCanvas::ClipBox (int &x, int &y, int &w, int &h, const uint8_t *&src, const int srcpitch) const
if (gameinfo.gametype == GAME_Hexen && gamestate == GS_DEMOSCREEN)
{ // On the Hexen title screen, the default dimming is not
// enough to make the menus readable.
amount = MIN<float>(1.f, amount*2.f);
}
// Add the cvar's dimming on top of the color passed to the function
if (color.a != 0)
{
if (x >= Width || y >= Height || x+w <= 0 || y+h <= 0)
{ // Completely clipped off screen
return true;
float dim[4] = { color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f };
V_AddBlend(dimmer.r / 255.f, dimmer.g / 255.f, dimmer.b / 255.f, amount, dim);
dimmer = PalEntry(uint8_t(dim[0] * 255), uint8_t(dim[1] * 255), uint8_t(dim[2] * 255));
amount = dim[3];
}
if (x < 0) // clip left edge
{
src -= x;
w += x;
x = 0;
}
if (x+w > Width) // clip right edge
{
w = Width - x;
}
if (y < 0) // clip top edge
{
src -= y*srcpitch;
h += y;
y = 0;
}
if (y+h > Height) // clip bottom edge
{
h = Height - y;
}
return false;
Dim(dimmer, amount, 0, 0, Width, Height);
}
//==========================================================================
//
// V_SetBorderNeedRefresh
@ -1251,7 +1276,7 @@ void V_SetBorderNeedRefresh()
//
//==========================================================================
void V_DrawFrame (int left, int top, int width, int height)
void DFrameBuffer::DrawFrame (int left, int top, int width, int height)
{
FTexture *p;
const gameborder_t *border = &gameinfo.Border;
@ -1264,21 +1289,21 @@ void V_DrawFrame (int left, int top, int width, int height)
// Draw top and bottom sides.
p = TexMan[border->t];
screen->FlatFill(left, top - p->GetHeight(), right, top, p, true);
FlatFill(left, top - p->GetHeight(), right, top, p, true);
p = TexMan[border->b];
screen->FlatFill(left, bottom, right, bottom + p->GetHeight(), p, true);
FlatFill(left, bottom, right, bottom + p->GetHeight(), p, true);
// Draw left and right sides.
p = TexMan[border->l];
screen->FlatFill(left - p->GetWidth(), top, left, bottom, p, true);
FlatFill(left - p->GetWidth(), top, left, bottom, p, true);
p = TexMan[border->r];
screen->FlatFill(right, top, right + p->GetWidth(), bottom, p, true);
FlatFill(right, top, right + p->GetWidth(), bottom, p, true);
// Draw beveled corners.
screen->DrawTexture (TexMan[border->tl], left-offset, top-offset, TAG_DONE);
screen->DrawTexture (TexMan[border->tr], left+width, top-offset, TAG_DONE);
screen->DrawTexture (TexMan[border->bl], left-offset, top+height, TAG_DONE);
screen->DrawTexture (TexMan[border->br], left+width, top+height, TAG_DONE);
DrawTexture (TexMan[border->tl], left-offset, top-offset, TAG_DONE);
DrawTexture (TexMan[border->tr], left+width, top-offset, TAG_DONE);
DrawTexture (TexMan[border->bl], left-offset, top+height, TAG_DONE);
DrawTexture (TexMan[border->br], left+width, top+height, TAG_DONE);
}
DEFINE_ACTION_FUNCTION(_Screen, DrawFrame)
@ -1288,17 +1313,17 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawFrame)
PARAM_INT(y);
PARAM_INT(w);
PARAM_INT(h);
V_DrawFrame(x, y, w, h);
screen->DrawFrame(x, y, w, h);
return 0;
}
//==========================================================================
//
// V_DrawBorder
// screen->DrawBorder
//
//==========================================================================
void V_DrawBorder (int x1, int y1, int x2, int y2)
void DFrameBuffer::DrawBorder (int x1, int y1, int x2, int y2)
{
FTextureID picnum;
@ -1313,11 +1338,11 @@ void V_DrawBorder (int x1, int y1, int x2, int y2)
if (picnum.isValid())
{
screen->FlatFill (x1, y1, x2, y2, TexMan(picnum));
FlatFill (x1, y1, x2, y2, TexMan(picnum));
}
else
{
screen->Clear (x1, y1, x2, y2, 0, 0);
Clear (x1, y1, x2, y2, 0, 0);
}
}
@ -1332,19 +1357,19 @@ void V_DrawBorder (int x1, int y1, int x2, int y2)
int BorderNeedRefresh;
static void V_DrawViewBorder (void)
void DFrameBuffer::DrawViewBorder (void)
{
if (viewwidth == SCREENWIDTH)
if (viewwidth == Width)
{
return;
}
V_DrawBorder (0, 0, SCREENWIDTH, viewwindowy);
V_DrawBorder (0, viewwindowy, viewwindowx, viewheight + viewwindowy);
V_DrawBorder (viewwindowx + viewwidth, viewwindowy, SCREENWIDTH, viewheight + viewwindowy);
V_DrawBorder (0, viewwindowy + viewheight, SCREENWIDTH, StatusBar->GetTopOfStatusbar());
DrawBorder (0, 0, Width, viewwindowy);
DrawBorder (0, viewwindowy, viewwindowx, viewheight + viewwindowy);
DrawBorder (viewwindowx + viewwidth, viewwindowy, Width, viewheight + viewwindowy);
DrawBorder (0, viewwindowy + viewheight, Width, StatusBar->GetTopOfStatusbar());
V_DrawFrame (viewwindowx, viewwindowy, viewwidth, viewheight);
DrawFrame (viewwindowx, viewwindowy, viewwidth, viewheight);
}
//==========================================================================
@ -1355,41 +1380,38 @@ static void V_DrawViewBorder (void)
//
//==========================================================================
static void V_DrawTopBorder ()
void DFrameBuffer::DrawTopBorder ()
{
FTexture *p;
int offset;
if (viewwidth == SCREENWIDTH)
if (viewwidth == Width)
return;
offset = gameinfo.Border.offset;
if (viewwindowy < 34)
{
V_DrawBorder (0, 0, viewwindowx, 34);
V_DrawBorder (viewwindowx, 0, viewwindowx + viewwidth, viewwindowy);
V_DrawBorder (viewwindowx + viewwidth, 0, SCREENWIDTH, 34);
DrawBorder (0, 0, viewwindowx, 34);
DrawBorder (viewwindowx, 0, viewwindowx + viewwidth, viewwindowy);
DrawBorder (viewwindowx + viewwidth, 0, Width, 34);
p = TexMan(gameinfo.Border.t);
screen->FlatFill(viewwindowx, viewwindowy - p->GetHeight(),
viewwindowx + viewwidth, viewwindowy, p, true);
FlatFill(viewwindowx, viewwindowy - p->GetHeight(), viewwindowx + viewwidth, viewwindowy, p, true);
p = TexMan(gameinfo.Border.l);
screen->FlatFill(viewwindowx - p->GetWidth(), viewwindowy,
viewwindowx, 35, p, true);
FlatFill(viewwindowx - p->GetWidth(), viewwindowy, viewwindowx, 35, p, true);
p = TexMan(gameinfo.Border.r);
screen->FlatFill(viewwindowx + viewwidth, viewwindowy,
viewwindowx + viewwidth + p->GetWidth(), 35, p, true);
FlatFill(viewwindowx + viewwidth, viewwindowy, viewwindowx + viewwidth + p->GetWidth(), 35, p, true);
p = TexMan(gameinfo.Border.tl);
screen->DrawTexture (p, viewwindowx - offset, viewwindowy - offset, TAG_DONE);
DrawTexture (p, viewwindowx - offset, viewwindowy - offset, TAG_DONE);
p = TexMan(gameinfo.Border.tr);
screen->DrawTexture (p, viewwindowx + viewwidth, viewwindowy - offset, TAG_DONE);
DrawTexture (p, viewwindowx + viewwidth, viewwindowy - offset, TAG_DONE);
}
else
{
V_DrawBorder (0, 0, SCREENWIDTH, 34);
DrawBorder (0, 0, Width, 34);
}
}
@ -1401,7 +1423,7 @@ static void V_DrawTopBorder ()
//
//==========================================================================
void V_RefreshViewBorder ()
void DFrameBuffer::RefreshViewBorder ()
{
if (setblocks < 10)
{
@ -1412,12 +1434,12 @@ void V_RefreshViewBorder ()
{
BorderTopRefresh--;
}
V_DrawViewBorder();
DrawViewBorder();
}
else if (BorderTopRefresh)
{
BorderTopRefresh--;
V_DrawTopBorder();
DrawTopBorder();
}
}
}

View file

@ -132,7 +132,7 @@ int GetCharFromString(const uint8_t *&string)
//
//==========================================================================
void DCanvas::DrawChar (FFont *font, int normalcolor, double x, double y, int character, int tag_first, ...)
void DFrameBuffer::DrawChar (FFont *font, int normalcolor, double x, double y, int character, int tag_first, ...)
{
if (font == NULL)
return;
@ -161,7 +161,7 @@ void DCanvas::DrawChar (FFont *font, int normalcolor, double x, double y, int ch
}
}
void DCanvas::DrawChar(FFont *font, int normalcolor, double x, double y, int character, VMVa_List &args)
void DFrameBuffer::DrawChar(FFont *font, int normalcolor, double x, double y, int character, VMVa_List &args)
{
if (font == NULL)
return;
@ -208,7 +208,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawChar)
//
//==========================================================================
void DCanvas::DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms)
void DFrameBuffer::DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms)
{
int w;
const uint8_t *ch;
@ -281,7 +281,7 @@ void DCanvas::DrawTextCommon(FFont *font, int normalcolor, double x, double y, c
}
}
void DCanvas::DrawText(FFont *font, int normalcolor, double x, double y, const char *string, int tag_first, ...)
void DFrameBuffer::DrawText(FFont *font, int normalcolor, double x, double y, const char *string, int tag_first, ...)
{
Va_List tags;
DrawParms parms;
@ -299,7 +299,7 @@ void DCanvas::DrawText(FFont *font, int normalcolor, double x, double y, const c
DrawTextCommon(font, normalcolor, x, y, string, parms);
}
void DCanvas::DrawText(FFont *font, int normalcolor, double x, double y, const char *string, VMVa_List &args)
void DFrameBuffer::DrawText(FFont *font, int normalcolor, double x, double y, const char *string, VMVa_List &args)
{
DrawParms parms;

View file

@ -191,19 +191,6 @@ CUSTOM_CVAR (Int, vid_refreshrate, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
}
}
CUSTOM_CVAR (Float, dimamount, -1.f, CVAR_ARCHIVE)
{
if (self < 0.f && self != -1.f)
{
self = -1.f;
}
else if (self > 1.f)
{
self = 1.f;
}
}
CVAR (Color, dimcolor, 0xffd700, CVAR_ARCHIVE)
// [RH] Set true when vid_setmode command has been executed
bool setmodeneeded = false;
// [RH] Resolution to change to when setmodeneeded is true
@ -248,78 +235,6 @@ bool DCanvas::IsValid ()
return false;
}
//==========================================================================
//
// DCanvas :: FlatFill
//
// Fill an area with a texture. If local_origin is false, then the origin
// used for the wrapping is (0,0). Otherwise, (left,right) is used.
//
//==========================================================================
void DCanvas::FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin)
{
int w = src->GetWidth();
int h = src->GetHeight();
// Repeatedly draw the texture, left-to-right, top-to-bottom.
for (int y = local_origin ? top : (top / h * h); y < bottom; y += h)
{
for (int x = local_origin ? left : (left / w * w); x < right; x += w)
{
DrawTexture (src, x, y,
DTA_ClipLeft, left,
DTA_ClipRight, right,
DTA_ClipTop, top,
DTA_ClipBottom, bottom,
DTA_TopOffset, 0,
DTA_LeftOffset, 0,
TAG_DONE);
}
}
}
//==========================================================================
//
// DCanvas :: Dim
//
// Applies a colored overlay to the entire screen, with the opacity
// determined by the dimamount cvar.
//
//==========================================================================
void DCanvas::Dim (PalEntry color)
{
PalEntry dimmer;
float amount;
if (dimamount >= 0)
{
dimmer = PalEntry(dimcolor);
amount = dimamount;
}
else
{
dimmer = gameinfo.dimcolor;
amount = gameinfo.dimamount;
}
if (gameinfo.gametype == GAME_Hexen && gamestate == GS_DEMOSCREEN)
{ // On the Hexen title screen, the default dimming is not
// enough to make the menus readable.
amount = MIN<float> (1.f, amount*2.f);
}
// Add the cvar's dimming on top of the color passed to the function
if (color.a != 0)
{
float dim[4] = { color.r/255.f, color.g/255.f, color.b/255.f, color.a/255.f };
V_AddBlend (dimmer.r/255.f, dimmer.g/255.f, dimmer.b/255.f, amount, dim);
dimmer = PalEntry (uint8_t(dim[0]*255), uint8_t(dim[1]*255), uint8_t(dim[2]*255));
amount = dim[3];
}
Dim (dimmer, amount, 0, 0, Width, Height);
}
//==========================================================================
//
// DCanvas :: GetScreenshotBuffer
@ -1196,7 +1111,7 @@ FNativePalette *DFrameBuffer::CreatePalette(FRemapTable *remap)
bool DFrameBuffer::WipeStartScreen(int type)
{
return wipe_StartScreen(type);
return false;
}
//==========================================================================
@ -1210,8 +1125,6 @@ bool DFrameBuffer::WipeStartScreen(int type)
void DFrameBuffer::WipeEndScreen()
{
wipe_EndScreen();
Unlock();
}
//==========================================================================
@ -1226,8 +1139,7 @@ void DFrameBuffer::WipeEndScreen()
bool DFrameBuffer::WipeDo(int ticks)
{
Lock(true);
return wipe_ScreenWipe(ticks);
return false;
}
//==========================================================================
@ -1238,7 +1150,6 @@ bool DFrameBuffer::WipeDo(int ticks)
void DFrameBuffer::WipeCleanup()
{
wipe_Cleanup();
}
//==========================================================================

View file

@ -219,36 +219,6 @@ public:
virtual void Unlock () = 0;
virtual bool IsLocked () { return Buffer != NULL; } // Returns true if the surface is locked
// Draw a linear block of pixels into the canvas
virtual void DrawBlock (int x, int y, int width, int height, const uint8_t *src) const;
// Reads a linear block of pixels into the view buffer.
virtual void GetBlock (int x, int y, int width, int height, uint8_t *dest) const;
// Dim the entire canvas for the menus
virtual void Dim (PalEntry color = 0);
// Dim part of the canvas
virtual void Dim (PalEntry color, float amount, int x1, int y1, int w, int h) final;
virtual void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h);
// Fill an area with a texture
virtual void FlatFill (int left, int top, int right, int bottom, FTexture *src, bool local_origin=false);
// Fill a simple polygon with a texture
virtual void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley, DAngle rotation,
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
// Set an area to a specified color
virtual void Clear (int left, int top, int right, int bottom, int palcolor, uint32_t color) final;
virtual void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color);
// Draws a line
virtual void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor);
// Draws a single pixel
virtual void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor);
// Calculate gamma table
void CalcGamma (float gamma, uint8_t gammalookup[256]);
@ -262,31 +232,6 @@ public:
// Releases the screenshot buffer.
virtual void ReleaseScreenshotBuffer();
// Text drawing functions -----------------------------------------------
// 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);
bool SetTextureParms(DrawParms *parms, FTexture *img, double x, double y) const;
void DrawTexture (FTexture *img, double x, double y, int tags, ...);
void DrawTexture(FTexture *img, double x, double y, VMVa_List &);
void FillBorder (FTexture *img); // Fills the border around a 4:3 part of the screen on non-4:3 displays
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;
#ifdef DrawText
#undef DrawText // See WinUser.h for the definition of DrawText as a macro
#endif
// 2D Text drawing
void DrawText(FFont *font, int normalcolor, double x, double y, const char *string, int tag_first, ...);
void DrawText(FFont *font, int normalcolor, double x, double y, const char *string, VMVa_List &args);
void DrawChar(FFont *font, int normalcolor, double x, double y, int character, int tag_first, ...);
void DrawChar(FFont *font, int normalcolor, double x, double y, int character, VMVa_List &args);
protected:
uint8_t *Buffer;
int Width;
@ -296,14 +241,6 @@ protected:
bool Bgra;
int clipleft = 0, cliptop = 0, clipwidth = -1, clipheight = -1;
void DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms);
bool ClipBox (int &left, int &top, int &width, int &height, const uint8_t *&src, const int srcpitch) const;
void DrawTextureV(FTexture *img, double x, double y, uint32_t tag, va_list tags) = delete;
virtual 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;
DCanvas() {}
@ -362,6 +299,15 @@ public:
class DFrameBuffer : public DSimpleCanvas
{
typedef DSimpleCanvas Super;
protected:
void DrawTextureV(FTexture *img, double x, double y, uint32_t tag, va_list tags) = delete;
virtual 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;
void DrawTextCommon(FFont *font, int normalcolor, double x, double y, const char *string, DrawParms &parms);
public:
DFrameBuffer (int width, int height, bool bgra);
@ -450,6 +396,63 @@ public:
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);
// Dim the entire canvas for the menus
virtual void Dim(PalEntry color = 0);
// Dim part of the canvas
virtual void Dim(PalEntry color, float amount, int x1, int y1, int w, int h) final;
virtual void DoDim(PalEntry color, float amount, int x1, int y1, int w, int h);
// Fill an area with a texture
virtual void FlatFill(int left, int top, int right, int bottom, FTexture *src, bool local_origin = false);
// Fill a simple polygon with a texture
virtual void FillSimplePoly(FTexture *tex, FVector2 *points, int npoints,
double originx, double originy, double scalex, double scaley, DAngle rotation,
const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
// Set an area to a specified color
virtual void Clear(int left, int top, int right, int bottom, int palcolor, uint32_t color) final;
virtual void DoClear(int left, int top, int right, int bottom, int palcolor, uint32_t color);
// Draws a line
virtual void DrawLine(int x0, int y0, int x1, int y1, int palColor, uint32_t realcolor);
// Draws a single pixel
virtual void DrawPixel(int x, int y, int palcolor, uint32_t rgbcolor);
bool SetTextureParms(DrawParms *parms, FTexture *img, double x, double y) const;
void DrawTexture(FTexture *img, double x, double y, int tags, ...);
void DrawTexture(FTexture *img, double x, double y, VMVa_List &);
void FillBorder(FTexture *img); // Fills the border around a 4:3 part of the screen on non-4:3 displays
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 -----------------------------------------------
#ifdef DrawText
#undef DrawText // See WinUser.h for the definition of DrawText as a macro
#endif
// 2D Text drawing
void DrawText(FFont *font, int normalcolor, double x, double y, const char *string, int tag_first, ...);
void DrawText(FFont *font, int normalcolor, double x, double y, const char *string, VMVa_List &args);
void DrawChar(FFont *font, int normalcolor, double x, double y, int character, int tag_first, ...);
void DrawChar(FFont *font, int normalcolor, double x, double y, int character, VMVa_List &args);
void DrawFrame(int left, int top, int width, int height);
void DrawBorder(int x1, int y1, int x2, int y2);
void DrawViewBorder();
void DrawTopBorder();
void RefreshViewBorder();
#ifdef _WIN32
virtual void PaletteChanged () = 0;
virtual int QueryNewPalette () = 0;
@ -552,12 +555,8 @@ 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);
void V_DrawFrame (int left, int top, int width, int height);
// If the view size is not full screen, draws a border around it.
void V_DrawBorder (int x1, int y1, int x2, int y2);
void V_RefreshViewBorder ();
void V_SetBorderNeedRefresh();
int CheckRatio (int width, int height, int *trueratio=NULL);