Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
plugin_view_host.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstddef>
4
6#include <pulp/view/view.hpp>
7#include <memory>
8#include <cstddef>
9#include <cstdint>
10#include <functional>
11#include <vector>
12
14
15namespace pulp::view {
16
17class NativeViewHost;
18
19namespace detail {
23class GpuSurfaceObserverRegistry;
24
33std::size_t lite_host_gpu_request_count() noexcept;
34} // namespace detail
35
36// Platform-specific handle types
37#ifdef __APPLE__
38using NativeViewHandle = void*; // NSView* (macOS) or UIView* (iOS)
39#elif defined(_WIN32)
40using NativeViewHandle = void*; // HWND
41#else
42using NativeViewHandle = void*; // X11 Window or nullptr
43#endif
44
48inline constexpr std::uint32_t kEditorHostClearRgb = 0x1E1E2E;
49
50// Channel spellings of the same default. Every Pulp host -- the standalone
51// window hosts and all four plug-in editor hosts -- seeds this opaque dark
52// background so no clear/undefined composite flashes before the first GPU
53// frame lands, and so the letterbox bars around a design viewport match the
54// editor rather than the DAW's own window content. It is defined here, beside
55// the packed value, because the standalone window hosts in view-core and the
56// plug-in editor hosts in the Pulp-kept layer both paint it; macOS derives its
57// NSColor and CGColor spellings from these (window_host_mac_internal.hpp).
58inline constexpr std::uint8_t kEditorHostClearR = (kEditorHostClearRgb >> 16) & 0xff;
59inline constexpr std::uint8_t kEditorHostClearG = (kEditorHostClearRgb >> 8) & 0xff;
60inline constexpr std::uint8_t kEditorHostClearB = kEditorHostClearRgb & 0xff;
61
62// Hosts a View tree inside a DAW plugin window
63// Creates a platform-native child view that paints the widget hierarchy
65public:
66 struct Size {
67 uint32_t width = 400;
68 uint32_t height = 300;
69 };
70
77 enum class PresentPolicy {
81 vsync,
97 nonblocking,
98 };
99
100 struct Options {
101 Size size = {400, 300};
102 bool use_gpu = false;
103
108
117 bool enable_gpu_timing = false;
118
127 };
128
129 // Create a plugin view host for the given view tree.
130 //
131 // create(), set_factory(), clear_factory(), has_factory(), and
132 // register_platform_plugin_view_host() are declared here but DEFINED in pulp-view-tooling,
133 // together with the platform hosts. A target
134 // that links only pulp-view-core can subclass PluginViewHost but cannot create one.
135 //
136 // Platform support:
137 // - macOS: NSView-backed impl in plugin_view_host_mac.mm, including
138 // native child-view attach/bounds/detach.
139 // - iOS: UIView-backed impl in plugin_view_host_ios.mm, including
140 // native child-view attach/bounds/detach.
141 // - Windows/Linux: native child-window hosts are registered on demand.
142 // - Android or custom hosts: host app registers a factory via
143 // set_factory(). Without a factory, create() returns nullptr
144 // explicitly.
145 static std::unique_ptr<PluginViewHost> create(View& root, Size size);
146 static std::unique_ptr<PluginViewHost> create(View& root, const Options& options);
147
148 // Host-registered factory. Installed by built-in platform hosts or by
149 // embedding apps on targets without a built-in host.
150 using Factory = std::function<std::unique_ptr<PluginViewHost>(
151 View& root, const Options& options)>;
152 static void set_factory(Factory factory);
153 static void clear_factory();
154 static bool has_factory();
155
160
161 // Get the native view handle to pass to the DAW host. A non-null host view
162 // does not by itself guarantee that this host can also embed other native
163 // child views; callers must branch on attach_native_child_view().
165
166 // Begin a native OUTBOUND file drag from this host's window (drag audio out
167 // to Finder/Explorer, a Canvas, another app). Default: unsupported → false.
168 //
169 // This is the host-owned drag path, distinct from the free function
170 // `begin_file_drag(native_view, request)` in drag_drop.hpp. macOS leaves
171 // this at the default and uses the free NSDraggingSession backend via
172 // native_handle(); Windows (OLE IDataObject/DoDragDrop) and Linux (XDND)
173 // override it because their drag needs host-owned native state — the HWND,
174 // or the Display* connection plus the interned Xdnd atoms — that the free
175 // function does not receive. `View::start_file_drag()` tries this first and
176 // only falls back to the free backend when it returns false. Call
177 // synchronously from within the pointer interaction that initiates the drag.
178 virtual bool start_file_drag(const FileDragRequest& request) {
179 (void)request;
180 return false;
181 }
182
183 // Attach this view to a parent native view (the DAW's editor window)
184 virtual void attach_to_parent(NativeViewHandle parent) = 0;
185
186 // Attempt to attach to `parent` and report whether this host ended up
187 // attached. The default composes the existing `attach_to_parent()` command
188 // with the `is_attached()` query, so every host gets a success signal for
189 // free; a host can override to report a more precise outcome. Foreign-host
190 // embedders (the flat-C embedding SDK) use this to decide whether to fire
191 // `ViewBridge::notify_attached()` — they must NOT fire it when attach failed,
192 // or the editor open/close lifecycle goes unbalanced. Call on the UI thread.
193 [[nodiscard]] virtual bool try_attach_to_parent(NativeViewHandle parent) {
194 attach_to_parent(parent);
195 return is_attached();
196 }
197
198 // True when this host's native view is currently parented (i.e. attach
199 // succeeded and detach has not run). Default is conservative: a host that
200 // has not opted into attachment observability reports false, so callers
201 // never treat an unknown host as attached. Apple hosts override this to
202 // reflect the real native view-hierarchy state. Query on the UI thread.
203 virtual bool is_attached() const noexcept { return false; }
204
205 // Detach from parent
206 virtual void detach() = 0;
207
208 // Request a repaint (call when parameters change)
209 virtual void repaint() = 0;
210
211 // Present one frame of the current tree NOW, before the host shows the
212 // view, so the first thing it composites is that frame rather than the
213 // backing layer's colour. `ViewBridge::prepare_first_frame()` calls this
214 // once the document is mounted (content-first open). A host that can paint
215 // without a window (the macOS GPU host draws into its CAMetalLayer) does so
216 // and returns true; one that only paints from the platform's display pass
217 // marks itself dirty, so that first pass draws the tree, and returns false.
218 // Main thread only.
219 virtual bool present_first_frame() {
220 repaint();
221 return false;
222 }
223
224 // ── Bounded repaint damage ──────────────────────────────────────────
225 //
226 // Mirrors WindowHost's pending-damage surface so `View::request_repaint(Rect)`
227 // has somewhere to put a bounded rect on the PLUG-IN path. Without this the
228 // producer discarded the rect and fell back to a full repaint, which made
229 // partial repaint unreachable for every plug-in editor on every platform.
230 //
231 // Damage only ever SHRINKS a repaint (see PendingDamage), so a host that
232 // ignores these is still correct — it just always repaints in full.
233 void mark_dirty_region(const Rect& root_rect) {
234 damage_.mark(root_rect);
235 repaint();
236 }
238 damage_.mark_full();
239 repaint();
240 }
241
244 virtual void request_frame() {
245 repaint();
246 }
247 bool pending_repaint_is_full() const { return damage_.is_full(); }
248 bool has_pending_dirty_bounds() const { return damage_.has_bounds(); }
249 Rect pending_dirty_bounds() const { return damage_.bounds(); }
251 void clear_pending_dirty() { damage_.clear(); }
252
253protected:
255
256public:
257
258 // Resize
259 virtual void set_size(uint32_t width, uint32_t height) = 0;
260 virtual Size get_size() const = 0;
261
262 // True only when this host is rendering through the GPU (Dawn/Skia
263 // Graphite) pipeline AND GPU initialization succeeded. CoreGraphics
264 // CPU hosts return false, and a GPU host that failed to initialize
265 // Dawn/Skia and fell back to CPU also returns false. Adapters read
266 // this after create() to scream when a GPU/scripted editor view
267 // silently took the CPU path (see `format/gpu_host_select.hpp`).
268 virtual bool is_gpu_backed() const { return false; }
269
270 // Mirrors WindowHost::gpu_surface() (window_host.hpp:142). Returns the
271 // host's live wgpu::Surface backing, or nullptr when the host is CPU,
272 // when GPU init failed, or when no surface has been allocated yet.
273 //
274 // This is the input port for the JS-side `navigator.gpu` /
275 // `canvas.getContext('webgpu')` bridge: WidgetBridge captures this
276 // pointer at construction (or via a later attach call) and forwards it
277 // to __describeNativeAdapterImpl / __createNativeAdapterImpl /
278 // __gpuCanvasConfigureImpl. Without a real surface here, those native
279 // impls return mocks and JS-rendered 3D output is black.
280 //
281 // PREFER observe_gpu_surface() over polling this. A one-shot read is only
282 // correct on hosts that build their surface in the constructor (Apple,
283 // Linux); the Windows host cannot create its Dawn surface until the HWND
284 // has its final parent and style, so a read taken at editor-open time is
285 // legitimately null and never becomes non-null on its own.
286 //
287 // Lifetime: the GpuSurface is owned by the PluginViewHost. Consumers
288 // capture the raw pointer; the WidgetBridge must be destroyed before
289 // the host.
290 virtual render::GpuSurface* gpu_surface() const { return nullptr; }
291
296 std::size_t budgeted = 0;
297 std::size_t purgeable = 0;
298 };
300 return {};
301 }
302
310 virtual void release_gpu_caches() {}
311
312 // ── GPU-surface lifecycle ───────────────────────────────────────────
313 //
314 // Whether a host HAS a GPU surface is a three-state answer, and the two
315 // "no" states need opposite reactions from a consumer:
316 //
317 // pending — this host intends to create one but has not yet. The
318 // null from gpu_surface() means "not yet", so a consumer
319 // must wait rather than conclude anything. Windows sits
320 // here between create() and attach_to_parent().
321 // ready — the surface is live; gpu_surface() is non-null.
322 // unavailable — there will be no surface: a CPU host, or GPU init that
323 // failed. This is the ONLY state in which a "silently fell
324 // back to CPU" diagnostic is true.
325 //
326 // Collapsing pending into unavailable is what made the Windows editor log
327 // `gpu-init-failed falling_back=cpu` on every open while actually running
328 // on the GPU, and what left the scripted UI holding the null it sampled
329 // before attach.
330 enum class GpuSurfaceState : uint8_t { pending, ready, unavailable };
331
332 // Reported to observers on every transition, and readable directly.
337
338 // Called on the UI thread whenever the host's surface status changes, and
339 // once immediately on subscription with the current status.
340 using GpuSurfaceObserver = std::function<void(const GpuSurfaceStatus&)>;
341
342 // RAII subscription. Destroying (or reset()ing) it guarantees the observer
343 // is never invoked again — including from the host's own destructor, which
344 // publishes `unavailable` to whoever is still subscribed. Safe in either
345 // destruction order: the subscription holds a weak reference to the host's
346 // observer registry, so outliving the host is inert rather than a
347 // use-after-free.
349 public:
354 : registry_(std::move(other.registry_)), id_(other.id_) {
355 other.registry_.reset();
356 other.id_ = 0;
357 }
359 if (this != &other) {
360 reset();
361 registry_ = std::move(other.registry_);
362 id_ = other.id_;
363 other.registry_.reset();
364 other.id_ = 0;
365 }
366 return *this;
367 }
369
370 void reset() noexcept;
371 bool active() const noexcept { return id_ != 0 && !registry_.expired(); }
372 explicit operator bool() const noexcept { return active(); }
373
374 private:
375 friend class PluginViewHost;
376 GpuSurfaceSubscription(std::weak_ptr<detail::GpuSurfaceObserverRegistry> r,
377 std::uint64_t id)
378 : registry_(std::move(r)), id_(id) {}
379
380 std::weak_ptr<detail::GpuSurfaceObserverRegistry> registry_;
381 std::uint64_t id_ = 0;
382 };
383
384 // Current surface status. Non-virtual: every host publishes through
385 // publish_gpu_surface(), so this is one stored answer rather than a
386 // per-host convention.
387 GpuSurfaceStatus gpu_surface_status() const noexcept { return gpu_status_; }
388 GpuSurfaceState gpu_surface_state() const noexcept { return gpu_status_.state; }
389
390 // Subscribe to surface transitions. `observer` fires immediately with the
391 // current status (so a late subscriber is never stuck on a state it
392 // missed), then on each change. UI thread only — the host publishes from
393 // attach/detach/destroy, which are UI-thread operations.
395 GpuSurfaceObserver observer);
396
397protected:
398 // Hosts call this after creating, replacing, or tearing down their surface.
399 // Publishing `ready` with a null pointer, or a non-null pointer with any
400 // other state, is a programming error and is normalized to `unavailable`.
401 // Re-publishing an identical status is a no-op, so a host may call it
402 // defensively.
404
405 // Shorthand for "this host will create a GPU surface later". Call from a
406 // GPU-capable host's constructor so pre-creation nulls read as `pending`.
410
411public:
412
413 // Native-frame resize notification. AU v2 has no host size callback — the
414 // DAW resizes the returned NSView directly. Hosts invoke this callback
415 // when their native view's frame changes (after they have already resized
416 // their own surfaces) so the adapter can forward to `ViewBridge::resize`
417 // (fires Processor::on_view_resized). VST3/CLAP drive resize through their
418 // own host size callbacks and don't need this. Default no-op.
419 virtual void set_resize_callback(std::function<void(uint32_t, uint32_t)> cb) {
420 (void) cb;
421 }
422
423 // Per-vsync idle pump. GPU hosts invoke this callback once per display
424 // link tick (before rendering) so a scripted UI's `ScriptedUiSession::poll()`
425 // — async results, timers, requestAnimationFrame — keeps running while
426 // the editor is embedded. CPU hosts ignore it. Default no-op.
427 virtual void set_idle_callback(std::function<void()> callback) {
428 (void) callback;
429 }
430
431 // Advance one host-owned frame at a monotonic presentation timestamp.
432 // Embedded hosts (CLAP timer support, VST3 Linux IRunLoop, or another
433 // format-owned UI callback) call this on their UI thread. The concrete
434 // host owns its FrameClock/HostFramePump and gates detached/hidden views;
435 // the default keeps foreign hosts that cannot schedule frames honest.
436 virtual void advance_frame(double timestamp_seconds) {
437 (void)timestamp_seconds;
438 }
439
440 // Capture the host's current back buffer as a PNG (mirrors
441 // `WindowHost::capture_back_buffer_png`, issue #2001). GPU hosts read
442 // back the rendered Skia frame via `SkiaSurface::read_current_rgba`;
443 // hosts that cannot capture return an empty vector. Used by the
444 // embedded-editor host smoke tests.
445 virtual std::vector<uint8_t> capture_back_buffer_png() { return {}; }
446
447 // Attach/detach a native child view inside the plugin editor host.
448 // Coordinates use Pulp's top-left origin convention, matching WindowHost.
449 // Returning false is the canonical unsupported/rejected signal. Non-Apple
450 // factory-backed hosts that support native child embedding must override
451 // all three methods and should keep attachment state in the concrete host.
453 float x,
454 float y,
455 float width,
456 float height) {
457 (void) child_view;
458 (void) x;
459 (void) y;
460 (void) width;
461 (void) height;
462 return false;
463 }
465 float x,
466 float y,
467 float width,
468 float height) {
469 (void) child_view;
470 (void) x;
471 (void) y;
472 (void) width;
473 (void) height;
474 return false;
475 }
477 (void) child_view;
478 }
479
480 // Clip an attached native child to `(x, y, width, height)` — the visible
481 // sub-rectangle expressed in the child's OWN [0,0,frame_w,frame_h] box, in
482 // Pulp's top-left origin convention (same units as
483 // set_native_child_view_bounds). The host masks the native view to that rect
484 // (e.g. a CALayer mask on Apple) so a child inside a scroll region does not
485 // spill past the viewport; masking preserves the child's content size rather
486 // than reflowing it by resizing the frame. When has_clip is false, any
487 // existing clip is removed. Returns false when unsupported or when the child
488 // is not attached to this host. Default: no-op unsupported.
490 bool has_clip,
491 float x,
492 float y,
493 float width,
494 float height) {
495 (void) child_view;
496 (void) has_clip;
497 (void) x;
498 (void) y;
499 (void) width;
500 (void) height;
501 return false;
502 }
503
504 // Pump any pending native drag-and-drop (and related) events on a host
505 // that owns its own platform connection. The Linux X11 host overrides this
506 // to drain its X connection and run the XDND target protocol (XdndEnter /
507 // Position / Drop), routing drops into the view tree via the shared
508 // dispatch core. Hosts driven by a host-owned event loop (Apple, the SDL
509 // standalone) do not need it. Default no-op. Call on the UI thread; a
510 // driver (standalone host idle, or a DAW editor idle hook) invokes it
511 // periodically so drags onto the embedded editor are serviced.
512 virtual void pump_x_events() {}
513
514 // ── Design viewport (mirrors WindowHost::set_design_viewport) ────────
515 //
516 // Constrain editor resize to a fixed aspect ratio. Plugin hosts do not
517 // own the OS window — the DAW does — so the host does not enforce the
518 // aspect itself. Per-format resize-hint paths drive enforcement (CLAP
519 // `gui_get_resize_hints.preserve_aspect_ratio`, VST3
520 // `checkSizeConstraint`). Stored here purely for API parity with
521 // `WindowHost` and so adapters can query it. Default no-op.
522 virtual void set_fixed_aspect_ratio(float ratio) { (void)ratio; }
523
524 // Set a fixed "design viewport". When set, the root view's bounds are
525 // pinned to (design_w x design_h) and paint applies an aspect-correct
526 // scale + letterbox translate to fit the current host size. Mouse
527 // coordinates receive the inverse transform before hit-test. Pass
528 // (0, 0) to disable.
529 //
530 // This mirrors `WindowHost::set_design_viewport` (see that method's
531 // docs for the design rationale, pulp #59/#63/#64/#65) so that an
532 // editor that already paints correctly in the standalone window host
533 // paints identically when embedded by a DAW. Default no-op for hosts
534 // that do not implement design-viewport scaling.
535 virtual void set_design_viewport(float design_w, float design_h) {
536 (void)design_w;
537 (void)design_h;
538 }
539
540 // Anchor the design viewport to the TOP of the host pane instead of
541 // centering it vertically (horizontal centering unchanged). The AU v3
542 // editor opts in so a fixed-aspect design in a taller host pane (REAPER's
543 // FX-chain pane, where AU can't negotiate the pane aspect like CLAP/VST3)
544 // reads like CLAP/VST3 — content at the top with the slack as a single
545 // bottom strip — instead of floating centered between two bands. Default
546 // no-op / centered for every other host + format.
547 virtual void set_design_viewport_top_align(bool top_align) {
548 (void)top_align;
549 }
550
551 // Inverse-map a host-space point (e.g. mouse coords in host logical
552 // pixels) into root-view space using the active design-viewport
553 // transform. Identity when no design viewport is set. Exposed so
554 // native event handlers AND unit tests can exercise the same
555 // inverse-transform path without needing AppKit / UIKit event
556 // delivery.
557 //
558 // The input is in host *logical* coordinates (DPI-independent points),
559 // matching the view tree's coordinate space. Platforms whose OS delivers
560 // input in physical pixels (Windows/Linux) divide by scale_factor() before
561 // calling this, so the design-viewport math stays purely logical and
562 // composes with HiDPI scale without double-counting it.
563 virtual Point window_to_root_point(Point pt) const { return pt; }
564
565 // Report the active design-viewport transform that maps ROOT (design-space)
566 // coordinates to HOST (window-space) coordinates:
567 // x' = x*sx + tx, y' = y*sy + ty, w' = w*sx, h' = h*sy
568 // Returns true and fills the outputs when a design viewport is active;
569 // returns false (identity — outputs untouched) when no viewport is set.
570 //
571 // This is the FORWARD companion to `window_to_root_point()`'s inverse map.
572 // `NativeViewHost` uses it to place an embedded native child at the same
573 // letterbox-scaled position + size as the surrounding Pulp widgets, so a
574 // tree mixing Pulp widgets and a native child stays pixel-aligned under a
575 // design viewport (paint scales the Pulp side; without this the native
576 // child would be pushed at raw design coords and drift on any off-size DAW
577 // pane). Default: no viewport → false. Only the mac plugin hosts and the
578 // GPU window host (the hosts that actually scale paint) override it.
579 virtual bool design_viewport_transform(float& sx, float& sy,
580 float& tx, float& ty) const {
581 (void)sx; (void)sy; (void)tx; (void)ty;
582 return false;
583 }
584
585 // ── HiDPI scale (W8 Windows / L9 Linux) ─────────────────────────────
586 //
587 // The DPI scale that maps host *logical* coordinates to physical pixels:
588 // the editor's view tree is laid out in logical units (a 100pt knob), the
589 // GPU/Skia surface is sized at logical × scale physical pixels, and the
590 // SkiaSurface applies this factor as a canvas transform at paint so the UI
591 // renders crisply on HiDPI displays instead of at 1× (small/blurry).
592 //
593 // Platform hosts auto-detect the scale from the OS (Windows:
594 // GetDpiForWindow; Linux: Xft.dpi / RANDR) and react to live DPI changes
595 // (WM_DPICHANGED). set_scale_factor() lets a DAW/host override the detected
596 // value (e.g. a per-editor zoom, or when the host owns DPI policy) and
597 // makes the scale plumbing testable without a real display. Passing a
598 // non-positive value is ignored. Default impl is a no-op getter returning
599 // 1.0 (CPU/stub hosts that do not scale).
600 virtual void set_scale_factor(float scale) { (void)scale; }
601 virtual float scale_factor() const { return 1.0f; }
602
603private:
604 // ── Attached-view registry ──────────────────────────────────────────────
605 //
606 // A NativeViewHost holds a RAW, non-owning pointer back to the host it
607 // attached to, and dereferences it in its destructor to detach. Nothing made
608 // that safe: if the host dies first, the view derefs a dead object.
609 //
610 // Every built-in Apple host happens to null the back-reference in its OWN
611 // destructor body, which works — but that is a per-subclass convention, not
612 // an invariant, and `set_factory` is public API, so a downstream host that
613 // implements native-child embedding and forgets that line gets a
614 // use-after-free on editor close. The best evidence it is easy to miss: the
615 // test fixtures are host subclasses, and they got it wrong.
616 //
617 // So the BASE destructor now clears every still-attached view's pointer. It
618 // deliberately does NOT call detach_native_child_view(): by then the derived
619 // object is gone and the call would dispatch to the base default (false), so
620 // the real OS detach would silently not happen. The derived destructors keep
621 // doing that through their live vtable; this is purely the safety net that
622 // makes the pointer invariant structural rather than conventional.
623 friend class NativeViewHost;
624 void register_native_view(NativeViewHost* view);
625 void unregister_native_view(NativeViewHost* view);
626
627 std::vector<NativeViewHost*> attached_native_views_;
628
629 // ── GPU-surface observers ───────────────────────────────────────────────
630 //
631 // Created lazily on the first observe_gpu_surface(): a host nobody watches
632 // pays nothing. The base destructor publishes `unavailable` before the
633 // derived surface members are gone, so a consumer that outlives the host
634 // still sees the detach edge rather than silently keeping a dead pointer.
635 std::shared_ptr<detail::GpuSurfaceObserverRegistry> gpu_observers_;
636 GpuSurfaceStatus gpu_status_{};
637};
638
639// Install the built-in platform PluginViewHost factory (and matching headless
640// screenshot provider) on non-Apple platforms (#3329 Win/Linux parity).
641//
642// Idempotent and thread-safe: the first call registers the platform factory via
643// PluginViewHost::set_factory(); subsequent calls are no-ops. A host that wants
644// a custom factory can call PluginViewHost::set_factory() AFTER this and win.
645//
646// Platform behavior:
647// - Windows (Skia build): registers the native HWND host
648// (plugin_view_host_win.cpp).
649// - Linux (Skia + X11 build): registers the native X11 host
650// (plugin_view_host_linux.cpp).
651// - Apple: no-op (built-in NSView/UIView hosts; no factory needed).
652// - Builds without a platform host: no-op (create() still returns nullptr,
653// but the headless render_to_png/rgba path remains available via Skia).
654//
655// PluginViewHost::create() calls this automatically on non-Apple platforms
656// before consulting the factory, so the foreign-host embed and the VST3/CLAP
657// adapters get a working host without the caller doing anything. Exposed
658// publicly so a host can force-register early (e.g. before its own
659// set_factory()) or in a test.
660//
661// Defined in pulp-view-tooling, not pulp-view-core, like create() and the
662// factory functions above.
664
665} // namespace pulp::view
Abstract GPU surface — a presentable rendering target backed by a native window/view.
Definition gpu_surface.hpp:112
A Yoga-laid-out widget that embeds a single platform-native child view (a system WebView,...
Definition native_view_host.hpp:72
Accumulated repaint damage for one frame, in root/window coordinates.
Definition pending_damage.hpp:32
Definition plugin_view_host.hpp:348
bool active() const noexcept
Definition plugin_view_host.hpp:371
friend class PluginViewHost
Definition plugin_view_host.hpp:375
GpuSurfaceSubscription(GpuSurfaceSubscription &&other) noexcept
Definition plugin_view_host.hpp:353
GpuSurfaceSubscription & operator=(GpuSurfaceSubscription &&other) noexcept
Definition plugin_view_host.hpp:358
GpuSurfaceSubscription & operator=(const GpuSurfaceSubscription &)=delete
~GpuSurfaceSubscription()
Definition plugin_view_host.hpp:368
GpuSurfaceSubscription(const GpuSurfaceSubscription &)=delete
Definition plugin_view_host.hpp:64
virtual ~PluginViewHost()
Out-of-line, and NOT trivial: it clears the back-pointer of every NativeViewHost still attached to th...
void mark_gpu_surface_pending()
Definition plugin_view_host.hpp:407
std::function< void(const GpuSurfaceStatus &)> GpuSurfaceObserver
Definition plugin_view_host.hpp:340
virtual float scale_factor() const
Definition plugin_view_host.hpp:601
virtual bool is_attached() const noexcept
Definition plugin_view_host.hpp:203
virtual void detach()=0
virtual void set_design_viewport(float design_w, float design_h)
Definition plugin_view_host.hpp:535
bool pending_repaint_is_full() const
Definition plugin_view_host.hpp:247
static std::unique_ptr< PluginViewHost > create(View &root, Size size)
static void set_factory(Factory factory)
Rect pending_dirty_bounds() const
Definition plugin_view_host.hpp:249
virtual Point window_to_root_point(Point pt) const
Definition plugin_view_host.hpp:563
virtual bool is_gpu_backed() const
Definition plugin_view_host.hpp:268
virtual void attach_to_parent(NativeViewHandle parent)=0
GpuSurfaceSubscription observe_gpu_surface(GpuSurfaceObserver observer)
virtual void set_resize_callback(std::function< void(uint32_t, uint32_t)> cb)
Definition plugin_view_host.hpp:419
virtual bool present_first_frame()
Definition plugin_view_host.hpp:219
virtual void repaint()=0
virtual Size get_size() const =0
virtual std::vector< uint8_t > capture_back_buffer_png()
Definition plugin_view_host.hpp:445
virtual render::GpuSurface * gpu_surface() const
Definition plugin_view_host.hpp:290
void publish_gpu_surface(render::GpuSurface *surface, GpuSurfaceState state)
virtual void request_frame()
A frame without damage (see WindowHost::request_frame()).
Definition plugin_view_host.hpp:244
virtual void detach_native_child_view(NativeViewHandle child_view)
Definition plugin_view_host.hpp:476
virtual bool set_native_child_view_clip(NativeViewHandle child_view, bool has_clip, float x, float y, float width, float height)
Definition plugin_view_host.hpp:489
virtual void set_design_viewport_top_align(bool top_align)
Definition plugin_view_host.hpp:547
virtual bool design_viewport_transform(float &sx, float &sy, float &tx, float &ty) const
Definition plugin_view_host.hpp:579
friend class NativeViewHost
Definition plugin_view_host.hpp:623
virtual void release_gpu_caches()
Return every GPU cache resource nothing references to the device.
Definition plugin_view_host.hpp:310
virtual GpuCacheUsage gpu_cache_usage() const
Definition plugin_view_host.hpp:299
void clear_pending_dirty()
Host calls this once the frame is painted and submitted.
Definition plugin_view_host.hpp:251
GpuSurfaceStatus gpu_surface_status() const noexcept
Definition plugin_view_host.hpp:387
virtual NativeViewHandle native_handle()=0
PresentPolicy
How a host presents finished frames (WAH-13).
Definition plugin_view_host.hpp:77
@ nonblocking
Do not block on acquire (Mailbox, then Immediate, then Fifo).
Definition plugin_view_host.hpp:97
bool has_pending_dirty_bounds() const
Definition plugin_view_host.hpp:248
virtual bool start_file_drag(const FileDragRequest &request)
Definition plugin_view_host.hpp:178
virtual void advance_frame(double timestamp_seconds)
Definition plugin_view_host.hpp:436
void mark_dirty_full()
Definition plugin_view_host.hpp:237
void mark_dirty_region(const Rect &root_rect)
Definition plugin_view_host.hpp:233
virtual void set_scale_factor(float scale)
Definition plugin_view_host.hpp:600
PendingDamage damage_
Definition plugin_view_host.hpp:254
virtual void set_idle_callback(std::function< void()> callback)
Definition plugin_view_host.hpp:427
static std::unique_ptr< PluginViewHost > create(View &root, const Options &options)
virtual bool try_attach_to_parent(NativeViewHandle parent)
Definition plugin_view_host.hpp:193
virtual bool attach_native_child_view(NativeViewHandle child_view, float x, float y, float width, float height)
Definition plugin_view_host.hpp:452
GpuSurfaceState
Definition plugin_view_host.hpp:330
@ unavailable
Definition plugin_view_host.hpp:330
@ pending
Definition plugin_view_host.hpp:330
virtual void pump_x_events()
Definition plugin_view_host.hpp:512
virtual void set_fixed_aspect_ratio(float ratio)
Definition plugin_view_host.hpp:522
virtual void set_size(uint32_t width, uint32_t height)=0
GpuSurfaceState gpu_surface_state() const noexcept
Definition plugin_view_host.hpp:388
virtual bool set_native_child_view_bounds(NativeViewHandle child_view, float x, float y, float width, float height)
Definition plugin_view_host.hpp:464
std::function< std::unique_ptr< PluginViewHost >( View &root, const Options &options)> Factory
Definition plugin_view_host.hpp:150
Definition view.hpp:73
SequencerStateChannel is the audio-safe transport for a plugin's structured NON-parameter state: the ...
Definition audio_device_manager.hpp:48
Definition accessibility_provider.hpp:65
std::size_t lite_host_gpu_request_count() noexcept
Requests noted by note_lite_host_gpu_request() in this process.
bool note_lite_host_gpu_request()
A lite editor binary (pulp_add_plugin LITE_EDITOR) is built without the GPU host.
Hover-cursor tracking for platform window hosts.
Definition fwd.hpp:27
constexpr std::uint8_t kEditorHostClearR
Definition plugin_view_host.hpp:58
constexpr std::uint32_t kEditorHostClearRgb
The background a plug-in editor host paints when the plug-in has not declared its own (Processor::edi...
Definition plugin_view_host.hpp:48
constexpr std::uint8_t kEditorHostClearB
Definition plugin_view_host.hpp:60
constexpr std::uint8_t kEditorHostClearG
Definition plugin_view_host.hpp:59
@ y
Definition input_events.hpp:42
@ r
Definition input_events.hpp:41
@ x
Definition input_events.hpp:41
@ height
Definition css_animation.hpp:128
void register_platform_plugin_view_host()
void * NativeViewHandle
Definition native_view_host.hpp:19
STL namespace.
Definition drag_drop.hpp:109
Bytes held by this host's GPU resource caches: budgeted against Skia's budget, purgeable what a trim ...
Definition plugin_view_host.hpp:295
std::size_t purgeable
Definition plugin_view_host.hpp:297
std::size_t budgeted
Definition plugin_view_host.hpp:296
Definition plugin_view_host.hpp:333
render::GpuSurface * surface
non-null iff state==ready
Definition plugin_view_host.hpp:334
GpuSurfaceState state
Definition plugin_view_host.hpp:335
Definition plugin_view_host.hpp:100
bool enable_gpu_timing
Enable GPU timing instrumentation (Dawn timestamp queries).
Definition plugin_view_host.hpp:117
PresentPolicy present_policy
Presentation policy for this host.
Definition plugin_view_host.hpp:107
bool use_gpu
Use GPU rendering (Dawn/Skia Graphite) instead of CoreGraphics.
Definition plugin_view_host.hpp:102
std::uint32_t background_rgb
The editor's own background, 0xRRGGBB.
Definition plugin_view_host.hpp:126
Size size
Definition plugin_view_host.hpp:101
Definition plugin_view_host.hpp:66
uint32_t height
Definition plugin_view_host.hpp:68
uint32_t width
Definition plugin_view_host.hpp:67
Definition geometry.hpp:20
Axis-aligned rectangle in continuous (float) coordinates.
Definition geometry.hpp:52