diff --git a/src/drawing/IDrawingEngine.h b/src/drawing/IDrawingEngine.h index 42177ac10c..7ccd5d3ef0 100644 --- a/src/drawing/IDrawingEngine.h +++ b/src/drawing/IDrawingEngine.h @@ -43,9 +43,11 @@ interface IDrawingEngine virtual void Invalidate(sint32 left, sint32 top, sint32 right, sint32 bottom) abstract; virtual void Draw() abstract; + virtual void CopyRect(sint32 x, sint32 y, sint32 width, sint32 height, sint32 dx, sint32 dy) abstract; virtual sint32 Screenshot() abstract; - virtual IDrawingContext * GetDrawingContext(rct_drawpixelinfo * dpi) abstract; + virtual IDrawingContext * GetDrawingContext(rct_drawpixelinfo * dpi) abstract; + virtual rct_drawpixelinfo * GetDrawingPixelInfo() abstract; virtual DRAWING_ENGINE_FLAGS GetFlags() abstract; }; diff --git a/src/drawing/NewDrawing.cpp b/src/drawing/NewDrawing.cpp index b1434c9c99..afdf52dea7 100644 --- a/src/drawing/NewDrawing.cpp +++ b/src/drawing/NewDrawing.cpp @@ -60,12 +60,26 @@ extern "C" _drawingEngine->Draw(); } + void drawing_engine_copy_rect(int x, int y, int width, int height, int dx, int dy) + { + if (_drawingEngine != nullptr) + { + _drawingEngine->CopyRect(x, y, width, height, dx, dy); + } + } + void drawing_engine_dispose() { delete _drawingEngine; _drawingEngine = nullptr; } + rct_drawpixelinfo * drawing_engine_get_dpi() + { + assert(_drawingEngine != nullptr); + return _drawingEngine->GetDrawingPixelInfo(); + } + bool drawing_engine_has_dirty_optimisations() { bool result = false; diff --git a/src/drawing/NewDrawing.h b/src/drawing/NewDrawing.h index 597baea001..164dc5dde0 100644 --- a/src/drawing/NewDrawing.h +++ b/src/drawing/NewDrawing.h @@ -25,8 +25,10 @@ void drawing_engine_init(); void drawing_engine_resize(); void drawing_engine_set_palette(SDL_Color * colours); void drawing_engine_draw(); +void drawing_engine_copy_rect(int x, int y, int width, int height, int dx, int dy); void drawing_engine_dispose(); +rct_drawpixelinfo * drawing_engine_get_dpi(); bool drawing_engine_has_dirty_optimisations(); #ifdef _cplusplus diff --git a/src/drawing/drawing.c b/src/drawing/drawing.c index 4d911275f7..9c9b973a7c 100644 --- a/src/drawing/drawing.c +++ b/src/drawing/drawing.c @@ -27,8 +27,6 @@ int gLastDrawStringX; int gLastDrawStringY; -rct_drawpixelinfo gScreenDPI; - uint8 gGamePalette[256 * 4]; uint32 gPaletteEffectFrame; @@ -177,17 +175,15 @@ void gfx_invalidate_screen() * right (dx) * bottom (bp) */ -void gfx_redraw_screen_rect(short left, short top, short right, short bottom) +void window_draw_all(rct_drawpixelinfo *dpi, short left, short top, short right, short bottom) { - rct_drawpixelinfo *screenDPI = &gScreenDPI; - rct_drawpixelinfo windowDPI; - windowDPI.bits = screenDPI->bits + left + ((screenDPI->width + screenDPI->pitch) * top); + windowDPI.bits = dpi->bits + left + ((dpi->width + dpi->pitch) * top); windowDPI.x = left; windowDPI.y = top; windowDPI.width = right - left; windowDPI.height = bottom - top; - windowDPI.pitch = screenDPI->width + screenDPI->pitch + left - right; + windowDPI.pitch = dpi->width + dpi->pitch + left - right; windowDPI.zoom_level = 0; for (rct_window *w = g_window_list; w < gWindowNextSlot; w++) { diff --git a/src/drawing/drawing.h b/src/drawing/drawing.h index c81e487a35..d05931d966 100644 --- a/src/drawing/drawing.h +++ b/src/drawing/drawing.h @@ -113,13 +113,10 @@ extern sint32 gPickupPeepY; extern rct_g1_element *g1Elements; extern rct_gx g2; -extern rct_drawpixelinfo gScreenDPI; - // bool clip_drawpixelinfo(rct_drawpixelinfo *dst, rct_drawpixelinfo *src, int x, int y, int width, int height); void gfx_set_dirty_blocks(sint16 left, sint16 top, sint16 right, sint16 bottom); void gfx_draw_all_dirty_blocks(); -void gfx_redraw_screen_rect(short left, short top, short right, short bottom); void gfx_invalidate_screen(); // palette diff --git a/src/drawing/engines/OpenGLDrawingEngine.cpp b/src/drawing/engines/OpenGLDrawingEngine.cpp index 65f7063146..1d601a6322 100644 --- a/src/drawing/engines/OpenGLDrawingEngine.cpp +++ b/src/drawing/engines/OpenGLDrawingEngine.cpp @@ -180,7 +180,7 @@ public: intro_draw(&_bitsDPI); } else { window_update_all_viewports(); - gfx_redraw_screen_rect(0, 0, _width - 1, _height - 1); + window_draw_all(&_bitsDPI, 0, 0, _width - 1, _height - 1); window_update_all(); gfx_draw_pickedup_peep(&_bitsDPI); @@ -196,12 +196,22 @@ public: return -1; } + void CopyRect(sint32 x, sint32 y, sint32 width, sint32 height, sint32 dx, sint32 dy) override + { + // Not applicable for this engine + } + IDrawingContext * GetDrawingContext(rct_drawpixelinfo * dpi) override { _drawingContext->SetDPI(dpi); return _drawingContext; } + rct_drawpixelinfo * GetDrawingPixelInfo() override + { + return &_bitsDPI; + } + DRAWING_ENGINE_FLAGS GetFlags() override { return DEF_NONE; @@ -262,8 +272,6 @@ private: dpi->width = width; dpi->height = height; dpi->pitch = _pitch - width; - - gScreenDPI = *dpi; } void Display() diff --git a/src/drawing/engines/SoftwareDrawingEngine.cpp b/src/drawing/engines/SoftwareDrawingEngine.cpp index ed472f4b51..9da30a42e6 100644 --- a/src/drawing/engines/SoftwareDrawingEngine.cpp +++ b/src/drawing/engines/SoftwareDrawingEngine.cpp @@ -316,6 +316,45 @@ public: Display(); } + void CopyRect(sint32 x, sint32 y, sint32 width, sint32 height, sint32 dx, sint32 dy) override + { + if (dx == 0 && dy == 0) return; + + // Originally 0x00683359 + // Adjust for move off screen + // NOTE: when zooming, there can be x, y, dx, dy combinations that go off the + // screen; hence the checks. This code should ultimately not be called when + // zooming because this function is specific to updating the screen on move + int lmargin = Math::Min(x - dx, 0); + int rmargin = Math::Min((sint32)_width - (x - dx + width), 0); + int tmargin = Math::Min(y - dy, 0); + int bmargin = Math::Min((sint32)_height - (y - dy + height), 0); + x -= lmargin; + y -= tmargin; + width += lmargin + rmargin; + height += tmargin + bmargin; + + sint32 stride = _bitsDPI.width + _bitsDPI.pitch; + uint8 * to = _bitsDPI.bits + y * stride + x; + uint8 * from = _bitsDPI.bits + (y - dy) * stride + x - dx; + + if (dy > 0) + { + // If positive dy, reverse directions + to += (height - 1) * stride; + from += (height - 1) * stride; + stride = -stride; + } + + // Move bytes + for (int i = 0; i < height; i++) + { + memmove(to, from, width); + to += stride; + from += stride; + } + } + sint32 Screenshot() override { return screenshot_dump_png(&_bitsDPI); @@ -327,6 +366,11 @@ public: return _drawingContext; } + rct_drawpixelinfo * GetDrawingPixelInfo() override + { + return &_bitsDPI; + } + DRAWING_ENGINE_FLAGS GetFlags() override { return DEF_DIRTY_OPTIMISATIONS; @@ -388,8 +432,6 @@ private: dpi->height = height; dpi->pitch = _pitch - width; - gScreenDPI = *dpi; - ConfigureDirtyGrid(); } @@ -480,7 +522,7 @@ private: } // Draw region - gfx_redraw_screen_rect(left, top, right, bottom); + window_draw_all(&_bitsDPI, left, top, right, bottom); } void Display() diff --git a/src/interface/viewport.c b/src/interface/viewport.c index d45a31d4fa..456307bfa7 100644 --- a/src/interface/viewport.c +++ b/src/interface/viewport.c @@ -224,58 +224,7 @@ void sub_683326(int left, int top, int right, int bottom) RCT2_CALLPROC_X(0x00683359, left, top, right, bottom, 0, 0, 0); } -/** - * shifts pixels from the region in a direction. Used when a viewport moves; - * consider putting in src/drawing/drawing.c or src/drawing/rect.c - * - * rct2: 0x00683359 - * ax = x - * bx = y; - * cx = width; - * dx = height; - * di = dx; - * si = dy; - */ -void gfx_move_screen_rect(int x, int y, int width, int height, int dx, int dy) -{ - // nothing to do - if (dx == 0 && dy == 0) - return; - - // get screen info - rct_drawpixelinfo *screenDPI = &gScreenDPI; - - // adjust for move off screen - // NOTE: when zooming, there can be x, y, dx, dy combinations that go off the - // screen; hence the checks. This code should ultimately not be called when - // zooming because this function is specific to updating the screen on move - int lmargin = min(x - dx, 0); - int rmargin = min(gScreenWidth - (x - dx + width), 0); - int tmargin = min(y - dy, 0); - int bmargin = min(gScreenHeight - (y - dy + height), 0); - x -= lmargin; - y -= tmargin; - width += lmargin + rmargin; - height += tmargin + bmargin; - - sint32 stride = screenDPI->width + screenDPI->pitch; - uint8* to = screenDPI->bits + y * stride + x; - uint8* from = screenDPI->bits + (y - dy) * stride + x - dx; - - if (dy > 0) - { - // if positive dy, reverse directions - to += (height - 1) * stride; - from += (height - 1) * stride; - stride = -stride; - } - - // move bits - for (int i = 0; i < height; i++, to += stride, from += stride) - memmove(to, from, width); -} - -void sub_6E7FF3(rct_window *window, rct_viewport *viewport, int x, int y) +void sub_6E7FF3(rct_drawpixelinfo *dpi, rct_window *window, rct_viewport *viewport, int x, int y) { // sub-divide by intersecting windows if (window < gWindowNextSlot) @@ -286,7 +235,7 @@ void sub_6E7FF3(rct_window *window, rct_viewport *viewport, int x, int y) viewport->x >= window->x + window->width || viewport->y + viewport->height <= window->y || viewport->y >= window->y + window->height){ - sub_6E7FF3(window + 1, viewport, x, y); + sub_6E7FF3(dpi, window + 1, viewport, x, y); return; } @@ -298,49 +247,49 @@ void sub_6E7FF3(rct_window *window, rct_viewport *viewport, int x, int y) { viewport->width = window->x - viewport->x; viewport->view_width = viewport->width << viewport->zoom; - sub_6E7FF3(window, viewport, x, y); + sub_6E7FF3(dpi, window, viewport, x, y); viewport->x += viewport->width; viewport->view_x += viewport->width << viewport->zoom; viewport->width = view_copy.width - viewport->width; viewport->view_width = viewport->width << viewport->zoom; - sub_6E7FF3(window, viewport, x, y); + sub_6E7FF3(dpi, window, viewport, x, y); } else if (viewport->x + viewport->width > window->x + window->width) { viewport->width = window->x + window->width - viewport->x; viewport->view_width = viewport->width << viewport->zoom; - sub_6E7FF3(window, viewport, x, y); + sub_6E7FF3(dpi, window, viewport, x, y); viewport->x += viewport->width; viewport->view_x += viewport->width << viewport->zoom; viewport->width = view_copy.width - viewport->width; viewport->view_width = viewport->width << viewport->zoom; - sub_6E7FF3(window, viewport, x, y); + sub_6E7FF3(dpi, window, viewport, x, y); } else if (viewport->y < window->y) { viewport->height = window->y - viewport->y; viewport->view_width = viewport->width << viewport->zoom; - sub_6E7FF3(window, viewport, x, y); + sub_6E7FF3(dpi, window, viewport, x, y); viewport->y += viewport->height; viewport->view_y += viewport->height << viewport->zoom; viewport->height = view_copy.height - viewport->height; viewport->view_width = viewport->width << viewport->zoom; - sub_6E7FF3(window, viewport, x, y); + sub_6E7FF3(dpi, window, viewport, x, y); } else if (viewport->y + viewport->height > window->y + window->height) { viewport->height = window->y + window->height - viewport->y; viewport->view_width = viewport->width << viewport->zoom; - sub_6E7FF3(window, viewport, x, y); + sub_6E7FF3(dpi, window, viewport, x, y); viewport->y += viewport->height; viewport->view_y += viewport->height << viewport->zoom; viewport->height = view_copy.height - viewport->height; viewport->view_width = viewport->width << viewport->zoom; - sub_6E7FF3(window, viewport, x, y); + sub_6E7FF3(dpi, window, viewport, x, y); } // restore viewport @@ -357,20 +306,20 @@ void sub_6E7FF3(rct_window *window, rct_viewport *viewport, int x, int y) if (abs(x) < viewport->width && abs(y) < viewport->height) { // update whole block ? - gfx_move_screen_rect(viewport->x, viewport->y, viewport->width, viewport->height, x, y); + drawing_engine_copy_rect(viewport->x, viewport->y, viewport->width, viewport->height, x, y); if (x > 0) { // draw left sint16 _right = viewport->x + x; - gfx_redraw_screen_rect(left, top, _right, bottom); + window_draw_all(dpi, left, top, _right, bottom); left += x; } else if (x < 0) { // draw right sint16 _left = viewport->x + viewport->width + x; - gfx_redraw_screen_rect(_left, top, right, bottom); + window_draw_all(dpi, _left, top, right, bottom); right += x; } @@ -378,24 +327,24 @@ void sub_6E7FF3(rct_window *window, rct_viewport *viewport, int x, int y) { // draw top bottom = viewport->y + y; - gfx_redraw_screen_rect(left, top, right, bottom); + window_draw_all(dpi, left, top, right, bottom); } else if (y < 0) { // draw bottom top = viewport->y + viewport->height + y; - gfx_redraw_screen_rect(left, top, right, bottom); + window_draw_all(dpi, left, top, right, bottom); } } else { // redraw whole viewport - gfx_redraw_screen_rect(left, top, right, bottom); + window_draw_all(dpi, left, top, right, bottom); } } } -void viewport_shift_pixels(rct_window* w, rct_viewport* viewport, sint16 x_diff, sint16 y_diff) +void viewport_shift_pixels(rct_drawpixelinfo *dpi, rct_window* w, rct_viewport* viewport, sint16 x_diff, sint16 y_diff) { rct_window* orignal_w = w; int left = 0, right = 0, top = 0, bottom = 0; @@ -424,11 +373,11 @@ void viewport_shift_pixels(rct_window* w, rct_viewport* viewport, sint16 x_diff, if (left >= right) continue; if (top >= bottom) continue; - gfx_redraw_screen_rect(left, top, right, bottom); + window_draw_all(dpi, left, top, right, bottom); } w = orignal_w; - sub_6E7FF3(w, viewport, x_diff, y_diff); + sub_6E7FF3(dpi, w, viewport, x_diff, y_diff); } void viewport_move(sint16 x, sint16 y, rct_window* w, rct_viewport* viewport) @@ -456,8 +405,11 @@ void viewport_move(sint16 x, sint16 y, rct_window* w, rct_viewport* viewport) if (left >= right) return; if (top >= bottom) return; - gfx_redraw_screen_rect(left, top, right, bottom); - return; + if (drawing_engine_has_dirty_optimisations()) { + rct_drawpixelinfo *dpi = drawing_engine_get_dpi(); + window_draw_all(dpi, left, top, right, bottom); + return; + } } rct_viewport view_copy; @@ -500,7 +452,8 @@ void viewport_move(sint16 x, sint16 y, rct_window* w, rct_viewport* viewport) } if (drawing_engine_has_dirty_optimisations()) { - viewport_shift_pixels(w, viewport, x_diff, y_diff); + rct_drawpixelinfo *dpi = drawing_engine_get_dpi(); + viewport_shift_pixels(dpi, w, viewport, x_diff, y_diff); } memcpy(viewport, &view_copy, sizeof(rct_viewport)); diff --git a/src/interface/window.h b/src/interface/window.h index 162a05bc6c..acdbe46d06 100644 --- a/src/interface/window.h +++ b/src/interface/window.h @@ -560,6 +560,7 @@ void window_zoom_out(rct_window *w); void window_show_textinput(rct_window *w, int widgetIndex, uint16 title, uint16 text, int value); void window_text_input_key(rct_window* w, int key); +void window_draw_all(rct_drawpixelinfo *dpi, short left, short top, short right, short bottom); void window_draw(rct_drawpixelinfo *dpi, rct_window *w, int left, int top, int right, int bottom); void window_draw_widgets(rct_window *w, rct_drawpixelinfo *dpi); void window_draw_viewport(rct_drawpixelinfo *dpi, rct_window *w);