Implement partial parallelisation of non-map mode viewport rendering

This commit is contained in:
Jonathan G Rennison
2022-11-09 22:24:31 +00:00
parent 07b752fe69
commit 7685c36f35
12 changed files with 479 additions and 269 deletions

View File

@@ -33,6 +33,8 @@
#include "table/sprites.h"
#include "table/control_codes.h"
#include <atomic>
#include "safeguards.h"
byte _dirkeys; ///< 1 = left, 2 = up, 4 = right, 8 = down
@@ -114,7 +116,7 @@ int8 _font_zoom_cfg; ///< Font zoom level in config.
* @ingroup dirty
*/
extern uint _dirty_block_colour;
extern std::atomic<uint> _dirty_block_colour;
static bool _whole_screen_dirty = false;
bool _gfx_draw_active = false;
@@ -1052,18 +1054,18 @@ static BlitterMode GetBlitterMode(PaletteID pal)
* @param y Top coordinate of image in viewport, scaled by zoom
* @param sub If available, draw only specified part of the sprite
*/
void DrawSpriteViewport(const DrawPixelInfo *dpi, SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub)
void DrawSpriteViewport(const SpritePointerHolder &sprite_store, const DrawPixelInfo *dpi, SpriteID img, PaletteID pal, int x, int y, const SubSprite *sub)
{
GfxBlitterCtx ctx(_cur_dpi);
GfxBlitterCtx ctx(dpi);
SpriteID real_sprite = GB(img, 0, SPRITE_WIDTH);
if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) {
ctx.colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1;
GfxMainBlitterViewport(ctx, GetSprite(real_sprite, ST_NORMAL), x, y, BM_TRANSPARENT, sub, real_sprite);
ctx.colour_remap_ptr = sprite_store.GetRecolourSprite(GB(pal, 0, PALETTE_WIDTH)) + 1;
GfxMainBlitterViewport(ctx, sprite_store.GetSprite(real_sprite, ST_NORMAL), x, y, BM_TRANSPARENT, sub, real_sprite);
} else if (pal != PAL_NONE) {
if (HasBit(pal, PALETTE_TEXT_RECOLOUR)) {
ctx.SetColourRemap((TextColour)GB(pal, 0, PALETTE_WIDTH));
} else if (GB(pal, 0, PALETTE_WIDTH) != PAL_NONE) {
ctx.colour_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR) + 1;
ctx.colour_remap_ptr = sprite_store.GetRecolourSprite(GB(pal, 0, PALETTE_WIDTH)) + 1;
}
if (HasBit(pal, PALETTE_BRIGHTNESS_MODIFY)) {
int adjust = GB(pal, PALETTE_BRIGHTNESS_OFFSET, PALETTE_BRIGHTNESS_WIDTH);
@@ -1071,9 +1073,22 @@ void DrawSpriteViewport(const DrawPixelInfo *dpi, SpriteID img, PaletteID pal, i
int sign_bit = 1 << (PALETTE_BRIGHTNESS_WIDTH - 1);
ctx.sprite_brightness_adjust = (adjust ^ sign_bit) - sign_bit;
}
GfxMainBlitterViewport(ctx, GetSprite(real_sprite, ST_NORMAL), x, y, GetBlitterMode(pal), sub, real_sprite);
GfxMainBlitterViewport(ctx, sprite_store.GetSprite(real_sprite, ST_NORMAL), x, y, GetBlitterMode(pal), sub, real_sprite);
} else {
GfxMainBlitterViewport(ctx, GetSprite(real_sprite, ST_NORMAL), x, y, BM_NORMAL, sub, real_sprite);
GfxMainBlitterViewport(ctx, sprite_store.GetSprite(real_sprite, ST_NORMAL), x, y, BM_NORMAL, sub, real_sprite);
}
}
void PrepareDrawSpriteViewportSpriteStore(SpritePointerHolder &sprite_store, SpriteID img, PaletteID pal)
{
SpriteID real_sprite = GB(img, 0, SPRITE_WIDTH);
sprite_store.CacheSprite(real_sprite, ST_NORMAL);
if (HasBit(img, PALETTE_MODIFIER_TRANSPARENT)) {
sprite_store.CacheSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR);
} else if (pal != PAL_NONE) {
if (!HasBit(pal, PALETTE_TEXT_RECOLOUR) && GB(pal, 0, PALETTE_WIDTH) != PAL_NONE) {
sprite_store.CacheSprite(GB(pal, 0, PALETTE_WIDTH), ST_RECOLOUR);
}
}
}
@@ -1678,12 +1693,8 @@ static void DrawDirtyViewport(uint occlusion, int left, int top, int right, int
if (_game_mode == GM_MENU) {
RedrawScreenRect(left, top, right, bottom);
} else {
extern void ViewportDrawChk(Viewport *vp, int left, int top, int right, int bottom);
ViewportDrawChk(_dirty_viewport, left, top, right, bottom);
if (_dirty_viewport_disp_flags & (ND_SHADE_GREY | ND_SHADE_DIMMED)) {
GfxFillRect(left, top, right - 1, bottom - 1,
(_dirty_viewport_disp_flags & ND_SHADE_DIMMED) ? PALETTE_TO_TRANSPARENT : PALETTE_NEWSPAPER, FILLRECT_RECOLOUR);
}
extern void ViewportDrawChk(Viewport *vp, int left, int top, int right, int bottom, uint8 display_flags);
ViewportDrawChk(_dirty_viewport, left, top, right, bottom, _dirty_viewport_disp_flags);
VideoDriver::GetInstance()->MakeDirty(left, top, right - left, bottom - top);
}
}
@@ -1743,7 +1754,7 @@ void DrawDirtyBlocks()
DrawOverlappedWindowFlags flags = DOWF_MARK_DIRTY;
if (unlikely(HasBit(_gfx_debug_flags, GDF_SHOW_WINDOW_DIRTY))) {
flags |= DOWF_SHOW_DEBUG;
_dirty_block_colour++;
_dirty_block_colour.fetch_add(1, std::memory_order_relaxed);
}
DrawOverlappedWindowWithClipping(w, w->left, w->top, w->left + w->width, w->top + w->height, flags);
w->flags &= ~(WF_DIRTY | WF_WIDGETS_DIRTY);
@@ -1755,7 +1766,7 @@ void DrawDirtyBlocks()
DrawOverlappedWindowFlags flags = DOWF_MARK_DIRTY;
if (unlikely(HasBit(_gfx_debug_flags, GDF_SHOW_WIDGET_DIRTY))) {
flags |= DOWF_SHOW_DEBUG;
_dirty_block_colour++;
_dirty_block_colour.fetch_add(1, std::memory_order_relaxed);
}
DrawOverlappedWindowWithClipping(w, w->left + widget->pos_x, w->top + widget->pos_y, w->left + widget->pos_x + widget->current_x, w->top + widget->pos_y + widget->current_y, flags);
}
@@ -1883,8 +1894,9 @@ void DrawDirtyBlocks()
RedrawScreenRect(r.left, r.top, r.right, r.bottom);
}
if (unlikely(HasBit(_gfx_debug_flags, GDF_SHOW_RECT_DIRTY))) {
ViewportDoDrawProcessAllPending();
for (const Rect &r : _dirty_blocks) {
GfxFillRect(r.left, r.top, r.right, r.bottom, _string_colourmap[++_dirty_block_colour & 0xF], FILLRECT_CHECKER);
GfxFillRect(r.left, r.top, r.right, r.bottom, _string_colourmap[(_dirty_block_colour.fetch_add(1, std::memory_order_relaxed) + 1) & 0xF], FILLRECT_CHECKER);
}
}
}
@@ -1900,8 +1912,9 @@ void DrawDirtyBlocks()
}
_dirty_blocks.clear();
}
ViewportDoDrawProcessAllPending();
_gfx_draw_active = false;
++_dirty_block_colour;
_dirty_block_colour.fetch_add(1, std::memory_order_relaxed);
extern void ClearViewportCaches();
ClearViewportCaches();