Skip to content
Techniques & Technology

Dirty Rectangles

Efficient screen updates

Dirty rectangle rendering optimised screen updates by tracking and redrawing only the areas that changed, saving CPU cycles when most of the display remained static.

commodore-amigaibm-pccommodore-64 graphicsoptimisationrendering 1985–present

Overview

Why redraw the entire screen when only a small part changed? Dirty rectangle rendering tracks which screen regions have changed and redraws only those areas. For games with mostly static backgrounds and a handful of moving sprites — point-and-click adventures, strategy games, GUI applications — this dramatically reduces rendering work compared to redrawing every pixel every frame.

Dirty rectangles fall between double-buffering (full redraw, swap) and direct screen drawing (write while displaying, risk tearing). They give you tear-free output without the cost of touching unchanged pixels.

Fast facts

  • Purpose: Reduce unnecessary redrawing.
  • Method: Track changed screen regions as bounding rectangles.
  • Benefit: Lower CPU usage when most of the screen is static.
  • Best for: Static backgrounds with a few moving elements (adventures, GUIs, board games).
  • Worst for: Full-screen scrolling, particle systems, fast-moving full-screen action.

How it works

Each frame:

StepAction
1Mark previous sprite/object positions as "dirty"
2Mark new sprite/object positions as "dirty"
3Coalesce overlapping or adjacent dirty rects
4For each dirty rect: redraw the background, then any objects that overlap it
5Copy only the dirty rects from back buffer to front buffer (or to display)

The dirty list is typically a small array of (x, y, w, h) rectangles, regenerated every frame.

Tracking changes

Change typeDirty region
Sprite movedOld position + new position (often coalesced if they overlap)
Animation frame changeSprite bounding box at current position
Score / HUD updateScore display area
Background changeAffected tiles (e.g. a door opening)
Particle effectBounding box of all particles (or per-particle if scattered)

Rectangle operations

A small library of rectangle primitives suffices:

OperationPurpose
UnionCombine two overlapping rects into one bounding rect
IntersectionFind overlap area
ContainmentDoes rect A entirely contain rect B?
ClippingRestrict rect to within screen bounds
CoalescingMerge nearby rects whose union is cheaper than two separate updates

The coalescing decision is heuristic: merge if the union area is less than the sum of the individual areas plus some overhead, otherwise keep them separate.

Pseudo-code

dirty_list = []

each_frame:
    # Phase 1: erase and remember what was where
    for sprite in moving_sprites:
        if sprite.moved or sprite.animated:
            dirty_list.append(sprite.previous_bbox())
            dirty_list.append(sprite.current_bbox())

    # Phase 2: coalesce overlapping rects
    coalesce(dirty_list)

    # Phase 3: redraw each dirty rect
    for rect in dirty_list:
        clip rect to screen
        redraw_background(rect)
        for sprite in sprites_overlapping(rect):
            draw_sprite_clipped_to(sprite, rect)

    # Phase 4: blit dirty rects to display
    for rect in dirty_list:
        blit(back_buffer, display, rect)

Advantages

BenefitImpact
CPU savingsMore processing time available for game logic
Reduced flickerSmaller updates blit faster, lower chance of catching the raster mid-update
Memory bandwidthLess data moved per frame; matters on shared-memory systems (Amiga chip RAM)
Scales with activityIdle screens cost nothing to "render"

Limitations

DrawbackSituation
Tracking overheadBookkeeping is non-trivial; small rects don't pay back
Full-screen changesIf everything moves, dirty-rect costs more than full redraw
Many objectsCoalesce-and-redraw degenerates toward full-screen as object count rises
ScrollingThe whole screen is dirty every frame; no benefit
Z-orderingRectangles overlapping in depth need careful redraw order
Complex backgroundsBackground reconstruction must be cheap, or savings vanish

When to use

Game styleDirty rects?
Point-and-click adventures (Sierra, LucasArts)Yes — ideal use case
Strategy games with mostly static mapsYes
Board games, card gamesYes
GUI applications (Workbench, GEM, Windows 1-2)Yes — original motivating use case
Side-scrolling platformersNo — too much movement
Vertical-scrolling shootersNo
Action games with full-screen scrollNo
Particle-heavy effectsMarginal at best

Platform-specific notes

PlatformApplication
AmigaPoint-and-click adventures (Indiana Jones, Monkey Island, Beneath a Steel Sky); GUI applications
PC (pre-VGA)EGA-era games before fast hardware blits; Sierra and LucasArts ports
C64Less common — sprites are hardware, so the technique mostly applies to the playfield
GUI systemsThe Amiga Workbench, Atari ST GEM, early Windows all use dirty-rect updating
HTML5 CanvasModern web games still use this; Canvas's clearRect + redraw pattern is dirty-rect rendering

Modern relevance

Dirty rectangles remain alive in:

  • Web rendering — browsers track dirty regions for repaint optimisation.
  • Game engines — UI systems use dirty-rect updating (Unity UGUI, Unreal Slate).
  • GUI toolkits — Qt, GTK, AppKit/UIKit all use damage-region tracking under the hood.
  • Compositing window managers — every modern window manager tracks per-window damage rectangles.

The terminology has evolved (now "damage tracking" or "invalidation") but the core idea is unchanged from the 1980s.

See also