Skip to content

Commit

Permalink
- avoid storing texture pointers in longer lived data
Browse files Browse the repository at this point in the history
* these circumvented all internal texture replacement logic. Texture objects should only be resolved right before drawing them
* added an explicit ‚tilebackground‘ option for the summary screen to fix problems with bad decision logic based on incorrect texture type checks. Automatic tiling no longer depends on texture type, but solely on size.
* added a DrawTexture variant that can be passed a texture ID instead of a pointer
  • Loading branch information
coelckers committed Jun 6, 2022
1 parent 21b6f72 commit 989dcfc
Show file tree
Hide file tree
Showing 9 changed files with 74 additions and 48 deletions.
27 changes: 21 additions & 6 deletions src/common/2d/v_draw.cpp
Expand Up @@ -194,10 +194,8 @@ int CleanXfac_1, CleanYfac_1, CleanWidth_1, CleanHeight_1;
//
//==========================================================================

void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int tags_first, ...)
static void DoDrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int tags_first, Va_List& tags)
{
Va_List tags;
va_start(tags.list, tags_first);
DrawParms parms;

if (!img || !img->isValid()) return;
Expand All @@ -210,6 +208,23 @@ void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int t
drawer->AddTexture(img, parms);
}


void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int tags_first, ...)
{
Va_List tags;
va_start(tags.list, tags_first);
DoDrawTexture(drawer, img, x, y, tags_first, tags);
}

void DrawTexture(F2DDrawer *drawer, FTextureID texid, bool animate, double x, double y, int tags_first, ...)
{
Va_List tags;
va_start(tags.list, tags_first);
auto img = TexMan.GetGameTexture(texid, animate);
DoDrawTexture(drawer, img, x, y, tags_first, tags);
}


//==========================================================================
//
// ZScript texture drawing function
Expand All @@ -218,7 +233,7 @@ void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int t

int ListGetInt(VMVa_List &tags);

static void DrawTexture(F2DDrawer *drawer, FGameTexture *img, double x, double y, VMVa_List &args)
static void DoDrawTexture(F2DDrawer *drawer, FGameTexture *img, double x, double y, VMVa_List &args)
{
DrawParms parms;
uint32_t tag = ListGetInt(args);
Expand All @@ -242,7 +257,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawTexture)

auto tex = TexMan.GameByIndex(texid, animate);
VMVa_List args = { param + 4, 0, numparam - 5, va_reginfo + 4 };
DrawTexture(twod, tex, x, y, args);
DoDrawTexture(twod, tex, x, y, args);
return 0;
}

Expand Down Expand Up @@ -1609,4 +1624,4 @@ DEFINE_ACTION_FUNCTION(_Screen, SetOffset)
PARAM_FLOAT(x);
PARAM_FLOAT(y);
ACTION_RETURN_VEC2(twod->SetOffset(DVector2(x, y)));
}
}
1 change: 1 addition & 0 deletions src/common/2d/v_draw.h
Expand Up @@ -274,6 +274,7 @@ void DrawText(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double
void DrawChar(F2DDrawer* drawer, FFont* font, int normalcolor, double x, double y, int character, int tag_first, ...);

void DrawTexture(F2DDrawer* drawer, FGameTexture* img, double x, double y, int tags_first, ...);
void DrawTexture(F2DDrawer *drawer, FTextureID texid, bool animate, double x, double y, int tags_first, ...);

void DoDim(F2DDrawer* drawer, PalEntry color, float amount, int x1, int y1, int w, int h, FRenderStyle* style = nullptr);
void Dim(F2DDrawer* drawer, PalEntry color, float damount, int x1, int y1, int w, int h, FRenderStyle* style = nullptr);
Expand Down
2 changes: 1 addition & 1 deletion src/common/console/c_console.cpp
Expand Up @@ -600,7 +600,7 @@ void C_DrawConsole ()

if (conback.isValid() && gamestate != GS_FULLCONSOLE)
{
DrawTexture (twod, TexMan.GetGameTexture(conback), 0, visheight - screen->GetHeight(),
DrawTexture (twod, conback, false, 0, visheight - screen->GetHeight(),
DTA_DestWidth, twod->GetWidth(),
DTA_DestHeight, twod->GetHeight(),
DTA_ColorOverlay, conshade,
Expand Down
2 changes: 1 addition & 1 deletion src/console/c_cmds.cpp
Expand Up @@ -941,7 +941,7 @@ CCMD(currentpos)
AActor *mo = players[consoleplayer].mo;
if(mo)
{
Printf("Current player position: (%1.3f,%1.3f,%1.3f), angle: %1.3f, floorheight: %1.3f, sector:%d, sector lightlevel: %d, actor lightlevel\n",
Printf("Current player position: (%1.3f,%1.3f,%1.3f), angle: %1.3f, floorheight: %1.3f, sector:%d, sector lightlevel: %d, actor lightlevel: %d\n",
mo->X(), mo->Y(), mo->Z(), mo->Angles.Yaw.Normalized360().Degrees, mo->floorz, mo->Sector->sectornum, mo->Sector->lightlevel, mo->LightLevel);
}
else
Expand Down
14 changes: 7 additions & 7 deletions src/d_main.cpp
Expand Up @@ -325,7 +325,7 @@ bool advancedemo;
FILE *debugfile;
gamestate_t wipegamestate = GS_DEMOSCREEN; // can be -1 to force a wipe
bool PageBlank;
FGameTexture *Advisory;
FTextureID Advisory;
FTextureID Page;
const char *Subtitle;
bool nospriterename;
Expand Down Expand Up @@ -1176,7 +1176,7 @@ void D_DoomLoop ()
r_NoInterpolate = true;
Page.SetInvalid();
Subtitle = nullptr;
Advisory = nullptr;
Advisory.SetInvalid();

vid_cursor.Callback();

Expand Down Expand Up @@ -1264,7 +1264,7 @@ void D_PageDrawer (void)
ClearRect(twod, 0, 0, SCREENWIDTH, SCREENHEIGHT, 0, 0);
if (Page.Exists())
{
DrawTexture(twod, TexMan.GetGameTexture(Page, true), 0, 0,
DrawTexture(twod, Page, true, 0, 0,
DTA_Fullscreen, true,
DTA_Masked, false,
DTA_BilinearFilter, true,
Expand All @@ -1275,9 +1275,9 @@ void D_PageDrawer (void)
FFont* font = generic_ui ? NewSmallFont : SmallFont;
DrawFullscreenSubtitle(font, GStrings[Subtitle]);
}
if (Advisory != nullptr)
if (Advisory.isValid())
{
DrawTexture(twod, Advisory, 4, 160, DTA_320x200, true, TAG_DONE);
DrawTexture(twod, Advisory, true, 4, 160, DTA_320x200, true, TAG_DONE);
}
}

Expand Down Expand Up @@ -1466,7 +1466,7 @@ void D_DoAdvanceDemo (void)
case 3:
if (gameinfo.advisoryTime)
{
Advisory = TexMan.GetGameTextureByName("ADVISOR");
Advisory = TexMan.GetTextureID("ADVISOR", ETextureType::MiscPatch);
demosequence = 1;
pagetic = (int)(gameinfo.advisoryTime * TICRATE);
break;
Expand All @@ -1475,7 +1475,7 @@ void D_DoAdvanceDemo (void)
[[fallthrough]];

case 1:
Advisory = NULL;
Advisory.SetInvalid();
if (!M_DemoNoPlay)
{
democount++;
Expand Down
3 changes: 1 addition & 2 deletions src/hu_scores.cpp
Expand Up @@ -430,8 +430,7 @@ static void HU_DrawPlayer (player_t *player, bool highlight, int col1, int col2,
auto icon = FSetTextureID(player->mo->IntVar(NAME_ScoreIcon));
if (icon.isValid())
{
auto pic = TexMan.GetGameTexture(icon);
DrawTexture(twod, pic, col3, y,
DrawTexture(twod, icon, false, col3, y,
DTA_CleanNoMove, true,
TAG_DONE);
}
Expand Down
8 changes: 4 additions & 4 deletions src/intermission/intermission.cpp
Expand Up @@ -244,7 +244,7 @@ void DIntermissionScreen::Drawer ()
{
if (!mFlatfill)
{
DrawTexture(twod, TexMan.GetGameTexture(mBackground), 0, 0, DTA_Fullscreen, true, TAG_DONE);
DrawTexture(twod, mBackground, false, 0, 0, DTA_Fullscreen, true, TAG_DONE);
}
else
{
Expand All @@ -258,7 +258,7 @@ void DIntermissionScreen::Drawer ()
for (unsigned i=0; i < mOverlays.Size(); i++)
{
if (CheckOverlay(i))
DrawTexture(twod, TexMan.GetGameTexture(mOverlays[i].mPic), mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, TAG_DONE);
DrawTexture(twod, mOverlays[i].mPic, false, mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, TAG_DONE);
}
FFont* font = generic_ui ? NewSmallFont : SmallFont;
DrawFullscreenSubtitle(font, mSubtitle);
Expand Down Expand Up @@ -311,11 +311,11 @@ void DIntermissionScreenFader::Drawer ()
if (mType == FADE_In) factor = 1.0 - factor;
int color = MAKEARGB(int(factor*255), 0,0,0);

DrawTexture(twod, TexMan.GetGameTexture(mBackground), 0, 0, DTA_Fullscreen, true, DTA_ColorOverlay, color, TAG_DONE);
DrawTexture(twod, mBackground, false, 0, 0, DTA_Fullscreen, true, DTA_ColorOverlay, color, TAG_DONE);
for (unsigned i=0; i < mOverlays.Size(); i++)
{
if (CheckOverlay(i))
DrawTexture(twod, TexMan.GetGameTexture(mOverlays[i].mPic), mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, DTA_ColorOverlay, color, TAG_DONE);
DrawTexture(twod, mOverlays[i].mPic, false, mOverlays[i].x, mOverlays[i].y, DTA_320x200, true, DTA_ColorOverlay, color, TAG_DONE);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/rendering/r_utility.cpp
Expand Up @@ -800,7 +800,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor

sector_t *oldsector = viewpoint.ViewLevel->PointInRenderSubsector(iview->Old.Pos)->sector;
if (gamestate != GS_TITLELEVEL &&
(player && ((player->cheats & CF_CHASECAM)) || (r_deathcamera && viewpoint.camera->health <= 0)))
((player && (player->cheats & CF_CHASECAM)) || (r_deathcamera && viewpoint.camera->health <= 0)))
{
// [RH] Use chasecam view
DefaultDraw = false;
Expand Down
63 changes: 37 additions & 26 deletions src/wi_stuff.cpp
Expand Up @@ -93,6 +93,7 @@ static const char *WI_Cmd[] = {

"NoAutostartMap",
"Screensize",
"TileBackground",

NULL
};
Expand Down Expand Up @@ -142,7 +143,7 @@ class DInterBackground : public DObject
int period; // period in tics between animations
yahpt_t loc; // location of animation
int data; // ALWAYS: n/a, RANDOM: period deviation (<256)
TArray<FGameTexture*> frames; // actual graphics for frames of animations
TArray<FTextureID> frames; // actual graphics for frames of animations

// following must be initialized to zero before use!
int nexttic; // next value of bcnt (used in conjunction with period)
Expand All @@ -165,13 +166,14 @@ class DInterBackground : public DObject
TArray<lnode_t> lnodes;
TArray<in_anim_t> anims;
int bcnt = 0; // used for timing of background animation
TArray<FGameTexture *> yah; // You Are Here graphic
FGameTexture* splat = nullptr; // splat
FGameTexture *background = nullptr;
TArray<FTextureID> yah; // You Are Here graphic
FTextureID splat{}; // splat
FTextureID background{};
wbstartstruct_t *wbs;
level_info_t *exitlevel;
int bgwidth = -1;
int bgheight = -1;
bool tilebackground = false;


public:
Expand Down Expand Up @@ -215,7 +217,7 @@ class DInterBackground : public DObject
//
//====================================================================

void drawOnLnode(int n, FGameTexture * c[], int numc, double backwidth, double backheight)
void drawOnLnode(int n, FTextureID c[], int numc, double backwidth, double backheight)
{
int i;
for (i = 0; i<numc; i++)
Expand All @@ -225,17 +227,17 @@ class DInterBackground : public DObject
double right;
double bottom;


right = c[i]->GetDisplayWidth();
bottom = c[i]->GetDisplayHeight();
left = lnodes[n].x - c[i]->GetDisplayLeftOffset();
top = lnodes[n].y - c[i]->GetDisplayTopOffset();
auto tex = TexMan.GetGameTexture(c[i]);
right = tex->GetDisplayWidth();
bottom = tex->GetDisplayHeight();
left = lnodes[n].x - tex->GetDisplayLeftOffset();
top = lnodes[n].y - tex->GetDisplayTopOffset();
right += left;
bottom += top;

if (left >= 0 && right < 320 && top >= 0 && bottom < 200)
{
DrawTexture(twod, c[i], lnodes[n].x, lnodes[n].y, DTA_FullscreenScale, FSMode_ScaleToFit43, DTA_VirtualWidthF, backwidth, DTA_VirtualHeightF, backheight, TAG_DONE);
DrawTexture(twod, tex, lnodes[n].x, lnodes[n].y, DTA_FullscreenScale, FSMode_ScaleToFit43, DTA_VirtualWidthF, backwidth, DTA_VirtualHeightF, backheight, TAG_DONE);
break;
}
}
Expand Down Expand Up @@ -355,20 +357,21 @@ bool DInterBackground::LoadBackground(bool isenterpic)
// Strife doesn't have an intermission pic so choose something neutral.
if (isenterpic) return false;
lumpname = gameinfo.BorderFlat;
tilebackground = true;
break;
}
}
if (lumpname == NULL)
{
// shouldn't happen!
background = NULL;
background.SetInvalid();
return false;
}

lnodes.Clear();
anims.Clear();
yah.Clear();
splat = NULL;
splat.SetInvalid();

// a name with a starting '$' indicates an intermission script
if (*lumpname != '$')
Expand All @@ -394,13 +397,13 @@ bool DInterBackground::LoadBackground(bool isenterpic)

case 1: // Splat
sc.MustGetString();
splat = TexMan.GetGameTextureByName(sc.String);
splat = TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny);
break;

case 2: // Pointers
while (sc.GetString() && !sc.Crossed)
{
yah.Push(TexMan.GetGameTextureByName(sc.String));
yah.Push(TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny));
}
if (sc.Crossed)
sc.UnGet();
Expand Down Expand Up @@ -466,6 +469,10 @@ bool DInterBackground::LoadBackground(bool isenterpic)
sc.MustGetNumber();
bgheight = sc.Number;
break;

case 16: // tilebackground
tilebackground = true;
break;

readanimation:
sc.MustGetString();
Expand Down Expand Up @@ -500,14 +507,14 @@ bool DInterBackground::LoadBackground(bool isenterpic)
if (!sc.CheckString("{"))
{
sc.MustGetString();
an.frames.Push(TexMan.GetGameTextureByName(sc.String));
an.frames.Push(TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny));
}
else
{
while (!sc.CheckString("}"))
{
sc.MustGetString();
an.frames.Push(TexMan.GetGameTextureByName(sc.String));
an.frames.Push(TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny));
}
}
an.ctr = -1;
Expand All @@ -522,7 +529,7 @@ bool DInterBackground::LoadBackground(bool isenterpic)
an.loc.y = sc.Number;
sc.MustGetString();
an.frames.Reserve(1); // allocate exactly one element
an.frames[0] = TexMan.GetGameTextureByName(sc.String);
an.frames[0] = TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny);
anims.Push(an);
break;

Expand All @@ -538,7 +545,10 @@ bool DInterBackground::LoadBackground(bool isenterpic)
texture = TexMan.GetTextureID("INTERPIC", ETextureType::MiscPatch);
}
}
background = TexMan.GetGameTexture(texture);
background = texture;
auto tex= TexMan.GetGameTexture(texture);
// extremely small textures will always be tiled.
if (tex && tex->GetDisplayWidth() < 128 && tex->GetDisplayHeight() < 128) tilebackground = true;
return noautostartmap;
}

Expand Down Expand Up @@ -605,25 +615,26 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe
double animwidth = bgwidth; // For a flat fill or clear background scale animations to 320x200
double animheight = bgheight;

if (background)
if (background.isValid())
{
auto bgtex = TexMan.GetGameTexture(background);
// background
if (background->isMiscPatch())
if (!tilebackground)
{
// if no explicit size was set scale all animations below to fit the size of the base pic
// The base pic is always scaled to fit the screen so this allows
// placing the animations precisely where they belong on the base pic
if (bgwidth < 0 || bgheight < 0)
{
animwidth = background->GetDisplayWidth();
animheight = background->GetDisplayHeight();
animwidth = bgtex->GetDisplayWidth();
animheight = bgtex->GetDisplayHeight();
if (animheight == 200) animwidth = 320; // deal with widescreen replacements that keep the original coordinates.
}
DrawTexture(twod, background, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, TAG_DONE);
DrawTexture(twod, bgtex, 0, 0, DTA_FullscreenEx, FSMode_ScaleToFit43, TAG_DONE);
}
else
{
twod->AddFlatFill(0, 0, twod->GetWidth(), twod->GetHeight(), background, (inter_classic_scaling ? -1 : 0));
twod->AddFlatFill(0, 0, twod->GetWidth(), twod->GetHeight(), bgtex, (inter_classic_scaling ? -1 : 0));
}
}
else
Expand Down Expand Up @@ -674,7 +685,7 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe
break;
}
if (a->ctr >= 0)
DrawTexture(twod, a->frames[a->ctr], a->loc.x, a->loc.y,
DrawTexture(twod, a->frames[a->ctr], false, a->loc.x, a->loc.y,
DTA_VirtualWidthF, animwidth, DTA_VirtualHeightF, animheight, DTA_FullscreenScale, FSMode_ScaleToFit43, TAG_DONE);
}

Expand Down

0 comments on commit 989dcfc

Please sign in to comment.