docs
Loading...
Searching...
No Matches
Renderer.h
Go to the documentation of this file.
1///
2/// Copyright (C) 2026 Ultralight, Inc. All rights reserved.
3/// A license is required for commercial use. https://ultralig.ht
4///
5#pragma once
7#include <Ultralight/RefPtr.h>
9#include <Ultralight/View.h>
12
13#include <type_traits>
14#include <utility>
15
16namespace ultralight {
17
18/// \cond INTERNAL
19namespace detail {
20
21// Trampolines behind the Renderer::PostTask / PostDelayedTask callable overloads.
22template <typename Fn>
23void InvokeTaskCallable(void* user_data) {
24 (*static_cast<Fn*>(user_data))();
25}
26template <typename Fn>
27void DeleteTaskCallable(void* user_data) {
28 delete static_cast<Fn*>(user_data);
29}
30
31} // namespace detail
32/// \endcond
33
34///
35/// Controls how aggressively Renderer::Recycle() reclaims memory.
36///
37enum class RecycleMode : uint8_t {
38 ///
39 /// A quick recycle, cheap enough to call every frame (the same work the automatic recycler
40 /// does).
41 ///
43
44 ///
45 /// A thorough recycle, for idle periods or transitions (eg, a loading screen). A call within a
46 /// second of the last one does nothing.
47 ///
49};
50
51///
52/// Core renderer singleton for the library, coordinates all library functions.
53///
54/// The Renderer class is responsible for creating and painting View%s, managing Session%s, as well
55/// as coordinating network requests, events, JavaScript execution, and more.
56///
57/// ## Creating the Renderer
58///
59/// \parblock
60/// @note A Renderer is created for you when you call App::Create() (access it with
61/// App::renderer()).
62/// \endparblock
63///
64/// \parblock
65/// @note App::Create() is part of the AppCore API and automatically manages window creation, run
66/// loop, input, painting, and most platform-specific functionality. (Available on desktop
67/// platforms only)
68/// \endparblock
69///
70/// ### Defining Platform Handlers
71///
72/// Before creating the Renderer, you should define your platform handlers via the Platform
73/// singleton. This can be used to customize file loading, font loading, clipboard access, and other
74/// functionality typically provided by the OS.
75///
76/// Default implementations for most platform handlers ship as Zlib-licensed source in the SDK's
77/// `platform` folder. You can use these stock implementations by copying the code into your
78/// project, or you can write your own.
79///
80/// At a minimum, you must provide a FileSystem and a FontLoader. Without them, the library exits
81/// the process with an error when it first needs them.
82///
83/// ### Setting Up the Config
84///
85/// You can configure various library options by creating a Config object and passing it to
86/// `Platform::instance().set_config()`.
87///
88/// ### Creating the Renderer
89///
90/// Once you've set up the Platform handlers and Config, you can create the Renderer by calling
91/// `Renderer::Create()`. You should store the result in a RefPtr to keep it alive.
92///
93/// @par Example creation code
94/// ```
95/// // Get the Platform singleton (maintains global library state)
96/// auto& platform = Platform::instance();
97///
98/// // Setup config
99/// Config my_config;
100/// platform.set_config(my_config);
101///
102/// // Create platform handlers (these are the minimum required)
103/// // (This is pseudo-code, you will need to define your own)
104/// MyFileSystem* file_system = new MyFileSystem();
105/// MyFontLoader* font_loader = new MyFontLoader();
106///
107/// // Setup platform handlers
108/// platform.set_file_system(file_system);
109/// platform.set_font_loader(font_loader);
110///
111/// // Create the Renderer
112/// RefPtr<Renderer> renderer = Renderer::Create();
113///
114/// // Create Views here
115/// ```
116///
117/// ## Updating Renderer Logic
118///
119/// You should call Renderer::Update() from your main update loop as often as possible to give the
120/// library an opportunity to dispatch events and timers:
121///
122/// @par Example update code
123/// ```
124/// void mainLoop()
125/// {
126/// while(true)
127/// {
128/// // Update program logic here
129/// renderer->Update();
130/// }
131/// }
132/// ```
133///
134/// ## Rendering Each Frame
135///
136/// When your program is ready to display a new frame (usually in sync with the monitor's
137/// refresh rate), you should call Renderer::RefreshDisplay() and Renderer::Render() so the
138/// library can render all active View%s as needed.
139///
140/// Animations and smooth scrolling advance with each RefreshDisplay() call. Call it once per
141/// frame you present (once per display refresh for a vsynced loop, or once per rendered frame for
142/// a vsync-off or variable-refresh game loop).
143///
144/// @par Example per-frame render code
145/// ```
146/// void displayFrame()
147/// {
148/// // Notify the renderer that the main display has refreshed. This updates animations,
149/// // smooth scrolling, and window.requestAnimationFrame() for all Views on that display.
150/// renderer->RefreshDisplay(0);
151///
152/// // Render all Views as needed
153/// renderer->Render();
154///
155/// // Each View renders to a
156/// // - Pixel-Buffer Surface (View::surface())
157/// // or
158/// // - GPU texture (View::render_target())
159/// // based on whether CPU or GPU rendering is used.
160/// //
161/// // You will need to display the image data here as needed.
162/// }
163/// ```
164///
166 public:
167 ///
168 /// Create the core renderer singleton for the library.
169 ///
170 /// You should set up the Platform singleton before calling this function.
171 ///
172 /// @return Returns a ref-pointer to a new Renderer instance, or nullptr on failure. Store it
173 /// in a RefPtr to keep it alive.
174 ///
175 /// \parblock
176 /// @note You do not need to call this if you're using the App class from AppCore.
177 /// \endparblock
178 ///
179 /// \parblock
180 /// @warning You must define a FontLoader and a FileSystem in the Platform singleton. Without
181 /// them, the library exits the process with an error when it first needs them.
182 /// \endparblock
183 ///
184 /// \parblock
185 /// @warning You should only create one Renderer during the lifetime of your program.
186 /// \endparblock
187 ///
189
190 ///
191 /// Create a unique, named Session to store browsing data in (cookies, local storage,
192 /// application cache, indexed db, etc).
193 ///
194 /// @param is_persistent Whether or not to store the session on disk. Persistent sessions are
195 /// stored in a subfolder of Config::cache_path with this session's name.
196 ///
197 /// @param name A unique name for this session.
198 ///
199 /// @return Returns a ref-pointer to a new Session instance.
200 ///
201 /// \parblock
202 /// @note A default, persistent Session is already created for you. You only need to call this
203 /// if you want a private, in-memory session or a separate session for each View.
204 /// \endparblock
205 ///
206 /// \parblock
207 /// @note The library doesn't check that names are unique: two persistent sessions with the
208 /// same name share one folder.
209 /// \endparblock
210 ///
211 virtual RefPtr<Session> CreateSession(bool is_persistent, const String& name) = 0;
212
213 ///
214 /// Get the default Session. This session is persistent (backed to disk) and has the name
215 /// "default".
216 ///
218
219 ///
220 /// Create a new View to load and display web pages in.
221 ///
222 /// Views are similar to a tab in a browser. They have certain dimensions but are rendered to an
223 /// offscreen surface and must be forwarded all input events.
224 ///
225 /// @param width The initial width, in pixels.
226 ///
227 /// @param height The initial height, in pixels.
228 ///
229 /// @param config Configuration details for the View.
230 ///
231 /// @param session The session to store local data in. Pass a nullptr to use the default
232 /// session.
233 ///
234 /// @return Returns a ref-pointer to a new View instance.
235 ///
236 virtual RefPtr<View> CreateView(uint32_t width, uint32_t height, const ViewConfig& config,
237 RefPtr<Session> session)
238 = 0;
239
240 ///
241 /// Update timers and dispatch callbacks.
242 ///
243 /// You should call this as often as you can from your application's run loop.
244 ///
245 virtual void Update() = 0;
246
247 ///
248 /// Notify the renderer that a display has refreshed.
249 ///
250 /// Call this once per frame you present, for each display (usually right after vsync). It
251 /// advances animations, smooth scrolling, and `window.requestAnimationFrame()` for the Views on
252 /// that display, so they can repaint during the next Render().
253 ///
254 /// @param display_id The id of the display that refreshed (see ViewConfig::display_id).
255 ///
256 /// \parblock
257 /// @note Keep calling this even while View::needs_paint() returns false: animations only
258 /// request a repaint from this call.
259 /// \endparblock
260 ///
261 /// \parblock
262 /// @note Call this on the thread the Renderer was created on.
263 /// \endparblock
264 ///
265 virtual void RefreshDisplay(uint32_t display_id) = 0;
266
267 ///
268 /// Notify the renderer that a display has refreshed, and when the resulting frame will be
269 /// shown.
270 ///
271 /// This works like RefreshDisplay(display_id), but animation time follows your timestamps
272 /// instead of the wall clock, so animations are timed for the moment the frame reaches the
273 /// screen.
274 ///
275 /// @param display_id The id of the display that refreshed.
276 ///
277 /// @param target_timestamp When this frame will be shown, in seconds. Use the system's
278 /// monotonic clock (eg, the target time your display link reports),
279 /// or your own timeline after calling SetDisplayUsesCustomClock().
280 /// Timestamps must never decrease.
281 ///
282 /// @note `performance.now()` stays on the wall clock, so pages that compare it to
283 /// `window.requestAnimationFrame()` timestamps will see the difference.
284 ///
285 /// @see SetDisplayRefreshRate(), SetDisplayUsesCustomClock()
286 ///
287 virtual void RefreshDisplay(uint32_t display_id, double target_timestamp) = 0;
288
289 ///
290 /// Post a task to run on the Renderer's thread during a future call to Update().
291 ///
292 /// You can use this to hand work from your other threads to the thread that drives the Renderer
293 /// (the only thread that may touch View%s and the DOM API).
294 ///
295 /// Tasks run in posting order during the next Update() after they are posted. A task posted
296 /// while Update() is draining tasks runs at the following Update().
297 ///
298 /// @param task Invoked once on the Renderer's thread with `user_data`.
299 ///
300 /// @param user_data Pointer passed through to `task` (can be nullptr).
301 ///
302 /// @param destroy_user_data Invoked exactly once after `task` runs, or without `task`
303 /// running if the Renderer is destroyed first (can be nullptr).
304 ///
305 /// \parblock
306 /// @note Safe to call from any thread.
307 /// \endparblock
308 ///
309 /// \parblock
310 /// @note With AppCore, App::PostTask() posts to this same queue and also wakes the app's
311 /// loop, so prefer it there.
312 /// \endparblock
313 ///
314 virtual void PostTask(void (*task)(void* user_data), void* user_data,
315 void (*destroy_user_data)(void* user_data) = nullptr)
316 = 0;
317
318 ///
319 /// Post a task to run on the Renderer's thread once a delay has elapsed.
320 ///
321 /// The clock is the Update() cadence, not a background timer. The task runs during the first
322 /// Update() at or after the deadline, so delivery waits while Update() is not being called
323 /// (eg, a paused application).
324 ///
325 /// Tasks whose deadlines fall in the same Update() run in posting order.
326 ///
327 /// @param delay_ms Minimum delay before the task may run, in milliseconds.
328 ///
329 /// @param task Invoked once on the Renderer's thread with `user_data`.
330 ///
331 /// @param user_data Pointer passed through to `task` (can be nullptr).
332 ///
333 /// @param destroy_user_data Invoked exactly once after `task` runs, or without `task`
334 /// running if the Renderer is destroyed first (can be nullptr).
335 ///
336 /// @note Safe to call from any thread.
337 ///
338 /// @see PostTask()
339 ///
340 virtual void PostDelayedTask(double delay_ms, void (*task)(void* user_data), void* user_data,
341 void (*destroy_user_data)(void* user_data) = nullptr)
342 = 0;
343
344 ///
345 /// Post a callable to run on the Renderer's thread during a future call to Update().
346 ///
347 /// Convenience overload of PostTask(). The callable is invoked once on the Renderer's thread,
348 /// then destroyed (destroyed without being invoked if the Renderer is destroyed first).
349 ///
350 /// Captures are the natural way to hand data across threads. You should capture by value.
351 ///
352 /// ```
353 /// worker_thread.OnFinished([renderer, result] {
354 /// renderer->PostTask([result] { ApplyResult(result); });
355 /// });
356 /// ```
357 ///
358 /// @param callback The callable to invoke on the Renderer's thread.
359 ///
360 /// @note Safe to call from any thread.
361 ///
362 template <typename F, typename = std::enable_if_t<std::is_invocable_v<std::decay_t<F>&>>>
363 void PostTask(F&& callback) {
364 using Fn = std::decay_t<F>;
365 auto* fn = new Fn(std::forward<F>(callback));
366 PostTask(&detail::InvokeTaskCallable<Fn>, fn, &detail::DeleteTaskCallable<Fn>);
367 }
368
369 ///
370 /// Post a callable to run on the Renderer's thread once a delay has elapsed.
371 ///
372 /// Convenience overload of PostDelayedTask(). See PostTask() for the callable's lifetime.
373 ///
374 /// @param delay_ms Minimum delay before the callable may run, in milliseconds.
375 ///
376 /// @param callback The callable to invoke on the Renderer's thread.
377 ///
378 /// @note Safe to call from any thread.
379 ///
380 template <typename F, typename = std::enable_if_t<std::is_invocable_v<std::decay_t<F>&>>>
381 void PostDelayedTask(double delay_ms, F&& callback) {
382 using Fn = std::decay_t<F>;
383 auto* fn = new Fn(std::forward<F>(callback));
384 PostDelayedTask(delay_ms, &detail::InvokeTaskCallable<Fn>, fn,
385 &detail::DeleteTaskCallable<Fn>);
386 }
387
388 ///
389 /// Render all active views to their respective render-targets/surfaces.
390 ///
391 /// @note Views are only repainted if they actually need painting.
392 ///
393 virtual void Render() = 0;
394
395 ///
396 /// Render a subset of views to their respective surfaces and render targets.
397 ///
398 /// @param view_array A C-array containing a list of View pointers.
399 ///
400 /// @param view_array_len The length of the C-array.
401 ///
402 /// @deprecated Use Render() instead. To stop a View from painting, pause it with
403 /// View::set_visible(false) (Render() skips hidden Views).
404 ///
405 [[deprecated("Use Render() instead.")]]
406 virtual void RenderOnly(View** view_array, size_t view_array_len) = 0;
407
408 ///
409 /// Recycle internal caches and reclaim memory.
410 ///
411 /// @note You normally do not need to call this. The library recycles automatically on a timer
412 /// (see Config::recycle_delay), and letting it drive recycling is recommended for best
413 /// performance. Call Recycle() yourself only when you want to control when reclamation
414 /// happens, for example to force a thorough reclaim during a loading screen or scene
415 /// transition.
416 ///
417 /// @param mode How aggressively to reclaim memory:
418 /// - **Lightweight**: cheap enough to call every frame. This is the same work the
419 /// automatic recycler performs.
420 /// - **Full**: a thorough, heavier reclaim best reserved for idle periods or
421 /// transitions. It can take noticeably longer on a busy page.
422 ///
423 /// @see PurgeMemory()
424 ///
426
427#if UL_HAS(GC_LISTENER)
428 ///
429 /// Reclaim memory, choosing how much compiled code to discard.
430 ///
431 /// Like Recycle(), but `code` sets how much compiled code a Full recycle discards. Discarding
432 /// more frees more memory, but pages run slower for a while as their code is compiled again.
433 ///
434 /// You can use this to shrink the JavaScript footprint at a moment you choose (eg, a loading
435 /// screen or level transition).
436 ///
437 /// @param mode See Recycle().
438 ///
439 /// @param code How aggressively to discard compiled code (see CodeDropMode).
440 ///
441 /// @note With `RecycleMode::Lightweight` the `code` parameter has no effect (no collection
442 /// runs).
443 ///
444 /// @pre Requires the Pro edition or higher.
445 ///
446 /// @see Recycle(), PurgeMemory()
447 ///
448 virtual void Recycle(RecycleMode mode, CodeDropMode code) = 0;
449
450 ///
451 /// Collect the JavaScript heap now, leaving rendering and GPU caches intact.
452 ///
453 /// Unlike Recycle(), this reclaims only the JavaScript heap. It runs a garbage collection
454 /// (optionally discarding compiled code, see CodeDropMode) and returns the freed memory to the
455 /// system. Rendering and GPU caches are left alone, so rendering stays fast.
456 ///
457 /// You can call this from GCListener::OnRequestGC() or at any moment when a short pause won't be
458 /// noticed (eg, a quiet point in your update loop).
459 ///
460 /// @param code How aggressively to discard compiled code (see CodeDropMode).
461 ///
462 /// @param sync If true (the default), collect synchronously before returning, briefly blocking
463 /// the calling thread. If false, start a collection that completes in the
464 /// background.
465 ///
466 /// \parblock
467 /// @note If you call this while JavaScript is running (eg, from a JS callback), the
468 /// collection waits until the script returns, even with `sync` set to true.
469 /// \endparblock
470 ///
471 /// \parblock
472 /// @note GCListener::OnCollectComplete() fires only for a synchronous collection.
473 /// \endparblock
474 ///
475 /// @pre Requires the Pro edition or higher.
476 ///
477 /// @see Recycle(), PurgeMemory(), GCListener::OnRequestGC()
478 ///
479 virtual void CollectNow(CodeDropMode code, bool sync = true) = 0;
480#endif
481
482 ///
483 /// Attempt to release as much memory as possible.
484 ///
485 /// This also discards all compiled JavaScript code, so pages run slower for a while as it's
486 /// recompiled.
487 ///
488 /// @warning Don't call this while the Renderer is rendering (eg, from a GPUDriver callback):
489 /// the rendering caches can't be released then, and are skipped with a warning.
490 ///
491 virtual void PurgeMemory() = 0;
492
493 ///
494 /// Print detailed memory usage statistics to the log.
495 ///
496 /// @see Platform::set_logger()
497 ///
498 virtual void LogMemoryUsage() = 0;
499
500 ///
501 /// Get formatted memory usage statistics as a string.
502 ///
503 /// @return Returns the same information as LogMemoryUsage(), as a String you can display in a
504 /// debug overlay or capture programmatically.
505 ///
506 virtual String GetMemoryUsage() = 0;
507
508 ///
509 /// Set the system color scheme that Views report to pages via the `prefers-color-scheme`
510 /// CSS media feature.
511 ///
512 /// The library never reads the OS setting itself; the scheme remains Light until this is
513 /// called. A change re-evaluates `prefers-color-scheme` media queries in every View whose
514 /// ViewConfig::preferred_color_scheme is ColorScheme::Auto; Views pinned Light or Dark are
515 /// unaffected.
516 ///
517 /// @param scheme ColorScheme::Light or ColorScheme::Dark. Passing ColorScheme::Auto is
518 /// invalid here (a warning is logged and the value is ignored).
519 ///
520 /// @note This is automatically managed for you when App::Create() is used (the OS setting
521 /// is fed at startup and tracked as it changes).
522 ///
523 /// @see View::set_preferred_color_scheme()
524 ///
525 virtual void set_system_color_scheme(ColorScheme scheme) = 0;
526
527 ///
528 /// The current system color scheme. (Default: ColorScheme::Light)
529 ///
530 /// @see set_system_color_scheme()
531 ///
532 virtual ColorScheme system_color_scheme() const = 0;
533
534 ///
535 /// Start the remote inspector server.
536 ///
537 /// While it runs, another Ultralight app (on the same machine or over the network) can inspect
538 /// this renderer's Views by loading this URL in a View:
539 ///
540 /// \code
541 /// inspector://<ADDRESS>:<PORT>
542 /// \endcode
543 ///
544 /// @param address The address for the server to listen on (eg, "127.0.0.1")
545 ///
546 /// @param port The port for the server to listen on (eg, 9222)
547 ///
548 /// @return Returns whether the server started successfully or not.
549 ///
550 /// @pre Not available in the Free edition (always returns false there).
551 ///
552 virtual bool StartRemoteInspectorServer(const char* address, uint16_t port) = 0;
553
554 ///
555 /// Describe the details of a gamepad, to be used with FireGamepadEvent and related
556 /// events below. This can be called multiple times with the same index if the details change.
557 ///
558 /// @param index The gamepad's connection slot, and the array position the page sees: a
559 /// gamepad described at index 1 arrives as `navigator.getGamepads()[1]`
560 /// with `gamepad.index` 1, leaving slot 0 `null`. Number your controllers
561 /// from 0.
562 ///
563 /// @param id A string ID representing the device, this will be made available
564 /// in JavaScript as gamepad.id
565 ///
566 /// @param axis_count The number of axes on the device.
567 ///
568 /// @param button_count The number of buttons on the device.
569 ///
570 virtual void SetGamepadDetails(uint32_t index, const String& id, uint32_t axis_count,
571 uint32_t button_count)
572 = 0;
573
574 ///
575 /// Fire a gamepad event (connection / disconnection).
576 ///
577 /// @note The gamepad should first be described via SetGamepadDetails before calling this
578 /// function.
579 ///
580 /// @see <https://developer.mozilla.org/en-US/docs/Web/API/Gamepad>
581 ///
582 virtual void FireGamepadEvent(const GamepadEvent& evt) = 0;
583
584 ///
585 /// Fire a gamepad axis event (to be called when an axis value is changed).
586 ///
587 /// @note The gamepad should be connected via a previous call to FireGamepadEvent.
588 ///
589 /// @see <https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/axes>
590 ///
591 virtual void FireGamepadAxisEvent(const GamepadAxisEvent& evt) = 0;
592
593 ///
594 /// Fire a gamepad button event (to be called when a button value is changed).
595 ///
596 /// @note The gamepad should be connected via a previous call to FireGamepadEvent.
597 ///
598 /// @see <https://developer.mozilla.org/en-US/docs/Web/API/Gamepad/buttons>
599 ///
600 virtual void FireGamepadButtonEvent(const GamepadButtonEvent& evt) = 0;
601
602#if UL_HAS(RENDER_TRACE)
603 ///
604 /// Begin recording a render trace to the specified file path.
605 ///
606 /// The trace file captures detailed rendering pipeline diagnostics in Perfetto format,
607 /// viewable at https://ui.perfetto.dev. This operates independently of the Profiler--
608 /// both can be active simultaneously.
609 ///
610 /// @param output_path Path to the output .perfetto-trace file.
611 ///
612 /// @param verbose If true, captures detailed annotations in addition to scope timing.
613 ///
614 /// @return Returns whether or not the trace started (false if a trace is already active or
615 /// the trace file can't be opened).
616 ///
617 /// @pre Requires the Enterprise edition or higher.
618 ///
619 virtual bool BeginRenderTrace(const char* output_path, bool verbose = true) = 0;
620
621 ///
622 /// End the current render trace.
623 ///
624 /// The trace file is finished and closed shortly after this returns (on the next Update()).
625 ///
626 /// @pre Requires the Enterprise edition or higher.
627 ///
628 virtual void EndRenderTrace() = 0;
629
630 ///
631 /// Whether or not a render trace is currently being recorded.
632 ///
633 /// @pre Requires the Enterprise edition or higher.
634 ///
635 virtual bool is_render_trace_active() const = 0;
636#endif // UL_HAS(RENDER_TRACE)
637
638#if UL_HAS(GC_LISTENER)
639 ///
640 /// Set a GCListener to observe and control the Renderer's JavaScript garbage collections.
641 ///
642 /// @param listener A user-defined GCListener implementation, ownership remains with the
643 /// caller. Pass a nullptr to detach the current listener.
644 ///
645 /// @note The listener must outlive the Renderer, or be cleared before the Renderer is
646 /// destroyed.
647 ///
648 /// @pre Requires the Pro edition or higher.
649 ///
650 /// @see GCListener
651 ///
652 virtual void set_gc_listener(GCListener* listener) = 0;
653
654 ///
655 /// Get the attached GCListener, if any.
656 ///
657 /// @return Returns the attached listener, or nullptr if none is set.
658 ///
659 /// @pre Requires the Pro edition or higher.
660 ///
661 virtual GCListener* gc_listener() const = 0;
662
663 ///
664 /// Get a snapshot of the current JS-heap reclamation state.
665 ///
666 /// @return Returns the current reclamation state (see GCInfo).
667 ///
668 /// @pre Requires the Pro edition or higher.
669 ///
670 virtual GCInfo gc_status() const = 0;
671#endif // UL_HAS(GC_LISTENER)
672
673 ///
674 /// Declare a display's refresh rate.
675 ///
676 /// Pages see the declared rate through `window.requestAnimationFrame()` scheduling. Call this
677 /// when the display's mode changes (eg, a variable-rate display switching between 120 Hz and
678 /// 48 Hz). Small changes are absorbed, and a change reaches pages at most once a second.
679 ///
680 /// @param display_id The id of the display.
681 ///
682 /// @param refresh_rate The display mode's nominal refresh rate in Hz (eg, 60.0, 59.94,
683 /// 120.0), or 0 to clear it (the library then measures how often
684 /// RefreshDisplay() is called).
685 ///
686 /// @note Call this on the thread the Renderer was created on.
687 ///
688 /// @see RefreshDisplay()
689 ///
690 virtual void SetDisplayRefreshRate(uint32_t display_id, double refresh_rate) = 0;
691
692 ///
693 /// Get the refresh rate declared for a display.
694 ///
695 /// @param display_id The id of the display.
696 ///
697 /// @return Returns the display's declared refresh rate (in Hz), or 0 if
698 /// SetDisplayRefreshRate() was never called for it.
699 ///
700 virtual double display_refresh_rate(uint32_t display_id) const = 0;
701
702 ///
703 /// Declare that a display's refresh timestamps are on your own timeline rather than the
704 /// system clock.
705 ///
706 /// By default, the timestamps you pass to RefreshDisplay(display_id, target_timestamp) are
707 /// treated as readings of the system's monotonic clock. Declare a custom clock when they're on
708 /// a timeline of your own (eg, a media timeline for offline rendering, or simulation time):
709 /// animation then follows your timestamps exactly.
710 ///
711 /// @param display_id The id of the display.
712 ///
713 /// @param uses_custom_clock True if timestamps for this display are on your own timeline.
714 ///
715 /// @pre Call this before the display's first timed refresh.
716 ///
717 /// @note Call this on the thread the Renderer was created on.
718 ///
719 /// @see RefreshDisplay()
720 ///
721 virtual void SetDisplayUsesCustomClock(uint32_t display_id, bool uses_custom_clock) = 0;
722
723 ///
724 /// Get whether a display was declared to use a custom clock.
725 ///
726 /// @param display_id The id of the display.
727 ///
728 /// @return Returns the value last passed to SetDisplayUsesCustomClock() for the display, or
729 /// false if it was never called.
730 ///
731 virtual bool display_uses_custom_clock(uint32_t display_id) const = 0;
732
733#if UL_HAS(TESTING)
734 /// \cond ignore
735 virtual void SetMockScrollbarsEnabled(bool enabled) = 0;
736 virtual void SetAllowAnySSLCertificate(bool allow) = 0;
737 virtual String GetHeapDiagnostics() = 0;
738 virtual String DumpHeapSnapshot(const String& path) = 0;
739 /// \endcond
740#endif // UL_HAS(TESTING)
741
742 protected:
743 virtual ~Renderer();
744};
745
746} // namespace ultralight
#define UExport
Definition Exports.h:22
User-defined interface to observe and control the Renderer's JavaScript garbage collections.
Definition GCListener.h:104
Event representing a change in gamepad axis state (eg, pressing a stick in a certain direction).
Definition GamepadEvent.h:54
Event representing a change in gamepad button state (eg, pressing a button on a gamepad).
Definition GamepadEvent.h:82
Event representing a change in gamepad connection state.
Definition GamepadEvent.h:16
Interface for all ref-counted objects that will be managed using the RefPtr<> smart pointer.
Definition RefPtr.h:49
A nullable smart pointer.
Definition RefPtr.h:126
Core renderer singleton for the library, coordinates all library functions.
Definition Renderer.h:165
virtual void set_system_color_scheme(ColorScheme scheme)=0
Set the system color scheme that Views report to pages via the prefers-color-scheme CSS media feature...
virtual void CollectNow(CodeDropMode code, bool sync=true)=0
Collect the JavaScript heap now, leaving rendering and GPU caches intact.
virtual void PostTask(void(*task)(void *user_data), void *user_data, void(*destroy_user_data)(void *user_data)=nullptr)=0
Post a task to run on the Renderer's thread during a future call to Update().
virtual void FireGamepadAxisEvent(const GamepadAxisEvent &evt)=0
Fire a gamepad axis event (to be called when an axis value is changed).
virtual void FireGamepadEvent(const GamepadEvent &evt)=0
Fire a gamepad event (connection / disconnection).
virtual RefPtr< Session > default_session()=0
Get the default Session.
virtual void PostDelayedTask(double delay_ms, void(*task)(void *user_data), void *user_data, void(*destroy_user_data)(void *user_data)=nullptr)=0
Post a task to run on the Renderer's thread once a delay has elapsed.
virtual double display_refresh_rate(uint32_t display_id) const =0
Get the refresh rate declared for a display.
virtual void Update()=0
Update timers and dispatch callbacks.
virtual void RenderOnly(View **view_array, size_t view_array_len)=0
Render a subset of views to their respective surfaces and render targets.
virtual void SetGamepadDetails(uint32_t index, const String &id, uint32_t axis_count, uint32_t button_count)=0
Describe the details of a gamepad, to be used with FireGamepadEvent and related events below.
virtual void set_gc_listener(GCListener *listener)=0
Set a GCListener to observe and control the Renderer's JavaScript garbage collections.
virtual bool StartRemoteInspectorServer(const char *address, uint16_t port)=0
Start the remote inspector server.
void PostDelayedTask(double delay_ms, F &&callback)
Post a callable to run on the Renderer's thread once a delay has elapsed.
Definition Renderer.h:381
virtual ColorScheme system_color_scheme() const =0
The current system color scheme.
virtual bool BeginRenderTrace(const char *output_path, bool verbose=true)=0
Begin recording a render trace to the specified file path.
virtual RefPtr< View > CreateView(uint32_t width, uint32_t height, const ViewConfig &config, RefPtr< Session > session)=0
Create a new View to load and display web pages in.
virtual void RefreshDisplay(uint32_t display_id, double target_timestamp)=0
Notify the renderer that a display has refreshed, and when the resulting frame will be shown.
virtual void Recycle(RecycleMode mode=RecycleMode::Lightweight)=0
Recycle internal caches and reclaim memory.
virtual void EndRenderTrace()=0
End the current render trace.
virtual String GetMemoryUsage()=0
Get formatted memory usage statistics as a string.
virtual void SetDisplayUsesCustomClock(uint32_t display_id, bool uses_custom_clock)=0
Declare that a display's refresh timestamps are on your own timeline rather than the system clock.
virtual bool is_render_trace_active() const =0
Whether or not a render trace is currently being recorded.
virtual void RefreshDisplay(uint32_t display_id)=0
Notify the renderer that a display has refreshed.
virtual RefPtr< Session > CreateSession(bool is_persistent, const String &name)=0
Create a unique, named Session to store browsing data in (cookies, local storage, application cache,...
virtual bool display_uses_custom_clock(uint32_t display_id) const =0
Get whether a display was declared to use a custom clock.
virtual void PurgeMemory()=0
Attempt to release as much memory as possible.
virtual void SetDisplayRefreshRate(uint32_t display_id, double refresh_rate)=0
Declare a display's refresh rate.
virtual void Render()=0
Render all active views to their respective render-targets/surfaces.
virtual GCListener * gc_listener() const =0
Get the attached GCListener, if any.
virtual void LogMemoryUsage()=0
Print detailed memory usage statistics to the log.
void PostTask(F &&callback)
Post a callable to run on the Renderer's thread during a future call to Update().
Definition Renderer.h:363
virtual void FireGamepadButtonEvent(const GamepadButtonEvent &evt)=0
Fire a gamepad button event (to be called when a button value is changed).
virtual GCInfo gc_status() const =0
Get a snapshot of the current JS-heap reclamation state.
virtual void Recycle(RecycleMode mode, CodeDropMode code)=0
Reclaim memory, choosing how much compiled code to discard.
static RefPtr< Renderer > Create()
Create the core renderer singleton for the library.
Unicode string container with conversions for UTF-8, UTF-16, and UTF-32.
Definition String.h:31
Web-page container rendered to an offscreen surface.
Definition View.h:483
Root namespace for every public Ultralight type, function, and enumeration.
CodeDropMode
How much compiled JavaScript code a collection discards.
Definition GCListener.h:22
RecycleMode
Controls how aggressively Renderer::Recycle() reclaims memory.
Definition Renderer.h:37
@ Lightweight
A quick recycle, cheap enough to call every frame (the same work the automatic recycler does).
Definition Renderer.h:42
@ Full
A thorough recycle, for idle periods or transitions (eg, a loading screen).
Definition Renderer.h:48
ColorScheme
A page color scheme, as reported to pages via the prefers-color-scheme CSS media feature.
Definition View.h:78
A snapshot of the JavaScript heap's state (see Renderer::gc_status()).
Definition GCListener.h:32
View-specific configuration settings.
Definition View.h:100