From ea2b04a6be83cbc8714cf6fb9698a2346c1f6325 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Fri, 9 Sep 2016 21:10:39 +0100 Subject: [PATCH 1/2] Add C++11 container utility functions. --- source.list | 1 + src/core/container_func.hpp | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 src/core/container_func.hpp diff --git a/source.list b/source.list index 59b2824ad0..b2c2f4d495 100644 --- a/source.list +++ b/source.list @@ -423,6 +423,7 @@ core/alloc_type.hpp core/backup_type.hpp core/bitmath_func.cpp core/bitmath_func.hpp +core/container_func.hpp core/endian_func.hpp core/endian_type.hpp core/enum_type.hpp diff --git a/src/core/container_func.hpp b/src/core/container_func.hpp new file mode 100644 index 0000000000..1b8e8ad847 --- /dev/null +++ b/src/core/container_func.hpp @@ -0,0 +1,35 @@ +/* $Id$ */ + +/* + * This file is part of OpenTTD. + * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2. + * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see . + */ + +/** @file container_func.hpp Functions related to use of containers. */ + +template unsigned int container_unordered_remove_if (C &container, UP predicate) { + unsigned int removecount = 0; + for (auto it = container.begin(); it != container.end();) { + if (predicate(*it)) { + removecount++; + if (std::next(it) != container.end()) { + *it = std::move(container.back()); + container.pop_back(); + } else { + container.pop_back(); + break; + } + } else { + ++it; + } + } + return removecount; +} + +template unsigned int container_unordered_remove(C &container, const V &value) { + return container_unordered_remove_if (container, [&](const typename C::value_type &v) { + return v == value; + }); +} From c137303584d1c6ff7e78078af9de7226f109e159 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Fri, 9 Sep 2016 21:19:05 +0100 Subject: [PATCH 2/2] Cache list of active viewports instead of always iterating window list. This is to speed up marking all viewports dirty, which is done very frequently. --- src/viewport.cpp | 36 ++++++++++++++---------------------- 1 file changed, 14 insertions(+), 22 deletions(-) diff --git a/src/viewport.cpp b/src/viewport.cpp index c520aae938..4cda1bdb83 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -96,6 +96,7 @@ #include "depot_base.h" #include "tunnelbridge_map.h" #include "gui.h" +#include "core/container_func.hpp" #include #include @@ -193,6 +194,8 @@ static void MarkRouteStepDirty(const TileIndex tile, uint order_nr); static DrawPixelInfo _dpi_for_text; static ViewportDrawer _vd; +static std::vector _viewport_window_cache; + RouteStepsMap _vp_route_steps; RouteStepsMap _vp_route_steps_last_mark_dirty; uint _vp_route_step_width = 0; @@ -242,6 +245,7 @@ void DeleteWindowViewport(Window *w) { if (w->viewport == NULL) return; + container_unordered_remove(_viewport_window_cache, w->viewport); delete w->viewport->overlay; free(w->viewport); w->viewport = NULL; @@ -304,6 +308,7 @@ void InitializeWindowViewport(Window *w, int x, int y, w->viewport = vp; vp->virtual_left = 0; // pt.x; vp->virtual_top = 0; // pt.y; + _viewport_window_cache.push_back(vp); } static Point _vp_move_offs; @@ -1402,11 +1407,8 @@ void ViewportSign::MarkDirty(ZoomLevel maxzoom) const zoomlevels[zoom].bottom = this->top + ScaleByZoom(VPSM_TOP + FONT_HEIGHT_NORMAL + VPSM_BOTTOM + 1, zoom); } - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { - ViewPort *vp = w->viewport; - if (vp != NULL && vp->zoom <= maxzoom) { - assert(vp->width != 0); + for (ViewPort *vp : _viewport_window_cache) { + if (vp->zoom <= maxzoom) { Rect &zl = zoomlevels[vp->zoom]; MarkViewportDirty(vp, zl.left, zl.top, zl.right, zl.bottom); } @@ -2799,31 +2801,21 @@ static void MarkViewportDirty(const ViewPort * const vp, int left, int top, int */ void MarkAllViewportsDirty(int left, int top, int right, int bottom, const ZoomLevel mark_dirty_if_zoomlevel_is_below) { - Window *w; - FOR_ALL_WINDOWS_FROM_BACK(w) { - const ViewPort * const vp = w->viewport; - if (vp != NULL) { - assert(vp->width != 0); - if (vp->zoom >= mark_dirty_if_zoomlevel_is_below) continue; - MarkViewportDirty(vp, left, top, right, bottom); - } + for (const ViewPort * const vp : _viewport_window_cache) { + if (vp->zoom >= mark_dirty_if_zoomlevel_is_below) continue; + MarkViewportDirty(vp, left, top, right, bottom); } } static void MarkRouteStepDirty(const TileIndex tile, uint order_nr) { assert(tile != INVALID_TILE); - Window *w; const Point pt = RemapCoords2(TileX(tile) * TILE_SIZE + TILE_SIZE / 2, TileY(tile) * TILE_SIZE + TILE_SIZE / 2); const int char_height = GetCharacterHeight(FS_SMALL) + 1; - FOR_ALL_WINDOWS_FROM_BACK(w) { - const ViewPort * const vp = w->viewport; - if (vp != NULL) { - assert(vp->width != 0); - const int half_width = ScaleByZoom((_vp_route_step_width / 2) + 1, vp->zoom); - const int height = ScaleByZoom(_vp_route_step_height_top + char_height * order_nr + _vp_route_step_height_bottom, vp->zoom); - MarkViewportDirty(vp, pt.x - half_width, pt.y - height, pt.x + half_width, pt.y); - } + for (const ViewPort * const vp : _viewport_window_cache) { + const int half_width = ScaleByZoom((_vp_route_step_width / 2) + 1, vp->zoom); + const int height = ScaleByZoom(_vp_route_step_height_top + char_height * order_nr + _vp_route_step_height_bottom, vp->zoom); + MarkViewportDirty(vp, pt.x - half_width, pt.y - height, pt.x + half_width, pt.y); } }