diff options
-rw-r--r-- | src/core/geometry_func.cpp | 22 | ||||
-rw-r--r-- | src/core/geometry_func.hpp | 12 | ||||
-rw-r--r-- | src/video/sdl2_v.cpp | 38 |
3 files changed, 46 insertions, 26 deletions
diff --git a/src/core/geometry_func.cpp b/src/core/geometry_func.cpp index 89e70fb5b..dccef72ec 100644 --- a/src/core/geometry_func.cpp +++ b/src/core/geometry_func.cpp @@ -26,3 +26,25 @@ Dimension maxdim(const Dimension &d1, const Dimension &d2) d.height = std::max(d1.height, d2.height); return d; } + +/** + * Compute the bounding rectangle around two rectangles. + * @param r1 First rectangle. + * @param r2 Second rectangle. + * @return The bounding rectangle, the smallest rectangle that contains both arguments. + */ +Rect BoundingRect(const Rect &r1, const Rect &r2) +{ + /* If either the first or the second is empty, return the other. */ + if (IsEmptyRect(r1)) return r2; + if (IsEmptyRect(r2)) return r1; + + Rect r; + + r.top = std::min(r1.top, r2.top); + r.bottom = std::max(r1.bottom, r2.bottom); + r.left = std::min(r1.left, r2.left); + r.right = std::max(r1.right, r2.right); + + return r; +} diff --git a/src/core/geometry_func.hpp b/src/core/geometry_func.hpp index cd136488a..41df35945 100644 --- a/src/core/geometry_func.hpp +++ b/src/core/geometry_func.hpp @@ -14,4 +14,16 @@ Dimension maxdim(const Dimension &d1, const Dimension &d2); +/** + * Check if a rectangle is empty. + * @param r Rectangle to check. + * @return True if and only if the rectangle doesn't define space. + */ +static inline bool IsEmptyRect(const Rect &r) +{ + return (r.left | r.top | r.right | r.bottom) == 0; +} + +Rect BoundingRect(const Rect &r1, const Rect &r2); + #endif /* GEOMETRY_FUNC_HPP */ diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index ce6bbc93f..d41f79d54 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -17,6 +17,8 @@ #include "../progress.h" #include "../core/random_func.hpp" #include "../core/math_func.hpp" +#include "../core/mem_func.hpp" +#include "../core/geometry_func.hpp" #include "../fileio_func.h" #include "../framerate_type.h" #include "../window_func.h" @@ -54,19 +56,12 @@ static SDL_Palette *_sdl_palette; static bool _cursor_new_in_window = false; #endif -#define MAX_DIRTY_RECTS 100 -static SDL_Rect _dirty_rects[MAX_DIRTY_RECTS]; -static int _num_dirty_rects; +static Rect _dirty_rect; void VideoDriver_SDL::MakeDirty(int left, int top, int width, int height) { - if (_num_dirty_rects < MAX_DIRTY_RECTS) { - _dirty_rects[_num_dirty_rects].x = left; - _dirty_rects[_num_dirty_rects].y = top; - _dirty_rects[_num_dirty_rects].w = width; - _dirty_rects[_num_dirty_rects].h = height; - } - _num_dirty_rects++; + Rect r = {left, top, left + width, top + height}; + _dirty_rect = BoundingRect(_dirty_rect, r); } static void UpdatePalette() @@ -133,7 +128,7 @@ static void Paint() { PerformanceMeasurer framerate(PFE_VIDEO); - if (_num_dirty_rects == 0) return; + if (IsEmptyRect(_dirty_rect) && _cur_palette.count_dirty == 0) return; if (_cur_palette.count_dirty != 0) { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); @@ -156,23 +151,14 @@ static void Paint() _cur_palette.count_dirty = 0; } - if (_num_dirty_rects > MAX_DIRTY_RECTS) { - if (_sdl_surface != _sdl_real_surface) { - SDL_BlitSurface(_sdl_surface, nullptr, _sdl_real_surface, nullptr); - } + SDL_Rect r = { _dirty_rect.left, _dirty_rect.top, _dirty_rect.right - _dirty_rect.left, _dirty_rect.bottom - _dirty_rect.top }; - SDL_UpdateWindowSurface(_sdl_window); - } else { - if (_sdl_surface != _sdl_real_surface) { - for (int i = 0; i < _num_dirty_rects; i++) { - SDL_BlitSurface(_sdl_surface, &_dirty_rects[i], _sdl_real_surface, &_dirty_rects[i]); - } - } - - SDL_UpdateWindowSurfaceRects(_sdl_window, _dirty_rects, _num_dirty_rects); + if (_sdl_surface != _sdl_real_surface) { + SDL_BlitSurface(_sdl_surface, &r, _sdl_real_surface, &r); } + SDL_UpdateWindowSurfaceRects(_sdl_window, &r, 1); - _num_dirty_rects = 0; + MemSetT(&_dirty_rect, 0); } static void PaintThread() @@ -356,7 +342,7 @@ bool VideoDriver_SDL::CreateMainSurface(uint w, uint h, bool resize) * gotten smaller, reset our dirty rects. GameSizeChanged() a bit lower * will mark the whole screen dirty again anyway, but this time with the * new dimensions. */ - _num_dirty_rects = 0; + MemSetT(&_dirty_rect, 0); _screen.width = _sdl_surface->w; _screen.height = _sdl_surface->h; |