Skip to main content

jag_draw/
lib.rs

1//! jag-draw: GPU-accelerated 2D rendering engine.
2#![allow(
3    clippy::collapsible_if,
4    clippy::too_many_arguments,
5    clippy::type_complexity,
6    clippy::get_first,
7    clippy::unnecessary_cast,
8    clippy::useless_conversion,
9    clippy::manual_clamp,
10    clippy::assign_op_pattern,
11    clippy::needless_borrow,
12    clippy::or_fun_call,
13    clippy::collapsible_match,
14    clippy::needless_range_loop,
15    clippy::manual_ok_or,
16    clippy::or_then_unwrap,
17    clippy::map_unwrap_or,
18    clippy::unnecessary_map_or,
19    clippy::unwrap_or_default,
20    clippy::manual_is_multiple_of,
21    clippy::manual_slice_size_calculation,
22    clippy::excessive_precision,
23    clippy::identity_op,
24    clippy::new_without_default,
25    clippy::needless_update,
26    clippy::empty_line_after_doc_comments,
27    clippy::doc_lazy_continuation,
28    clippy::field_reassign_with_default,
29    clippy::option_map_or_none
30)]
31
32use std::sync::Arc;
33
34use anyhow::Result;
35
36/// Re-export wgpu for downstream crates while avoiding direct dependency leakage.
37pub use wgpu;
38
39mod allocator;
40pub use allocator::{OwnedBuffer, OwnedTexture, RenderAllocator};
41
42/// Top-level engine handle.
43pub struct GraphicsEngine {
44    device: Arc<wgpu::Device>,
45    queue: Arc<wgpu::Queue>,
46    allocator: RenderAllocator,
47}
48
49impl GraphicsEngine {
50    /// Initialize the engine with an existing device/queue.
51    pub fn new(device: wgpu::Device, queue: wgpu::Queue) -> Self {
52        let device = Arc::new(device);
53        let queue = Arc::new(queue);
54        let allocator = RenderAllocator::new(device.clone());
55        Self {
56            device,
57            queue,
58            allocator,
59        }
60    }
61
62    /// Get a clone of the device handle.
63    pub fn device(&self) -> Arc<wgpu::Device> {
64        self.device.clone()
65    }
66
67    /// Get a clone of the queue handle.
68    pub fn queue(&self) -> Arc<wgpu::Queue> {
69        self.queue.clone()
70    }
71
72    /// Access the allocator.
73    pub fn allocator(&self) -> &RenderAllocator {
74        &self.allocator
75    }
76    pub fn allocator_mut(&mut self) -> &mut RenderAllocator {
77        &mut self.allocator
78    }
79
80    /// Placeholder render function to be expanded later.
81    pub fn render_dummy(&self) -> Result<()> {
82        // No-op for now.
83        let _ = (&self.device, &self.queue);
84        Ok(())
85    }
86}
87
88/// Choose an sRGB surface format when available; otherwise, pick the first format.
89pub fn choose_srgb_surface_format(
90    adapter: &wgpu::Adapter,
91    surface: &wgpu::Surface,
92) -> wgpu::TextureFormat {
93    let caps = surface.get_capabilities(adapter);
94    caps.formats
95        .iter()
96        .copied()
97        .find(|f| f.is_srgb())
98        .unwrap_or(caps.formats[0])
99}
100
101/// Create a surface configuration for the given size, favoring FIFO present mode when present.
102pub fn make_surface_config(
103    adapter: &wgpu::Adapter,
104    surface: &wgpu::Surface,
105    width: u32,
106    height: u32,
107) -> wgpu::SurfaceConfiguration {
108    let caps = surface.get_capabilities(adapter);
109    let format = choose_srgb_surface_format(adapter, surface);
110    let present_mode = caps
111        .present_modes
112        .iter()
113        .copied()
114        .find(|m| *m == wgpu::PresentMode::Fifo)
115        .unwrap_or(caps.present_modes[0]);
116    let alpha_mode = caps
117        .alpha_modes
118        .iter()
119        .copied()
120        .find(|m| *m == wgpu::CompositeAlphaMode::Opaque)
121        .unwrap_or(caps.alpha_modes[0]);
122    wgpu::SurfaceConfiguration {
123        usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
124        format,
125        width,
126        height,
127        present_mode,
128        alpha_mode,
129        view_formats: vec![],
130        desired_maximum_frame_latency: 1,
131    }
132}
133
134// Scene and display list (Phase 2)
135mod color; // sRGB conversion helpers for ColorLinPremul
136mod display_list;
137mod dpi;
138mod hit_test;
139mod image_cache;
140mod painter;
141mod pass_manager;
142mod pipeline;
143mod scene;
144mod svg;
145mod text;
146mod text_layout;
147mod upload;
148
149pub use display_list::*;
150pub use dpi::*;
151pub use hit_test::*;
152pub use image_cache::*;
153pub use painter::*;
154pub use pass_manager::Background as RootBackground;
155pub use pass_manager::*;
156pub use pipeline::Blitter;
157pub use pipeline::*;
158pub use scene::*;
159pub use svg::*;
160pub use text::*;
161pub use text_layout::*;
162pub use upload::*;
163
164// Optional: PDF export backend using `pdf-writer`.
165#[cfg(feature = "pdf_export")]
166mod pdf_backend;
167#[cfg(feature = "pdf_export")]
168pub use pdf_backend::render_display_list_to_pdf;