Avoid using globals to control drawing of viewport sprites

This commit is contained in:
Jonathan G Rennison
2022-11-08 18:26:08 +00:00
parent e8463a15c3
commit ee2763dcfd
3 changed files with 63 additions and 48 deletions

View File

@@ -83,8 +83,19 @@ byte _colour_value[COLOUR_END] = {
15, // COLOUR_WHITE, 15, // COLOUR_WHITE,
}; };
static void GfxMainBlitterViewport(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = nullptr, SpriteID sprite_id = SPR_CURSOR_MOUSE); struct GfxBlitterCtx {
static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = nullptr, SpriteID sprite_id = SPR_CURSOR_MOUSE, ZoomLevel zoom = ZOOM_LVL_NORMAL); const DrawPixelInfo *dpi;
const byte *colour_remap_ptr = nullptr;
byte string_colourremap[3]; ///< Recoloursprite for stringdrawing. The grf loader ensures that #ST_FONT sprites only use colours 0 to 2.
int sprite_brightness_adjust = 0;
GfxBlitterCtx(const DrawPixelInfo *dpi) : dpi(dpi) {}
void SetColourRemap(TextColour colour);
};
static void GfxMainBlitterViewport(const GfxBlitterCtx &ctx, const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = nullptr, SpriteID sprite_id = SPR_CURSOR_MOUSE);
static void GfxMainBlitter(const GfxBlitterCtx &ctx, const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub = nullptr, SpriteID sprite_id = SPR_CURSOR_MOUSE, ZoomLevel zoom = ZOOM_LVL_NORMAL);
static ReusableBuffer<uint8> _cursor_backup; static ReusableBuffer<uint8> _cursor_backup;
@@ -102,9 +113,6 @@ int8 _font_zoom_cfg; ///< Font zoom level in config.
* *
* @ingroup dirty * @ingroup dirty
*/ */
static const byte *_colour_remap_ptr;
static byte _string_colourremap[3]; ///< Recoloursprite for stringdrawing. The grf loader ensures that #ST_FONT sprites only use colours 0 to 2.
static int _sprite_brightness_adjust;
extern uint _dirty_block_colour; extern uint _dirty_block_colour;
static bool _whole_screen_dirty = false; static bool _whole_screen_dirty = false;
@@ -478,7 +486,7 @@ void DrawBox(int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3)
* Set the colour remap to be for the given colour. * Set the colour remap to be for the given colour.
* @param colour the new colour of the remap. * @param colour the new colour of the remap.
*/ */
static void SetColourRemap(TextColour colour) void GfxBlitterCtx::SetColourRemap(TextColour colour)
{ {
if (colour == TC_INVALID) return; if (colour == TC_INVALID) return;
@@ -488,9 +496,9 @@ static void SetColourRemap(TextColour colour)
bool raw_colour = (colour & TC_IS_PALETTE_COLOUR) != 0; bool raw_colour = (colour & TC_IS_PALETTE_COLOUR) != 0;
colour &= ~(TC_NO_SHADE | TC_IS_PALETTE_COLOUR | TC_FORCED); colour &= ~(TC_NO_SHADE | TC_IS_PALETTE_COLOUR | TC_FORCED);
_string_colourremap[1] = raw_colour ? (byte)colour : _string_colourmap[colour]; this->string_colourremap[1] = raw_colour ? (byte)colour : _string_colourmap[colour];
_string_colourremap[2] = no_shade ? 0 : 1; this->string_colourremap[2] = no_shade ? 0 : 1;
_colour_remap_ptr = _string_colourremap; this->colour_remap_ptr = this->string_colourremap;
} }
/** /**
@@ -587,6 +595,8 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
NOT_REACHED(); NOT_REACHED();
} }
GfxBlitterCtx ctx(_cur_dpi);
TextColour colour = TC_BLACK; TextColour colour = TC_BLACK;
bool draw_shadow = false; bool draw_shadow = false;
for (int run_index = 0; run_index < line.CountRuns(); run_index++) { for (int run_index = 0; run_index < line.CountRuns(); run_index++) {
@@ -595,7 +605,7 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
FontCache *fc = f->fc; FontCache *fc = f->fc;
colour = f->colour; colour = f->colour;
SetColourRemap(colour); ctx.SetColourRemap(colour);
DrawPixelInfo *dpi = _cur_dpi; DrawPixelInfo *dpi = _cur_dpi;
int dpi_left = dpi->left; int dpi_left = dpi->left;
@@ -621,11 +631,11 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
if (begin_x + sprite->x_offs > dpi_right || begin_x + sprite->x_offs + sprite->width /* - 1 + 1 */ < dpi_left) continue; if (begin_x + sprite->x_offs > dpi_right || begin_x + sprite->x_offs + sprite->width /* - 1 + 1 */ < dpi_left) continue;
if (draw_shadow && (glyph & SPRITE_GLYPH) == 0) { if (draw_shadow && (glyph & SPRITE_GLYPH) == 0) {
SetColourRemap(TC_BLACK); ctx.SetColourRemap(TC_BLACK);
GfxMainBlitter(sprite, begin_x + 1, top + 1, BM_COLOUR_REMAP); GfxMainBlitter(ctx, sprite, begin_x + 1, top + 1, BM_COLOUR_REMAP);
SetColourRemap(colour); ctx.SetColourRemap(colour);
} }
GfxMainBlitter(sprite, begin_x, top, BM_COLOUR_REMAP); GfxMainBlitter(ctx, sprite, begin_x, top, BM_COLOUR_REMAP);
} }
} }
@@ -633,16 +643,16 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left,
int x = (_current_text_dir == TD_RTL) ? left : (right - 3 * dot_width); int x = (_current_text_dir == TD_RTL) ? left : (right - 3 * dot_width);
for (int i = 0; i < 3; i++, x += dot_width) { for (int i = 0; i < 3; i++, x += dot_width) {
if (draw_shadow) { if (draw_shadow) {
SetColourRemap(TC_BLACK); ctx.SetColourRemap(TC_BLACK);
GfxMainBlitter(dot_sprite, x + 1, y + 1, BM_COLOUR_REMAP); GfxMainBlitter(ctx, dot_sprite, x + 1, y + 1, BM_COLOUR_REMAP);
SetColourRemap(colour); ctx.SetColourRemap(colour);
} }
GfxMainBlitter(dot_sprite, x, y, BM_COLOUR_REMAP); GfxMainBlitter(ctx, dot_sprite, x, y, BM_COLOUR_REMAP);
} }
} }
if (underline) { if (underline) {
GfxFillRect(left, y + h, right, y + h, _string_colourremap[1]); GfxFillRect(left, y + h, right, y + h, ctx.string_colourremap[1]);
} }
return (align & SA_HOR_MASK) == SA_RIGHT ? left : right; return (align & SA_HOR_MASK) == SA_RIGHT ? left : right;
@@ -984,8 +994,9 @@ const char *GetCharAtPosition(const char *str, int x, FontSize start_fontsize)
*/ */
void DrawCharCentered(WChar c, const Rect &r, TextColour colour) void DrawCharCentered(WChar c, const Rect &r, TextColour colour)
{ {
SetColourRemap(colour); GfxBlitterCtx ctx(_cur_dpi);
GfxMainBlitter(GetGlyph(FS_NORMAL, c), ctx.SetColourRemap(colour);
GfxMainBlitter(ctx, GetGlyph(FS_NORMAL, c),
CenterBounds(r.left, r.right, GetCharacterWidth(FS_NORMAL, c)), CenterBounds(r.left, r.right, GetCharacterWidth(FS_NORMAL, c)),
CenterBounds(r.top, r.bottom, FONT_HEIGHT_NORMAL), CenterBounds(r.top, r.bottom, FONT_HEIGHT_NORMAL),
BM_COLOUR_REMAP); BM_COLOUR_REMAP);
@@ -1034,33 +1045,35 @@ static BlitterMode GetBlitterMode(PaletteID pal)
/** /**
* Draw a sprite in a viewport. * Draw a sprite in a viewport.
* @param dpi Draw pixel info
* @param img Image number to draw * @param img Image number to draw
* @param pal Palette to use. * @param pal Palette to use.
* @param x Left coordinate of image in viewport, scaled by zoom * @param x Left coordinate of image in viewport, scaled by zoom
* @param y Top coordinate of image in viewport, scaled by zoom * @param y Top coordinate of image in viewport, scaled by zoom
* @param sub If available, draw only specified part of the sprite * @param sub If available, draw only specified part of the sprite
*/ */
void DrawSpriteViewport(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub) void DrawSpriteViewport(const DrawPixelInfo *dpi, SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub)
{ {
GfxBlitterCtx ctx(_cur_dpi);
SpriteID real_sprite = GB(img, 0, SPRITE_WIDTH); SpriteID real_sprite = GB(img, 0, SPRITE_WIDTH);
if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) { if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) {
_colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1; ctx.colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1;
GfxMainBlitterViewport(GetSprite(real_sprite, ST_NORMAL), x, y, BM_TRANSPARENT, sub, real_sprite); GfxMainBlitterViewport(ctx, GetSprite(real_sprite, ST_NORMAL), x, y, BM_TRANSPARENT, sub, real_sprite);
} else if (pal != PAL_NONE) { } else if (pal != PAL_NONE) {
if (HasBit(pal, PALETTE_TEXT_RECOLOUR)) { if (HasBit(pal, PALETTE_TEXT_RECOLOUR)) {
SetColourRemap((TextColour)GB(pal, 0, PALETTE_WIDTH)); ctx.SetColourRemap((TextColour)GB(pal, 0, PALETTE_WIDTH));
} else if (GB(pal, 0, PALETTE_WIDTH) != PAL_NONE) { } else if (GB(pal, 0, PALETTE_WIDTH) != PAL_NONE) {
_colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1; ctx.colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1;
} }
if (HasBit(pal, PALETTE_BRIGHTNESS_MODIFY)) { if (HasBit(pal, PALETTE_BRIGHTNESS_MODIFY)) {
int adjust = GB(pal, PALETTE_BRIGHTNESS_OFFSET, PALETTE_BRIGHTNESS_WIDTH); int adjust = GB(pal, PALETTE_BRIGHTNESS_OFFSET, PALETTE_BRIGHTNESS_WIDTH);
/* Sign extend */ /* Sign extend */
int sign_bit = 1 << (PALETTE_BRIGHTNESS_WIDTH - 1); int sign_bit = 1 << (PALETTE_BRIGHTNESS_WIDTH - 1);
_sprite_brightness_adjust = (adjust ^ sign_bit) - sign_bit; ctx.sprite_brightness_adjust = (adjust ^ sign_bit) - sign_bit;
} }
GfxMainBlitterViewport(GetSprite(real_sprite, ST_NORMAL), x, y, GetBlitterMode(pal), sub, real_sprite); GfxMainBlitterViewport(ctx, GetSprite(real_sprite, ST_NORMAL), x, y, GetBlitterMode(pal), sub, real_sprite);
} else { } else {
GfxMainBlitterViewport(GetSprite(real_sprite, ST_NORMAL), x, y, BM_NORMAL, sub, real_sprite); GfxMainBlitterViewport(ctx, GetSprite(real_sprite, ST_NORMAL), x, y, BM_NORMAL, sub, real_sprite);
} }
} }
@@ -1075,19 +1088,20 @@ void DrawSpriteViewport(SpriteID img, PaletteID pal, int x, int y, const SubSpri
*/ */
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom) void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub, ZoomLevel zoom)
{ {
GfxBlitterCtx ctx(_cur_dpi);
SpriteID real_sprite = GB(img, 0, SPRITE_WIDTH); SpriteID real_sprite = GB(img, 0, SPRITE_WIDTH);
if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) { if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) {
_colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1; ctx.colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1;
GfxMainBlitter(GetSprite(real_sprite, ST_NORMAL), x, y, BM_TRANSPARENT, sub, real_sprite, zoom); GfxMainBlitter(ctx, GetSprite(real_sprite, ST_NORMAL), x, y, BM_TRANSPARENT, sub, real_sprite, zoom);
} else if (pal != PAL_NONE) { } else if (pal != PAL_NONE) {
if (HasBit(pal, PALETTE_TEXT_RECOLOUR)) { if (HasBit(pal, PALETTE_TEXT_RECOLOUR)) {
SetColourRemap((TextColour)GB(pal, 0, PALETTE_WIDTH)); ctx.SetColourRemap((TextColour)GB(pal, 0, PALETTE_WIDTH));
} else { } else {
_colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1; ctx.colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1;
} }
GfxMainBlitter(GetSprite(real_sprite, ST_NORMAL), x, y, GetBlitterMode(pal), sub, real_sprite, zoom); GfxMainBlitter(ctx, GetSprite(real_sprite, ST_NORMAL), x, y, GetBlitterMode(pal), sub, real_sprite, zoom);
} else { } else {
GfxMainBlitter(GetSprite(real_sprite, ST_NORMAL), x, y, BM_NORMAL, sub, real_sprite, zoom); GfxMainBlitter(ctx, GetSprite(real_sprite, ST_NORMAL), x, y, BM_NORMAL, sub, real_sprite, zoom);
} }
} }
@@ -1104,9 +1118,9 @@ void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub,
* @tparam SCALED_XY Whether the X and Y are scaled or unscaled. * @tparam SCALED_XY Whether the X and Y are scaled or unscaled.
*/ */
template <int ZOOM_BASE, bool SCALED_XY> template <int ZOOM_BASE, bool SCALED_XY>
static void GfxBlitter(const Sprite * const sprite, int x, int y, BlitterMode mode, const SubSprite * const sub, SpriteID sprite_id, ZoomLevel zoom, const DrawPixelInfo *dst = nullptr) static void GfxBlitter(const GfxBlitterCtx &ctx, const Sprite * const sprite, int x, int y, BlitterMode mode, const SubSprite * const sub, SpriteID sprite_id, ZoomLevel zoom)
{ {
const DrawPixelInfo *dpi = (dst != nullptr) ? dst : _cur_dpi; const DrawPixelInfo *dpi = ctx.dpi;
Blitter::BlitterParams bp; Blitter::BlitterParams bp;
if (SCALED_XY) { if (SCALED_XY) {
@@ -1154,8 +1168,8 @@ static void GfxBlitter(const Sprite * const sprite, int x, int y, BlitterMode mo
bp.dst = dpi->dst_ptr; bp.dst = dpi->dst_ptr;
bp.pitch = dpi->pitch; bp.pitch = dpi->pitch;
bp.remap = _colour_remap_ptr; bp.remap = ctx.colour_remap_ptr;
bp.brightness_adjust = _sprite_brightness_adjust; bp.brightness_adjust = ctx.sprite_brightness_adjust;
if (bp.width <= 0) return; if (bp.width <= 0) return;
if (bp.height <= 0) return; if (bp.height <= 0) return;
@@ -1265,7 +1279,8 @@ std::unique_ptr<uint32[]> DrawSpriteToRgbaBuffer(SpriteID spriteId, ZoomLevel zo
/* Temporarily disable screen animations while blitting - This prevents 40bpp_anim from writing to the animation buffer. */ /* Temporarily disable screen animations while blitting - This prevents 40bpp_anim from writing to the animation buffer. */
Backup<bool> disable_anim(_screen_disable_anim, true, FILE_LINE); Backup<bool> disable_anim(_screen_disable_anim, true, FILE_LINE);
GfxBlitter<1, true>(sprite, 0, 0, BM_NORMAL, nullptr, real_sprite, zoom, &dpi); GfxBlitterCtx ctx(&dpi);
GfxBlitter<1, true>(ctx, sprite, 0, 0, BM_NORMAL, nullptr, real_sprite, zoom);
disable_anim.Restore(); disable_anim.Restore();
if (blitter->GetScreenDepth() == 8) { if (blitter->GetScreenDepth() == 8) {
@@ -1280,14 +1295,14 @@ std::unique_ptr<uint32[]> DrawSpriteToRgbaBuffer(SpriteID spriteId, ZoomLevel zo
return result; return result;
} }
static void GfxMainBlitterViewport(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub, SpriteID sprite_id) static void GfxMainBlitterViewport(const GfxBlitterCtx &ctx, const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub, SpriteID sprite_id)
{ {
GfxBlitter<ZOOM_LVL_BASE, false>(sprite, x, y, mode, sub, sprite_id, _cur_dpi->zoom); GfxBlitter<ZOOM_LVL_BASE, false>(ctx, sprite, x, y, mode, sub, sprite_id, ctx.dpi->zoom);
} }
static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub, SpriteID sprite_id, ZoomLevel zoom) static void GfxMainBlitter(const GfxBlitterCtx &ctx, const Sprite *sprite, int x, int y, BlitterMode mode, const SubSprite *sub, SpriteID sprite_id, ZoomLevel zoom)
{ {
GfxBlitter<1, true>(sprite, x, y, mode, sub, sprite_id, zoom); GfxBlitter<1, true>(ctx, sprite, x, y, mode, sub, sprite_id, zoom);
} }
void DoPaletteAnimations(); void DoPaletteAnimations();

View File

@@ -91,7 +91,7 @@ static const int DRAW_STRING_BUFFER = 2048;
void RedrawScreenRect(int left, int top, int right, int bottom); void RedrawScreenRect(int left, int top, int right, int bottom);
Dimension GetSpriteSize(SpriteID sprid, Point *offset = nullptr, ZoomLevel zoom = ZOOM_LVL_GUI); Dimension GetSpriteSize(SpriteID sprid, Point *offset = nullptr, ZoomLevel zoom = ZOOM_LVL_GUI);
void DrawSpriteViewport(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = nullptr); void DrawSpriteViewport(const DrawPixelInfo *dpi, SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = nullptr);
void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = nullptr, ZoomLevel zoom = ZOOM_LVL_GUI); void DrawSprite(SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub = nullptr, ZoomLevel zoom = ZOOM_LVL_GUI);
std::unique_ptr<uint32[]> DrawSpriteToRgbaBuffer(SpriteID spriteId, ZoomLevel zoom = ZOOM_LVL_GUI); std::unique_ptr<uint32[]> DrawSpriteToRgbaBuffer(SpriteID spriteId, ZoomLevel zoom = ZOOM_LVL_GUI);

View File

@@ -1906,7 +1906,7 @@ void ViewportSign::MarkDirty(ZoomLevel maxzoom) const
static void ViewportDrawTileSprites(const TileSpriteToDrawVector *tstdv) static void ViewportDrawTileSprites(const TileSpriteToDrawVector *tstdv)
{ {
for (const TileSpriteToDraw &ts : *tstdv) { for (const TileSpriteToDraw &ts : *tstdv) {
DrawSpriteViewport(ts.image, ts.pal, ts.x, ts.y, ts.sub); DrawSpriteViewport(_cur_dpi, ts.image, ts.pal, ts.x, ts.y, ts.sub);
} }
} }
@@ -1977,7 +1977,7 @@ static void ViewportSortParentSprites(ParentSpriteToSortVector *psdv)
static void ViewportDrawParentSprites(const ParentSpriteToSortVector *psd, const ChildScreenSpriteToDrawVector *csstdv) static void ViewportDrawParentSprites(const ParentSpriteToSortVector *psd, const ChildScreenSpriteToDrawVector *csstdv)
{ {
for (const ParentSpriteToDraw *ps : *psd) { for (const ParentSpriteToDraw *ps : *psd) {
if (ps->image != SPR_EMPTY_BOUNDING_BOX) DrawSpriteViewport(ps->image, ps->pal, ps->x, ps->y, ps->sub); if (ps->image != SPR_EMPTY_BOUNDING_BOX) DrawSpriteViewport(_cur_dpi, ps->image, ps->pal, ps->x, ps->y, ps->sub);
int child_idx = ps->first_child; int child_idx = ps->first_child;
while (child_idx >= 0) { while (child_idx >= 0) {
@@ -1989,7 +1989,7 @@ static void ViewportDrawParentSprites(const ParentSpriteToSortVector *psd, const
x += ps->left; x += ps->left;
y += ps->top; y += ps->top;
} }
DrawSpriteViewport(cs->image, cs->pal, x, y, cs->sub); DrawSpriteViewport(_cur_dpi, cs->image, cs->pal, x, y, cs->sub);
} }
} }
} }