From db924a4681f019a6372f5192693af5aede36d080 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Tue, 16 Jan 2018 23:23:52 +0000 Subject: [PATCH] Codechange: [Blitter] Change DrawLine to be templated This is remove per-pixel overheads due to use of the SetPixel virtual method. These overheads included: * expensive virtual method call which prevents inlining * palette lookup for every pixel * branch on whether palette animation is enabled on every pixel Regenerate project files. --- projects/openttd_vs140.vcxproj | 2 +- projects/openttd_vs140.vcxproj.filters | 6 +++--- projects/openttd_vs141.vcxproj | 2 +- projects/openttd_vs141.vcxproj.filters | 6 +++--- source.list | 2 +- src/blitter/32bpp_anim.cpp | 19 +++++++++++++++++++ src/blitter/32bpp_anim.hpp | 1 + src/blitter/32bpp_base.cpp | 9 +++++++++ src/blitter/32bpp_base.hpp | 1 + src/blitter/8bpp_base.cpp | 8 ++++++++ src/blitter/8bpp_base.hpp | 1 + src/blitter/base.hpp | 4 +++- src/blitter/{base.cpp => common.hpp} | 19 +++++++++++-------- 13 files changed, 62 insertions(+), 18 deletions(-) rename src/blitter/{base.cpp => common.hpp} (86%) diff --git a/projects/openttd_vs140.vcxproj b/projects/openttd_vs140.vcxproj index f08c26f09b..59f52a08da 100644 --- a/projects/openttd_vs140.vcxproj +++ b/projects/openttd_vs140.vcxproj @@ -1201,8 +1201,8 @@ - + diff --git a/projects/openttd_vs140.vcxproj.filters b/projects/openttd_vs140.vcxproj.filters index 7ad671fc7c..e93c94f1f7 100644 --- a/projects/openttd_vs140.vcxproj.filters +++ b/projects/openttd_vs140.vcxproj.filters @@ -2691,12 +2691,12 @@ Blitters - - Blitters - Blitters + + Blitters + Blitters diff --git a/projects/openttd_vs141.vcxproj b/projects/openttd_vs141.vcxproj index 552b9b9a95..525119179d 100644 --- a/projects/openttd_vs141.vcxproj +++ b/projects/openttd_vs141.vcxproj @@ -1201,8 +1201,8 @@ - + diff --git a/projects/openttd_vs141.vcxproj.filters b/projects/openttd_vs141.vcxproj.filters index 7ad671fc7c..e93c94f1f7 100644 --- a/projects/openttd_vs141.vcxproj.filters +++ b/projects/openttd_vs141.vcxproj.filters @@ -2691,12 +2691,12 @@ Blitters - - Blitters - Blitters + + Blitters + Blitters diff --git a/source.list b/source.list index f78b8cecff..358b16a7cd 100644 --- a/source.list +++ b/source.list @@ -948,8 +948,8 @@ blitter/8bpp_optimized.hpp blitter/8bpp_simple.cpp blitter/8bpp_simple.hpp #end -blitter/base.cpp blitter/base.hpp +blitter/common.hpp blitter/factory.hpp blitter/null.cpp blitter/null.hpp diff --git a/src/blitter/32bpp_anim.cpp b/src/blitter/32bpp_anim.cpp index 98ae22b00c..27b1fbd5b8 100644 --- a/src/blitter/32bpp_anim.cpp +++ b/src/blitter/32bpp_anim.cpp @@ -12,6 +12,7 @@ #include "../stdafx.h" #include "../video/video_driver.hpp" #include "32bpp_anim.hpp" +#include "common.hpp" #include "../table/sprites.h" @@ -321,6 +322,24 @@ void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8 colour) this->anim_buf[this->ScreenToAnimOffset((uint32 *)video) + x + y * this->anim_buf_pitch] = colour | (DEFAULT_BRIGHTNESS << 8); } +void Blitter_32bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8 colour, int width, int dash) +{ + const Colour c = LookupColourInPalette(colour); + + if (_screen_disable_anim) { + this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [&](int x, int y) { + *((Colour *)video + x + y * _screen.pitch) = c; + }); + } else { + uint16 * const offset_anim_buf = this->anim_buf + this->ScreenToAnimOffset((uint32 *)video); + const uint16 anim_colour = colour | (DEFAULT_BRIGHTNESS << 8); + this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [&](int x, int y) { + *((Colour *)video + x + y * _screen.pitch) = c; + offset_anim_buf[x + y * this->anim_buf_pitch] = anim_colour; + }); + } +} + void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colour) { if (_screen_disable_anim) { diff --git a/src/blitter/32bpp_anim.hpp b/src/blitter/32bpp_anim.hpp index da33ec95bb..ecf6dcfca0 100644 --- a/src/blitter/32bpp_anim.hpp +++ b/src/blitter/32bpp_anim.hpp @@ -40,6 +40,7 @@ public: /* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom); /* virtual */ void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal); /* virtual */ void SetPixel(void *video, int x, int y, uint8 colour); + /* virtual */ void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8 colour, int width, int dash); /* virtual */ void DrawRect(void *video, int width, int height, uint8 colour); /* virtual */ void CopyFromBuffer(void *video, const void *src, int width, int height); /* virtual */ void CopyToBuffer(const void *video, void *dst, int width, int height); diff --git a/src/blitter/32bpp_base.cpp b/src/blitter/32bpp_base.cpp index c396e45410..b2e66b0be1 100644 --- a/src/blitter/32bpp_base.cpp +++ b/src/blitter/32bpp_base.cpp @@ -11,6 +11,7 @@ #include "../stdafx.h" #include "32bpp_base.hpp" +#include "common.hpp" #include "../safeguards.h" @@ -24,6 +25,14 @@ void Blitter_32bppBase::SetPixel(void *video, int x, int y, uint8 colour) *((Colour *)video + x + y * _screen.pitch) = LookupColourInPalette(colour); } +void Blitter_32bppBase::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8 colour, int width, int dash) +{ + const Colour c = LookupColourInPalette(colour); + this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [=](int x, int y) { + *((Colour *)video + x + y * _screen.pitch) = c; + }); +} + void Blitter_32bppBase::DrawRect(void *video, int width, int height, uint8 colour) { Colour colour32 = LookupColourInPalette(colour); diff --git a/src/blitter/32bpp_base.hpp b/src/blitter/32bpp_base.hpp index 9b76271704..697593da6a 100644 --- a/src/blitter/32bpp_base.hpp +++ b/src/blitter/32bpp_base.hpp @@ -23,6 +23,7 @@ public: /* virtual */ uint8 GetScreenDepth() { return 32; } /* virtual */ void *MoveTo(void *video, int x, int y); /* virtual */ void SetPixel(void *video, int x, int y, uint8 colour); + /* virtual */ void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8 colour, int width, int dash); /* virtual */ void DrawRect(void *video, int width, int height, uint8 colour); /* virtual */ void CopyFromBuffer(void *video, const void *src, int width, int height); /* virtual */ void CopyToBuffer(const void *video, void *dst, int width, int height); diff --git a/src/blitter/8bpp_base.cpp b/src/blitter/8bpp_base.cpp index eab6eaa0db..dccfda3d70 100644 --- a/src/blitter/8bpp_base.cpp +++ b/src/blitter/8bpp_base.cpp @@ -12,6 +12,7 @@ #include "../stdafx.h" #include "../gfx_func.h" #include "8bpp_base.hpp" +#include "common.hpp" #include "../safeguards.h" @@ -35,6 +36,13 @@ void Blitter_8bppBase::SetPixel(void *video, int x, int y, uint8 colour) *((uint8 *)video + x + y * _screen.pitch) = colour; } +void Blitter_8bppBase::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8 colour, int width, int dash) +{ + this->DrawLineGeneric(x, y, x2, y2, screen_width, screen_height, width, dash, [=](int x, int y) { + *((uint8 *)video + x + y * _screen.pitch) = colour; + }); +} + void Blitter_8bppBase::DrawRect(void *video, int width, int height, uint8 colour) { do { diff --git a/src/blitter/8bpp_base.hpp b/src/blitter/8bpp_base.hpp index 2dff784992..8f75dda5d3 100644 --- a/src/blitter/8bpp_base.hpp +++ b/src/blitter/8bpp_base.hpp @@ -21,6 +21,7 @@ public: /* virtual */ void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal); /* virtual */ void *MoveTo(void *video, int x, int y); /* virtual */ void SetPixel(void *video, int x, int y, uint8 colour); + /* virtual */ void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8 colour, int width, int dash); /* virtual */ void DrawRect(void *video, int width, int height, uint8 colour); /* virtual */ void CopyFromBuffer(void *video, const void *src, int width, int height); /* virtual */ void CopyToBuffer(const void *video, void *dst, int width, int height); diff --git a/src/blitter/base.hpp b/src/blitter/base.hpp index a9403b339d..388359441f 100644 --- a/src/blitter/base.hpp +++ b/src/blitter/base.hpp @@ -122,7 +122,7 @@ public: * @param width Line width. * @param dash Length of dashes for dashed lines. 0 means solid line. */ - virtual void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8 colour, int width, int dash = 0); + virtual void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8 colour, int width, int dash = 0) = 0; /** * Copy from a buffer to the screen. @@ -203,6 +203,8 @@ public: virtual void PostResize() { }; virtual ~Blitter() { } + + template void DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, int screen_height, int width, int dash, SetPixelT set_pixel); }; #endif /* BLITTER_BASE_HPP */ diff --git a/src/blitter/base.cpp b/src/blitter/common.hpp similarity index 86% rename from src/blitter/base.cpp rename to src/blitter/common.hpp index e83df2e714..0e255ca9a3 100644 --- a/src/blitter/base.cpp +++ b/src/blitter/common.hpp @@ -7,15 +7,16 @@ * 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 base.cpp Implementation of the base for all blitters. */ +/** @file common.hpp Common functionality for all blitter implementations. */ + +#ifndef BLITTER_COMMON_HPP +#define BLITTER_COMMON_HPP -#include "../stdafx.h" #include "base.hpp" #include "../core/math_func.hpp" -#include "../safeguards.h" - -void Blitter::DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8 colour, int width, int dash) +template +void Blitter::DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, int screen_height, int width, int dash, SetPixelT set_pixel) { int dy; int dx; @@ -40,7 +41,7 @@ void Blitter::DrawLine(void *video, int x, int y, int x2, int y2, int screen_wid if (dx == 0 && dy == 0) { /* The algorithm below cannot handle this special case; make it work at least for line width 1 */ - if (x >= 0 && x < screen_width && y >= 0 && y < screen_height) this->SetPixel(video, x, y, colour); + if (x >= 0 && x < screen_width && y >= 0 && y < screen_height) set_pixel(x, y); return; } @@ -83,7 +84,7 @@ void Blitter::DrawLine(void *video, int x, int y, int x2, int y2, int screen_wid while (x != x2) { if (dash_count < dash && x >= 0 && x < screen_width) { for (int y = y_low; y != y_high; y += stepy) { - if (y >= 0 && y < screen_height) this->SetPixel(video, x, y, colour); + if (y >= 0 && y < screen_height) set_pixel(x, y); } } if (frac_low >= 0) { @@ -118,7 +119,7 @@ void Blitter::DrawLine(void *video, int x, int y, int x2, int y2, int screen_wid while (y != y2) { if (dash_count < dash && y >= 0 && y < screen_height) { for (int x = x_low; x != x_high; x += stepx) { - if (x >= 0 && x < screen_width) this->SetPixel(video, x, y, colour); + if (x >= 0 && x < screen_width) set_pixel(x, y); } } if (frac_low >= 0) { @@ -136,3 +137,5 @@ void Blitter::DrawLine(void *video, int x, int y, int x2, int y2, int screen_wid } } } + +#endif /* BLITTER_COMMON_HPP */