1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
//! The [`Presenter`] trait: what a renderer crate implements to rasterize a
//! grid and present it to a window surface.
//!
//! `Presenter` is an [`Output`](retroglyph_core::backend::Output) supertrait plus
//! window-surface operations, with no input methods: the event loop
//! owns input, and [`WindowBackend`](crate::WindowBackend) forwards
//! translated events into its own queue instead.
//!
//! | Presenter | `present()` | `init_surface()` |
//! |---|---|---|
//! | `SoftwareRenderer` (retroglyph-software) | Copies pixel buffer to softbuffer surface | Creates `softbuffer::Context` + `Surface` |
//! | `WgpuRenderer` (future) | Submits render pass + presents swap chain | Creates `wgpu::Surface` + `Device` |
//! | `GlRenderer` (future) | Draws full-screen quad + swaps buffers | Creates GL context from the window |
//!
//! See the crate-level docs (`crate` root, "DPI, scale, and the resize contract" and
//! "Threading model" sections) for the physical-pixel/no-auto-scaling contract on
//! [`cell_size`](Presenter::cell_size), the sub-cell-remainder behavior on
//! [`resize_surface`](Presenter::resize_surface), and the single-threaded execution model
//! every `Presenter` implementation runs under.
use ;
use Output;
use Arc;
/// A window/display handle pair, as one trait.
///
/// Presenters receive [`raw-window-handle`](raw_window_handle) types, not a
/// concrete `winit::window::Window`: softbuffer, wgpu, and glutin all accept
/// these handles directly, so any windowing library that produces them can
/// drive the same presenter, and only this crate depends on winit itself.
///
/// `raw-window-handle` has no combined trait, and surface libraries need to
/// *own* the handle (softbuffer stores it for the surface's lifetime), so
/// presenters receive `Arc<dyn WindowHandle>` -- rwh implements the handle
/// traits for `Arc<H: ?Sized>`, so the trait object passes straight into
/// `softbuffer::Surface::new` / `wgpu::Instance::create_surface`.
/// A surface-lifecycle error that can optionally signal whether it's worth retrying.
///
/// [`Presenter::SurfaceError`] is a per-implementation associated type: softbuffer's error enum
/// has no `Lost`/`Outdated`/`Timeout` discrimination the way `wgpu::SurfaceError` does, so today's
/// only backend (`SoftwareRenderer`) has no structured way to say "this specific failure is
/// fatal, don't bother retrying." [`is_recoverable`](Self::is_recoverable) is that hook: a
/// presenter with real error categories can override it to return `false` for a truly fatal
/// failure, while every presenter that doesn't need the distinction (including every backend that
/// exists in this crate today) can implement this trait with an empty body and inherit the
/// default `true`.
///
/// Deliberately not blanket-implemented for every `Debug + Display` type: that would make it
/// impossible for any concrete error type to override [`is_recoverable`](Self::is_recoverable) at
/// all (a specific `impl` would conflict with the blanket one), defeating the point of the trait.
/// Instead, each `SurfaceError` type needs one explicit (and usually empty) `impl
/// RecoverableError for ...` block -- see `retroglyph_software`'s `SurfaceError` for the minimal
/// case that just inherits the default.
// `Infallible` is uninhabited -- no value of it can ever exist, so `is_recoverable` can never
// actually be called on one -- but a presenter that can't fail (e.g. a test mock) still needs
// `type SurfaceError = core::convert::Infallible` to satisfy the `RecoverableError` bound, so
// this impl exists purely for that convenience.
/// A renderer that rasterizes grid content and presents it to a window
/// surface.
///
/// A supertrait of [`Output`], adding the surface lifecycle (`init_surface`, `resize_surface`,
/// `present`, `cell_size`) that the event loop drives. Every `Presenter` implementation is an
/// `Output` implementation for free: [`WindowBackend`](crate::WindowBackend) delegates its own
/// `Output` impl straight through to `P: Presenter`, with no duplicated method bodies.