From 8212c83965f8766a0020097bdc7935ec6693ddaa Mon Sep 17 00:00:00 2001 From: Michael Bernardi Date: Tue, 17 Sep 2024 03:00:43 +1000 Subject: [PATCH] Rewrite ViewportPaint to handle new DPI coords --- .../engines/opengl/OpenGLDrawingEngine.cpp | 8 +- src/openrct2-ui/interface/Window.cpp | 4 +- src/openrct2-ui/windows/Main.cpp | 5 +- src/openrct2/interface/Screenshot.cpp | 2 +- src/openrct2/interface/Viewport.cpp | 115 +++++++----------- src/openrct2/interface/Viewport.h | 2 +- src/openrct2/ride/TrackDesign.cpp | 3 +- 7 files changed, 52 insertions(+), 87 deletions(-) diff --git a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp index a9566ec51f..5b80e51fe4 100644 --- a/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp +++ b/src/openrct2-ui/drawing/engines/opengl/OpenGLDrawingEngine.cpp @@ -707,10 +707,10 @@ void OpenGLDrawingContext::DrawSprite(DrawPixelInfo& dpi, const ImageId imageId, { DrawPixelInfo zoomedDPI; zoomedDPI.bits = dpi.bits; - zoomedDPI.SetX(dpi.zoom_level.ApplyInversedTo(dpi.WorldX()) / 2); - zoomedDPI.SetY(dpi.zoom_level.ApplyInversedTo(dpi.WorldY()) / 2); - zoomedDPI.SetHeight(dpi.zoom_level.ApplyInversedTo(dpi.WorldHeight()) / 2); - zoomedDPI.SetWidth(dpi.zoom_level.ApplyInversedTo(dpi.WorldWidth()) / 2); + zoomedDPI.SetX(dpi.ScreenX()); + zoomedDPI.SetY(dpi.ScreenY()); + zoomedDPI.SetHeight(dpi.ScreenHeight()); + zoomedDPI.SetWidth(dpi.ScreenWidth()); zoomedDPI.pitch = dpi.pitch; zoomedDPI.zoom_level = dpi.zoom_level - 1; DrawSprite(zoomedDPI, imageId.WithIndex(imageId.GetIndex() - g1Element->zoomed_offset), x >> 1, y >> 1); diff --git a/src/openrct2-ui/interface/Window.cpp b/src/openrct2-ui/interface/Window.cpp index 9d7d6df784..ffbacd67ba 100644 --- a/src/openrct2-ui/interface/Window.cpp +++ b/src/openrct2-ui/interface/Window.cpp @@ -1299,9 +1299,7 @@ namespace OpenRCT2::Ui::Windows */ void WindowDrawViewport(DrawPixelInfo& dpi, WindowBase& w) { - ViewportRender( - dpi, w.viewport, - { { dpi.ScreenX(), dpi.ScreenY() }, { dpi.ScreenX() + dpi.ScreenWidth(), dpi.ScreenY() + dpi.ScreenHeight() } }); + ViewportRender(dpi, w.viewport); } /** diff --git a/src/openrct2-ui/windows/Main.cpp b/src/openrct2-ui/windows/Main.cpp index 6cc1df8395..9a95880621 100644 --- a/src/openrct2-ui/windows/Main.cpp +++ b/src/openrct2-ui/windows/Main.cpp @@ -48,10 +48,7 @@ namespace OpenRCT2::Ui::Windows void OnDraw(DrawPixelInfo& dpi) override { - ViewportRender( - dpi, viewport, - { { dpi.ScreenX(), dpi.ScreenY() }, - { dpi.ScreenX() + dpi.ScreenWidth(), dpi.ScreenY() + dpi.ScreenHeight() } }); + ViewportRender(dpi, viewport); } private: diff --git a/src/openrct2/interface/Screenshot.cpp b/src/openrct2/interface/Screenshot.cpp index 44f334e426..91e7345ef7 100644 --- a/src/openrct2/interface/Screenshot.cpp +++ b/src/openrct2/interface/Screenshot.cpp @@ -319,7 +319,7 @@ static void RenderViewport(IDrawingEngine* drawingEngine, const Viewport& viewpo drawingEngine = tempDrawingEngine.get(); } dpi.DrawingEngine = drawingEngine; - ViewportRender(dpi, &viewport, { { 0, 0 }, { viewport.width, viewport.height } }); + ViewportRender(dpi, &viewport); } void ScreenshotGiant() diff --git a/src/openrct2/interface/Viewport.cpp b/src/openrct2/interface/Viewport.cpp index 1a07d0678f..1f6605e1c4 100644 --- a/src/openrct2/interface/Viewport.cpp +++ b/src/openrct2/interface/Viewport.cpp @@ -74,7 +74,7 @@ InteractionInfo::InteractionInfo(const PaintStruct* ps) } static void ViewportPaintWeatherGloom(DrawPixelInfo& dpi); -static void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const ScreenRect& screenRect); +static void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi); static void ViewportUpdateFollowSprite(WindowBase* window); static void ViewportUpdateSmartFollowEntity(WindowBase* window); static void ViewportUpdateSmartFollowStaff(WindowBase* window, const Staff& peep); @@ -925,20 +925,18 @@ void ViewportRotateAll(int32_t direction) * edi: dpi * ebp: bottom */ -void ViewportRender(DrawPixelInfo& dpi, const Viewport* viewport, const ScreenRect& screenRect) +void ViewportRender(DrawPixelInfo& dpi, const Viewport* viewport) { if (viewport->flags & VIEWPORT_FLAG_RENDERING_INHIBITED) return; - auto [topLeft, bottomRight] = screenRect; - - if (bottomRight.x <= viewport->pos.x) + if (dpi.ScreenX() + dpi.ScreenWidth() <= viewport->pos.x) return; - if (bottomRight.y <= viewport->pos.y) + if (dpi.ScreenY() + dpi.ScreenHeight() <= viewport->pos.y) return; - if (topLeft.x >= viewport->pos.x + viewport->width) + if (dpi.ScreenX() >= viewport->pos.x + viewport->width) return; - if (topLeft.y >= viewport->pos.y + viewport->height) + if (dpi.ScreenY() >= viewport->pos.y + viewport->height) return; #ifdef DEBUG_SHOW_DIRTY_BOX @@ -946,19 +944,7 @@ void ViewportRender(DrawPixelInfo& dpi, const Viewport* viewport, const ScreenRe const auto dirtyBoxTopRight = bottomRight - ScreenCoordsXY{ 1, 1 }; #endif - topLeft -= viewport->pos; - topLeft = ScreenCoordsXY{ - viewport->zoom.ApplyTo(std::max(topLeft.x, 0)), - viewport->zoom.ApplyTo(std::max(topLeft.y, 0)), - } + viewport->viewPos; - - bottomRight -= viewport->pos; - bottomRight = ScreenCoordsXY{ - viewport->zoom.ApplyTo(std::min(bottomRight.x, viewport->width)), - viewport->zoom.ApplyTo(std::min(bottomRight.y, viewport->height)), - } + viewport->viewPos; - - ViewportPaint(viewport, dpi, { topLeft, bottomRight }); + ViewportPaint(viewport, dpi); #ifdef DEBUG_SHOW_DIRTY_BOX // FIXME g_viewport_list doesn't exist anymore @@ -1016,47 +1002,28 @@ static void ViewportPaintColumn(PaintSession& session) * edi: dpi * ebp: bottom */ -static void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const ScreenRect& screenRect) +static void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi) { PROFILED_FUNCTION(); - const uint32_t viewFlags = viewport->flags; - if (viewFlags & VIEWPORT_FLAG_RENDERING_INHIBITED) - return; + const int32_t offsetX = dpi.ScreenX() - viewport->pos.x; + const int32_t offsetY = dpi.ScreenY() - viewport->pos.y; + const int32_t worldX = viewport->zoom.ApplyInversedTo(viewport->viewPos.x) + std::max(0, offsetX); + const int32_t worldY = viewport->zoom.ApplyInversedTo(viewport->viewPos.y) + std::max(0, offsetY); + const int32_t width = std::min(viewport->pos.x + viewport->width, dpi.ScreenX() + dpi.ScreenWidth()) + - std::max(viewport->pos.x, dpi.ScreenX()); + const int32_t height = std::min(viewport->pos.y + viewport->height, dpi.ScreenY() + dpi.ScreenHeight()) + - std::max(viewport->pos.y, dpi.ScreenY()); - uint32_t width = screenRect.GetWidth(); - uint32_t height = screenRect.GetHeight(); - // TODO: (mber) remove this masking code. - const uint32_t bitmask = viewport->zoom >= ZoomLevel{ 0 } ? 0xFFFFFFFF & (viewport->zoom.ApplyTo(0xFFFFFFFF)) : 0xFFFFFFFF; - ScreenCoordsXY topLeft = screenRect.Point1; - - width &= bitmask; - height &= bitmask; - topLeft.x &= bitmask; - topLeft.y &= bitmask; - - auto x = topLeft.x - static_cast(viewport->viewPos.x & bitmask); - x = viewport->zoom.ApplyInversedTo(x); - x += viewport->pos.x; - - auto y = topLeft.y - static_cast(viewport->viewPos.y & bitmask); - y = viewport->zoom.ApplyInversedTo(y); - y += viewport->pos.y; - - DrawPixelInfo dpi1; - dpi1.DrawingEngine = dpi.DrawingEngine; - dpi1.bits = dpi.bits + (x - dpi.ScreenX()) + ((y - dpi.ScreenY()) * dpi.LineStride()); - dpi1.SetX(viewport->zoom.ApplyInversedTo(topLeft.x)); - dpi1.SetY(viewport->zoom.ApplyInversedTo(topLeft.y)); - dpi1.SetWidth(viewport->zoom.ApplyInversedTo(width)); - dpi1.SetHeight(viewport->zoom.ApplyInversedTo(height)); - dpi1.pitch = dpi.LineStride() - viewport->zoom.ApplyInversedTo(width); - dpi1.zoom_level = viewport->zoom; - - // make sure, the compare operation is done in int32_t to avoid the loop becoming an infinite loop. - // this as well as the [x += 32] in the loop causes signed integer overflow -> undefined behaviour. - auto rightBorder = dpi1.WorldX() + dpi1.WorldWidth(); - auto alignedX = Floor2(dpi1.WorldX(), 32); + DrawPixelInfo worldDpi; + worldDpi.DrawingEngine = dpi.DrawingEngine; + worldDpi.bits = dpi.bits + std::max(0, -offsetX) + std::max(0, -offsetY) * dpi.LineStride(); + worldDpi.SetX(worldX); + worldDpi.SetY(worldY); + worldDpi.SetWidth(width); + worldDpi.SetHeight(height); + worldDpi.pitch = dpi.LineStride() - worldDpi.ScreenWidth(); + worldDpi.zoom_level = viewport->zoom; _paintColumns.clear(); @@ -1076,30 +1043,34 @@ static void ViewportPaint(const Viewport* viewport, DrawPixelInfo& dpi, const Sc useParallelDrawing = true; } + const int32_t columnWidth = worldDpi.zoom_level.ApplyInversedTo(kCoordsXYStep); + const int32_t rightBorder = worldDpi.ScreenX() + worldDpi.ScreenWidth(); + const int32_t alignedX = Floor2(worldDpi.ScreenX(), columnWidth); + // Generate and sort columns. - for (x = alignedX; x < rightBorder; x += 32) + for (int32_t x = alignedX; x < rightBorder; x += columnWidth) { - PaintSession* session = PaintSessionAlloc(dpi1, viewFlags, viewport->rotation); + PaintSession* session = PaintSessionAlloc(worldDpi, viewport->flags, viewport->rotation); _paintColumns.push_back(session); - DrawPixelInfo& dpi2 = session->DPI; - if (x >= dpi2.WorldX()) + DrawPixelInfo& columnDpi = session->DPI; + if (x >= columnDpi.ScreenX()) { - auto leftPitch = x - dpi2.WorldX(); - dpi2.SetWidth(dpi2.ScreenWidth() - dpi2.zoom_level.ApplyInversedTo(leftPitch)); - dpi2.bits += dpi2.zoom_level.ApplyInversedTo(leftPitch); - dpi2.pitch += dpi2.zoom_level.ApplyInversedTo(leftPitch); - dpi2.SetX(dpi2.zoom_level.ApplyInversedTo(x)); + const int32_t leftPitch = x - columnDpi.ScreenX(); + columnDpi.SetWidth(columnDpi.ScreenWidth() - leftPitch); + columnDpi.bits += leftPitch; + columnDpi.pitch += leftPitch; + columnDpi.SetX(x); } - auto paintRight = dpi2.WorldX() + dpi2.WorldWidth(); - if (paintRight >= x + 32) + int32_t paintRight = columnDpi.ScreenX() + columnDpi.ScreenWidth(); + if (paintRight >= x + columnWidth) { - auto rightPitch = paintRight - x - 32; + const int32_t rightPitch = paintRight - x - columnWidth; paintRight -= rightPitch; - dpi2.pitch += dpi2.zoom_level.ApplyInversedTo(rightPitch); + columnDpi.pitch += rightPitch; } - dpi2.SetWidth(dpi2.zoom_level.ApplyInversedTo(paintRight - dpi2.WorldX())); + columnDpi.SetWidth(paintRight - columnDpi.ScreenX()); if (useMultithreading) { diff --git a/src/openrct2/interface/Viewport.h b/src/openrct2/interface/Viewport.h index 087eaf9f48..17e2e94c89 100644 --- a/src/openrct2/interface/Viewport.h +++ b/src/openrct2/interface/Viewport.h @@ -140,7 +140,7 @@ void ViewportUpdatePosition(WindowBase* window); void ViewportUpdateSmartFollowGuest(WindowBase* window, const Guest& peep); void ViewportRotateSingle(WindowBase* window, int32_t direction); void ViewportRotateAll(int32_t direction); -void ViewportRender(DrawPixelInfo& dpi, const Viewport* viewport, const ScreenRect& screenRect); +void ViewportRender(DrawPixelInfo& dpi, const Viewport* viewport); CoordsXYZ ViewportAdjustForMapHeight(const ScreenCoordsXY& startCoords, uint8_t rotation); diff --git a/src/openrct2/ride/TrackDesign.cpp b/src/openrct2/ride/TrackDesign.cpp index 09af8ec60e..0c91b12c3a 100644 --- a/src/openrct2/ride/TrackDesign.cpp +++ b/src/openrct2/ride/TrackDesign.cpp @@ -2119,7 +2119,6 @@ void TrackDesignDrawPreview(TrackDesign& td, uint8_t* pixels) view.flags = VIEWPORT_FLAG_HIDE_BASE | VIEWPORT_FLAG_HIDE_ENTITIES; DrawPixelInfo dpi; - // dpi.zoom_level = zoom_level; // TODO (mber) this can be removed I think dpi.SetX(0); dpi.SetY(0); dpi.SetWidth(370); @@ -2135,7 +2134,7 @@ void TrackDesignDrawPreview(TrackDesign& td, uint8_t* pixels) { view.viewPos = Translate3DTo2DWithZ(i, centre) - offset; view.rotation = i; - ViewportRender(dpi, &view, { {}, ScreenCoordsXY{ size_x, size_y } }); + ViewportRender(dpi, &view); dpi.bits += kTrackPreviewImageSize; }