mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-04 13:42:55 +01:00
Rewrite ViewportRedrawAfterShift to avoid copying Viewport
This commit is contained in:
@@ -1181,7 +1181,7 @@ void OpenGLDrawingContext::HandleTransparency()
|
||||
void OpenGLDrawingContext::CalculcateClipping(DrawPixelInfo& dpi)
|
||||
{
|
||||
auto screenDPI = _engine.GetDPI();
|
||||
auto bytesPerRow = screenDPI->GetBytesPerRow();
|
||||
auto bytesPerRow = screenDPI->LineStride();
|
||||
auto bitsOffset = static_cast<size_t>(dpi.bits - screenDPI->bits);
|
||||
# ifndef NDEBUG
|
||||
auto bitsSize = static_cast<size_t>(screenDPI->ScreenHeight()) * bytesPerRow;
|
||||
|
||||
@@ -883,25 +883,20 @@ std::optional<PaletteMap> GetPaletteMapForColour(colour_t paletteId)
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
size_t DrawPixelInfo::GetBytesPerRow() const
|
||||
{
|
||||
return static_cast<size_t>(width) + pitch;
|
||||
}
|
||||
|
||||
uint8_t* DrawPixelInfo::GetBitsOffset(const ScreenCoordsXY& pos) const
|
||||
{
|
||||
return bits + pos.x + (pos.y * GetBytesPerRow());
|
||||
return bits + pos.x + pos.y * LineStride();
|
||||
}
|
||||
|
||||
DrawPixelInfo DrawPixelInfo::Crop(const ScreenCoordsXY& pos, const ScreenSize& size) const
|
||||
{
|
||||
DrawPixelInfo result = *this;
|
||||
result.bits = GetBitsOffset(pos);
|
||||
result.x = static_cast<int16_t>(pos.x);
|
||||
result.y = static_cast<int16_t>(pos.y);
|
||||
result.width = static_cast<int16_t>(size.width);
|
||||
result.height = static_cast<int16_t>(size.height);
|
||||
result.pitch = static_cast<int16_t>(width + pitch - size.width);
|
||||
result.x = pos.x;
|
||||
result.y = pos.y;
|
||||
result.width = size.width;
|
||||
result.height = size.height;
|
||||
result.pitch = width + pitch - size.width;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -1140,7 +1135,7 @@ void ToggleWindowedMode()
|
||||
Config::Save();
|
||||
}
|
||||
|
||||
void DebugDPI(DrawPixelInfo& dpi)
|
||||
void DebugDPI(const DrawPixelInfo& dpi)
|
||||
{
|
||||
DrawPixelInfo unzoomed = dpi;
|
||||
unzoomed.zoom_level = ZoomLevel{ 0 };
|
||||
@@ -1150,13 +1145,21 @@ void DebugDPI(DrawPixelInfo& dpi)
|
||||
unzoomed.SetHeight(dpi.ScreenHeight());
|
||||
|
||||
ScreenCoordsXY topLeft = { unzoomed.ScreenX(), unzoomed.ScreenY() };
|
||||
ScreenCoordsXY topRight = { unzoomed.ScreenX() + unzoomed.ScreenWidth() - 1, unzoomed.ScreenY() };
|
||||
ScreenCoordsXY bottomLeft = { unzoomed.ScreenX(), unzoomed.ScreenY() + unzoomed.ScreenHeight() - 1 };
|
||||
ScreenCoordsXY bottomRight = { unzoomed.ScreenX() + unzoomed.ScreenWidth() - 1,
|
||||
unzoomed.ScreenY() + unzoomed.ScreenHeight() - 1 };
|
||||
GfxDrawLine(unzoomed, { topLeft, bottomRight }, PALETTE_INDEX_129);
|
||||
ScreenCoordsXY topRight = { unzoomed.ScreenX() + unzoomed.ScreenWidth() - 1, unzoomed.ScreenY() };
|
||||
ScreenCoordsXY bottomLeft = { unzoomed.ScreenX(), unzoomed.ScreenY() + unzoomed.ScreenHeight() - 1 };
|
||||
|
||||
GfxDrawLine(unzoomed, { topLeft, bottomRight }, PALETTE_INDEX_136);
|
||||
GfxDrawLine(unzoomed, { bottomLeft, topRight }, PALETTE_INDEX_136);
|
||||
GfxDrawLine(unzoomed, { topLeft, topRight }, PALETTE_INDEX_129);
|
||||
GfxDrawLine(unzoomed, { topRight, bottomRight }, PALETTE_INDEX_129);
|
||||
GfxDrawLine(unzoomed, { bottomLeft, bottomRight }, PALETTE_INDEX_129);
|
||||
GfxDrawLine(unzoomed, { topLeft, bottomLeft }, PALETTE_INDEX_129);
|
||||
|
||||
GfxDrawLine(unzoomed, { topLeft, topLeft + ScreenCoordsXY{ 4, 0 } }, PALETTE_INDEX_136);
|
||||
|
||||
const auto str = std::to_string(dpi.ScreenX());
|
||||
DrawText(
|
||||
unzoomed, ScreenCoordsXY{ unzoomed.ScreenX(), unzoomed.ScreenY() }, { COLOUR_WHITE, FontStyle::Tiny }, str.c_str());
|
||||
}
|
||||
@@ -124,7 +124,6 @@ public:
|
||||
|
||||
OpenRCT2::Drawing::IDrawingEngine* DrawingEngine{};
|
||||
|
||||
size_t GetBytesPerRow() const;
|
||||
uint8_t* GetBitsOffset(const ScreenCoordsXY& pos) const;
|
||||
DrawPixelInfo Crop(const ScreenCoordsXY& pos, const ScreenSize& size) const;
|
||||
|
||||
@@ -685,6 +684,6 @@ void UpdatePaletteEffects();
|
||||
void RefreshVideo();
|
||||
void ToggleWindowedMode();
|
||||
|
||||
void DebugDPI(DrawPixelInfo& dpi);
|
||||
void DebugDPI(const DrawPixelInfo& dpi);
|
||||
|
||||
#include "NewDrawing.h"
|
||||
|
||||
@@ -326,115 +326,103 @@ CoordsXYZ ViewportAdjustForMapHeight(const ScreenCoordsXY& startCoords, uint8_t
|
||||
/*
|
||||
* rct2: 0x006E7FF3
|
||||
*/
|
||||
static void ViewportRedrawAfterShift(DrawPixelInfo& dpi, WindowBase* window, Viewport* viewport, const ScreenCoordsXY& coords)
|
||||
static void ViewportRedrawAfterShift(
|
||||
DrawPixelInfo& dpi, WindowBase* window, const WindowBase* originalWindow, const ScreenCoordsXY shift,
|
||||
const ScreenRect& drawRect)
|
||||
{
|
||||
// sub-divide by intersecting windows
|
||||
if (window != nullptr)
|
||||
{
|
||||
// skip current window and non-intersecting windows
|
||||
if (viewport == window->viewport || viewport->pos.x + viewport->width <= window->windowPos.x
|
||||
|| viewport->pos.x >= window->windowPos.x + window->width
|
||||
|| viewport->pos.y + viewport->height <= window->windowPos.y
|
||||
|| viewport->pos.y >= window->windowPos.y + window->height)
|
||||
if (window == originalWindow || drawRect.GetRight() <= window->windowPos.x
|
||||
|| drawRect.GetLeft() >= window->windowPos.x + window->width || drawRect.GetBottom() <= window->windowPos.y
|
||||
|| drawRect.GetTop() >= window->windowPos.y + window->height)
|
||||
{
|
||||
auto itWindowPos = WindowGetIterator(window);
|
||||
auto itNextWindow = itWindowPos != g_window_list.end() ? std::next(itWindowPos) : g_window_list.end();
|
||||
ViewportRedrawAfterShift(
|
||||
dpi, itNextWindow == g_window_list.end() ? nullptr : itNextWindow->get(), viewport, coords);
|
||||
dpi, itNextWindow == g_window_list.end() ? nullptr : itNextWindow->get(), originalWindow, shift, drawRect);
|
||||
return;
|
||||
}
|
||||
|
||||
// save viewport
|
||||
Viewport view_copy = *viewport;
|
||||
|
||||
if (viewport->pos.x < window->windowPos.x)
|
||||
if (drawRect.GetLeft() < window->windowPos.x)
|
||||
{
|
||||
viewport->width = window->windowPos.x - viewport->pos.x;
|
||||
ViewportRedrawAfterShift(dpi, window, viewport, coords);
|
||||
ScreenRect leftRect = { drawRect.Point1, { window->windowPos.x, drawRect.GetBottom() } };
|
||||
ViewportRedrawAfterShift(dpi, window, originalWindow, shift, leftRect);
|
||||
|
||||
viewport->pos.x += viewport->width;
|
||||
viewport->viewPos.x += viewport->zoom.ApplyTo(viewport->width);
|
||||
viewport->width = view_copy.width - viewport->width;
|
||||
ViewportRedrawAfterShift(dpi, window, viewport, coords);
|
||||
ScreenRect rightRect = { { window->windowPos.x, drawRect.GetTop() }, drawRect.Point2 };
|
||||
ViewportRedrawAfterShift(dpi, window, originalWindow, shift, rightRect);
|
||||
}
|
||||
else if (viewport->pos.x + viewport->width > window->windowPos.x + window->width)
|
||||
else if (drawRect.GetRight() > window->windowPos.x + window->width)
|
||||
{
|
||||
viewport->width = window->windowPos.x + window->width - viewport->pos.x;
|
||||
ViewportRedrawAfterShift(dpi, window, viewport, coords);
|
||||
ScreenRect leftRect = { drawRect.Point1, { window->windowPos.x + window->width, drawRect.GetBottom() } };
|
||||
ViewportRedrawAfterShift(dpi, window, originalWindow, shift, leftRect);
|
||||
|
||||
viewport->pos.x += viewport->width;
|
||||
viewport->viewPos.x += viewport->zoom.ApplyTo(viewport->width);
|
||||
viewport->width = view_copy.width - viewport->width;
|
||||
ViewportRedrawAfterShift(dpi, window, viewport, coords);
|
||||
ScreenRect rightRect = { { window->windowPos.x + window->width, drawRect.GetTop() }, drawRect.Point2 };
|
||||
ViewportRedrawAfterShift(dpi, window, originalWindow, shift, rightRect);
|
||||
}
|
||||
else if (viewport->pos.y < window->windowPos.y)
|
||||
else if (drawRect.GetTop() < window->windowPos.y)
|
||||
{
|
||||
viewport->height = window->windowPos.y - viewport->pos.y;
|
||||
ViewportRedrawAfterShift(dpi, window, viewport, coords);
|
||||
ScreenRect topRect = { drawRect.Point1, { drawRect.GetRight(), window->windowPos.y } };
|
||||
ViewportRedrawAfterShift(dpi, window, originalWindow, shift, topRect);
|
||||
|
||||
viewport->pos.y += viewport->height;
|
||||
viewport->viewPos.y += viewport->zoom.ApplyTo(viewport->height);
|
||||
viewport->height = view_copy.height - viewport->height;
|
||||
ViewportRedrawAfterShift(dpi, window, viewport, coords);
|
||||
ScreenRect bottomRect = { { drawRect.GetLeft(), window->windowPos.y }, drawRect.Point2 };
|
||||
ViewportRedrawAfterShift(dpi, window, originalWindow, shift, bottomRect);
|
||||
}
|
||||
else if (viewport->pos.y + viewport->height > window->windowPos.y + window->height)
|
||||
else if (drawRect.GetBottom() > window->windowPos.y + window->height)
|
||||
{
|
||||
viewport->height = window->windowPos.y + window->height - viewport->pos.y;
|
||||
ViewportRedrawAfterShift(dpi, window, viewport, coords);
|
||||
ScreenRect topRect = { drawRect.Point1, { drawRect.GetRight(), window->windowPos.y + window->height } };
|
||||
ViewportRedrawAfterShift(dpi, window, originalWindow, shift, topRect);
|
||||
|
||||
viewport->pos.y += viewport->height;
|
||||
viewport->viewPos.y += viewport->zoom.ApplyTo(viewport->height);
|
||||
viewport->height = view_copy.height - viewport->height;
|
||||
ViewportRedrawAfterShift(dpi, window, viewport, coords);
|
||||
ScreenRect bottomRect = { { drawRect.GetLeft(), window->windowPos.y + window->height }, drawRect.Point2 };
|
||||
ViewportRedrawAfterShift(dpi, window, originalWindow, shift, bottomRect);
|
||||
}
|
||||
|
||||
// restore viewport
|
||||
*viewport = view_copy;
|
||||
}
|
||||
else
|
||||
{
|
||||
auto left = viewport->pos.x;
|
||||
auto right = viewport->pos.x + viewport->width;
|
||||
auto top = viewport->pos.y;
|
||||
auto bottom = viewport->pos.y + viewport->height;
|
||||
auto left = drawRect.GetLeft();
|
||||
auto right = drawRect.GetRight();
|
||||
auto top = drawRect.GetTop();
|
||||
auto bottom = drawRect.GetBottom();
|
||||
|
||||
// if moved more than the viewport size
|
||||
if (abs(coords.x) < viewport->width && abs(coords.y) < viewport->height)
|
||||
// if moved more than the draw rectangle size
|
||||
if (abs(shift.x) < drawRect.GetWidth() && abs(shift.y) < drawRect.GetHeight())
|
||||
{
|
||||
// update whole block ?
|
||||
DrawingEngineCopyRect(viewport->pos.x, viewport->pos.y, viewport->width, viewport->height, coords.x, coords.y);
|
||||
DrawingEngineCopyRect(
|
||||
drawRect.GetLeft(), drawRect.GetTop(), drawRect.GetWidth(), drawRect.GetHeight(), shift.x, shift.y);
|
||||
|
||||
if (coords.x > 0)
|
||||
if (shift.x > 0)
|
||||
{
|
||||
// draw left
|
||||
auto _right = viewport->pos.x + coords.x;
|
||||
auto _right = left + shift.x;
|
||||
WindowDrawAll(dpi, left, top, _right, bottom);
|
||||
left += coords.x;
|
||||
left += shift.x;
|
||||
}
|
||||
else if (coords.x < 0)
|
||||
else if (shift.x < 0)
|
||||
{
|
||||
// draw right
|
||||
auto _left = viewport->pos.x + viewport->width + coords.x;
|
||||
auto _left = right + shift.x;
|
||||
WindowDrawAll(dpi, _left, top, right, bottom);
|
||||
right += coords.x;
|
||||
right += shift.x;
|
||||
}
|
||||
|
||||
if (coords.y > 0)
|
||||
if (shift.y > 0)
|
||||
{
|
||||
// draw top
|
||||
bottom = viewport->pos.y + coords.y;
|
||||
bottom = top + shift.y;
|
||||
WindowDrawAll(dpi, left, top, right, bottom);
|
||||
}
|
||||
else if (coords.y < 0)
|
||||
else if (shift.y < 0)
|
||||
{
|
||||
// draw bottom
|
||||
top = viewport->pos.y + viewport->height + coords.y;
|
||||
top = bottom + shift.y;
|
||||
WindowDrawAll(dpi, left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// redraw whole viewport
|
||||
// redraw whole draw rectangle
|
||||
WindowDrawAll(dpi, left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
@@ -442,6 +430,7 @@ static void ViewportRedrawAfterShift(DrawPixelInfo& dpi, WindowBase* window, Vie
|
||||
|
||||
static void ViewportShiftPixels(DrawPixelInfo& dpi, WindowBase* window, Viewport* viewport, int32_t x_diff, int32_t y_diff)
|
||||
{
|
||||
// This loop redraws all parts covered by transparent windows.
|
||||
auto it = WindowGetIterator(window);
|
||||
for (; it != g_window_list.end(); it++)
|
||||
{
|
||||
@@ -484,7 +473,9 @@ static void ViewportShiftPixels(DrawPixelInfo& dpi, WindowBase* window, Viewport
|
||||
WindowDrawAll(dpi, left, top, right, bottom);
|
||||
}
|
||||
|
||||
ViewportRedrawAfterShift(dpi, window, viewport, { x_diff, y_diff });
|
||||
ViewportRedrawAfterShift(
|
||||
dpi, window, window, { x_diff, y_diff },
|
||||
{ viewport->pos, { viewport->pos.x + viewport->width, viewport->pos.y + viewport->height } });
|
||||
}
|
||||
|
||||
static void ViewportMove(const ScreenCoordsXY& coords, WindowBase* w, Viewport* viewport)
|
||||
|
||||
@@ -174,7 +174,6 @@ struct Viewport
|
||||
// from its x, y, z
|
||||
[[nodiscard]] constexpr bool Contains(const ScreenCoordsXY& vpos) const
|
||||
{
|
||||
// TODO (mber), change to compare in screen space coords.
|
||||
return (
|
||||
vpos.y >= viewPos.y && vpos.y < viewPos.y + ViewHeight() && vpos.x >= viewPos.x
|
||||
&& vpos.x < viewPos.x + ViewWidth());
|
||||
|
||||
Reference in New Issue
Block a user