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 pub fn physical_size(&self) -> Result<(u32, u32)> {
233 let native = maplibre_core::render::render_target_extent_to_native(self.to_core());
234 let mut width = 0u32;
235 let mut height = 0u32;
236 maplibre_core::check(unsafe {
239 sys::mln_render_target_extent_physical_size(&native, &mut width, &mut height)
240 })?;
241 Ok((width, height))
242 }
243}
244
245impl Default for RenderTargetExtent {
246 fn default() -> Self {
247 Self::new(256, 256, 1.0)
248 }
249}
250
251#[derive(Debug, Clone, PartialEq)]
252#[non_exhaustive]
253pub struct MetalContextDescriptor {
254 pub device: NativePointer,
255}
256
257impl MetalContextDescriptor {
258 pub fn new(device: NativePointer) -> Self {
259 Self { device }
260 }
261
262 pub(crate) fn to_core(&self) -> maplibre_core::render::MetalContextDescriptorFields {
263 maplibre_core::render::MetalContextDescriptorFields {
264 device: self.device.as_void_ptr(),
265 }
266 }
267}
268
269impl Default for MetalContextDescriptor {
270 fn default() -> Self {
271 Self::new(NativePointer::NULL)
272 }
273}
274
275#[derive(Debug, Clone, PartialEq)]
276#[non_exhaustive]
277pub struct VulkanContextDescriptor {
278 pub instance: NativePointer,
279 pub physical_device: NativePointer,
280 pub device: NativePointer,
281 pub graphics_queue: NativePointer,
282 pub graphics_queue_family_index: u32,
283 pub get_instance_proc_addr: NativePointer,
284 pub get_device_proc_addr: NativePointer,
285}
286
287impl VulkanContextDescriptor {
288 #[allow(clippy::too_many_arguments)]
289 pub fn new(
290 instance: NativePointer,
291 physical_device: NativePointer,
292 device: NativePointer,
293 graphics_queue: NativePointer,
294 graphics_queue_family_index: u32,
295 ) -> Self {
296 Self {
297 instance,
298 physical_device,
299 device,
300 graphics_queue,
301 graphics_queue_family_index,
302 get_instance_proc_addr: NativePointer::NULL,
303 get_device_proc_addr: NativePointer::NULL,
304 }
305 }
306
307 pub(crate) fn to_core(&self) -> maplibre_core::render::VulkanContextDescriptorFields {
308 maplibre_core::render::VulkanContextDescriptorFields {
309 instance: self.instance.as_void_ptr(),
310 physical_device: self.physical_device.as_void_ptr(),
311 device: self.device.as_void_ptr(),
312 graphics_queue: self.graphics_queue.as_void_ptr(),
313 graphics_queue_family_index: self.graphics_queue_family_index,
314 get_instance_proc_addr: self.get_instance_proc_addr.as_void_ptr(),
315 get_device_proc_addr: self.get_device_proc_addr.as_void_ptr(),
316 }
317 }
318}
319
320impl Default for VulkanContextDescriptor {
321 fn default() -> Self {
322 Self::new(
323 NativePointer::NULL,
324 NativePointer::NULL,
325 NativePointer::NULL,
326 NativePointer::NULL,
327 0,
328 )
329 }
330}
331
332#[derive(Debug, Clone, PartialEq)]
333#[non_exhaustive]
334pub struct WglContextDescriptor {
335 pub device_context: NativePointer,
336 pub share_context: NativePointer,
337 pub get_proc_address: NativePointer,
338}
339
340impl WglContextDescriptor {
341 pub fn new(device_context: NativePointer, share_context: NativePointer) -> Self {
342 Self {
343 device_context,
344 share_context,
345 get_proc_address: NativePointer::NULL,
346 }
347 }
348
349 pub(crate) fn to_core(&self) -> maplibre_core::render::WglContextDescriptorFields {
350 maplibre_core::render::WglContextDescriptorFields {
351 device_context: self.device_context.as_void_ptr(),
352 share_context: self.share_context.as_void_ptr(),
353 get_proc_address: self.get_proc_address.as_void_ptr(),
354 }
355 }
356}
357
358impl Default for WglContextDescriptor {
359 fn default() -> Self {
360 Self::new(NativePointer::NULL, NativePointer::NULL)
361 }
362}
363
364#[derive(Debug, Clone, PartialEq)]
365#[non_exhaustive]
366pub struct EglContextDescriptor {
367 pub display: NativePointer,
368 pub config: NativePointer,
369 pub share_context: NativePointer,
370 pub get_proc_address: NativePointer,
371}
372
373impl EglContextDescriptor {
374 pub fn new(
375 display: NativePointer,
376 config: NativePointer,
377 share_context: NativePointer,
378 ) -> Self {
379 Self {
380 display,
381 config,
382 share_context,
383 get_proc_address: NativePointer::NULL,
384 }
385 }
386
387 pub(crate) fn to_core(&self) -> maplibre_core::render::EglContextDescriptorFields {
388 maplibre_core::render::EglContextDescriptorFields {
389 display: self.display.as_void_ptr(),
390 config: self.config.as_void_ptr(),
391 share_context: self.share_context.as_void_ptr(),
392 get_proc_address: self.get_proc_address.as_void_ptr(),
393 }
394 }
395}
396
397impl Default for EglContextDescriptor {
398 fn default() -> Self {
399 Self::new(
400 NativePointer::NULL,
401 NativePointer::NULL,
402 NativePointer::NULL,
403 )
404 }
405}
406
407#[derive(Debug, Clone, PartialEq)]
408#[non_exhaustive]
409pub enum OpenGLContextDescriptor {
410 Wgl(WglContextDescriptor),
411 Egl(EglContextDescriptor),
412}
413
414impl OpenGLContextDescriptor {
415 pub(crate) fn to_core(&self) -> maplibre_core::render::OpenGLContextDescriptorFields {
416 match self {
417 Self::Wgl(descriptor) => {
418 maplibre_core::render::OpenGLContextDescriptorFields::Wgl(descriptor.to_core())
419 }
420 Self::Egl(descriptor) => {
421 maplibre_core::render::OpenGLContextDescriptorFields::Egl(descriptor.to_core())
422 }
423 }
424 }
425}
426
427#[derive(Debug, Clone, PartialEq)]
428#[non_exhaustive]
429pub struct MetalSurfaceDescriptor {
430 pub extent: RenderTargetExtent,
431 pub context: MetalContextDescriptor,
432 pub layer: NativePointer,
433}
434
435impl MetalSurfaceDescriptor {
436 pub fn new(
437 extent: RenderTargetExtent,
438 context: MetalContextDescriptor,
439 layer: NativePointer,
440 ) -> Self {
441 Self {
442 extent,
443 context,
444 layer,
445 }
446 }
447
448 pub(crate) fn to_native(&self) -> sys::mln_metal_surface_descriptor {
449 maplibre_core::render::metal_surface_descriptor_to_native(
450 maplibre_core::render::MetalSurfaceDescriptorFields {
451 extent: self.extent.to_core(),
452 context: self.context.to_core(),
453 layer: self.layer.as_void_ptr(),
454 },
455 )
456 }
457}
458
459#[derive(Debug, Clone, PartialEq)]
460#[non_exhaustive]
461pub struct VulkanSurfaceDescriptor {
462 pub extent: RenderTargetExtent,
463 pub context: VulkanContextDescriptor,
464 pub surface: NativePointer,
465}
466
467impl VulkanSurfaceDescriptor {
468 pub fn new(
469 extent: RenderTargetExtent,
470 context: VulkanContextDescriptor,
471 surface: NativePointer,
472 ) -> Self {
473 Self {
474 extent,
475 context,
476 surface,
477 }
478 }
479
480 pub(crate) fn to_native(&self) -> sys::mln_vulkan_surface_descriptor {
481 maplibre_core::render::vulkan_surface_descriptor_to_native(
482 maplibre_core::render::VulkanSurfaceDescriptorFields {
483 extent: self.extent.to_core(),
484 context: self.context.to_core(),
485 surface: self.surface.as_void_ptr(),
486 },
487 )
488 }
489}
490
491#[derive(Debug, Clone, PartialEq)]
492#[non_exhaustive]
493pub struct OpenGLSurfaceDescriptor {
494 pub extent: RenderTargetExtent,
495 pub context: OpenGLContextDescriptor,
496 pub surface: NativePointer,
497}
498
499impl OpenGLSurfaceDescriptor {
500 pub fn new(
501 extent: RenderTargetExtent,
502 context: OpenGLContextDescriptor,
503 surface: NativePointer,
504 ) -> Self {
505 Self {
506 extent,
507 context,
508 surface,
509 }
510 }
511
512 pub(crate) fn to_native(&self) -> sys::mln_opengl_surface_descriptor {
513 maplibre_core::render::opengl_surface_descriptor_to_native(
514 maplibre_core::render::OpenGLSurfaceDescriptorFields {
515 extent: self.extent.to_core(),
516 context: self.context.to_core(),
517 surface: self.surface.as_void_ptr(),
518 },
519 )
520 }
521}
522
523#[derive(Debug, Clone, PartialEq)]
524#[non_exhaustive]
525pub struct MetalOwnedTextureDescriptor {
526 pub extent: RenderTargetExtent,
527 pub context: MetalContextDescriptor,
528}
529
530impl MetalOwnedTextureDescriptor {
531 pub fn new(extent: RenderTargetExtent, context: MetalContextDescriptor) -> Self {
532 Self { extent, context }
533 }
534
535 pub(crate) fn to_native(&self) -> sys::mln_metal_owned_texture_descriptor {
536 maplibre_core::render::metal_owned_texture_descriptor_to_native(
537 maplibre_core::render::MetalOwnedTextureDescriptorFields {
538 extent: self.extent.to_core(),
539 context: self.context.to_core(),
540 },
541 )
542 }
543}
544
545#[derive(Debug, Clone, PartialEq)]
546#[non_exhaustive]
547pub struct MetalBorrowedTextureDescriptor {
548 pub extent: RenderTargetExtent,
549 pub physical_width: u32,
552 pub physical_height: u32,
553 pub texture: NativePointer,
554}
555
556impl MetalBorrowedTextureDescriptor {
557 pub fn new(
558 extent: RenderTargetExtent,
559 physical_width: u32,
560 physical_height: u32,
561 texture: NativePointer,
562 ) -> Self {
563 Self {
564 extent,
565 physical_width,
566 physical_height,
567 texture,
568 }
569 }
570
571 pub(crate) fn to_native(&self) -> sys::mln_metal_borrowed_texture_descriptor {
572 maplibre_core::render::metal_borrowed_texture_descriptor_to_native(
573 maplibre_core::render::MetalBorrowedTextureDescriptorFields {
574 extent: self.extent.to_core(),
575 physical_width: self.physical_width,
576 physical_height: self.physical_height,
577 texture: self.texture.as_void_ptr(),
578 },
579 )
580 }
581}
582
583#[derive(Debug, Clone, PartialEq)]
584#[non_exhaustive]
585pub struct VulkanOwnedTextureDescriptor {
586 pub extent: RenderTargetExtent,
587 pub context: VulkanContextDescriptor,
588}
589
590impl VulkanOwnedTextureDescriptor {
591 pub fn new(extent: RenderTargetExtent, context: VulkanContextDescriptor) -> Self {
592 Self { extent, context }
593 }
594
595 pub(crate) fn to_native(&self) -> sys::mln_vulkan_owned_texture_descriptor {
596 maplibre_core::render::vulkan_owned_texture_descriptor_to_native(
597 maplibre_core::render::VulkanOwnedTextureDescriptorFields {
598 extent: self.extent.to_core(),
599 context: self.context.to_core(),
600 },
601 )
602 }
603}
604
605#[derive(Debug, Clone, PartialEq)]
606#[non_exhaustive]
607pub struct VulkanBorrowedTextureDescriptor {
608 pub extent: RenderTargetExtent,
609 pub physical_width: u32,
612 pub physical_height: u32,
613 pub context: VulkanContextDescriptor,
614 pub image: NativePointer,
615 pub image_view: NativePointer,
616 pub format: u32,
617 pub initial_layout: u32,
618 pub final_layout: u32,
619}
620
621impl VulkanBorrowedTextureDescriptor {
622 #[allow(clippy::too_many_arguments)]
623 pub fn new(
624 extent: RenderTargetExtent,
625 physical_width: u32,
626 physical_height: u32,
627 context: VulkanContextDescriptor,
628 image: NativePointer,
629 image_view: NativePointer,
630 format: u32,
631 initial_layout: u32,
632 final_layout: u32,
633 ) -> Self {
634 Self {
635 extent,
636 physical_width,
637 physical_height,
638 context,
639 image,
640 image_view,
641 format,
642 initial_layout,
643 final_layout,
644 }
645 }
646
647 pub(crate) fn to_native(&self) -> sys::mln_vulkan_borrowed_texture_descriptor {
648 maplibre_core::render::vulkan_borrowed_texture_descriptor_to_native(
649 maplibre_core::render::VulkanBorrowedTextureDescriptorFields {
650 extent: self.extent.to_core(),
651 physical_width: self.physical_width,
652 physical_height: self.physical_height,
653 context: self.context.to_core(),
654 image: self.image.as_void_ptr(),
655 image_view: self.image_view.as_void_ptr(),
656 format: self.format,
657 initial_layout: self.initial_layout,
658 final_layout: self.final_layout,
659 },
660 )
661 }
662}
663
664#[derive(Debug, Clone, PartialEq)]
665#[non_exhaustive]
666pub struct OpenGLOwnedTextureDescriptor {
667 pub extent: RenderTargetExtent,
668 pub context: OpenGLContextDescriptor,
669}
670
671impl OpenGLOwnedTextureDescriptor {
672 pub fn new(extent: RenderTargetExtent, context: OpenGLContextDescriptor) -> Self {
673 Self { extent, context }
674 }
675
676 pub(crate) fn to_native(&self) -> sys::mln_opengl_owned_texture_descriptor {
677 maplibre_core::render::opengl_owned_texture_descriptor_to_native(
678 maplibre_core::render::OpenGLOwnedTextureDescriptorFields {
679 extent: self.extent.to_core(),
680 context: self.context.to_core(),
681 },
682 )
683 }
684}
685
686#[derive(Debug, Clone, PartialEq)]
687#[non_exhaustive]
688pub struct OpenGLBorrowedTextureDescriptor {
689 pub extent: RenderTargetExtent,
690 pub physical_width: u32,
693 pub physical_height: u32,
694 pub context: OpenGLContextDescriptor,
695 pub texture: u32,
696 pub target: u32,
697}
698
699impl OpenGLBorrowedTextureDescriptor {
700 pub fn new(
701 extent: RenderTargetExtent,
702 physical_width: u32,
703 physical_height: u32,
704 context: OpenGLContextDescriptor,
705 texture: u32,
706 target: u32,
707 ) -> Self {
708 Self {
709 extent,
710 physical_width,
711 physical_height,
712 context,
713 texture,
714 target,
715 }
716 }
717
718 pub(crate) fn to_native(&self) -> sys::mln_opengl_borrowed_texture_descriptor {
719 maplibre_core::render::opengl_borrowed_texture_descriptor_to_native(
720 maplibre_core::render::OpenGLBorrowedTextureDescriptorFields {
721 extent: self.extent.to_core(),
722 physical_width: self.physical_width,
723 physical_height: self.physical_height,
724 context: self.context.to_core(),
725 texture: self.texture,
726 target: self.target,
727 },
728 )
729 }
730}
731
732#[derive(Debug)]
733struct RenderSessionState {
734 handle: ThreadAffineNativeHandle<sys::mln_render_session>,
735 map: RefCell<Option<Rc<MapState>>>,
736 detached: Cell<bool>,
737 frame_acquired: Cell<bool>,
738}
739
740impl RenderSessionState {
741 fn new(ptr: NonNull<sys::mln_render_session>, map: Rc<MapState>) -> Self {
742 let handle = unsafe {
745 ThreadAffineNativeHandle::from_raw(
746 ptr,
747 sys::mln_render_session_destroy,
748 "mln_render_session",
749 )
750 };
751 Self {
752 handle,
753 map: RefCell::new(Some(map)),
754 detached: Cell::new(false),
755 frame_acquired: Cell::new(false),
756 }
757 }
758
759 fn ensure_no_frame_acquired(&self) -> Result<()> {
760 if self.frame_acquired.get() {
761 Err(frame_acquired_error())
762 } else {
763 Ok(())
764 }
765 }
766
767 fn as_ptr(&self) -> Result<*mut sys::mln_render_session> {
768 let ptr = self.handle.as_ptr();
769 if ptr.is_null() {
770 Err(closed_handle_error("RenderSessionHandle"))
771 } else {
772 Ok(ptr)
773 }
774 }
775
776 fn release_map(&self) {
782 self.map.borrow_mut().take();
783 }
784
785 fn close(&self) -> Result<()> {
786 self.handle.close()?;
787 self.release_map();
788 Ok(())
789 }
790}
791
792pub struct RenderSessionHandle {
794 inner: Rc<RenderSessionState>,
795}
796
797impl fmt::Debug for RenderSessionHandle {
798 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
799 f.debug_struct("RenderSessionHandle")
800 .field("closed", &self.inner.handle.is_closed())
801 .field("detached", &self.inner.detached.get())
802 .finish()
803 }
804}
805
806pub struct DetachedRenderSessionHandle {
811 inner: Rc<RenderSessionState>,
812}
813
814impl fmt::Debug for DetachedRenderSessionHandle {
815 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
816 f.debug_struct("DetachedRenderSessionHandle")
817 .field("closed", &self.inner.handle.is_closed())
818 .finish()
819 }
820}
821
822impl DetachedRenderSessionHandle {
823 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
825 if let Err(error) = self.inner.close() {
826 return Err(HandleOperationError::new(error, self));
827 }
828 Ok(())
829 }
830}
831
832fn frame_acquired_error() -> crate::Error {
833 crate::Error::new(
834 crate::ErrorKind::InvalidState,
835 None,
836 "render session has an acquired texture frame",
837 )
838}
839
840#[derive(Debug, Clone, Copy, PartialEq)]
845#[non_exhaustive]
846pub struct MetalOwnedTextureFrame {
847 pub generation: u64,
848 pub width: u32,
849 pub height: u32,
850 pub scale_factor: f64,
851 pub frame_id: u64,
852 pub pixel_format: u64,
853}
854
855impl MetalOwnedTextureFrame {
856 fn from_native(raw: &sys::mln_metal_owned_texture_frame) -> Self {
857 Self {
858 generation: raw.generation,
859 width: raw.width,
860 height: raw.height,
861 scale_factor: raw.scale_factor,
862 frame_id: raw.frame_id,
863 pixel_format: raw.pixel_format,
864 }
865 }
866}
867
868#[derive(Debug, Clone, Copy, PartialEq)]
873#[non_exhaustive]
874pub struct VulkanOwnedTextureFrame {
875 pub generation: u64,
876 pub width: u32,
877 pub height: u32,
878 pub scale_factor: f64,
879 pub frame_id: u64,
880 pub format: u32,
881 pub layout: u32,
882}
883
884impl VulkanOwnedTextureFrame {
885 fn from_native(raw: &sys::mln_vulkan_owned_texture_frame) -> Self {
886 Self {
887 generation: raw.generation,
888 width: raw.width,
889 height: raw.height,
890 scale_factor: raw.scale_factor,
891 frame_id: raw.frame_id,
892 format: raw.format,
893 layout: raw.layout,
894 }
895 }
896}
897
898#[derive(Debug, Clone, Copy, PartialEq)]
903#[non_exhaustive]
904pub struct OpenGLOwnedTextureFrame {
905 pub generation: u64,
906 pub width: u32,
907 pub height: u32,
908 pub scale_factor: f64,
909 pub frame_id: u64,
910 pub target: u32,
911 pub internal_format: u32,
912 pub format: u32,
913 pub type_: u32,
914}
915
916impl OpenGLOwnedTextureFrame {
917 fn from_native(raw: &sys::mln_opengl_owned_texture_frame) -> Self {
918 Self {
919 generation: raw.generation,
920 width: raw.width,
921 height: raw.height,
922 scale_factor: raw.scale_factor,
923 frame_id: raw.frame_id,
924 target: raw.target,
925 internal_format: raw.internal_format,
926 format: raw.format,
927 type_: raw.type_,
928 }
929 }
930}
931
932pub struct MetalOwnedTextureFrameHandle {
936 session: Rc<RenderSessionState>,
937 raw: sys::mln_metal_owned_texture_frame,
938 frame: MetalOwnedTextureFrame,
939 closed: Cell<bool>,
940 _thread_affine: PhantomData<Rc<()>>,
941}
942
943impl fmt::Debug for MetalOwnedTextureFrameHandle {
944 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
945 f.debug_struct("MetalOwnedTextureFrameHandle")
946 .field("closed", &self.closed.get())
947 .field("frame", &self.frame)
948 .finish()
949 }
950}
951
952impl MetalOwnedTextureFrameHandle {
953 pub fn frame(&self) -> Result<&MetalOwnedTextureFrame> {
955 if self.closed.get() {
956 Err(closed_handle_error("MetalOwnedTextureFrameHandle"))
957 } else {
958 Ok(&self.frame)
959 }
960 }
961 pub unsafe fn texture(&self) -> Result<FrameNativePointer<'_>> {
969 if self.closed.get() {
970 Err(closed_handle_error("MetalOwnedTextureFrameHandle"))
971 } else {
972 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.texture) })
975 }
976 }
977
978 pub unsafe fn device(&self) -> Result<FrameNativePointer<'_>> {
985 if self.closed.get() {
986 Err(closed_handle_error("MetalOwnedTextureFrameHandle"))
987 } else {
988 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.device) })
990 }
991 }
992
993 #[allow(clippy::result_large_err)]
995 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
996 self.close_with_release(sys::mln_metal_owned_texture_release_frame)
997 }
998
999 #[allow(clippy::result_large_err)]
1000 fn close_with_release(
1001 self,
1002 release: unsafe extern "C" fn(
1003 *mut sys::mln_render_session,
1004 *const sys::mln_metal_owned_texture_frame,
1005 ) -> sys::mln_status,
1006 ) -> std::result::Result<(), HandleOperationError<Self>> {
1007 if self.closed.get() {
1008 return Ok(());
1009 }
1010 let session = match self.session.as_ptr() {
1011 Ok(session) => session,
1012 Err(error) => return Err(HandleOperationError::new(error, self)),
1013 };
1014 if let Err(error) = maplibre_core::check(unsafe { release(session, &self.raw) }) {
1017 return Err(HandleOperationError::new(error, self));
1018 }
1019 self.closed.set(true);
1020 self.session.frame_acquired.set(false);
1021 Ok(())
1022 }
1023}
1024
1025impl Drop for MetalOwnedTextureFrameHandle {
1026 fn drop(&mut self) {
1027 if self.closed.get() {
1028 return;
1029 }
1030 if let Ok(session) = self.session.as_ptr() {
1031 let status = unsafe { sys::mln_metal_owned_texture_release_frame(session, &self.raw) };
1034 if status == sys::MLN_STATUS_OK {
1035 self.closed.set(true);
1036 self.session.frame_acquired.set(false);
1037 }
1038 }
1039 }
1040}
1041
1042pub struct VulkanOwnedTextureFrameHandle {
1047 session: Rc<RenderSessionState>,
1048 raw: sys::mln_vulkan_owned_texture_frame,
1049 frame: VulkanOwnedTextureFrame,
1050 closed: Cell<bool>,
1051 _thread_affine: PhantomData<Rc<()>>,
1052}
1053
1054impl fmt::Debug for VulkanOwnedTextureFrameHandle {
1055 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1056 f.debug_struct("VulkanOwnedTextureFrameHandle")
1057 .field("closed", &self.closed.get())
1058 .field("frame", &self.frame)
1059 .finish()
1060 }
1061}
1062
1063impl VulkanOwnedTextureFrameHandle {
1064 pub fn frame(&self) -> Result<&VulkanOwnedTextureFrame> {
1066 if self.closed.get() {
1067 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1068 } else {
1069 Ok(&self.frame)
1070 }
1071 }
1072 pub unsafe fn image(&self) -> Result<FrameNativePointer<'_>> {
1080 if self.closed.get() {
1081 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1082 } else {
1083 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.image) })
1086 }
1087 }
1088
1089 pub unsafe fn image_view(&self) -> Result<FrameNativePointer<'_>> {
1096 if self.closed.get() {
1097 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1098 } else {
1099 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.image_view) })
1101 }
1102 }
1103
1104 pub unsafe fn device(&self) -> Result<FrameNativePointer<'_>> {
1111 if self.closed.get() {
1112 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1113 } else {
1114 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.device) })
1116 }
1117 }
1118
1119 #[allow(clippy::result_large_err)]
1121 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1122 if self.closed.get() {
1123 return Ok(());
1124 }
1125 let session = match self.session.as_ptr() {
1126 Ok(session) => session,
1127 Err(error) => return Err(HandleOperationError::new(error, self)),
1128 };
1129 if let Err(error) = maplibre_core::check(unsafe {
1132 sys::mln_vulkan_owned_texture_release_frame(session, &self.raw)
1133 }) {
1134 return Err(HandleOperationError::new(error, self));
1135 }
1136 self.closed.set(true);
1137 self.session.frame_acquired.set(false);
1138 Ok(())
1139 }
1140}
1141
1142impl Drop for VulkanOwnedTextureFrameHandle {
1143 fn drop(&mut self) {
1144 if self.closed.get() {
1145 return;
1146 }
1147 if let Ok(session) = self.session.as_ptr() {
1148 let status = unsafe { sys::mln_vulkan_owned_texture_release_frame(session, &self.raw) };
1151 if status == sys::MLN_STATUS_OK {
1152 self.closed.set(true);
1153 self.session.frame_acquired.set(false);
1154 }
1155 }
1156 }
1157}
1158
1159pub struct OpenGLOwnedTextureFrameHandle {
1163 session: Rc<RenderSessionState>,
1164 raw: sys::mln_opengl_owned_texture_frame,
1165 frame: OpenGLOwnedTextureFrame,
1166 closed: Cell<bool>,
1167 _thread_affine: PhantomData<Rc<()>>,
1168}
1169
1170impl fmt::Debug for OpenGLOwnedTextureFrameHandle {
1171 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1172 f.debug_struct("OpenGLOwnedTextureFrameHandle")
1173 .field("closed", &self.closed.get())
1174 .field("frame", &self.frame)
1175 .finish()
1176 }
1177}
1178
1179impl OpenGLOwnedTextureFrameHandle {
1180 pub fn frame(&self) -> Result<&OpenGLOwnedTextureFrame> {
1182 if self.closed.get() {
1183 Err(closed_handle_error("OpenGLOwnedTextureFrameHandle"))
1184 } else {
1185 Ok(&self.frame)
1186 }
1187 }
1188 pub fn texture(&self) -> Result<FrameOpenGLTextureName<'_>> {
1190 if self.closed.get() {
1191 Err(closed_handle_error("OpenGLOwnedTextureFrameHandle"))
1192 } else {
1193 Ok(FrameOpenGLTextureName::new(self.raw.texture))
1194 }
1195 }
1196
1197 #[allow(clippy::result_large_err)]
1199 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1200 if self.closed.get() {
1201 return Ok(());
1202 }
1203 let session = match self.session.as_ptr() {
1204 Ok(session) => session,
1205 Err(error) => return Err(HandleOperationError::new(error, self)),
1206 };
1207 if let Err(error) = maplibre_core::check(unsafe {
1210 sys::mln_opengl_owned_texture_release_frame(session, &self.raw)
1211 }) {
1212 return Err(HandleOperationError::new(error, self));
1213 }
1214 self.closed.set(true);
1215 self.session.frame_acquired.set(false);
1216 Ok(())
1217 }
1218}
1219
1220impl Drop for OpenGLOwnedTextureFrameHandle {
1221 fn drop(&mut self) {
1222 if self.closed.get() {
1223 return;
1224 }
1225 if let Ok(session) = self.session.as_ptr() {
1226 let status = unsafe { sys::mln_opengl_owned_texture_release_frame(session, &self.raw) };
1229 if status == sys::MLN_STATUS_OK {
1230 self.closed.set(true);
1231 self.session.frame_acquired.set(false);
1232 }
1233 }
1234 }
1235}
1236
1237impl RenderSessionHandle {
1238 pub(crate) fn attach<F>(map: &MapHandle, attach: F) -> Result<Self>
1239 where
1240 F: FnOnce(*mut sys::mln_map, *mut *mut sys::mln_render_session) -> sys::mln_status,
1241 {
1242 let map_ptr = map.inner.as_ptr()?;
1243 let mut out = maplibre_core::ptr::OutPtr::<sys::mln_render_session>::new();
1244 let status = attach(map_ptr, out.as_mut_ptr());
1245 maplibre_core::check(status)?;
1246 let ptr = out_handle(out, "mln_render_session")?;
1247 Ok(Self {
1248 inner: Rc::new(RenderSessionState::new(ptr, Rc::clone(&map.inner))),
1249 })
1250 }
1251
1252 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1257 if let Err(error) = self.inner.ensure_no_frame_acquired() {
1258 return Err(HandleOperationError::new(error, self));
1259 }
1260 if let Err(error) = self.inner.close() {
1261 return Err(HandleOperationError::new(error, self));
1262 }
1263 Ok(())
1264 }
1265 pub fn resize(&self, width: u32, height: u32, scale_factor: f64) -> Result<()> {
1277 self.inner.ensure_no_frame_acquired()?;
1278 let session = self.inner.as_ptr()?;
1279 maplibre_core::check(unsafe {
1281 sys::mln_render_session_resize(session, width, height, scale_factor)
1282 })
1283 }
1284
1285 pub fn render_update(&self) -> Result<bool> {
1295 self.inner.ensure_no_frame_acquired()?;
1296 let session = self.inner.as_ptr()?;
1297 let mut rendered = false;
1298 maplibre_core::check(unsafe {
1301 sys::mln_render_session_render_update(session, &raw mut rendered)
1302 })?;
1303 Ok(rendered)
1304 }
1305
1306 pub fn detach(
1316 self,
1317 ) -> std::result::Result<DetachedRenderSessionHandle, HandleOperationError<Self>> {
1318 if let Err(error) = self.inner.ensure_no_frame_acquired() {
1319 return Err(HandleOperationError::new(error, self));
1320 }
1321 let session = match self.inner.as_ptr() {
1322 Ok(session) => session,
1323 Err(error) => return Err(HandleOperationError::new(error, self)),
1324 };
1325 if let Err(error) = maplibre_core::check(unsafe { sys::mln_render_session_detach(session) })
1327 {
1328 return Err(HandleOperationError::new(error, self));
1329 }
1330 self.inner.detached.set(true);
1331 self.inner.release_map();
1335 Ok(DetachedRenderSessionHandle {
1336 inner: Rc::clone(&self.inner),
1337 })
1338 }
1339
1340 pub fn reduce_memory_use(&self) -> Result<()> {
1342 self.inner.ensure_no_frame_acquired()?;
1343 let session = self.inner.as_ptr()?;
1344 maplibre_core::check(unsafe { sys::mln_render_session_reduce_memory_use(session) })
1346 }
1347
1348 pub fn clear_data(&self) -> Result<()> {
1350 self.inner.ensure_no_frame_acquired()?;
1351 let session = self.inner.as_ptr()?;
1352 maplibre_core::check(unsafe { sys::mln_render_session_clear_data(session) })
1354 }
1355
1356 pub fn dump_debug_logs(&self) -> Result<()> {
1358 self.inner.ensure_no_frame_acquired()?;
1359 let session = self.inner.as_ptr()?;
1360 maplibre_core::check(unsafe { sys::mln_render_session_dump_debug_logs(session) })
1362 }
1363
1364 pub fn texture_image_info(&self) -> Result<TextureImageInfo> {
1366 self.inner.ensure_no_frame_acquired()?;
1367 let session = self.inner.as_ptr()?;
1368 let mut info = unsafe { sys::mln_texture_image_info_default() };
1370 let status = unsafe {
1373 sys::mln_texture_read_premultiplied_rgba8(session, std::ptr::null_mut(), 0, &mut info)
1374 };
1375 if status == sys::MLN_STATUS_OK
1376 || (status == sys::MLN_STATUS_INVALID_ARGUMENT && info.byte_length > 0)
1377 {
1378 Ok(maplibre_core::values::texture_image_info_from_native(&info))
1379 } else {
1380 Err(crate::Error::from_status(status))
1381 }
1382 }
1383
1384 pub fn read_premultiplied_rgba8_into(&self, data: &mut [u8]) -> Result<TextureImageInfo> {
1386 self.inner.ensure_no_frame_acquired()?;
1387 let session = self.inner.as_ptr()?;
1388 let mut info = unsafe { sys::mln_texture_image_info_default() };
1390 let data_ptr = if data.is_empty() {
1391 std::ptr::null_mut()
1392 } else {
1393 data.as_mut_ptr()
1394 };
1395 maplibre_core::check(unsafe {
1399 sys::mln_texture_read_premultiplied_rgba8(session, data_ptr, data.len(), &mut info)
1400 })?;
1401 Ok(maplibre_core::values::texture_image_info_from_native(&info))
1402 }
1403
1404 pub fn acquire_metal_owned_texture_frame(&self) -> Result<MetalOwnedTextureFrameHandle> {
1406 self.inner.ensure_no_frame_acquired()?;
1407 let session = self.inner.as_ptr()?;
1408 let mut raw = empty_metal_owned_texture_frame();
1409 maplibre_core::check(unsafe {
1411 sys::mln_metal_owned_texture_acquire_frame(session, &mut raw)
1412 })?;
1413 self.inner.frame_acquired.set(true);
1414 Ok(MetalOwnedTextureFrameHandle {
1415 session: Rc::clone(&self.inner),
1416 frame: MetalOwnedTextureFrame::from_native(&raw),
1417 raw,
1418 closed: Cell::new(false),
1419 _thread_affine: PhantomData,
1420 })
1421 }
1422
1423 pub fn acquire_vulkan_owned_texture_frame(&self) -> Result<VulkanOwnedTextureFrameHandle> {
1425 self.inner.ensure_no_frame_acquired()?;
1426 let session = self.inner.as_ptr()?;
1427 let mut raw = empty_vulkan_owned_texture_frame();
1428 maplibre_core::check(unsafe {
1430 sys::mln_vulkan_owned_texture_acquire_frame(session, &mut raw)
1431 })?;
1432 self.inner.frame_acquired.set(true);
1433 Ok(VulkanOwnedTextureFrameHandle {
1434 session: Rc::clone(&self.inner),
1435 frame: VulkanOwnedTextureFrame::from_native(&raw),
1436 raw,
1437 closed: Cell::new(false),
1438 _thread_affine: PhantomData,
1439 })
1440 }
1441
1442 pub fn acquire_opengl_owned_texture_frame(&self) -> Result<OpenGLOwnedTextureFrameHandle> {
1444 self.inner.ensure_no_frame_acquired()?;
1445 let session = self.inner.as_ptr()?;
1446 let mut raw = empty_opengl_owned_texture_frame();
1447 maplibre_core::check(unsafe {
1449 sys::mln_opengl_owned_texture_acquire_frame(session, &mut raw)
1450 })?;
1451 self.inner.frame_acquired.set(true);
1452 Ok(OpenGLOwnedTextureFrameHandle {
1453 session: Rc::clone(&self.inner),
1454 frame: OpenGLOwnedTextureFrame::from_native(&raw),
1455 raw,
1456 closed: Cell::new(false),
1457 _thread_affine: PhantomData,
1458 })
1459 }
1460}
1461
1462fn empty_metal_owned_texture_frame() -> sys::mln_metal_owned_texture_frame {
1463 sys::mln_metal_owned_texture_frame {
1464 size: mem::size_of::<sys::mln_metal_owned_texture_frame>() as u32,
1465 generation: 0,
1466 width: 0,
1467 height: 0,
1468 scale_factor: 0.0,
1469 frame_id: 0,
1470 texture: std::ptr::null_mut(),
1471 device: std::ptr::null_mut(),
1472 pixel_format: 0,
1473 }
1474}
1475
1476fn empty_vulkan_owned_texture_frame() -> sys::mln_vulkan_owned_texture_frame {
1477 sys::mln_vulkan_owned_texture_frame {
1478 size: mem::size_of::<sys::mln_vulkan_owned_texture_frame>() as u32,
1479 generation: 0,
1480 width: 0,
1481 height: 0,
1482 scale_factor: 0.0,
1483 frame_id: 0,
1484 image: std::ptr::null_mut(),
1485 image_view: std::ptr::null_mut(),
1486 device: std::ptr::null_mut(),
1487 format: 0,
1488 layout: 0,
1489 }
1490}
1491
1492fn empty_opengl_owned_texture_frame() -> sys::mln_opengl_owned_texture_frame {
1493 sys::mln_opengl_owned_texture_frame {
1494 size: mem::size_of::<sys::mln_opengl_owned_texture_frame>() as u32,
1495 generation: 0,
1496 width: 0,
1497 height: 0,
1498 scale_factor: 0.0,
1499 frame_id: 0,
1500 texture: 0,
1501 target: 0,
1502 internal_format: 0,
1503 format: 0,
1504 type_: 0,
1505 }
1506}
1507
1508#[cfg(test)]
1509mod tests;