Port dirty block handling from JGRPP
This commit is contained in:
+98
-20
@@ -214,7 +214,7 @@ struct ViewportDrawer {
|
||||
citymania::TileHighlight cm_highlight;
|
||||
};
|
||||
|
||||
static bool MarkViewportDirty(const Viewport *vp, int left, int top, int right, int bottom);
|
||||
static bool MarkViewportDirty(Viewport *vp, int left, int top, int right, int bottom);
|
||||
|
||||
static ViewportDrawer _vd;
|
||||
|
||||
@@ -246,7 +246,7 @@ void DeleteWindowViewport(Window *w)
|
||||
if (w->viewport == nullptr) return;
|
||||
|
||||
delete w->viewport->overlay;
|
||||
free(w->viewport);
|
||||
delete w->viewport;
|
||||
w->viewport = nullptr;
|
||||
}
|
||||
|
||||
@@ -267,8 +267,9 @@ void InitializeWindowViewport(Window *w, int x, int y,
|
||||
{
|
||||
assert(w->viewport == nullptr);
|
||||
|
||||
ViewportData *vp = CallocT<ViewportData>(1);
|
||||
ViewportData *vp = new ViewportData();
|
||||
|
||||
vp->overlay = nullptr;
|
||||
vp->left = x + w->left;
|
||||
vp->top = y + w->top;
|
||||
vp->width = width;
|
||||
@@ -276,9 +277,13 @@ void InitializeWindowViewport(Window *w, int x, int y,
|
||||
|
||||
vp->zoom = static_cast<ZoomLevel>(Clamp(zoom, _settings_client.gui.zoom_min, _settings_client.gui.zoom_max));
|
||||
|
||||
vp->virtual_left = 0;
|
||||
vp->virtual_top = 0;
|
||||
vp->virtual_width = ScaleByZoom(width, zoom);
|
||||
vp->virtual_height = ScaleByZoom(height, zoom);
|
||||
|
||||
UpdateViewportSizeZoom(vp);
|
||||
|
||||
Point pt;
|
||||
|
||||
if (follow_flags & 0x80000000) {
|
||||
@@ -303,8 +308,6 @@ void InitializeWindowViewport(Window *w, int x, int y,
|
||||
vp->overlay = nullptr;
|
||||
|
||||
w->viewport = vp;
|
||||
vp->virtual_left = 0; // pt.x;
|
||||
vp->virtual_top = 0; // pt.y;
|
||||
}
|
||||
|
||||
static Point _vp_move_offs;
|
||||
@@ -375,6 +378,15 @@ static void DoSetViewportPosition(Window::IteratorToFront it, int left, int top,
|
||||
}
|
||||
}
|
||||
|
||||
inline void UpdateViewportDirtyBlockLeftMargin(Viewport *vp)
|
||||
{
|
||||
// if (vp->zoom >= ZOOM_LVL_DRAW_MAP) {
|
||||
// vp->dirty_block_left_margin = 0;
|
||||
// } else {
|
||||
vp->dirty_block_left_margin = UnScaleByZoomLower((-vp->virtual_left) & 127, vp->zoom);
|
||||
// }
|
||||
}
|
||||
|
||||
static void SetViewportPosition(Window *w, int x, int y)
|
||||
{
|
||||
Viewport *vp = w->viewport;
|
||||
@@ -385,6 +397,7 @@ static void SetViewportPosition(Window *w, int x, int y)
|
||||
|
||||
vp->virtual_left = x;
|
||||
vp->virtual_top = y;
|
||||
UpdateViewportDirtyBlockLeftMargin(vp);
|
||||
|
||||
/* Viewport is bound to its left top corner, so it must be rounded down (UnScaleByZoomLower)
|
||||
* else glitch described in FS#1412 will happen (offset by 1 pixel with zoom level > NORMAL)
|
||||
@@ -1234,8 +1247,8 @@ static void ViewportAddLandscape()
|
||||
* - Right column is column of upper_right (rounded up) and one column to the right.
|
||||
* Note: Integer-division does not round down for negative numbers, so ensure rounding with another increment/decrement.
|
||||
*/
|
||||
int left_column = (upper_left.y - upper_left.x) / (int)TILE_SIZE - 2;
|
||||
int right_column = (upper_right.y - upper_right.x) / (int)TILE_SIZE + 2;
|
||||
int left_column = DivTowardsNegativeInf(upper_left.y - upper_left.x, (int)TILE_SIZE) - 1;
|
||||
int right_column = DivTowardsPositiveInf(upper_right.y - upper_right.x, (int)TILE_SIZE) + 1;
|
||||
|
||||
int potential_bridge_height = ZOOM_LVL_BASE * TILE_HEIGHT * _settings_game.construction.max_bridge_height;
|
||||
|
||||
@@ -1243,7 +1256,7 @@ static void ViewportAddLandscape()
|
||||
* The first row that could possibly be visible is the row above upper_left (if it is at height 0).
|
||||
* Due to integer-division not rounding down for negative numbers, we need another decrement.
|
||||
*/
|
||||
int row = (upper_left.x + upper_left.y) / (int)TILE_SIZE - 2;
|
||||
int row = DivTowardsNegativeInf(upper_left.y + upper_left.x, (int)TILE_SIZE) - 1;
|
||||
bool last_row = false;
|
||||
for (; !last_row; row++) {
|
||||
last_row = true;
|
||||
@@ -1717,7 +1730,7 @@ static void ViewportDrawBoundingBoxes(const ParentSpriteToSortVector *psd)
|
||||
/**
|
||||
* Draw/colour the blocks that have been redrawn.
|
||||
*/
|
||||
static void ViewportDrawDirtyBlocks()
|
||||
void ViewportDrawDirtyBlocks()
|
||||
{
|
||||
Blitter *blitter = BlitterFactory::GetCurrentBlitter();
|
||||
const DrawPixelInfo *dpi = _cur_dpi;
|
||||
@@ -1789,8 +1802,8 @@ void ViewportDoDraw(const Viewport *vp, int left, int top, int right, int bottom
|
||||
_vd.dpi.pitch = old_dpi->pitch;
|
||||
_vd.last_child = nullptr;
|
||||
|
||||
int x = UnScaleByZoom(_vd.dpi.left - (vp->virtual_left & mask), vp->zoom) + vp->left;
|
||||
int y = UnScaleByZoom(_vd.dpi.top - (vp->virtual_top & mask), vp->zoom) + vp->top;
|
||||
int x = UnScaleByZoomLower(_vd.dpi.left - (vp->virtual_left & mask), vp->zoom) + vp->left;
|
||||
int y = UnScaleByZoomLower(_vd.dpi.top - (vp->virtual_top & mask), vp->zoom) + vp->top;
|
||||
|
||||
_vd.dpi.dst_ptr = BlitterFactory::GetCurrentBlitter()->MoveTo(old_dpi->dst_ptr, x - old_dpi->left, y - old_dpi->top);
|
||||
|
||||
@@ -1845,7 +1858,16 @@ void ViewportDoDraw(const Viewport *vp, int left, int top, int right, int bottom
|
||||
_vd.child_screen_sprites_to_draw.clear();
|
||||
}
|
||||
|
||||
static inline void ViewportDraw(const Viewport *vp, int left, int top, int right, int bottom)
|
||||
void ViewportDrawChk(const Viewport *vp, int left, int top, int right, int bottom) {
|
||||
ViewportDoDraw(vp,
|
||||
ScaleByZoom(left - vp->left, vp->zoom) + vp->virtual_left,
|
||||
ScaleByZoom(top - vp->top, vp->zoom) + vp->virtual_top,
|
||||
ScaleByZoom(right - vp->left, vp->zoom) + vp->virtual_left,
|
||||
ScaleByZoom(bottom - vp->top, vp->zoom) + vp->virtual_top
|
||||
);
|
||||
}
|
||||
|
||||
static inline void ViewportDraw(Viewport *vp, int left, int top, int right, int bottom)
|
||||
{
|
||||
if (right <= vp->left || bottom <= vp->top) return;
|
||||
|
||||
@@ -1859,6 +1881,8 @@ static inline void ViewportDraw(const Viewport *vp, int left, int top, int right
|
||||
if (top < vp->top) top = vp->top;
|
||||
if (bottom > vp->top + vp->height) bottom = vp->top + vp->height;
|
||||
|
||||
vp->is_drawn = true;
|
||||
|
||||
ViewportDoDraw(vp,
|
||||
ScaleByZoom(left - vp->left, vp->zoom) + vp->virtual_left,
|
||||
ScaleByZoom(top - vp->top, vp->zoom) + vp->virtual_top,
|
||||
@@ -1959,6 +1983,32 @@ void UpdateViewportPosition(Window *w)
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateViewportSizeZoom(Viewport *vp)
|
||||
{
|
||||
vp->dirty_blocks_per_column = CeilDiv(vp->height, vp->GetDirtyBlockHeight());
|
||||
vp->dirty_blocks_per_row = CeilDiv(vp->width, vp->GetDirtyBlockWidth());
|
||||
uint size = vp->dirty_blocks_per_row * vp->dirty_blocks_per_column;
|
||||
vp->dirty_blocks.assign(size, false);
|
||||
UpdateViewportDirtyBlockLeftMargin(vp);
|
||||
|
||||
// if (vp->zoom >= ZOOM_LVL_DRAW_MAP) {
|
||||
// memset(vp->map_draw_vehicles_cache.done_hash_bits, 0, sizeof(vp->map_draw_vehicles_cache.done_hash_bits));
|
||||
// vp->map_draw_vehicles_cache.vehicle_pixels.assign(vp->ScreenArea(), false);
|
||||
|
||||
// if (BlitterFactory::GetCurrentBlitter()->GetScreenDepth() == 32) {
|
||||
// vp->land_pixel_cache.assign(vp->ScreenArea() * 4, 0xD7);
|
||||
// } else {
|
||||
// vp->land_pixel_cache.assign(vp->ScreenArea(), 0xD7);
|
||||
// }
|
||||
// } else {
|
||||
// vp->map_draw_vehicles_cache.vehicle_pixels.clear();
|
||||
// vp->land_pixel_cache.clear();
|
||||
// vp->land_pixel_cache.shrink_to_fit();
|
||||
// }
|
||||
// vp->update_vehicles = true;
|
||||
// FillViewportCoverageRect();
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a viewport as dirty for repaint if it displays (a part of) the area the needs to be repainted.
|
||||
* @param vp The viewport to mark as dirty
|
||||
@@ -1969,7 +2019,7 @@ void UpdateViewportPosition(Window *w)
|
||||
* @return true if the viewport contains a dirty block
|
||||
* @ingroup dirty
|
||||
*/
|
||||
static bool MarkViewportDirty(const Viewport *vp, int left, int top, int right, int bottom)
|
||||
static bool MarkViewportDirty(Viewport *vp, int left, int top, int right, int bottom)
|
||||
{
|
||||
/* Rounding wrt. zoom-out level */
|
||||
right += (1 << vp->zoom) - 1;
|
||||
@@ -1989,12 +2039,40 @@ static bool MarkViewportDirty(const Viewport *vp, int left, int top, int right,
|
||||
|
||||
if (top >= vp->virtual_height) return false;
|
||||
|
||||
AddDirtyBlock(
|
||||
UnScaleByZoomLower(left, vp->zoom) + vp->left,
|
||||
UnScaleByZoomLower(top, vp->zoom) + vp->top,
|
||||
UnScaleByZoom(right, vp->zoom) + vp->left + 1,
|
||||
UnScaleByZoom(bottom, vp->zoom) + vp->top + 1
|
||||
);
|
||||
uint x = std::max<int>(0, UnScaleByZoomLower(left, vp->zoom) - vp->dirty_block_left_margin) >> vp->GetDirtyBlockWidthShift();
|
||||
uint y = UnScaleByZoomLower(top, vp->zoom) >> vp->GetDirtyBlockHeightShift();
|
||||
uint w = (std::max<int>(0, UnScaleByZoomLower(right, vp->zoom) - 1 - vp->dirty_block_left_margin) >> vp->GetDirtyBlockWidthShift()) + 1 - x;
|
||||
uint h = ((UnScaleByZoom(bottom, vp->zoom) - 1) >> vp->GetDirtyBlockHeightShift()) + 1 - y;
|
||||
|
||||
// TODO somehow not needed in jgrpp
|
||||
assert(x < vp->dirty_blocks_per_row);
|
||||
assert(y < vp->dirty_blocks_per_column);
|
||||
h -= std::max((int)y + (int)h - (int)vp->dirty_blocks_per_column, 0);
|
||||
w -= std::max((int)x + (int)w - (int)vp->dirty_blocks_per_row, 0);
|
||||
|
||||
uint column_skip = vp->dirty_blocks_per_column - h;
|
||||
uint pos = (x * vp->dirty_blocks_per_column) + y;
|
||||
for (uint i = 0; i < w; i++) {
|
||||
for (uint j = 0; j < h; j++) {
|
||||
vp->dirty_blocks[pos] = true;
|
||||
pos++;
|
||||
}
|
||||
pos += column_skip;
|
||||
}
|
||||
vp->is_dirty = true;
|
||||
|
||||
/*if (unlikely(vp->zoom >= ZOOM_LVL_DRAW_MAP && !(flags & VMDF_NOT_LANDSCAPE))) {
|
||||
uint l = UnScaleByZoomLower(left, vp->zoom);
|
||||
uint t = UnScaleByZoomLower(top, vp->zoom);
|
||||
uint w = UnScaleByZoom(right, vp->zoom) - l;
|
||||
uint h = UnScaleByZoom(bottom, vp->zoom) - t;
|
||||
uint bitdepth = BlitterFactory::GetCurrentBlitter()->GetScreenDepth() / 8;
|
||||
uint8 *land_cache = vp->land_pixel_cache.data() + ((l + (t * vp->width)) * bitdepth);
|
||||
while (--h) {
|
||||
memset(land_cache, 0xD7, (size_t)w * bitdepth);
|
||||
land_cache += vp->width * bitdepth;
|
||||
}
|
||||
}*/
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -2012,7 +2090,7 @@ bool MarkAllViewportsDirty(int left, int top, int right, int bottom)
|
||||
{
|
||||
bool dirty = false;
|
||||
|
||||
for (const Window *w : Window::Iterate()) {
|
||||
for (Window *w : Window::Iterate()) {
|
||||
Viewport *vp = w->viewport;
|
||||
if (vp != nullptr) {
|
||||
assert(vp->width != 0);
|
||||
|
||||
Reference in New Issue
Block a user