Browse Source

CLX renderer: Cache the last drawn outline

pull/7145/head
Gleb Mazovetskiy 2 years ago committed by Anders Jenbo
parent
commit
2e7d565b05
  1. 2
      Source/diablo.cpp
  2. 35
      Source/engine/render/clx_render.cpp
  3. 7
      Source/engine/render/clx_render.hpp

2
Source/diablo.cpp

@ -36,6 +36,7 @@
#include "engine/load_cel.hpp"
#include "engine/load_file.hpp"
#include "engine/random.hpp"
#include "engine/render/clx_render.hpp"
#include "engine/sound.h"
#include "gamemenu.h"
#include "gmenu.h"
@ -2860,6 +2861,7 @@ void LoadGameLevel(bool firstflag, lvl_entry lvldir)
MakeLightTable();
SetDungeonMicros();
LoadLvlGFX();
ClearClxDrawCache();
IncProgress();
if (firstflag) {

35
Source/engine/render/clx_render.cpp

@ -259,6 +259,13 @@ constexpr size_t MaxOutlineSpriteWidth = 256;
using OutlinePixels = StaticVector<PointOf<int16_t>, MaxOutlinePixels>;
using OutlineRowSolidRuns = StaticVector<std::pair<int16_t, int16_t>, MaxOutlineSpriteWidth / 2 + 1>;
struct OutlinePixelsCacheEntry {
OutlinePixels outlinePixels;
const void *spriteData = nullptr;
bool skipColorIndexZero;
};
OutlinePixelsCacheEntry OutlinePixelsCache;
void PopulateOutlinePixelsForRow(
const StaticBitVector<MaxOutlineSpriteWidth> &rowBelow,
const StaticBitVector<MaxOutlineSpriteWidth> &rowAbove,
@ -289,11 +296,10 @@ void AppendOutlineRowSolidRuns(int x, int w, OutlineRowSolidRuns &solidRuns)
}
template <bool SkipColorIndexZero>
OutlinePixels GetOutline(ClxSprite sprite) // NOLINT(readability-function-cognitive-complexity)
void GetOutline(ClxSprite sprite, OutlinePixels &result) // NOLINT(readability-function-cognitive-complexity)
{
const unsigned width = sprite.width();
assert(width < MaxOutlineSpriteWidth);
OutlinePixels result;
StaticBitVector<MaxOutlineSpriteWidth> rows[3] = {
StaticBitVector<MaxOutlineSpriteWidth>(width),
StaticBitVector<MaxOutlineSpriteWidth>(width),
@ -387,21 +393,33 @@ OutlinePixels GetOutline(ClxSprite sprite) // NOLINT(readability-function-cognit
}
rowAbove->reset();
PopulateOutlinePixelsForRow(*rowBelow, *rowAbove, *solidRun, y + 1, result);
return result;
}
template <bool SkipColorIndexZero>
void UpdateOutlinePixelsCache(ClxSprite sprite)
{
if (OutlinePixelsCache.spriteData == sprite.pixelData()
&& OutlinePixelsCache.skipColorIndexZero == SkipColorIndexZero) {
return;
}
OutlinePixelsCache.skipColorIndexZero = SkipColorIndexZero;
OutlinePixelsCache.spriteData = sprite.pixelData();
OutlinePixelsCache.outlinePixels.clear();
GetOutline<SkipColorIndexZero>(sprite, OutlinePixelsCache.outlinePixels);
}
template <bool SkipColorIndexZero>
void RenderClxOutline(const Surface &out, Point position, ClxSprite sprite, uint8_t color)
{
const OutlinePixels pixels = GetOutline<SkipColorIndexZero>(sprite);
UpdateOutlinePixelsCache<SkipColorIndexZero>(sprite);
position.y -= sprite.height() - 1;
if (position.x > 0 && position.x + sprite.width() < out.w()
&& position.y > 0 && position.y + sprite.height() < out.h()) {
for (auto [x, y] : pixels) {
for (const auto &[x, y] : OutlinePixelsCache.outlinePixels) {
*out.at(position.x + x, position.y + y) = color;
}
} else {
for (auto [x, y] : pixels) {
for (const auto &[x, y] : OutlinePixelsCache.outlinePixels) {
out.SetPixel(Point(position.x + x, position.y + y), color);
}
}
@ -591,4 +609,9 @@ void ClxDrawOutlineSkipColorZero(const Surface &out, uint8_t col, Point position
RenderClxOutline</*SkipColorIndexZero=*/true>(out, position, clx, col);
}
void ClearClxDrawCache()
{
OutlinePixelsCache.spriteData = nullptr;
}
} // namespace devilution

7
Source/engine/render/clx_render.hpp

@ -121,6 +121,13 @@ bool IsPointWithinClx(Point position, ClxSprite clx);
*/
std::pair<int, int> ClxMeasureSolidHorizontalBounds(ClxSprite clx);
/**
* @brief Clears the CLX draw cache.
*
* Must be called whenever CLX sprites are freed.
*/
void ClearClxDrawCache();
#ifdef DEBUG_CLX
std::string ClxDescribe(ClxSprite clx);
#endif

Loading…
Cancel
Save