Pulp 1.88.0
Cross-platform audio plugin framework
Loading...
Searching...
No Matches
skia_surface.hpp
Go to the documentation of this file.
1#pragma once
2
6#include <algorithm>
7#include <array>
8#include <chrono>
9#include <cstddef>
10#include <cstdint>
11#include <memory>
12#include <functional>
13#include <optional>
14#include <vector>
15
16namespace skgpu::graphite {
17class Context;
18}
19
20namespace pulp::render {
21
46
50constexpr bool frame_reached_output(FrameOutcome outcome) {
51 return outcome == FrameOutcome::presented ||
52 outcome == FrameOutcome::offscreen;
53}
54
63 std::size_t budgeted = 0;
64 std::size_t purgeable = 0;
65};
66
76 public:
77 using Clock = std::chrono::steady_clock;
78 static constexpr std::chrono::milliseconds kInterval{1000};
79 static constexpr std::chrono::milliseconds kUnusedAge{2000};
80 static constexpr std::size_t kUnusedFrames = 30;
81
82 explicit GpuIdleTrimSchedule(Clock::time_point start) : last_(start) {}
83
86 void note_frame(Clock::time_point start) {
87 frame_starts_[next_] = start;
88 next_ = (next_ + 1) % kUnusedFrames;
89 if (frames_ < kUnusedFrames)
90 ++frames_;
91 }
92
97 std::optional<std::chrono::milliseconds> unused_age(Clock::time_point now) const {
98 if (frames_ < kUnusedFrames)
99 return std::nullopt;
100 // With the ring full, the next slot to overwrite is the oldest start.
101 const auto span = std::chrono::ceil<std::chrono::milliseconds>(now - frame_starts_[next_]);
102 return std::max(kUnusedAge, span);
103 }
104
106 bool due(Clock::time_point now) {
107 if (now - last_ < kInterval)
108 return false;
109 last_ = now;
110 ++trims_;
111 return true;
112 }
113
115 std::uint64_t trims() const {
116 return trims_;
117 }
118
119 private:
120 Clock::time_point last_;
121 std::uint64_t trims_ = 0;
122 std::array<Clock::time_point, kUnusedFrames> frame_starts_{};
123 std::size_t next_ = 0;
124 std::size_t frames_ = 0;
125};
126
141public:
142 struct Config {
143 uint32_t width = 800;
144 uint32_t height = 600;
145 float scale_factor = 1.0f; // HiDPI
150 };
151
155 static std::unique_ptr<SkiaSurface> create(GpuSurface& gpu, const Config& config);
156
157#if defined(__EMSCRIPTEN__)
162 struct WebGlConfig {
163 const char* canvas_selector = "#pulp";
164 uint32_t width = 0;
165 uint32_t height = 0;
166 float scale_factor = 1.0f; // devicePixelRatio
168 };
169
181 static std::unique_ptr<SkiaSurface> create_webgl(const WebGlConfig& config);
182#endif
183
184 virtual ~SkiaSurface() = default;
185
198
210 virtual FrameOutcome end_frame() = 0;
211
216
220 virtual bool has_presentable_target() const = 0;
221
226 virtual void resize(uint32_t width, uint32_t height, float scale = 1.0f) = 0;
227
245 virtual bool set_persistent_scene(bool /*enable*/) { return false; }
246
248 virtual bool persistent_scene() const { return false; }
249
260
265
270 virtual bool read_current_rgba(std::vector<uint8_t>& pixels,
271 uint32_t& pixel_width,
272 uint32_t& pixel_height) = 0;
273
275 virtual bool is_available() const = 0;
276
283 virtual skgpu::graphite::Context* graphite_context() const = 0;
284
291 virtual double gpu_render_time_ms() const = 0;
292
296 virtual bool gpu_render_timing_available() const = 0;
297
301 virtual int gpu_frames_in_flight() const { return -1; }
302
309 virtual bool wait_for_submitted_work() {
310 return false;
311 }
312
314 class TrimLevel {
315 public:
318 static TrimLevel unused_for(std::chrono::milliseconds idle) {
319 return TrimLevel(idle, false);
320 }
321
322 static TrimLevel everything() {
323 return TrimLevel({}, true);
324 }
325
326 bool frees_everything() const {
327 return everything_;
328 }
329 std::chrono::milliseconds idle() const {
330 return idle_;
331 }
332
333 private:
334 TrimLevel(std::chrono::milliseconds idle, bool everything)
335 : idle_(idle), everything_(everything) {}
336 std::chrono::milliseconds idle_;
337 bool everything_;
338 };
339
352 virtual void trim_gpu_resources(TrimLevel /*level*/) {}
353
357 return {};
358 }
359
361 virtual std::uint64_t idle_trim_count() const {
362 return 0;
363 }
364
368 virtual std::uint64_t render_target_allocations() const {
369 return 0;
370 }
371
372#if !defined(__EMSCRIPTEN__)
380 using InsertOutcomeHook = bool (*)(bool accepted);
382
387 static void set_async_readback_for_testing(bool enabled);
388
395 using TrimClockHook = GpuIdleTrimSchedule::Clock::time_point (*)();
397#endif
398};
399
400} // namespace pulp::render
Definition canvas.hpp:240
GpuIdleTrimSchedule(Clock::time_point start)
Definition skia_surface.hpp:82
std::optional< std::chrono::milliseconds > unused_age(Clock::time_point now) const
How long a resource must have gone unused at now to be trimmed: at least kUnusedAge,...
Definition skia_surface.hpp:97
std::uint64_t trims() const
Trims due() has scheduled since construction.
Definition skia_surface.hpp:115
static constexpr std::size_t kUnusedFrames
Definition skia_surface.hpp:80
bool due(Clock::time_point now)
True when a trim is due at now; records now as the last trim.
Definition skia_surface.hpp:106
void note_frame(Clock::time_point start)
Records the start of a frame; begin_frame() calls it when it hands out a canvas, before anything in t...
Definition skia_surface.hpp:86
static constexpr std::chrono::milliseconds kUnusedAge
Definition skia_surface.hpp:79
static constexpr std::chrono::milliseconds kInterval
Definition skia_surface.hpp:78
std::chrono::steady_clock Clock
Definition skia_surface.hpp:77
Abstract GPU surface — a presentable rendering target backed by a native window/view.
Definition gpu_surface.hpp:112
How much a GPU trim frees.
Definition skia_surface.hpp:314
bool frees_everything() const
Definition skia_surface.hpp:326
static TrimLevel everything()
Free every purgeable resource, for a hidden or idle editor.
Definition skia_surface.hpp:322
static TrimLevel unused_for(std::chrono::milliseconds idle)
Free purgeable resources nothing has used for idle.
Definition skia_surface.hpp:318
std::chrono::milliseconds idle() const
Definition skia_surface.hpp:329
Skia Graphite rendering surface.
Definition skia_surface.hpp:140
GpuIdleTrimSchedule::Clock::time_point(*)() TrimClockHook
Test seam for the idle-trim clock.
Definition skia_surface.hpp:395
static void set_async_readback_for_testing(bool enabled)
Test seam for read_current_rgba().
virtual canvas::TextRasterPolicy text_raster_policy() const
The policy surfaces are currently created with.
Definition skia_surface.hpp:262
static std::unique_ptr< SkiaSurface > create(GpuSurface &gpu, const Config &config)
Create a Skia Graphite surface.
virtual void resize(uint32_t width, uint32_t height, float scale=1.0f)=0
Record a new logical size and backing scale.
virtual FrameOutcome end_frame()=0
End a frame: submits the Graphite recording to the GPU, and reports whether the frame reached its int...
virtual int gpu_frames_in_flight() const
Frames submitted to the GPU whose work has not finished yet (see GpuFramesInFlight in gpu_render_time...
Definition skia_surface.hpp:301
virtual bool read_current_rgba(std::vector< uint8_t > &pixels, uint32_t &pixel_width, uint32_t &pixel_height)=0
Read the current rendered frame into an RGBA buffer.
static void set_insert_outcome_hook_for_testing(InsertOutcomeHook hook)
virtual bool gpu_render_timing_available() const =0
Whether GPU render timing is available this run — the adapter offered timestamp-query AND Graphite ad...
virtual ~SkiaSurface()=default
virtual std::uint64_t render_target_allocations() const
Graphite render targets this surface has allocated (the offscreen and persistent-scene targets; the p...
Definition skia_surface.hpp:368
virtual void set_text_raster_policy(canvas::TextRasterPolicy)
Change the glyph preblend of every surface this one creates.
Definition skia_surface.hpp:259
virtual GpuCacheBytes gpu_cache_bytes() const
Bytes held by this surface's GPU resource caches.
Definition skia_surface.hpp:356
virtual bool has_presentable_target() const =0
Whether this surface has a presentable native drawable.
virtual skgpu::graphite::Context * graphite_context() const =0
The live Graphite Context backing this surface, or nullptr when Skia/Graphite is unavailable — includ...
virtual void trim_gpu_resources(TrimLevel)
Return purgeable GPU memory to the device.
Definition skia_surface.hpp:352
virtual FrameOutcome last_frame_outcome() const
Outcome of the most recent begin_frame()/end_frame() pair.
Definition skia_surface.hpp:215
virtual bool persistent_scene() const
Whether persistent-scene mode is currently active.
Definition skia_surface.hpp:248
virtual bool set_persistent_scene(bool)
Enable/disable persistent-scene mode (partial-repaint support, FU-2).
Definition skia_surface.hpp:245
virtual bool wait_for_submitted_work()
Block until the GPU has finished the work this surface submitted.
Definition skia_surface.hpp:309
virtual double gpu_render_time_ms() const =0
Most recent whole-recording GPU render time in milliseconds, sampled from Skia Graphite's GpuStats(kE...
static void set_trim_clock_for_testing(TrimClockHook hook)
virtual bool is_available() const =0
Check if Skia rendering is available.
virtual std::uint64_t idle_trim_count() const
Idle trims end_frame() has run since the surface was created.
Definition skia_surface.hpp:361
bool(*)(bool accepted) InsertOutcomeHook
Test seam for Graphite recording inserts.
Definition skia_surface.hpp:380
virtual canvas::Canvas * begin_frame()=0
Begin a frame: returns a Canvas to draw into, or nullptr on failure.
TextRasterPolicy
Glyph preblend a surface is created with.
Definition text_raster_policy.hpp:33
@ legacy
Definition text_raster_policy.hpp:34
Definition gpu_fwd.hpp:31
constexpr bool frame_reached_output(FrameOutcome outcome)
True when outcome means the frame's pixels reached their intended output, i.e.
Definition skia_surface.hpp:50
FrameOutcome
Where a frame actually ended up.
Definition skia_surface.hpp:35
@ recreate
The native drawable could not be wrapped or blitted.
Definition skia_surface.hpp:42
@ offscreen
No native surface exists by design; the offscreen target IS the output.
Definition skia_surface.hpp:39
@ presented
Drew into, and submitted to, the intended presentable drawable.
Definition skia_surface.hpp:37
@ failed
Definition gpu_pass.hpp:556
Definition skia_surface.hpp:16
GPU bytes held by a surface's Skia resource caches.
Definition skia_surface.hpp:62
std::size_t purgeable
Definition skia_surface.hpp:64
std::size_t budgeted
Definition skia_surface.hpp:63
Definition skia_surface.hpp:142
uint32_t height
Definition skia_surface.hpp:144
canvas::TextRasterPolicy text_raster_policy
Glyph preblend for every surface this one creates (frame target, offscreen, persistent scene,...
Definition skia_surface.hpp:149
uint32_t width
Definition skia_surface.hpp:143
float scale_factor
Definition skia_surface.hpp:145