diff --git a/src/gfx.cpp b/src/gfx.cpp index 80f564fb52..bfee35916a 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -83,8 +83,19 @@ byte _colour_value[COLOUR_END] = { 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); -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); +struct GfxBlitterCtx { + 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 _cursor_backup; @@ -102,9 +113,6 @@ int8 _font_zoom_cfg; ///< Font zoom level in config. * * @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; 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. * @param colour the new colour of the remap. */ -static void SetColourRemap(TextColour colour) +void GfxBlitterCtx::SetColourRemap(TextColour colour) { if (colour == TC_INVALID) return; @@ -488,9 +496,9 @@ static void SetColourRemap(TextColour colour) bool raw_colour = (colour & TC_IS_PALETTE_COLOUR) != 0; colour &= ~(TC_NO_SHADE | TC_IS_PALETTE_COLOUR | TC_FORCED); - _string_colourremap[1] = raw_colour ? (byte)colour : _string_colourmap[colour]; - _string_colourremap[2] = no_shade ? 0 : 1; - _colour_remap_ptr = _string_colourremap; + this->string_colourremap[1] = raw_colour ? (byte)colour : _string_colourmap[colour]; + this->string_colourremap[2] = no_shade ? 0 : 1; + this->colour_remap_ptr = this->string_colourremap; } /** @@ -587,6 +595,8 @@ static int DrawLayoutLine(const ParagraphLayouter::Line &line, int y, int left, NOT_REACHED(); } + GfxBlitterCtx ctx(_cur_dpi); + TextColour colour = TC_BLACK; bool draw_shadow = false; 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; colour = f->colour; - SetColourRemap(colour); + ctx.SetColourRemap(colour); DrawPixelInfo *dpi = _cur_dpi; 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 (draw_shadow && (glyph & SPRITE_GLYPH) == 0) { - SetColourRemap(TC_BLACK); - GfxMainBlitter(sprite, begin_x + 1, top + 1, BM_COLOUR_REMAP); - SetColourRemap(colour); + ctx.SetColourRemap(TC_BLACK); + GfxMainBlitter(ctx, sprite, begin_x + 1, top + 1, BM_COLOUR_REMAP); + 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); for (int i = 0; i < 3; i++, x += dot_width) { if (draw_shadow) { - SetColourRemap(TC_BLACK); - GfxMainBlitter(dot_sprite, x + 1, y + 1, BM_COLOUR_REMAP); - SetColourRemap(colour); + ctx.SetColourRemap(TC_BLACK); + GfxMainBlitter(ctx, dot_sprite, x + 1, y + 1, BM_COLOUR_REMAP); + ctx.SetColourRemap(colour); } - GfxMainBlitter(dot_sprite, x, y, BM_COLOUR_REMAP); + GfxMainBlitter(ctx, dot_sprite, x, y, BM_COLOUR_REMAP); } } 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; @@ -984,8 +994,9 @@ const char *GetCharAtPosition(const char *str, int x, FontSize start_fontsize) */ void DrawCharCentered(WChar c, const Rect &r, TextColour colour) { - SetColourRemap(colour); - GfxMainBlitter(GetGlyph(FS_NORMAL, c), + GfxBlitterCtx ctx(_cur_dpi); + ctx.SetColourRemap(colour); + GfxMainBlitter(ctx, GetGlyph(FS_NORMAL, c), CenterBounds(r.left, r.right, GetCharacterWidth(FS_NORMAL, c)), CenterBounds(r.top, r.bottom, FONT_HEIGHT_NORMAL), BM_COLOUR_REMAP); @@ -1034,33 +1045,35 @@ static BlitterMode GetBlitterMode(PaletteID pal) /** * Draw a sprite in a viewport. + * @param dpi Draw pixel info * @param img Image number to draw * @param pal Palette to use. * @param x Left 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 */ -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); if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) { - _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); + ctx.colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1; + GfxMainBlitterViewport(ctx, GetSprite(real_sprite, ST_NORMAL), x, y, BM_TRANSPARENT, sub, real_sprite); } else if (pal != PAL_NONE) { 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) { - _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)) { int adjust = GB(pal, PALETTE_BRIGHTNESS_OFFSET, PALETTE_BRIGHTNESS_WIDTH); /* Sign extend */ 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 { - 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) { + GfxBlitterCtx ctx(_cur_dpi); SpriteID real_sprite = GB(img, 0, SPRITE_WIDTH); if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) { - _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); + ctx.colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1; + GfxMainBlitter(ctx, GetSprite(real_sprite, ST_NORMAL), x, y, BM_TRANSPARENT, sub, real_sprite, zoom); } else if (pal != PAL_NONE) { if (HasBit(pal, PALETTE_TEXT_RECOLOUR)) { - SetColourRemap((TextColour)GB(pal, 0, PALETTE_WIDTH)); + ctx.SetColourRemap((TextColour)GB(pal, 0, PALETTE_WIDTH)); } 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 { - 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. */ template -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; 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.pitch = dpi->pitch; - bp.remap = _colour_remap_ptr; - bp.brightness_adjust = _sprite_brightness_adjust; + bp.remap = ctx.colour_remap_ptr; + bp.brightness_adjust = ctx.sprite_brightness_adjust; if (bp.width <= 0) return; if (bp.height <= 0) return; @@ -1265,7 +1279,8 @@ std::unique_ptr DrawSpriteToRgbaBuffer(SpriteID spriteId, ZoomLevel zo /* Temporarily disable screen animations while blitting - This prevents 40bpp_anim from writing to the animation buffer. */ Backup 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(); if (blitter->GetScreenDepth() == 8) { @@ -1280,14 +1295,14 @@ std::unique_ptr DrawSpriteToRgbaBuffer(SpriteID spriteId, ZoomLevel zo 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(sprite, x, y, mode, sub, sprite_id, _cur_dpi->zoom); + GfxBlitter(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(); diff --git a/src/gfx_func.h b/src/gfx_func.h index 8d1b7ed615..e1b1e9527f 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -91,7 +91,7 @@ static const int DRAW_STRING_BUFFER = 2048; void RedrawScreenRect(int left, int top, int right, int bottom); 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); std::unique_ptr DrawSpriteToRgbaBuffer(SpriteID spriteId, ZoomLevel zoom = ZOOM_LVL_GUI); diff --git a/src/viewport.cpp b/src/viewport.cpp index 81df3323bb..e3fb8fbad9 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -1906,7 +1906,7 @@ void ViewportSign::MarkDirty(ZoomLevel maxzoom) const static void ViewportDrawTileSprites(const TileSpriteToDrawVector *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) { 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; while (child_idx >= 0) { @@ -1989,7 +1989,7 @@ static void ViewportDrawParentSprites(const ParentSpriteToSortVector *psd, const x += ps->left; y += ps->top; } - DrawSpriteViewport(cs->image, cs->pal, x, y, cs->sub); + DrawSpriteViewport(_cur_dpi, cs->image, cs->pal, x, y, cs->sub); } } }