- avoid storing texture pointers in longer lived data

* 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
This commit is contained in:
Christoph Oelckers 2022-06-07 00:00:43 +02:00
parent 21b6f722be
commit 989dcfcf1c
9 changed files with 74 additions and 48 deletions

View file

@ -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; DrawParms parms;
if (!img || !img->isValid()) return; if (!img || !img->isValid()) return;
@ -210,6 +208,23 @@ void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int t
drawer->AddTexture(img, parms); 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 // ZScript texture drawing function
@ -218,7 +233,7 @@ void DrawTexture(F2DDrawer *drawer, FGameTexture* img, double x, double y, int t
int ListGetInt(VMVa_List &tags); 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; DrawParms parms;
uint32_t tag = ListGetInt(args); uint32_t tag = ListGetInt(args);
@ -242,7 +257,7 @@ DEFINE_ACTION_FUNCTION(_Screen, DrawTexture)
auto tex = TexMan.GameByIndex(texid, animate); auto tex = TexMan.GameByIndex(texid, animate);
VMVa_List args = { param + 4, 0, numparam - 5, va_reginfo + 4 }; 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; return 0;
} }

View file

@ -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 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, 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 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); void Dim(F2DDrawer* drawer, PalEntry color, float damount, int x1, int y1, int w, int h, FRenderStyle* style = nullptr);

View file

@ -600,7 +600,7 @@ void C_DrawConsole ()
if (conback.isValid() && gamestate != GS_FULLCONSOLE) 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_DestWidth, twod->GetWidth(),
DTA_DestHeight, twod->GetHeight(), DTA_DestHeight, twod->GetHeight(),
DTA_ColorOverlay, conshade, DTA_ColorOverlay, conshade,

View file

@ -941,7 +941,7 @@ CCMD(currentpos)
AActor *mo = players[consoleplayer].mo; AActor *mo = players[consoleplayer].mo;
if(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); mo->X(), mo->Y(), mo->Z(), mo->Angles.Yaw.Normalized360().Degrees, mo->floorz, mo->Sector->sectornum, mo->Sector->lightlevel, mo->LightLevel);
} }
else else

View file

@ -325,7 +325,7 @@ bool advancedemo;
FILE *debugfile; FILE *debugfile;
gamestate_t wipegamestate = GS_DEMOSCREEN; // can be -1 to force a wipe gamestate_t wipegamestate = GS_DEMOSCREEN; // can be -1 to force a wipe
bool PageBlank; bool PageBlank;
FGameTexture *Advisory; FTextureID Advisory;
FTextureID Page; FTextureID Page;
const char *Subtitle; const char *Subtitle;
bool nospriterename; bool nospriterename;
@ -1176,7 +1176,7 @@ void D_DoomLoop ()
r_NoInterpolate = true; r_NoInterpolate = true;
Page.SetInvalid(); Page.SetInvalid();
Subtitle = nullptr; Subtitle = nullptr;
Advisory = nullptr; Advisory.SetInvalid();
vid_cursor.Callback(); vid_cursor.Callback();
@ -1264,7 +1264,7 @@ void D_PageDrawer (void)
ClearRect(twod, 0, 0, SCREENWIDTH, SCREENHEIGHT, 0, 0); ClearRect(twod, 0, 0, SCREENWIDTH, SCREENHEIGHT, 0, 0);
if (Page.Exists()) if (Page.Exists())
{ {
DrawTexture(twod, TexMan.GetGameTexture(Page, true), 0, 0, DrawTexture(twod, Page, true, 0, 0,
DTA_Fullscreen, true, DTA_Fullscreen, true,
DTA_Masked, false, DTA_Masked, false,
DTA_BilinearFilter, true, DTA_BilinearFilter, true,
@ -1275,9 +1275,9 @@ void D_PageDrawer (void)
FFont* font = generic_ui ? NewSmallFont : SmallFont; FFont* font = generic_ui ? NewSmallFont : SmallFont;
DrawFullscreenSubtitle(font, GStrings[Subtitle]); 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);
} }
} }
@ -1466,7 +1466,7 @@ void D_DoAdvanceDemo (void)
case 3: case 3:
if (gameinfo.advisoryTime) if (gameinfo.advisoryTime)
{ {
Advisory = TexMan.GetGameTextureByName("ADVISOR"); Advisory = TexMan.GetTextureID("ADVISOR", ETextureType::MiscPatch);
demosequence = 1; demosequence = 1;
pagetic = (int)(gameinfo.advisoryTime * TICRATE); pagetic = (int)(gameinfo.advisoryTime * TICRATE);
break; break;
@ -1475,7 +1475,7 @@ void D_DoAdvanceDemo (void)
[[fallthrough]]; [[fallthrough]];
case 1: case 1:
Advisory = NULL; Advisory.SetInvalid();
if (!M_DemoNoPlay) if (!M_DemoNoPlay)
{ {
democount++; democount++;

View file

@ -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)); auto icon = FSetTextureID(player->mo->IntVar(NAME_ScoreIcon));
if (icon.isValid()) if (icon.isValid())
{ {
auto pic = TexMan.GetGameTexture(icon); DrawTexture(twod, icon, false, col3, y,
DrawTexture(twod, pic, col3, y,
DTA_CleanNoMove, true, DTA_CleanNoMove, true,
TAG_DONE); TAG_DONE);
} }

View file

@ -244,7 +244,7 @@ void DIntermissionScreen::Drawer ()
{ {
if (!mFlatfill) 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 else
{ {
@ -258,7 +258,7 @@ void DIntermissionScreen::Drawer ()
for (unsigned i=0; i < mOverlays.Size(); i++) for (unsigned i=0; i < mOverlays.Size(); i++)
{ {
if (CheckOverlay(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; FFont* font = generic_ui ? NewSmallFont : SmallFont;
DrawFullscreenSubtitle(font, mSubtitle); DrawFullscreenSubtitle(font, mSubtitle);
@ -311,11 +311,11 @@ void DIntermissionScreenFader::Drawer ()
if (mType == FADE_In) factor = 1.0 - factor; if (mType == FADE_In) factor = 1.0 - factor;
int color = MAKEARGB(int(factor*255), 0,0,0); 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++) for (unsigned i=0; i < mOverlays.Size(); i++)
{ {
if (CheckOverlay(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);
} }
} }
} }

View file

@ -800,7 +800,7 @@ void R_SetupFrame (FRenderViewpoint &viewpoint, FViewWindow &viewwindow, AActor
sector_t *oldsector = viewpoint.ViewLevel->PointInRenderSubsector(iview->Old.Pos)->sector; sector_t *oldsector = viewpoint.ViewLevel->PointInRenderSubsector(iview->Old.Pos)->sector;
if (gamestate != GS_TITLELEVEL && 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 // [RH] Use chasecam view
DefaultDraw = false; DefaultDraw = false;

View file

@ -93,6 +93,7 @@ static const char *WI_Cmd[] = {
"NoAutostartMap", "NoAutostartMap",
"Screensize", "Screensize",
"TileBackground",
NULL NULL
}; };
@ -142,7 +143,7 @@ class DInterBackground : public DObject
int period; // period in tics between animations int period; // period in tics between animations
yahpt_t loc; // location of animation yahpt_t loc; // location of animation
int data; // ALWAYS: n/a, RANDOM: period deviation (<256) 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! // following must be initialized to zero before use!
int nexttic; // next value of bcnt (used in conjunction with period) int nexttic; // next value of bcnt (used in conjunction with period)
@ -165,13 +166,14 @@ private:
TArray<lnode_t> lnodes; TArray<lnode_t> lnodes;
TArray<in_anim_t> anims; TArray<in_anim_t> anims;
int bcnt = 0; // used for timing of background animation int bcnt = 0; // used for timing of background animation
TArray<FGameTexture *> yah; // You Are Here graphic TArray<FTextureID> yah; // You Are Here graphic
FGameTexture* splat = nullptr; // splat FTextureID splat{}; // splat
FGameTexture *background = nullptr; FTextureID background{};
wbstartstruct_t *wbs; wbstartstruct_t *wbs;
level_info_t *exitlevel; level_info_t *exitlevel;
int bgwidth = -1; int bgwidth = -1;
int bgheight = -1; int bgheight = -1;
bool tilebackground = false;
public: public:
@ -215,7 +217,7 @@ private:
// //
//==================================================================== //====================================================================
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; int i;
for (i = 0; i<numc; i++) for (i = 0; i<numc; i++)
@ -225,17 +227,17 @@ private:
double right; double right;
double bottom; double bottom;
auto tex = TexMan.GetGameTexture(c[i]);
right = c[i]->GetDisplayWidth(); right = tex->GetDisplayWidth();
bottom = c[i]->GetDisplayHeight(); bottom = tex->GetDisplayHeight();
left = lnodes[n].x - c[i]->GetDisplayLeftOffset(); left = lnodes[n].x - tex->GetDisplayLeftOffset();
top = lnodes[n].y - c[i]->GetDisplayTopOffset(); top = lnodes[n].y - tex->GetDisplayTopOffset();
right += left; right += left;
bottom += top; bottom += top;
if (left >= 0 && right < 320 && top >= 0 && bottom < 200) 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; break;
} }
} }
@ -355,20 +357,21 @@ bool DInterBackground::LoadBackground(bool isenterpic)
// Strife doesn't have an intermission pic so choose something neutral. // Strife doesn't have an intermission pic so choose something neutral.
if (isenterpic) return false; if (isenterpic) return false;
lumpname = gameinfo.BorderFlat; lumpname = gameinfo.BorderFlat;
tilebackground = true;
break; break;
} }
} }
if (lumpname == NULL) if (lumpname == NULL)
{ {
// shouldn't happen! // shouldn't happen!
background = NULL; background.SetInvalid();
return false; return false;
} }
lnodes.Clear(); lnodes.Clear();
anims.Clear(); anims.Clear();
yah.Clear(); yah.Clear();
splat = NULL; splat.SetInvalid();
// a name with a starting '$' indicates an intermission script // a name with a starting '$' indicates an intermission script
if (*lumpname != '$') if (*lumpname != '$')
@ -394,13 +397,13 @@ bool DInterBackground::LoadBackground(bool isenterpic)
case 1: // Splat case 1: // Splat
sc.MustGetString(); sc.MustGetString();
splat = TexMan.GetGameTextureByName(sc.String); splat = TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny);
break; break;
case 2: // Pointers case 2: // Pointers
while (sc.GetString() && !sc.Crossed) 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) if (sc.Crossed)
sc.UnGet(); sc.UnGet();
@ -467,6 +470,10 @@ bool DInterBackground::LoadBackground(bool isenterpic)
bgheight = sc.Number; bgheight = sc.Number;
break; break;
case 16: // tilebackground
tilebackground = true;
break;
readanimation: readanimation:
sc.MustGetString(); sc.MustGetString();
an.LevelName = sc.String; an.LevelName = sc.String;
@ -500,14 +507,14 @@ bool DInterBackground::LoadBackground(bool isenterpic)
if (!sc.CheckString("{")) if (!sc.CheckString("{"))
{ {
sc.MustGetString(); sc.MustGetString();
an.frames.Push(TexMan.GetGameTextureByName(sc.String)); an.frames.Push(TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny));
} }
else else
{ {
while (!sc.CheckString("}")) while (!sc.CheckString("}"))
{ {
sc.MustGetString(); sc.MustGetString();
an.frames.Push(TexMan.GetGameTextureByName(sc.String)); an.frames.Push(TexMan.CheckForTexture(sc.String, ETextureType::MiscPatch, FTextureManager::TEXMAN_TryAny));
} }
} }
an.ctr = -1; an.ctr = -1;
@ -522,7 +529,7 @@ bool DInterBackground::LoadBackground(bool isenterpic)
an.loc.y = sc.Number; an.loc.y = sc.Number;
sc.MustGetString(); sc.MustGetString();
an.frames.Reserve(1); // allocate exactly one element 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); anims.Push(an);
break; break;
@ -538,7 +545,10 @@ bool DInterBackground::LoadBackground(bool isenterpic)
texture = TexMan.GetTextureID("INTERPIC", ETextureType::MiscPatch); 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; return noautostartmap;
} }
@ -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 animwidth = bgwidth; // For a flat fill or clear background scale animations to 320x200
double animheight = bgheight; double animheight = bgheight;
if (background) if (background.isValid())
{ {
auto bgtex = TexMan.GetGameTexture(background);
// 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 // 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 // The base pic is always scaled to fit the screen so this allows
// placing the animations precisely where they belong on the base pic // placing the animations precisely where they belong on the base pic
if (bgwidth < 0 || bgheight < 0) if (bgwidth < 0 || bgheight < 0)
{ {
animwidth = background->GetDisplayWidth(); animwidth = bgtex->GetDisplayWidth();
animheight = background->GetDisplayHeight(); animheight = bgtex->GetDisplayHeight();
if (animheight == 200) animwidth = 320; // deal with widescreen replacements that keep the original coordinates. 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 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 else
@ -674,7 +685,7 @@ void DInterBackground::drawBackground(int state, bool drawsplat, bool snl_pointe
break; break;
} }
if (a->ctr >= 0) 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); DTA_VirtualWidthF, animwidth, DTA_VirtualHeightF, animheight, DTA_FullscreenScale, FSMode_ScaleToFit43, TAG_DONE);
} }