Do not override global blitter to render overlay/plans to cache buffer

Creates thread safety issues with active draw jobs
pull/647/head
Jonathan G Rennison 4 months ago
parent 816d4eb657
commit 4a9803c6f0

@ -114,6 +114,7 @@ uint32_t _gfx_debug_flags;
* Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen.
*
* @pre dpi->zoom == ZOOM_LVL_NORMAL, right >= left, bottom >= top
* @param blitter Blitter to use
* @param dpi Draw pixel info
* @param left Minimum X (inclusive)
* @param top Minimum Y (inclusive)
@ -125,9 +126,8 @@ uint32_t _gfx_debug_flags;
* FILLRECT_CHECKER: Like FILLRECT_OPAQUE, but only draw every second pixel (used to grey out things)
* FILLRECT_RECOLOUR: Apply a recolour sprite to every pixel in the rectangle currently on screen
*/
void GfxFillRect(const DrawPixelInfo *dpi, int left, int top, int right, int bottom, int colour, FillRectMode mode)
void GfxFillRect(Blitter *blitter, const DrawPixelInfo *dpi, int left, int top, int right, int bottom, int colour, FillRectMode mode)
{
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
void *dst;
const int otop = top;
const int oleft = left;
@ -173,6 +173,11 @@ void GfxFillRect(const DrawPixelInfo *dpi, int left, int top, int right, int bot
}
}
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode)
{
GfxFillRect(BlitterFactory::GetCurrentBlitter(), _cur_dpi, left, top, right, bottom, colour, mode);
}
typedef std::pair<Point, Point> LineSegment;
/**
@ -319,6 +324,7 @@ void GfxFillPolygon(const std::vector<Point> &shape, int colour, FillRectMode mo
/**
* Check line clipping by using a linear equation and draw the visible part of
* the line given by x/y and x2/y2.
* @param blitter Blitter to use.
* @param video Destination pointer to draw into.
* @param x X coordinate of first point.
* @param y Y coordinate of first point.
@ -330,10 +336,8 @@ void GfxFillPolygon(const std::vector<Point> &shape, int colour, FillRectMode mo
* @param width Width of the line.
* @param dash Length of dashes for dashed lines. 0 means solid line.
*/
static inline void GfxDoDrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash = 0)
static inline void GfxDoDrawLine(Blitter *blitter, void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash = 0)
{
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
assert(width > 0);
if (y2 == y || x2 == x) {
@ -403,17 +407,24 @@ static inline bool GfxPreprocessLine(const DrawPixelInfo *dpi, int &x, int &y, i
return true;
}
void GfxDrawLine(const DrawPixelInfo *dpi, int x, int y, int x2, int y2, int colour, int width, int dash)
void GfxDrawLine(Blitter *blitter, const DrawPixelInfo *dpi, int x, int y, int x2, int y2, int colour, int width, int dash)
{
if (GfxPreprocessLine(dpi, x, y, x2, y2, width)) {
GfxDoDrawLine(dpi->dst_ptr, x, y, x2, y2, dpi->width, dpi->height, colour, width, dash);
GfxDoDrawLine(blitter, dpi->dst_ptr, x, y, x2, y2, dpi->width, dpi->height, colour, width, dash);
}
}
void GfxDrawLine(int x, int y, int x2, int y2, int colour, int width, int dash)
{
if (GfxPreprocessLine(_cur_dpi, x, y, x2, y2, width)) {
GfxDoDrawLine(BlitterFactory::GetCurrentBlitter(), _cur_dpi->dst_ptr, x, y, x2, y2, _cur_dpi->width, _cur_dpi->height, colour, width, dash);
}
}
void GfxDrawLineUnscaled(const DrawPixelInfo *dpi, int x, int y, int x2, int y2, int colour)
static void GfxDrawLineUnscaled(const DrawPixelInfo *dpi, int x, int y, int x2, int y2, int colour)
{
if (GfxPreprocessLine(dpi, x, y, x2, y2, 1)) {
GfxDoDrawLine(dpi->dst_ptr,
GfxDoDrawLine(BlitterFactory::GetCurrentBlitter(), dpi->dst_ptr,
UnScaleByZoom(x, dpi->zoom), UnScaleByZoom(y, dpi->zoom),
UnScaleByZoom(x2, dpi->zoom), UnScaleByZoom(y2, dpi->zoom),
UnScaleByZoom(dpi->width, dpi->zoom), UnScaleByZoom(dpi->height, dpi->zoom), colour, 1);

@ -117,11 +117,11 @@ int DrawStringMultiLine(int left, int right, int top, int bottom, StringID str,
void DrawCharCentered(char32_t c, const Rect &r, TextColour colour);
void GfxFillRect(const DrawPixelInfo *dpi, int left, int top, int right, int bottom, int colour, FillRectMode mode = FILLRECT_OPAQUE);
inline void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode = FILLRECT_OPAQUE) { GfxFillRect(_cur_dpi, left, top, right, bottom, colour, mode); }
void GfxFillRect(struct Blitter *blitter, const DrawPixelInfo *dpi, int left, int top, int right, int bottom, int colour, FillRectMode mode = FILLRECT_OPAQUE);
void GfxFillRect(int left, int top, int right, int bottom, int colour, FillRectMode mode = FILLRECT_OPAQUE);
void GfxFillPolygon(const std::vector<Point> &shape, int colour, FillRectMode mode = FILLRECT_OPAQUE, GfxFillRectModeFunctor *fill_functor = nullptr);
void GfxDrawLine(const DrawPixelInfo *dpi, int left, int top, int right, int bottom, int colour, int width = 1, int dash = 0);
inline void GfxDrawLine(int left, int top, int right, int bottom, int colour, int width = 1, int dash = 0) { GfxDrawLine(_cur_dpi, left, top, right, bottom, colour, width, dash); }
void GfxDrawLine(struct Blitter * blitter, const DrawPixelInfo *dpi, int left, int top, int right, int bottom, int colour, int width = 1, int dash = 0);
void GfxDrawLine(int left, int top, int right, int bottom, int colour, int width = 1, int dash = 0);
void DrawBox(const DrawPixelInfo *dpi, int x, int y, int dx1, int dy1, int dx2, int dy2, int dx3, int dy3);
void DrawRectOutline(const Rect &r, int colour, int width = 1, int dash = 0);

@ -467,22 +467,22 @@ void LinkGraphOverlay::PrepareDraw()
* Draw the linkgraph overlay or some part of it, in the area given.
* @param dpi Area to be drawn to.
*/
void LinkGraphOverlay::Draw(const DrawPixelInfo *dpi) const
void LinkGraphOverlay::Draw(Blitter *blitter, const DrawPixelInfo *dpi) const
{
this->DrawLinks(dpi);
this->DrawStationDots(dpi);
this->DrawLinks(blitter, dpi);
this->DrawStationDots(blitter, dpi);
}
/**
* Draw the cached links or part of them into the given area.
* @param dpi Area to be drawn to.
*/
void LinkGraphOverlay::DrawLinks(const DrawPixelInfo *dpi) const
void LinkGraphOverlay::DrawLinks(Blitter *blitter, const DrawPixelInfo *dpi) const
{
int width = ScaleGUITrad(this->scale);
for (const auto &i : this->cached_links) {
if (!this->IsLinkVisible(i.from_pt, i.to_pt, dpi, width + 2)) continue;
this->DrawContent(dpi, i.from_pt, i.to_pt, i.prop);
this->DrawContent(blitter, dpi, i.from_pt, i.to_pt, i.prop);
}
}
@ -492,7 +492,7 @@ void LinkGraphOverlay::DrawLinks(const DrawPixelInfo *dpi) const
* @param ptb Destination of the link.
* @param cargo Properties of the link.
*/
void LinkGraphOverlay::DrawContent(const DrawPixelInfo *dpi, Point pta, Point ptb, const LinkProperties &cargo) const
void LinkGraphOverlay::DrawContent(Blitter *blitter, const DrawPixelInfo *dpi, Point pta, Point ptb, const LinkProperties &cargo) const
{
uint usage_or_plan = std::min(cargo.capacity * 2 + 1, cargo.Usage());
int colour = LinkGraphOverlay::LINK_COLOURS[_settings_client.gui.linkgraph_colours][usage_or_plan * lengthof(LinkGraphOverlay::LINK_COLOURS[0]) / (cargo.capacity * 2 + 2)];
@ -504,20 +504,20 @@ void LinkGraphOverlay::DrawContent(const DrawPixelInfo *dpi, Point pta, Point pt
int side = _settings_game.vehicle.road_side ? 1 : -1;
if (abs(pta.x - ptb.x) < abs(pta.y - ptb.y)) {
int offset_x = (pta.y > ptb.y ? 1 : -1) * side * width;
GfxDrawLine(dpi, pta.x + offset_x, pta.y, ptb.x + offset_x, ptb.y, colour, width, dash);
GfxDrawLine(blitter, dpi, pta.x + offset_x, pta.y, ptb.x + offset_x, ptb.y, colour, width, dash);
} else {
int offset_y = (pta.x < ptb.x ? 1 : -1) * side * width;
GfxDrawLine(dpi, pta.x, pta.y + offset_y, ptb.x, ptb.y + offset_y, colour, width, dash);
GfxDrawLine(blitter, dpi, pta.x, pta.y + offset_y, ptb.x, ptb.y + offset_y, colour, width, dash);
}
GfxDrawLine(dpi, pta.x, pta.y, ptb.x, ptb.y, _colour_gradient[COLOUR_GREY][1], width);
GfxDrawLine(blitter, dpi, pta.x, pta.y, ptb.x, ptb.y, _colour_gradient[COLOUR_GREY][1], width);
}
/**
* Draw dots for stations into the smallmap. The dots' sizes are determined by the amount of
* cargo produced there, their colours by the type of cargo produced.
*/
void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
void LinkGraphOverlay::DrawStationDots(Blitter *blitter, const DrawPixelInfo *dpi) const
{
int width = ScaleGUITrad(this->scale);
for (const auto &i : this->cached_stations) {
@ -529,7 +529,7 @@ void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
uint r = width * 2 + width * 2 * std::min<uint>(200, i.quantity) / 200;
LinkGraphOverlay::DrawVertex(dpi, pt.x, pt.y, r,
LinkGraphOverlay::DrawVertex(blitter, dpi, pt.x, pt.y, r,
_colour_gradient[st->owner != OWNER_NONE ?
(Colours)Company::Get(st->owner)->colour : COLOUR_GREY][5],
_colour_gradient[COLOUR_GREY][1]);
@ -544,20 +544,20 @@ void LinkGraphOverlay::DrawStationDots(const DrawPixelInfo *dpi) const
* @param colour Colour with which the vertex will be filled.
* @param border_colour Colour for the border of the vertex.
*/
/* static */ void LinkGraphOverlay::DrawVertex(const DrawPixelInfo *dpi, int x, int y, int size, int colour, int border_colour)
/* static */ void LinkGraphOverlay::DrawVertex(Blitter *blitter, const DrawPixelInfo *dpi, int x, int y, int size, int colour, int border_colour)
{
size--;
int w1 = size / 2;
int w2 = size / 2 + size % 2;
GfxFillRect(dpi, x - w1, y - w1, x + w2, y + w2, colour);
GfxFillRect(blitter, dpi, x - w1, y - w1, x + w2, y + w2, colour);
w1++;
w2++;
GfxDrawLine(dpi, x - w1, y - w1, x + w2, y - w1, border_colour);
GfxDrawLine(dpi, x - w1, y + w2, x + w2, y + w2, border_colour);
GfxDrawLine(dpi, x - w1, y - w1, x - w1, y + w2, border_colour);
GfxDrawLine(dpi, x + w2, y - w1, x + w2, y + w2, border_colour);
GfxDrawLine(blitter, dpi, x - w1, y - w1, x + w2, y - w1, border_colour);
GfxDrawLine(blitter, dpi, x - w1, y + w2, x + w2, y + w2, border_colour);
GfxDrawLine(blitter, dpi, x - w1, y - w1, x - w1, y + w2, border_colour);
GfxDrawLine(blitter, dpi, x + w2, y - w1, x + w2, y + w2, border_colour);
}
bool LinkGraphOverlay::ShowTooltip(Point pt, TooltipCloseCondition close_cond)

@ -84,7 +84,7 @@ public:
bool CacheStillValid() const;
void MarkStationViewportLinksDirty(const Station *st);
void PrepareDraw();
void Draw(const DrawPixelInfo *dpi) const;
void Draw(struct Blitter *blitter, const DrawPixelInfo *dpi) const;
void SetCargoMask(CargoTypes cargo_mask);
void SetCompanyMask(CompanyMask company_mask);
@ -117,15 +117,15 @@ protected:
Point GetStationMiddle(const Station *st) const;
void RefreshDrawCache();
void DrawLinks(const DrawPixelInfo *dpi) const;
void DrawStationDots(const DrawPixelInfo *dpi) const;
void DrawContent(const DrawPixelInfo *dpi, Point pta, Point ptb, const LinkProperties &cargo) const;
void DrawLinks(struct Blitter *blitter, const DrawPixelInfo *dpi) const;
void DrawStationDots(struct Blitter *blitter, const DrawPixelInfo *dpi) const;
void DrawContent(struct Blitter *blitter, const DrawPixelInfo *dpi, Point pta, Point ptb, const LinkProperties &cargo) const;
bool IsLinkVisible(Point pta, Point ptb, const DrawPixelInfo *dpi, int padding = 0) const;
bool IsPointVisible(Point pt, const DrawPixelInfo *dpi, int padding = 0) const;
void GetWidgetDpi(DrawPixelInfo *dpi, uint margin = 0) const;
static void AddStats(CargoID new_cargo, uint new_cap, uint new_usg, uint new_plan, uint32_t time, bool new_shared, LinkProperties &cargo);
static void DrawVertex(const DrawPixelInfo *dpi, int x, int y, int size, int colour, int border_colour);
static void DrawVertex(struct Blitter *blitter, const DrawPixelInfo *dpi, int x, int y, int size, int colour, int border_colour);
};
void ShowLinkGraphLegend();

@ -27,6 +27,7 @@
#include "zoom_func.h"
#include "object_map.h"
#include "newgrf_object.h"
#include "blitter/factory.hpp"
#include "smallmap_colours.h"
#include "smallmap_gui.h"
@ -1007,7 +1008,7 @@ void SmallMapWindow::DrawSmallMap(DrawPixelInfo *dpi, bool draw_indicators) cons
/* Draw link stat overlay */
if (this->map_type == SMT_LINKSTATS) {
this->overlay->PrepareDraw();
this->overlay->Draw(dpi);
this->overlay->Draw(BlitterFactory::GetCurrentBlitter(), dpi);
}
/* Draw town names */

@ -327,7 +327,7 @@ struct ViewportDrawerDynamic {
static void MarkRouteStepDirty(RouteStepsMap::const_iterator cit);
static void MarkRouteStepDirty(const TileIndex tile, uint order_nr);
static void HideMeasurementTooltips();
static void ViewportDrawPlans(const Viewport *vp, DrawPixelInfo *plan_dpi);
static void ViewportDrawPlans(const Viewport *vp, Blitter *blitter, DrawPixelInfo *plan_dpi);
static std::unique_ptr<ViewportDrawerDynamic> _vdd;
std::vector<std::unique_ptr<ViewportDrawerDynamic>> _spare_viewport_drawers;
@ -561,8 +561,7 @@ static void ScrollPlanPixelCache(Viewport *vp, int offset_x, int offset_y)
const int pitch = vp->width;
Blitter_8bppDrawing blitter(&pitch);
BlitterFactory::TemporaryCurrentBlitterOverride current_blitter(&blitter);
ViewportDrawPlans(vp, &plan_dpi);
ViewportDrawPlans(vp, &blitter, &plan_dpi);
});
if (clear) ClearViewportPlanPixelCache(vp);
}
@ -588,8 +587,7 @@ static void ScrollOrInvalidateOverlayPixelCache(Viewport *vp, int offset_x, int
const int pitch = vp->width;
Blitter_8bppDrawing blitter(&pitch);
BlitterFactory::TemporaryCurrentBlitterOverride current_blitter(&blitter);
vp->overlay->Draw(&overlay_dpi);
vp->overlay->Draw(&blitter, &overlay_dpi);
});
if (clear) vp->overlay_pixel_cache.clear();
}
@ -2603,10 +2601,10 @@ void ViewportRouteOverlay::DrawVehicleRoutePath(const Viewport *vp, ViewportDraw
int line_width = 3;
if (_settings_client.gui.dash_level_of_route_lines == 0) {
GfxDrawLine(&dpi_for_text, from_x, from_y, to_x, to_y, PC_BLACK, 3, _settings_client.gui.dash_level_of_route_lines);
GfxDrawLine(BlitterFactory::GetCurrentBlitter(), &dpi_for_text, from_x, from_y, to_x, to_y, PC_BLACK, 3, _settings_client.gui.dash_level_of_route_lines);
line_width = 1;
}
GfxDrawLine(&dpi_for_text, from_x, from_y, to_x, to_y, iter.order_conditional ? PC_YELLOW : PC_WHITE, line_width, _settings_client.gui.dash_level_of_route_lines);
GfxDrawLine(BlitterFactory::GetCurrentBlitter(), &dpi_for_text, from_x, from_y, to_x, to_y, iter.order_conditional ? PC_YELLOW : PC_WHITE, line_width, _settings_client.gui.dash_level_of_route_lines);
}
}
@ -2797,7 +2795,7 @@ static void ViewportDrawVehicleRouteSteps(const Viewport * const vp)
}
}
static void ViewportDrawPlans(const Viewport *vp, DrawPixelInfo *plan_dpi)
static void ViewportDrawPlans(const Viewport *vp, Blitter *blitter, DrawPixelInfo *plan_dpi)
{
const Rect bounds = {
ScaleByZoom(plan_dpi->left - 2, vp->zoom),
@ -2843,11 +2841,11 @@ static void ViewportDrawPlans(const Viewport *vp, DrawPixelInfo *plan_dpi)
const int to_x = UnScaleByZoom(to_pt.x, vp->zoom);
const int to_y = UnScaleByZoom(to_pt.y, vp->zoom);
GfxDrawLine(plan_dpi, from_x, from_y, to_x, to_y, PC_BLACK, 3);
GfxDrawLine(blitter, plan_dpi, from_x, from_y, to_x, to_y, PC_BLACK, 3);
if (pl->focused) {
GfxDrawLine(plan_dpi, from_x, from_y, to_x, to_y, PC_RED, 1);
GfxDrawLine(blitter, plan_dpi, from_x, from_y, to_x, to_y, PC_RED, 1);
} else {
GfxDrawLine(plan_dpi, from_x, from_y, to_x, to_y, _colour_value[p->colour], 1);
GfxDrawLine(blitter, plan_dpi, from_x, from_y, to_x, to_y, _colour_value[p->colour], 1);
}
}
}
@ -2874,7 +2872,7 @@ static void ViewportDrawPlans(const Viewport *vp, DrawPixelInfo *plan_dpi)
const int to_x = UnScaleByZoom(to_pt.x, vp->zoom);
const int to_y = UnScaleByZoom(to_pt.y, vp->zoom);
GfxDrawLine(plan_dpi, from_x, from_y, to_x, to_y, _colour_value[_current_plan->colour], 3, 1);
GfxDrawLine(blitter, plan_dpi, from_x, from_y, to_x, to_y, _colour_value[_current_plan->colour], 3, 1);
}
}
}
@ -3907,8 +3905,7 @@ void ViewportDoDraw(Viewport *vp, int left, int top, int right, int bottom, uint
const int pitch = vp->width;
Blitter_8bppDrawing blitter(&pitch);
BlitterFactory::TemporaryCurrentBlitterOverride current_blitter(&blitter);
vp->overlay->Draw(&overlay_dpi);
vp->overlay->Draw(&blitter, &overlay_dpi);
}
}
@ -3944,8 +3941,7 @@ void ViewportDoDraw(Viewport *vp, int left, int top, int right, int bottom, uint
const int pitch = vp->width;
Blitter_8bppDrawing blitter(&pitch);
BlitterFactory::TemporaryCurrentBlitterOverride current_blitter(&blitter);
ViewportDrawPlans(vp, &plan_dpi);
ViewportDrawPlans(vp, &blitter, &plan_dpi);
}
} else {
vp->plan_pixel_cache.clear();
@ -4082,7 +4078,7 @@ static void ViewportDoDrawPhase2(Viewport *vp, ViewportDrawerDynamic *vdd)
dp.height = UnScaleByZoom(dp.height, zoom);
dp.left = vdd->offset_x + vp->left;
dp.top = vdd->offset_y + vp->top;
vp->overlay->Draw(&dp);
vp->overlay->Draw(BlitterFactory::GetCurrentBlitter(), &dp);
} else {
const int pixel_cache_start = vdd->offset_x + (vdd->offset_y * vp->width);
BlitterFactory::GetCurrentBlitter()->SetRectNoD7(vdd->dpi.dst_ptr, 0, 0, vp->overlay_pixel_cache.data() + pixel_cache_start,
@ -4117,7 +4113,7 @@ static void ViewportDoDrawPhase3(Viewport *vp)
if (vp->zoom < ZOOM_LVL_DRAW_MAP && AreAnyPlansVisible()) {
DrawPixelInfo plan_dpi = _vdd->MakeDPIForText();
ViewportDrawPlans(vp, &plan_dpi);
ViewportDrawPlans(vp, BlitterFactory::GetCurrentBlitter(), &plan_dpi);
} else if (vp->zoom >= ZOOM_LVL_DRAW_MAP && !vp->plan_pixel_cache.empty()) {
const int pixel_cache_start = _vdd->offset_x + (_vdd->offset_y * vp->width);
BlitterFactory::GetCurrentBlitter()->SetRectNoD7(_vdd->dpi.dst_ptr, 0, 0, vp->plan_pixel_cache.data() + pixel_cache_start,
@ -4126,7 +4122,7 @@ static void ViewportDoDrawPhase3(Viewport *vp)
if (_vdd->display_flags & (ND_SHADE_GREY | ND_SHADE_DIMMED)) {
DrawPixelInfo dp = _vdd->MakeDPIForText();
GfxFillRect(&dp, dp.left, dp.top, dp.left + dp.width, dp.top + dp.height,
GfxFillRect(BlitterFactory::GetCurrentBlitter(), &dp, dp.left, dp.top, dp.left + dp.width, dp.top + dp.height,
(_vdd->display_flags & ND_SHADE_DIMMED) ? PALETTE_TO_TRANSPARENT : PALETTE_NEWSPAPER, FILLRECT_RECOLOUR);
}

Loading…
Cancel
Save