Skip to content

Multi-Monitor Foundation: Multi-surface architecture refactoring #38

@dskvr

Description

@dskvr

Description

Critical foundational work for robust per-monitor configurations. Note: hyprlax already implements a shared EGL context with per-monitor Wayland layer surfaces. This issue now focuses on completing hotplug removal/cleanup, per-output frame scheduling, and a shared texture cache.

Current Status

  • Phase 0 (zero-config multi-monitor) completed ✅
  • Phase 0.5 (workspace abstraction) completed ✅
  • Currently using single surface architecture
  • Need refactoring to properly support multiple monitors
  • Multi-surface + shared EGL context implemented; remaining foundations: output removal + cleanup, per-monitor frame scheduling, texture cache, CLI monitor filters

Core Tasks

Monitor Data Structure Refactoring

  • Replace single monitor tracking with monitor list
  • Create monitor_instance_t structure with per-monitor state
  • Implement monitor list management (add, remove, find)
  • Create texture cache with thread-safe reference counting
  • Update hyprlax_context_t to use monitor list
  • Wire CLI monitor selection/exclusion to monitor list filtering (--monitor, --disable-monitor)

Wayland Platform Multi-Surface

  • Add wl_output listener for monitor hotplug (addition) events
  • Implement per-monitor surface creation (layer-shell per-output)
  • Handle output geometry and scale events
  • Add output removal cleanup (destroy per-monitor wl_surface, zwlr_layer_surface_v1, wl_egl_window, EGLSurface; remove from list)
  • Update registry_global to track outputs
  • Implement registry_global_remove to handle output removal and teardown
  • Remove or gate legacy single-surface paths behind USE_LEGACY

Shared EGL Context

  • Create egl_shared_t structure for shared context
  • Use renderer-managed single shared EGL context (GLES2) with helpers (gles2_create_monitor_surface, gles2_make_current)
  • Modify renderer init for single shared context
  • Implement per-monitor EGL surface creation
  • Add eglMakeCurrent management for surface switching
  • Ensure proper cleanup on monitor removal (destroy EGLSurface safely; unset current if needed)

Per-Output Frame Scheduling

  • Implement frame callback system per monitor (wl_surface_frame per monitor)
  • Modify main loop for non-blocking operation (drive via callbacks instead of global sleep)
  • Add per-monitor render scheduling (use monitor_should_render, callbacks, and per-monitor cadence)
  • Track frame timing per monitor (update last_frame_time on frame done; respect target_frame_time)
  • Handle mixed refresh rates properly (render each output at its own rate)

Why This Is Needed

Without this foundation, we cannot:

  • Properly render to multiple monitors independently under hotplug and mixed-refresh
  • Handle different refresh rates per monitor accurately
  • Support per-monitor configurations and monitor filters
  • Implement monitor groups or spanning wallpapers safely

Success Criteria

  • Multiple surfaces rendering simultaneously
  • No performance regression (maintain 144 FPS)
  • Proper cleanup on exit and on monitor removal
  • No memory leaks
  • Handle monitor hotplug correctly (add and remove)
  • Mixed refresh rates render correctly per output

References

Note

This is infrastructure work that enables the user-facing features described in issues #17#19.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions