1use std::cell::{Cell, RefCell};
2use std::fmt;
3use std::marker::PhantomData;
4use std::mem;
5use std::ptr::NonNull;
6use std::rc::Rc;
7
8pub use maplibre_core::{PremultipliedRgba8Image, TextureImageInfo};
9use maplibre_native_core as maplibre_core;
10use maplibre_native_sys as sys;
11
12use crate::handle::{ThreadAffineNativeHandle, closed_handle_error, out_handle};
13use crate::map::{MapHandle, MapState};
14#[cfg(test)]
15use crate::{Feature, JsonValue};
16use crate::{HandleOperationError, Result};
17
18#[derive(Clone, Copy, PartialEq, Eq, Hash)]
24pub struct NativePointer {
25 address: usize,
26 _thread_affine: PhantomData<Rc<()>>,
27}
28
29impl NativePointer {
30 pub const NULL: Self = Self {
32 address: 0,
33 _thread_affine: PhantomData,
34 };
35
36 pub unsafe fn from_address(address: usize) -> Self {
45 if address == 0 {
46 Self::NULL
47 } else {
48 Self {
49 address,
50 _thread_affine: PhantomData,
51 }
52 }
53 }
54
55 pub unsafe fn from_ptr<T>(ptr: *mut T) -> Self {
62 unsafe { Self::from_address(ptr as usize) }
65 }
66
67 pub fn address(self) -> usize {
69 self.address
70 }
71
72 pub fn is_null(self) -> bool {
74 self.address == 0
75 }
76
77 pub unsafe fn as_ptr<T>(self) -> *mut T {
85 self.address as *mut T
86 }
87
88 fn as_void_ptr(self) -> *mut std::ffi::c_void {
89 self.address as *mut std::ffi::c_void
90 }
91}
92
93impl fmt::Debug for NativePointer {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 write!(f, "NativePointer(0x{:x})", self.address)
96 }
97}
98
99#[derive(Clone, Copy, PartialEq, Eq, Hash)]
106pub struct FrameNativePointer<'frame> {
107 address: usize,
108 _frame: PhantomData<&'frame ()>,
109 _thread_affine: PhantomData<Rc<()>>,
110}
111
112impl<'frame> FrameNativePointer<'frame> {
113 unsafe fn from_ptr<T>(ptr: *mut T) -> Self {
114 Self {
115 address: ptr as usize,
116 _frame: PhantomData,
117 _thread_affine: PhantomData,
118 }
119 }
120
121 pub unsafe fn address(self) -> usize {
130 self.address
131 }
132
133 pub fn is_null(self) -> bool {
135 self.address == 0
136 }
137
138 pub unsafe fn as_ptr<T>(self) -> *mut T {
146 self.address as *mut T
147 }
148}
149
150impl fmt::Debug for FrameNativePointer<'_> {
151 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
152 write!(f, "FrameNativePointer(0x{:x})", self.address)
153 }
154}
155
156#[derive(Clone, Copy, PartialEq, Eq, Hash)]
158pub struct FrameOpenGLTextureName<'frame> {
159 name: u32,
160 _frame: PhantomData<&'frame ()>,
161 _thread_affine: PhantomData<Rc<()>>,
162}
163
164impl<'frame> FrameOpenGLTextureName<'frame> {
165 fn new(name: u32) -> Self {
166 Self {
167 name,
168 _frame: PhantomData,
169 _thread_affine: PhantomData,
170 }
171 }
172
173 pub fn is_zero(self) -> bool {
175 self.name == 0
176 }
177
178 pub unsafe fn value(self) -> u32 {
186 self.name
187 }
188}
189
190impl fmt::Debug for FrameOpenGLTextureName<'_> {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 write!(f, "FrameOpenGLTextureName({})", self.name)
193 }
194}
195
196mod query;
197pub use query::{
198 FeatureExtensionResult, FeatureStateSelector, QueriedFeature, RenderedFeatureQueryOptions,
199 RenderedQueryGeometry, SourceFeatureQueryOptions,
200};
201#[derive(Debug, Clone, PartialEq)]
202#[non_exhaustive]
203pub struct RenderTargetExtent {
204 pub width: u32,
205 pub height: u32,
206 pub scale_factor: f64,
207}
208
209impl RenderTargetExtent {
210 pub fn new(width: u32, height: u32, scale_factor: f64) -> Self {
211 Self {
212 width,
213 height,
214 scale_factor,
215 }
216 }
217
218 pub(crate) fn to_core(&self) -> maplibre_core::render::RenderTargetExtentFields {
219 maplibre_core::render::RenderTargetExtentFields {
220 width: self.width,
221 height: self.height,
222 scale_factor: self.scale_factor,
223 }
224 }
225}
226
227impl Default for RenderTargetExtent {
228 fn default() -> Self {
229 Self::new(256, 256, 1.0)
230 }
231}
232
233#[derive(Debug, Clone, PartialEq)]
234#[non_exhaustive]
235pub struct MetalContextDescriptor {
236 pub device: NativePointer,
237}
238
239impl MetalContextDescriptor {
240 pub fn new(device: NativePointer) -> Self {
241 Self { device }
242 }
243
244 pub(crate) fn to_core(&self) -> maplibre_core::render::MetalContextDescriptorFields {
245 maplibre_core::render::MetalContextDescriptorFields {
246 device: self.device.as_void_ptr(),
247 }
248 }
249}
250
251impl Default for MetalContextDescriptor {
252 fn default() -> Self {
253 Self::new(NativePointer::NULL)
254 }
255}
256
257#[derive(Debug, Clone, PartialEq)]
258#[non_exhaustive]
259pub struct VulkanContextDescriptor {
260 pub instance: NativePointer,
261 pub physical_device: NativePointer,
262 pub device: NativePointer,
263 pub graphics_queue: NativePointer,
264 pub graphics_queue_family_index: u32,
265 pub get_instance_proc_addr: NativePointer,
266 pub get_device_proc_addr: NativePointer,
267}
268
269impl VulkanContextDescriptor {
270 #[allow(clippy::too_many_arguments)]
271 pub fn new(
272 instance: NativePointer,
273 physical_device: NativePointer,
274 device: NativePointer,
275 graphics_queue: NativePointer,
276 graphics_queue_family_index: u32,
277 ) -> Self {
278 Self {
279 instance,
280 physical_device,
281 device,
282 graphics_queue,
283 graphics_queue_family_index,
284 get_instance_proc_addr: NativePointer::NULL,
285 get_device_proc_addr: NativePointer::NULL,
286 }
287 }
288
289 pub fn with_proc_addresses(
290 mut self,
291 get_instance_proc_addr: NativePointer,
292 get_device_proc_addr: NativePointer,
293 ) -> Self {
294 self.get_instance_proc_addr = get_instance_proc_addr;
295 self.get_device_proc_addr = get_device_proc_addr;
296 self
297 }
298
299 pub(crate) fn to_core(&self) -> maplibre_core::render::VulkanContextDescriptorFields {
300 maplibre_core::render::VulkanContextDescriptorFields {
301 instance: self.instance.as_void_ptr(),
302 physical_device: self.physical_device.as_void_ptr(),
303 device: self.device.as_void_ptr(),
304 graphics_queue: self.graphics_queue.as_void_ptr(),
305 graphics_queue_family_index: self.graphics_queue_family_index,
306 get_instance_proc_addr: self.get_instance_proc_addr.as_void_ptr(),
307 get_device_proc_addr: self.get_device_proc_addr.as_void_ptr(),
308 }
309 }
310}
311
312impl Default for VulkanContextDescriptor {
313 fn default() -> Self {
314 Self::new(
315 NativePointer::NULL,
316 NativePointer::NULL,
317 NativePointer::NULL,
318 NativePointer::NULL,
319 0,
320 )
321 }
322}
323
324#[derive(Debug, Clone, PartialEq)]
325#[non_exhaustive]
326pub struct WglContextDescriptor {
327 pub device_context: NativePointer,
328 pub share_context: NativePointer,
329 pub get_proc_address: NativePointer,
330}
331
332impl WglContextDescriptor {
333 pub fn new(device_context: NativePointer, share_context: NativePointer) -> Self {
334 Self {
335 device_context,
336 share_context,
337 get_proc_address: NativePointer::NULL,
338 }
339 }
340
341 pub fn with_proc_address(mut self, get_proc_address: NativePointer) -> Self {
342 self.get_proc_address = get_proc_address;
343 self
344 }
345
346 pub(crate) fn to_core(&self) -> maplibre_core::render::WglContextDescriptorFields {
347 maplibre_core::render::WglContextDescriptorFields {
348 device_context: self.device_context.as_void_ptr(),
349 share_context: self.share_context.as_void_ptr(),
350 get_proc_address: self.get_proc_address.as_void_ptr(),
351 }
352 }
353}
354
355impl Default for WglContextDescriptor {
356 fn default() -> Self {
357 Self::new(NativePointer::NULL, NativePointer::NULL)
358 }
359}
360
361#[derive(Debug, Clone, PartialEq)]
362#[non_exhaustive]
363pub struct EglContextDescriptor {
364 pub display: NativePointer,
365 pub config: NativePointer,
366 pub share_context: NativePointer,
367 pub get_proc_address: NativePointer,
368}
369
370impl EglContextDescriptor {
371 pub fn new(
372 display: NativePointer,
373 config: NativePointer,
374 share_context: NativePointer,
375 ) -> Self {
376 Self {
377 display,
378 config,
379 share_context,
380 get_proc_address: NativePointer::NULL,
381 }
382 }
383
384 pub fn with_proc_address(mut self, get_proc_address: NativePointer) -> Self {
385 self.get_proc_address = get_proc_address;
386 self
387 }
388
389 pub(crate) fn to_core(&self) -> maplibre_core::render::EglContextDescriptorFields {
390 maplibre_core::render::EglContextDescriptorFields {
391 display: self.display.as_void_ptr(),
392 config: self.config.as_void_ptr(),
393 share_context: self.share_context.as_void_ptr(),
394 get_proc_address: self.get_proc_address.as_void_ptr(),
395 }
396 }
397}
398
399impl Default for EglContextDescriptor {
400 fn default() -> Self {
401 Self::new(
402 NativePointer::NULL,
403 NativePointer::NULL,
404 NativePointer::NULL,
405 )
406 }
407}
408
409#[derive(Debug, Clone, PartialEq)]
410#[non_exhaustive]
411pub enum OpenGLContextDescriptor {
412 Wgl(WglContextDescriptor),
413 Egl(EglContextDescriptor),
414}
415
416impl OpenGLContextDescriptor {
417 pub fn wgl(descriptor: WglContextDescriptor) -> Self {
418 Self::Wgl(descriptor)
419 }
420
421 pub fn egl(descriptor: EglContextDescriptor) -> Self {
422 Self::Egl(descriptor)
423 }
424
425 pub(crate) fn to_core(&self) -> maplibre_core::render::OpenGLContextDescriptorFields {
426 match self {
427 Self::Wgl(descriptor) => {
428 maplibre_core::render::OpenGLContextDescriptorFields::Wgl(descriptor.to_core())
429 }
430 Self::Egl(descriptor) => {
431 maplibre_core::render::OpenGLContextDescriptorFields::Egl(descriptor.to_core())
432 }
433 }
434 }
435}
436
437#[derive(Debug, Clone, PartialEq)]
438#[non_exhaustive]
439pub struct MetalSurfaceDescriptor {
440 pub extent: RenderTargetExtent,
441 pub context: MetalContextDescriptor,
442 pub layer: NativePointer,
443}
444
445impl MetalSurfaceDescriptor {
446 pub fn new(
447 extent: RenderTargetExtent,
448 context: MetalContextDescriptor,
449 layer: NativePointer,
450 ) -> Self {
451 Self {
452 extent,
453 context,
454 layer,
455 }
456 }
457
458 pub(crate) fn to_native(&self) -> sys::mln_metal_surface_descriptor {
459 maplibre_core::render::metal_surface_descriptor_to_native(
460 maplibre_core::render::MetalSurfaceDescriptorFields {
461 extent: self.extent.to_core(),
462 context: self.context.to_core(),
463 layer: self.layer.as_void_ptr(),
464 },
465 )
466 }
467}
468
469#[derive(Debug, Clone, PartialEq)]
470#[non_exhaustive]
471pub struct VulkanSurfaceDescriptor {
472 pub extent: RenderTargetExtent,
473 pub context: VulkanContextDescriptor,
474 pub surface: NativePointer,
475}
476
477impl VulkanSurfaceDescriptor {
478 pub fn new(
479 extent: RenderTargetExtent,
480 context: VulkanContextDescriptor,
481 surface: NativePointer,
482 ) -> Self {
483 Self {
484 extent,
485 context,
486 surface,
487 }
488 }
489
490 pub(crate) fn to_native(&self) -> sys::mln_vulkan_surface_descriptor {
491 maplibre_core::render::vulkan_surface_descriptor_to_native(
492 maplibre_core::render::VulkanSurfaceDescriptorFields {
493 extent: self.extent.to_core(),
494 context: self.context.to_core(),
495 surface: self.surface.as_void_ptr(),
496 },
497 )
498 }
499}
500
501#[derive(Debug, Clone, PartialEq)]
502#[non_exhaustive]
503pub struct OpenGLSurfaceDescriptor {
504 pub extent: RenderTargetExtent,
505 pub context: OpenGLContextDescriptor,
506 pub surface: NativePointer,
507}
508
509impl OpenGLSurfaceDescriptor {
510 pub fn new(
511 extent: RenderTargetExtent,
512 context: OpenGLContextDescriptor,
513 surface: NativePointer,
514 ) -> Self {
515 Self {
516 extent,
517 context,
518 surface,
519 }
520 }
521
522 pub(crate) fn to_native(&self) -> sys::mln_opengl_surface_descriptor {
523 maplibre_core::render::opengl_surface_descriptor_to_native(
524 maplibre_core::render::OpenGLSurfaceDescriptorFields {
525 extent: self.extent.to_core(),
526 context: self.context.to_core(),
527 surface: self.surface.as_void_ptr(),
528 },
529 )
530 }
531}
532
533#[derive(Debug, Clone, PartialEq)]
534#[non_exhaustive]
535pub struct MetalOwnedTextureDescriptor {
536 pub extent: RenderTargetExtent,
537 pub context: MetalContextDescriptor,
538}
539
540impl MetalOwnedTextureDescriptor {
541 pub fn new(extent: RenderTargetExtent, context: MetalContextDescriptor) -> Self {
542 Self { extent, context }
543 }
544
545 pub(crate) fn to_native(&self) -> sys::mln_metal_owned_texture_descriptor {
546 maplibre_core::render::metal_owned_texture_descriptor_to_native(
547 maplibre_core::render::MetalOwnedTextureDescriptorFields {
548 extent: self.extent.to_core(),
549 context: self.context.to_core(),
550 },
551 )
552 }
553}
554
555#[derive(Debug, Clone, PartialEq)]
556#[non_exhaustive]
557pub struct MetalBorrowedTextureDescriptor {
558 pub extent: RenderTargetExtent,
559 pub texture: NativePointer,
560}
561
562impl MetalBorrowedTextureDescriptor {
563 pub fn new(extent: RenderTargetExtent, texture: NativePointer) -> Self {
564 Self { extent, texture }
565 }
566
567 pub(crate) fn to_native(&self) -> sys::mln_metal_borrowed_texture_descriptor {
568 maplibre_core::render::metal_borrowed_texture_descriptor_to_native(
569 maplibre_core::render::MetalBorrowedTextureDescriptorFields {
570 extent: self.extent.to_core(),
571 texture: self.texture.as_void_ptr(),
572 },
573 )
574 }
575}
576
577#[derive(Debug, Clone, PartialEq)]
578#[non_exhaustive]
579pub struct VulkanOwnedTextureDescriptor {
580 pub extent: RenderTargetExtent,
581 pub context: VulkanContextDescriptor,
582}
583
584impl VulkanOwnedTextureDescriptor {
585 pub fn new(extent: RenderTargetExtent, context: VulkanContextDescriptor) -> Self {
586 Self { extent, context }
587 }
588
589 pub(crate) fn to_native(&self) -> sys::mln_vulkan_owned_texture_descriptor {
590 maplibre_core::render::vulkan_owned_texture_descriptor_to_native(
591 maplibre_core::render::VulkanOwnedTextureDescriptorFields {
592 extent: self.extent.to_core(),
593 context: self.context.to_core(),
594 },
595 )
596 }
597}
598
599#[derive(Debug, Clone, PartialEq)]
600#[non_exhaustive]
601pub struct VulkanBorrowedTextureDescriptor {
602 pub extent: RenderTargetExtent,
603 pub context: VulkanContextDescriptor,
604 pub image: NativePointer,
605 pub image_view: NativePointer,
606 pub format: u32,
607 pub initial_layout: u32,
608 pub final_layout: u32,
609}
610
611impl VulkanBorrowedTextureDescriptor {
612 #[allow(clippy::too_many_arguments)]
613 pub fn new(
614 extent: RenderTargetExtent,
615 context: VulkanContextDescriptor,
616 image: NativePointer,
617 image_view: NativePointer,
618 format: u32,
619 initial_layout: u32,
620 final_layout: u32,
621 ) -> Self {
622 Self {
623 extent,
624 context,
625 image,
626 image_view,
627 format,
628 initial_layout,
629 final_layout,
630 }
631 }
632
633 pub(crate) fn to_native(&self) -> sys::mln_vulkan_borrowed_texture_descriptor {
634 maplibre_core::render::vulkan_borrowed_texture_descriptor_to_native(
635 maplibre_core::render::VulkanBorrowedTextureDescriptorFields {
636 extent: self.extent.to_core(),
637 context: self.context.to_core(),
638 image: self.image.as_void_ptr(),
639 image_view: self.image_view.as_void_ptr(),
640 format: self.format,
641 initial_layout: self.initial_layout,
642 final_layout: self.final_layout,
643 },
644 )
645 }
646}
647
648#[derive(Debug, Clone, PartialEq)]
649#[non_exhaustive]
650pub struct OpenGLOwnedTextureDescriptor {
651 pub extent: RenderTargetExtent,
652 pub context: OpenGLContextDescriptor,
653}
654
655impl OpenGLOwnedTextureDescriptor {
656 pub fn new(extent: RenderTargetExtent, context: OpenGLContextDescriptor) -> Self {
657 Self { extent, context }
658 }
659
660 pub(crate) fn to_native(&self) -> sys::mln_opengl_owned_texture_descriptor {
661 maplibre_core::render::opengl_owned_texture_descriptor_to_native(
662 maplibre_core::render::OpenGLOwnedTextureDescriptorFields {
663 extent: self.extent.to_core(),
664 context: self.context.to_core(),
665 },
666 )
667 }
668}
669
670#[derive(Debug, Clone, PartialEq)]
671#[non_exhaustive]
672pub struct OpenGLBorrowedTextureDescriptor {
673 pub extent: RenderTargetExtent,
674 pub context: OpenGLContextDescriptor,
675 pub texture: u32,
676 pub target: u32,
677}
678
679impl OpenGLBorrowedTextureDescriptor {
680 pub fn new(
681 extent: RenderTargetExtent,
682 context: OpenGLContextDescriptor,
683 texture: u32,
684 target: u32,
685 ) -> Self {
686 Self {
687 extent,
688 context,
689 texture,
690 target,
691 }
692 }
693
694 pub(crate) fn to_native(&self) -> sys::mln_opengl_borrowed_texture_descriptor {
695 maplibre_core::render::opengl_borrowed_texture_descriptor_to_native(
696 maplibre_core::render::OpenGLBorrowedTextureDescriptorFields {
697 extent: self.extent.to_core(),
698 context: self.context.to_core(),
699 texture: self.texture,
700 target: self.target,
701 },
702 )
703 }
704}
705
706#[derive(Debug)]
707struct RenderSessionState {
708 handle: ThreadAffineNativeHandle<sys::mln_render_session>,
709 map: RefCell<Option<Rc<MapState>>>,
710 detached: Cell<bool>,
711 frame_acquired: Cell<bool>,
712}
713
714impl RenderSessionState {
715 fn new(ptr: NonNull<sys::mln_render_session>, map: Rc<MapState>) -> Self {
716 let handle = unsafe {
719 ThreadAffineNativeHandle::from_raw(
720 ptr,
721 sys::mln_render_session_destroy,
722 "mln_render_session",
723 )
724 };
725 Self {
726 handle,
727 map: RefCell::new(Some(map)),
728 detached: Cell::new(false),
729 frame_acquired: Cell::new(false),
730 }
731 }
732
733 fn ensure_no_frame_acquired(&self) -> Result<()> {
734 if self.frame_acquired.get() {
735 Err(frame_acquired_error())
736 } else {
737 Ok(())
738 }
739 }
740
741 fn as_ptr(&self) -> Result<*mut sys::mln_render_session> {
742 let ptr = self.handle.as_ptr();
743 if ptr.is_null() {
744 Err(closed_handle_error("RenderSessionHandle"))
745 } else {
746 Ok(ptr)
747 }
748 }
749
750 fn close(&self) -> Result<()> {
751 self.handle.close()?;
752 self.map.borrow_mut().take();
753 Ok(())
754 }
755}
756
757pub struct RenderSessionHandle {
759 inner: Rc<RenderSessionState>,
760}
761
762impl fmt::Debug for RenderSessionHandle {
763 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
764 f.debug_struct("RenderSessionHandle")
765 .field("closed", &self.is_closed())
766 .field("detached", &self.inner.detached.get())
767 .finish()
768 }
769}
770
771pub struct DetachedRenderSessionHandle {
773 inner: Rc<RenderSessionState>,
774}
775
776impl fmt::Debug for DetachedRenderSessionHandle {
777 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
778 f.debug_struct("DetachedRenderSessionHandle")
779 .field("closed", &self.is_closed())
780 .finish()
781 }
782}
783
784impl DetachedRenderSessionHandle {
785 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
787 if let Err(error) = self.inner.close() {
788 return Err(HandleOperationError::new(error, self));
789 }
790 Ok(())
791 }
792
793 pub fn is_closed(&self) -> bool {
794 self.inner.handle.is_closed()
795 }
796}
797
798fn frame_acquired_error() -> crate::Error {
799 crate::Error::new(
800 crate::ErrorKind::InvalidState,
801 None,
802 "render session has an acquired texture frame",
803 )
804}
805
806#[derive(Debug, Clone, Copy, PartialEq)]
811#[non_exhaustive]
812pub struct MetalOwnedTextureFrame {
813 pub generation: u64,
814 pub width: u32,
815 pub height: u32,
816 pub scale_factor: f64,
817 pub frame_id: u64,
818 pub pixel_format: u64,
819}
820
821impl MetalOwnedTextureFrame {
822 fn from_native(raw: &sys::mln_metal_owned_texture_frame) -> Self {
823 Self {
824 generation: raw.generation,
825 width: raw.width,
826 height: raw.height,
827 scale_factor: raw.scale_factor,
828 frame_id: raw.frame_id,
829 pixel_format: raw.pixel_format,
830 }
831 }
832}
833
834#[derive(Debug, Clone, Copy, PartialEq)]
839#[non_exhaustive]
840pub struct VulkanOwnedTextureFrame {
841 pub generation: u64,
842 pub width: u32,
843 pub height: u32,
844 pub scale_factor: f64,
845 pub frame_id: u64,
846 pub format: u32,
847 pub layout: u32,
848}
849
850impl VulkanOwnedTextureFrame {
851 fn from_native(raw: &sys::mln_vulkan_owned_texture_frame) -> Self {
852 Self {
853 generation: raw.generation,
854 width: raw.width,
855 height: raw.height,
856 scale_factor: raw.scale_factor,
857 frame_id: raw.frame_id,
858 format: raw.format,
859 layout: raw.layout,
860 }
861 }
862}
863
864#[derive(Debug, Clone, Copy, PartialEq)]
869#[non_exhaustive]
870pub struct OpenGLOwnedTextureFrame {
871 pub generation: u64,
872 pub width: u32,
873 pub height: u32,
874 pub scale_factor: f64,
875 pub frame_id: u64,
876 pub target: u32,
877 pub internal_format: u32,
878 pub format: u32,
879 pub type_: u32,
880}
881
882impl OpenGLOwnedTextureFrame {
883 fn from_native(raw: &sys::mln_opengl_owned_texture_frame) -> Self {
884 Self {
885 generation: raw.generation,
886 width: raw.width,
887 height: raw.height,
888 scale_factor: raw.scale_factor,
889 frame_id: raw.frame_id,
890 target: raw.target,
891 internal_format: raw.internal_format,
892 format: raw.format,
893 type_: raw.type_,
894 }
895 }
896}
897
898pub struct MetalOwnedTextureFrameHandle {
902 session: Rc<RenderSessionState>,
903 raw: sys::mln_metal_owned_texture_frame,
904 frame: MetalOwnedTextureFrame,
905 closed: Cell<bool>,
906 _thread_affine: PhantomData<Rc<()>>,
907}
908
909impl fmt::Debug for MetalOwnedTextureFrameHandle {
910 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
911 f.debug_struct("MetalOwnedTextureFrameHandle")
912 .field("closed", &self.is_closed())
913 .field("frame", &self.frame)
914 .finish()
915 }
916}
917
918impl MetalOwnedTextureFrameHandle {
919 pub fn frame(&self) -> Result<&MetalOwnedTextureFrame> {
921 if self.closed.get() {
922 Err(closed_handle_error("MetalOwnedTextureFrameHandle"))
923 } else {
924 Ok(&self.frame)
925 }
926 }
927
928 pub fn is_closed(&self) -> bool {
929 self.closed.get()
930 }
931
932 pub unsafe fn texture(&self) -> Result<FrameNativePointer<'_>> {
940 if self.closed.get() {
941 Err(closed_handle_error("MetalOwnedTextureFrameHandle"))
942 } else {
943 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.texture) })
946 }
947 }
948
949 pub unsafe fn device(&self) -> Result<FrameNativePointer<'_>> {
956 if self.closed.get() {
957 Err(closed_handle_error("MetalOwnedTextureFrameHandle"))
958 } else {
959 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.device) })
961 }
962 }
963
964 #[allow(clippy::result_large_err)]
966 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
967 if self.closed.get() {
968 return Ok(());
969 }
970 let session = match self.session.as_ptr() {
971 Ok(session) => session,
972 Err(error) => return Err(HandleOperationError::new(error, self)),
973 };
974 if let Err(error) = maplibre_core::check(unsafe {
977 sys::mln_metal_owned_texture_release_frame(session, &self.raw)
978 }) {
979 return Err(HandleOperationError::new(error, self));
980 }
981 self.closed.set(true);
982 self.session.frame_acquired.set(false);
983 Ok(())
984 }
985}
986
987impl Drop for MetalOwnedTextureFrameHandle {
988 fn drop(&mut self) {
989 if self.closed.get() {
990 return;
991 }
992 if let Ok(session) = self.session.as_ptr() {
993 let status = unsafe { sys::mln_metal_owned_texture_release_frame(session, &self.raw) };
996 if status == sys::MLN_STATUS_OK {
997 self.closed.set(true);
998 self.session.frame_acquired.set(false);
999 }
1000 }
1001 }
1002}
1003
1004pub struct VulkanOwnedTextureFrameHandle {
1009 session: Rc<RenderSessionState>,
1010 raw: sys::mln_vulkan_owned_texture_frame,
1011 frame: VulkanOwnedTextureFrame,
1012 closed: Cell<bool>,
1013 _thread_affine: PhantomData<Rc<()>>,
1014}
1015
1016impl fmt::Debug for VulkanOwnedTextureFrameHandle {
1017 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1018 f.debug_struct("VulkanOwnedTextureFrameHandle")
1019 .field("closed", &self.is_closed())
1020 .field("frame", &self.frame)
1021 .finish()
1022 }
1023}
1024
1025impl VulkanOwnedTextureFrameHandle {
1026 pub fn frame(&self) -> Result<&VulkanOwnedTextureFrame> {
1028 if self.closed.get() {
1029 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1030 } else {
1031 Ok(&self.frame)
1032 }
1033 }
1034
1035 pub fn is_closed(&self) -> bool {
1036 self.closed.get()
1037 }
1038
1039 pub unsafe fn image(&self) -> Result<FrameNativePointer<'_>> {
1047 if self.closed.get() {
1048 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1049 } else {
1050 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.image) })
1053 }
1054 }
1055
1056 pub unsafe fn image_view(&self) -> Result<FrameNativePointer<'_>> {
1063 if self.closed.get() {
1064 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1065 } else {
1066 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.image_view) })
1068 }
1069 }
1070
1071 pub unsafe fn device(&self) -> Result<FrameNativePointer<'_>> {
1078 if self.closed.get() {
1079 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1080 } else {
1081 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.device) })
1083 }
1084 }
1085
1086 #[allow(clippy::result_large_err)]
1088 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1089 if self.closed.get() {
1090 return Ok(());
1091 }
1092 let session = match self.session.as_ptr() {
1093 Ok(session) => session,
1094 Err(error) => return Err(HandleOperationError::new(error, self)),
1095 };
1096 if let Err(error) = maplibre_core::check(unsafe {
1099 sys::mln_vulkan_owned_texture_release_frame(session, &self.raw)
1100 }) {
1101 return Err(HandleOperationError::new(error, self));
1102 }
1103 self.closed.set(true);
1104 self.session.frame_acquired.set(false);
1105 Ok(())
1106 }
1107}
1108
1109impl Drop for VulkanOwnedTextureFrameHandle {
1110 fn drop(&mut self) {
1111 if self.closed.get() {
1112 return;
1113 }
1114 if let Ok(session) = self.session.as_ptr() {
1115 let status = unsafe { sys::mln_vulkan_owned_texture_release_frame(session, &self.raw) };
1118 if status == sys::MLN_STATUS_OK {
1119 self.closed.set(true);
1120 self.session.frame_acquired.set(false);
1121 }
1122 }
1123 }
1124}
1125
1126pub struct OpenGLOwnedTextureFrameHandle {
1130 session: Rc<RenderSessionState>,
1131 raw: sys::mln_opengl_owned_texture_frame,
1132 frame: OpenGLOwnedTextureFrame,
1133 closed: Cell<bool>,
1134 _thread_affine: PhantomData<Rc<()>>,
1135}
1136
1137impl fmt::Debug for OpenGLOwnedTextureFrameHandle {
1138 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1139 f.debug_struct("OpenGLOwnedTextureFrameHandle")
1140 .field("closed", &self.is_closed())
1141 .field("frame", &self.frame)
1142 .finish()
1143 }
1144}
1145
1146impl OpenGLOwnedTextureFrameHandle {
1147 pub fn frame(&self) -> Result<&OpenGLOwnedTextureFrame> {
1149 if self.closed.get() {
1150 Err(closed_handle_error("OpenGLOwnedTextureFrameHandle"))
1151 } else {
1152 Ok(&self.frame)
1153 }
1154 }
1155
1156 pub fn is_closed(&self) -> bool {
1157 self.closed.get()
1158 }
1159
1160 pub fn texture(&self) -> Result<FrameOpenGLTextureName<'_>> {
1162 if self.closed.get() {
1163 Err(closed_handle_error("OpenGLOwnedTextureFrameHandle"))
1164 } else {
1165 Ok(FrameOpenGLTextureName::new(self.raw.texture))
1166 }
1167 }
1168
1169 #[allow(clippy::result_large_err)]
1171 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1172 if self.closed.get() {
1173 return Ok(());
1174 }
1175 let session = match self.session.as_ptr() {
1176 Ok(session) => session,
1177 Err(error) => return Err(HandleOperationError::new(error, self)),
1178 };
1179 if let Err(error) = maplibre_core::check(unsafe {
1182 sys::mln_opengl_owned_texture_release_frame(session, &self.raw)
1183 }) {
1184 return Err(HandleOperationError::new(error, self));
1185 }
1186 self.closed.set(true);
1187 self.session.frame_acquired.set(false);
1188 Ok(())
1189 }
1190}
1191
1192impl Drop for OpenGLOwnedTextureFrameHandle {
1193 fn drop(&mut self) {
1194 if self.closed.get() {
1195 return;
1196 }
1197 if let Ok(session) = self.session.as_ptr() {
1198 let status = unsafe { sys::mln_opengl_owned_texture_release_frame(session, &self.raw) };
1201 if status == sys::MLN_STATUS_OK {
1202 self.closed.set(true);
1203 self.session.frame_acquired.set(false);
1204 }
1205 }
1206 }
1207}
1208
1209impl RenderSessionHandle {
1210 pub(crate) fn attach<F>(map: &MapHandle, attach: F) -> Result<Self>
1211 where
1212 F: FnOnce(*mut sys::mln_map, *mut *mut sys::mln_render_session) -> sys::mln_status,
1213 {
1214 let map_ptr = map.inner.as_ptr()?;
1215 let mut out = maplibre_core::ptr::OutPtr::<sys::mln_render_session>::new();
1216 let status = attach(map_ptr, out.as_mut_ptr());
1217 maplibre_core::check(status)?;
1218 let ptr = out_handle(out, "mln_render_session")?;
1219 Ok(Self {
1220 inner: Rc::new(RenderSessionState::new(ptr, Rc::clone(&map.inner))),
1221 })
1222 }
1223
1224 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1229 if let Err(error) = self.inner.ensure_no_frame_acquired() {
1230 return Err(HandleOperationError::new(error, self));
1231 }
1232 if let Err(error) = self.inner.close() {
1233 return Err(HandleOperationError::new(error, self));
1234 }
1235 Ok(())
1236 }
1237
1238 pub fn is_closed(&self) -> bool {
1239 self.inner.handle.is_closed()
1240 }
1241
1242 pub fn resize(&self, width: u32, height: u32, scale_factor: f64) -> Result<()> {
1244 self.inner.ensure_no_frame_acquired()?;
1245 let session = self.inner.as_ptr()?;
1246 maplibre_core::check(unsafe {
1248 sys::mln_render_session_resize(session, width, height, scale_factor)
1249 })
1250 }
1251
1252 pub fn render_update(&self) -> Result<()> {
1254 self.inner.ensure_no_frame_acquired()?;
1255 let session = self.inner.as_ptr()?;
1256 maplibre_core::check(unsafe { sys::mln_render_session_render_update(session) })
1258 }
1259
1260 pub fn detach(
1265 self,
1266 ) -> std::result::Result<DetachedRenderSessionHandle, HandleOperationError<Self>> {
1267 if let Err(error) = self.inner.ensure_no_frame_acquired() {
1268 return Err(HandleOperationError::new(error, self));
1269 }
1270 let session = match self.inner.as_ptr() {
1271 Ok(session) => session,
1272 Err(error) => return Err(HandleOperationError::new(error, self)),
1273 };
1274 if let Err(error) = maplibre_core::check(unsafe { sys::mln_render_session_detach(session) })
1276 {
1277 return Err(HandleOperationError::new(error, self));
1278 }
1279 self.inner.detached.set(true);
1280 Ok(DetachedRenderSessionHandle {
1281 inner: Rc::clone(&self.inner),
1282 })
1283 }
1284
1285 pub fn reduce_memory_use(&self) -> Result<()> {
1287 self.inner.ensure_no_frame_acquired()?;
1288 let session = self.inner.as_ptr()?;
1289 maplibre_core::check(unsafe { sys::mln_render_session_reduce_memory_use(session) })
1291 }
1292
1293 pub fn clear_data(&self) -> Result<()> {
1295 self.inner.ensure_no_frame_acquired()?;
1296 let session = self.inner.as_ptr()?;
1297 maplibre_core::check(unsafe { sys::mln_render_session_clear_data(session) })
1299 }
1300
1301 pub fn dump_debug_logs(&self) -> Result<()> {
1303 self.inner.ensure_no_frame_acquired()?;
1304 let session = self.inner.as_ptr()?;
1305 maplibre_core::check(unsafe { sys::mln_render_session_dump_debug_logs(session) })
1307 }
1308
1309 pub fn texture_image_info(&self) -> Result<TextureImageInfo> {
1311 self.inner.ensure_no_frame_acquired()?;
1312 let session = self.inner.as_ptr()?;
1313 let mut info = unsafe { sys::mln_texture_image_info_default() };
1315 let status = unsafe {
1318 sys::mln_texture_read_premultiplied_rgba8(session, std::ptr::null_mut(), 0, &mut info)
1319 };
1320 if status == sys::MLN_STATUS_OK
1321 || (status == sys::MLN_STATUS_INVALID_ARGUMENT && info.byte_length > 0)
1322 {
1323 Ok(maplibre_core::values::texture_image_info_from_native(&info))
1324 } else {
1325 Err(crate::Error::from_status(status))
1326 }
1327 }
1328
1329 pub fn read_premultiplied_rgba8_into(&self, data: &mut [u8]) -> Result<TextureImageInfo> {
1331 self.inner.ensure_no_frame_acquired()?;
1332 let session = self.inner.as_ptr()?;
1333 let mut info = unsafe { sys::mln_texture_image_info_default() };
1335 let data_ptr = if data.is_empty() {
1336 std::ptr::null_mut()
1337 } else {
1338 data.as_mut_ptr()
1339 };
1340 maplibre_core::check(unsafe {
1344 sys::mln_texture_read_premultiplied_rgba8(session, data_ptr, data.len(), &mut info)
1345 })?;
1346 Ok(maplibre_core::values::texture_image_info_from_native(&info))
1347 }
1348
1349 pub fn read_premultiplied_rgba8(&self) -> Result<PremultipliedRgba8Image> {
1351 let info = self.texture_image_info()?;
1352 let mut data = vec![0; info.byte_length];
1353 let info = self.read_premultiplied_rgba8_into(&mut data)?;
1354 Ok(PremultipliedRgba8Image::new(info, data))
1355 }
1356
1357 pub fn acquire_metal_owned_texture_frame(&self) -> Result<MetalOwnedTextureFrameHandle> {
1359 self.inner.ensure_no_frame_acquired()?;
1360 let session = self.inner.as_ptr()?;
1361 let mut raw = empty_metal_owned_texture_frame();
1362 maplibre_core::check(unsafe {
1364 sys::mln_metal_owned_texture_acquire_frame(session, &mut raw)
1365 })?;
1366 self.inner.frame_acquired.set(true);
1367 Ok(MetalOwnedTextureFrameHandle {
1368 session: Rc::clone(&self.inner),
1369 frame: MetalOwnedTextureFrame::from_native(&raw),
1370 raw,
1371 closed: Cell::new(false),
1372 _thread_affine: PhantomData,
1373 })
1374 }
1375
1376 pub fn acquire_vulkan_owned_texture_frame(&self) -> Result<VulkanOwnedTextureFrameHandle> {
1378 self.inner.ensure_no_frame_acquired()?;
1379 let session = self.inner.as_ptr()?;
1380 let mut raw = empty_vulkan_owned_texture_frame();
1381 maplibre_core::check(unsafe {
1383 sys::mln_vulkan_owned_texture_acquire_frame(session, &mut raw)
1384 })?;
1385 self.inner.frame_acquired.set(true);
1386 Ok(VulkanOwnedTextureFrameHandle {
1387 session: Rc::clone(&self.inner),
1388 frame: VulkanOwnedTextureFrame::from_native(&raw),
1389 raw,
1390 closed: Cell::new(false),
1391 _thread_affine: PhantomData,
1392 })
1393 }
1394
1395 pub fn acquire_opengl_owned_texture_frame(&self) -> Result<OpenGLOwnedTextureFrameHandle> {
1397 self.inner.ensure_no_frame_acquired()?;
1398 let session = self.inner.as_ptr()?;
1399 let mut raw = empty_opengl_owned_texture_frame();
1400 maplibre_core::check(unsafe {
1402 sys::mln_opengl_owned_texture_acquire_frame(session, &mut raw)
1403 })?;
1404 self.inner.frame_acquired.set(true);
1405 Ok(OpenGLOwnedTextureFrameHandle {
1406 session: Rc::clone(&self.inner),
1407 frame: OpenGLOwnedTextureFrame::from_native(&raw),
1408 raw,
1409 closed: Cell::new(false),
1410 _thread_affine: PhantomData,
1411 })
1412 }
1413}
1414
1415fn empty_metal_owned_texture_frame() -> sys::mln_metal_owned_texture_frame {
1416 sys::mln_metal_owned_texture_frame {
1417 size: mem::size_of::<sys::mln_metal_owned_texture_frame>() as u32,
1418 generation: 0,
1419 width: 0,
1420 height: 0,
1421 scale_factor: 0.0,
1422 frame_id: 0,
1423 texture: std::ptr::null_mut(),
1424 device: std::ptr::null_mut(),
1425 pixel_format: 0,
1426 }
1427}
1428
1429fn empty_vulkan_owned_texture_frame() -> sys::mln_vulkan_owned_texture_frame {
1430 sys::mln_vulkan_owned_texture_frame {
1431 size: mem::size_of::<sys::mln_vulkan_owned_texture_frame>() as u32,
1432 generation: 0,
1433 width: 0,
1434 height: 0,
1435 scale_factor: 0.0,
1436 frame_id: 0,
1437 image: std::ptr::null_mut(),
1438 image_view: std::ptr::null_mut(),
1439 device: std::ptr::null_mut(),
1440 format: 0,
1441 layout: 0,
1442 }
1443}
1444
1445fn empty_opengl_owned_texture_frame() -> sys::mln_opengl_owned_texture_frame {
1446 sys::mln_opengl_owned_texture_frame {
1447 size: mem::size_of::<sys::mln_opengl_owned_texture_frame>() as u32,
1448 generation: 0,
1449 width: 0,
1450 height: 0,
1451 scale_factor: 0.0,
1452 frame_id: 0,
1453 texture: 0,
1454 target: 0,
1455 internal_format: 0,
1456 format: 0,
1457 type_: 0,
1458 }
1459}
1460
1461#[cfg(test)]
1462mod tests;