diff --git a/src/blitter/32bpp_anim.cpp b/src/blitter/32bpp_anim.cpp index 70869bd59a..5006305789 100644 --- a/src/blitter/32bpp_anim.cpp +++ b/src/blitter/32bpp_anim.cpp @@ -458,11 +458,7 @@ void Blitter_32bppAnim::ScrollBuffer(void *video, int &left, int &top, int &widt uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x); uint th = height - scroll_y; - for (; th > 0; th--) { - std::copy_n(src, tw, dst); - src -= this->anim_buf_pitch; - dst -= this->anim_buf_pitch; - } + Blitter::MovePixels(src, dst, tw, th, -this->anim_buf_pitch); } else { /* Calculate pointers */ dst = this->anim_buf + left + top * this->anim_buf_pitch; @@ -475,15 +471,9 @@ void Blitter_32bppAnim::ScrollBuffer(void *video, int &left, int &top, int &widt src -= scroll_x; } - /* the y-displacement may be 0 therefore we have to use memmove, - * because source and destination may overlap */ uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x); uint th = height + scroll_y; - for (; th > 0; th--) { - memmove(dst, src, tw * sizeof(uint16_t)); - src += this->anim_buf_pitch; - dst += this->anim_buf_pitch; - } + Blitter::MovePixels(src, dst, tw, th, this->anim_buf_pitch); } Blitter_32bppBase::ScrollBuffer(video, left, top, width, height, scroll_x, scroll_y); diff --git a/src/blitter/32bpp_base.cpp b/src/blitter/32bpp_base.cpp index 2895d4feba..5c25d4185f 100644 --- a/src/blitter/32bpp_base.cpp +++ b/src/blitter/32bpp_base.cpp @@ -106,11 +106,7 @@ void Blitter_32bppBase::ScrollBuffer(void *video, int &left, int &top, int &widt width += scroll_x; } - for (int h = height; h > 0; h--) { - std::copy_n(src, width, dst); - src -= _screen.pitch; - dst -= _screen.pitch; - } + Blitter::MovePixels(src, dst, width, height, -_screen.pitch); } else { /* Calculate pointers */ dst = (uint32_t *)video + left + top * _screen.pitch; @@ -130,13 +126,7 @@ void Blitter_32bppBase::ScrollBuffer(void *video, int &left, int &top, int &widt width += scroll_x; } - /* the y-displacement may be 0 therefore we have to use memmove, - * because source and destination may overlap */ - for (int h = height; h > 0; h--) { - memmove(dst, src, width * sizeof(uint32_t)); - src += _screen.pitch; - dst += _screen.pitch; - } + Blitter::MovePixels(src, dst, width, height, _screen.pitch); } } diff --git a/src/blitter/40bpp_anim.cpp b/src/blitter/40bpp_anim.cpp index 02df4be0a8..7ef8cd4ba8 100644 --- a/src/blitter/40bpp_anim.cpp +++ b/src/blitter/40bpp_anim.cpp @@ -493,11 +493,7 @@ void Blitter_40bppAnim::ScrollBuffer(void *video, int &left, int &top, int &widt uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x); uint th = height - scroll_y; - for (; th > 0; th--) { - std::copy_n(src, tw, dst); - src -= _screen.pitch; - dst -= _screen.pitch; - } + Blitter::MovePixels(src, dst, tw, th, -_screen.pitch); } else { /* Calculate pointers */ dst = anim_buf + left + top * _screen.pitch; @@ -510,15 +506,9 @@ void Blitter_40bppAnim::ScrollBuffer(void *video, int &left, int &top, int &widt src -= scroll_x; } - /* the y-displacement may be 0 therefore we have to use memmove, - * because source and destination may overlap */ uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x); uint th = height + scroll_y; - for (; th > 0; th--) { - memmove(dst, src, tw * sizeof(uint8_t)); - src += _screen.pitch; - dst += _screen.pitch; - } + Blitter::MovePixels(src, dst, tw, th, _screen.pitch); } Blitter_32bppBase::ScrollBuffer(video, left, top, width, height, scroll_x, scroll_y); diff --git a/src/blitter/8bpp_base.cpp b/src/blitter/8bpp_base.cpp index 131b9519da..db4e18b3fe 100644 --- a/src/blitter/8bpp_base.cpp +++ b/src/blitter/8bpp_base.cpp @@ -111,11 +111,7 @@ void Blitter_8bppBase::ScrollBuffer(void *video, int &left, int &top, int &width width += scroll_x; } - for (int h = height; h > 0; h--) { - std::copy_n(src, width, dst); - src -= _screen.pitch; - dst -= _screen.pitch; - } + Blitter::MovePixels(src, dst, width, height, -_screen.pitch); } else { /* Calculate pointers */ dst = (uint8_t *)video + left + top * _screen.pitch; @@ -135,13 +131,7 @@ void Blitter_8bppBase::ScrollBuffer(void *video, int &left, int &top, int &width width += scroll_x; } - /* the y-displacement may be 0 therefore we have to use memmove, - * because source and destination may overlap */ - for (int h = height; h > 0; h--) { - memmove(dst, src, width * sizeof(uint8_t)); - src += _screen.pitch; - dst += _screen.pitch; - } + Blitter::MovePixels(src, dst, width, height, _screen.pitch); } } diff --git a/src/blitter/base.hpp b/src/blitter/base.hpp index 7ee97a6c20..2a31d1d0b0 100644 --- a/src/blitter/base.hpp +++ b/src/blitter/base.hpp @@ -207,6 +207,8 @@ public: virtual ~Blitter() = default; template void DrawLineGeneric(int x, int y, int x2, int y2, int screen_width, int screen_height, int width, int dash, SetPixelT set_pixel); + + template static void MovePixels(const T *src, T *dst, size_t width, size_t height, ptrdiff_t pitch); }; #endif /* BLITTER_BASE_HPP */ diff --git a/src/blitter/common.hpp b/src/blitter/common.hpp index eebdfc05e7..6b36feb980 100644 --- a/src/blitter/common.hpp +++ b/src/blitter/common.hpp @@ -192,4 +192,24 @@ void Blitter::DrawLineGeneric(int x1, int y1, int x2, int y2, int screen_width, } } +template +/* static */ void Blitter::MovePixels(const T *src, T *dst, size_t width, size_t height, ptrdiff_t pitch) +{ + if (src == dst) return; + + if (src < dst) { + for (size_t i = 0; i < height; ++i) { + std::move_backward(src, src + width, dst + width); + src += pitch; + dst += pitch; + } + } else { + for (size_t i = 0; i < height; ++i) { + std::move(src, src + width, dst); + src += pitch; + dst += pitch; + } + } +} + #endif /* BLITTER_COMMON_HPP */