dirty

package
v0.1.18 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 1, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package dirty provides dirty region tracking for efficient partial repaints.

The tracker collects rectangular areas of the widget tree that have changed and need repainting. It supports region merging to reduce the number of draw calls, and a full-repaint fallback when too many small regions accumulate.

This is an internal package used by the rendering loop. Widgets mark themselves as needing redraw via widget.WidgetBase.SetNeedsRedraw, and the Collector walks the tree to populate the tracker before each frame.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Collector

type Collector struct {
	// contains filtered or unexported fields
}

Collector walks the widget tree and collects dirty regions from widgets that have NeedsRedraw set. It populates a Tracker with the bounds of each dirty widget.

func NewCollector

func NewCollector(tracker *Tracker) *Collector

NewCollector creates a new Collector that writes dirty regions to the given tracker.

func (*Collector) Collect

func (c *Collector) Collect(root widget.Widget)

Collect walks the widget tree starting from root, adding the bounds of any widget with NeedsRedraw() == true to the tracker.

Widgets that do not implement the NeedsRedraw interface (i.e., they do not embed widget.WidgetBase) are treated as always dirty for safety, matching the behavior of widget.NeedsRedrawInTree.

Invisible widgets and their subtrees are skipped.

type Region

type Region struct {
	Bounds geometry.Rect
}

Region represents a rectangular area that needs repainting.

type Tracker

type Tracker struct {
	// contains filtered or unexported fields
}

Tracker collects and manages dirty regions for a frame.

Usage:

  1. Call Reset at frame start.
  2. Walk the widget tree with a Collector, which calls MarkDirty for each widget that needs redraw.
  3. Call Optimize to merge overlapping/nearby regions.
  4. Use DirtyRegions to get the list of areas to repaint, or IsEmpty to skip the frame entirely.

func NewTracker

func NewTracker() *Tracker

NewTracker creates a new dirty region tracker with default settings.

func NewTrackerWithOptions

func NewTrackerWithOptions(opts ...TrackerOption) *Tracker

NewTrackerWithOptions creates a new dirty region tracker with custom settings.

func (*Tracker) DirtyRegions

func (t *Tracker) DirtyRegions() []Region

DirtyRegions returns the optimized list of regions to repaint. The returned slice must not be modified by the caller.

func (*Tracker) FullRepaint

func (t *Tracker) FullRepaint(viewport geometry.Rect)

FullRepaint marks the entire viewport as dirty. This replaces any existing regions with a single viewport-sized region.

func (*Tracker) Intersects

func (t *Tracker) Intersects(bounds geometry.Rect) bool

Intersects checks if the given bounds intersect any dirty region. This is used by widgets during the draw pass to skip rendering when their bounds are entirely outside all dirty regions.

func (*Tracker) IsEmpty

func (t *Tracker) IsEmpty() bool

IsEmpty returns true if no regions are dirty, meaning the frame can be skipped.

func (*Tracker) MarkDirty

func (t *Tracker) MarkDirty(bounds geometry.Rect)

MarkDirty adds a rectangular area as dirty (needs repaint). Empty rectangles are ignored.

func (*Tracker) NeedsFullRepaint

func (t *Tracker) NeedsFullRepaint() bool

NeedsFullRepaint returns true if the number of dirty regions exceeds the maximum threshold, indicating a full repaint would be more efficient.

func (*Tracker) Optimize

func (t *Tracker) Optimize()

Optimize merges overlapping and nearby dirty regions to reduce draw calls.

The algorithm:

  1. Sort regions by Y then X for spatial locality.
  2. Repeatedly scan for pairs that overlap or have a gap smaller than the merge threshold, replacing them with their union.
  3. Repeat until no more merges are possible.

This trades a small amount of overdraw for fewer clip/draw cycles.

func (*Tracker) RegionCount

func (t *Tracker) RegionCount() int

RegionCount returns the current number of dirty regions.

func (*Tracker) Reset

func (t *Tracker) Reset()

Reset clears all dirty regions. Call at the start of each frame.

type TrackerOption

type TrackerOption func(*Tracker)

TrackerOption configures a Tracker.

func WithMaxRegions

func WithMaxRegions(n int) TrackerOption

WithMaxRegions sets the maximum number of dirty regions before falling back to a full-viewport repaint.

func WithMergeGap

func WithMergeGap(gap float32) TrackerOption

WithMergeGap sets the pixel gap threshold for merging nearby regions. Two regions separated by less than gap pixels are merged into their union.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL