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(crate) fn to_core(&self) -> maplibre_core::render::VulkanContextDescriptorFields {
290 maplibre_core::render::VulkanContextDescriptorFields {
291 instance: self.instance.as_void_ptr(),
292 physical_device: self.physical_device.as_void_ptr(),
293 device: self.device.as_void_ptr(),
294 graphics_queue: self.graphics_queue.as_void_ptr(),
295 graphics_queue_family_index: self.graphics_queue_family_index,
296 get_instance_proc_addr: self.get_instance_proc_addr.as_void_ptr(),
297 get_device_proc_addr: self.get_device_proc_addr.as_void_ptr(),
298 }
299 }
300}
301
302impl Default for VulkanContextDescriptor {
303 fn default() -> Self {
304 Self::new(
305 NativePointer::NULL,
306 NativePointer::NULL,
307 NativePointer::NULL,
308 NativePointer::NULL,
309 0,
310 )
311 }
312}
313
314#[derive(Debug, Clone, PartialEq)]
315#[non_exhaustive]
316pub struct WglContextDescriptor {
317 pub device_context: NativePointer,
318 pub share_context: NativePointer,
319 pub get_proc_address: NativePointer,
320}
321
322impl WglContextDescriptor {
323 pub fn new(device_context: NativePointer, share_context: NativePointer) -> Self {
324 Self {
325 device_context,
326 share_context,
327 get_proc_address: NativePointer::NULL,
328 }
329 }
330
331 pub(crate) fn to_core(&self) -> maplibre_core::render::WglContextDescriptorFields {
332 maplibre_core::render::WglContextDescriptorFields {
333 device_context: self.device_context.as_void_ptr(),
334 share_context: self.share_context.as_void_ptr(),
335 get_proc_address: self.get_proc_address.as_void_ptr(),
336 }
337 }
338}
339
340impl Default for WglContextDescriptor {
341 fn default() -> Self {
342 Self::new(NativePointer::NULL, NativePointer::NULL)
343 }
344}
345
346#[derive(Debug, Clone, PartialEq)]
347#[non_exhaustive]
348pub struct EglContextDescriptor {
349 pub display: NativePointer,
350 pub config: NativePointer,
351 pub share_context: NativePointer,
352 pub get_proc_address: NativePointer,
353}
354
355impl EglContextDescriptor {
356 pub fn new(
357 display: NativePointer,
358 config: NativePointer,
359 share_context: NativePointer,
360 ) -> Self {
361 Self {
362 display,
363 config,
364 share_context,
365 get_proc_address: NativePointer::NULL,
366 }
367 }
368
369 pub(crate) fn to_core(&self) -> maplibre_core::render::EglContextDescriptorFields {
370 maplibre_core::render::EglContextDescriptorFields {
371 display: self.display.as_void_ptr(),
372 config: self.config.as_void_ptr(),
373 share_context: self.share_context.as_void_ptr(),
374 get_proc_address: self.get_proc_address.as_void_ptr(),
375 }
376 }
377}
378
379impl Default for EglContextDescriptor {
380 fn default() -> Self {
381 Self::new(
382 NativePointer::NULL,
383 NativePointer::NULL,
384 NativePointer::NULL,
385 )
386 }
387}
388
389#[derive(Debug, Clone, PartialEq)]
390#[non_exhaustive]
391pub enum OpenGLContextDescriptor {
392 Wgl(WglContextDescriptor),
393 Egl(EglContextDescriptor),
394}
395
396impl OpenGLContextDescriptor {
397 pub(crate) fn to_core(&self) -> maplibre_core::render::OpenGLContextDescriptorFields {
398 match self {
399 Self::Wgl(descriptor) => {
400 maplibre_core::render::OpenGLContextDescriptorFields::Wgl(descriptor.to_core())
401 }
402 Self::Egl(descriptor) => {
403 maplibre_core::render::OpenGLContextDescriptorFields::Egl(descriptor.to_core())
404 }
405 }
406 }
407}
408
409#[derive(Debug, Clone, PartialEq)]
410#[non_exhaustive]
411pub struct MetalSurfaceDescriptor {
412 pub extent: RenderTargetExtent,
413 pub context: MetalContextDescriptor,
414 pub layer: NativePointer,
415}
416
417impl MetalSurfaceDescriptor {
418 pub fn new(
419 extent: RenderTargetExtent,
420 context: MetalContextDescriptor,
421 layer: NativePointer,
422 ) -> Self {
423 Self {
424 extent,
425 context,
426 layer,
427 }
428 }
429
430 pub(crate) fn to_native(&self) -> sys::mln_metal_surface_descriptor {
431 maplibre_core::render::metal_surface_descriptor_to_native(
432 maplibre_core::render::MetalSurfaceDescriptorFields {
433 extent: self.extent.to_core(),
434 context: self.context.to_core(),
435 layer: self.layer.as_void_ptr(),
436 },
437 )
438 }
439}
440
441#[derive(Debug, Clone, PartialEq)]
442#[non_exhaustive]
443pub struct VulkanSurfaceDescriptor {
444 pub extent: RenderTargetExtent,
445 pub context: VulkanContextDescriptor,
446 pub surface: NativePointer,
447}
448
449impl VulkanSurfaceDescriptor {
450 pub fn new(
451 extent: RenderTargetExtent,
452 context: VulkanContextDescriptor,
453 surface: NativePointer,
454 ) -> Self {
455 Self {
456 extent,
457 context,
458 surface,
459 }
460 }
461
462 pub(crate) fn to_native(&self) -> sys::mln_vulkan_surface_descriptor {
463 maplibre_core::render::vulkan_surface_descriptor_to_native(
464 maplibre_core::render::VulkanSurfaceDescriptorFields {
465 extent: self.extent.to_core(),
466 context: self.context.to_core(),
467 surface: self.surface.as_void_ptr(),
468 },
469 )
470 }
471}
472
473#[derive(Debug, Clone, PartialEq)]
474#[non_exhaustive]
475pub struct OpenGLSurfaceDescriptor {
476 pub extent: RenderTargetExtent,
477 pub context: OpenGLContextDescriptor,
478 pub surface: NativePointer,
479}
480
481impl OpenGLSurfaceDescriptor {
482 pub fn new(
483 extent: RenderTargetExtent,
484 context: OpenGLContextDescriptor,
485 surface: NativePointer,
486 ) -> Self {
487 Self {
488 extent,
489 context,
490 surface,
491 }
492 }
493
494 pub(crate) fn to_native(&self) -> sys::mln_opengl_surface_descriptor {
495 maplibre_core::render::opengl_surface_descriptor_to_native(
496 maplibre_core::render::OpenGLSurfaceDescriptorFields {
497 extent: self.extent.to_core(),
498 context: self.context.to_core(),
499 surface: self.surface.as_void_ptr(),
500 },
501 )
502 }
503}
504
505#[derive(Debug, Clone, PartialEq)]
506#[non_exhaustive]
507pub struct MetalOwnedTextureDescriptor {
508 pub extent: RenderTargetExtent,
509 pub context: MetalContextDescriptor,
510}
511
512impl MetalOwnedTextureDescriptor {
513 pub fn new(extent: RenderTargetExtent, context: MetalContextDescriptor) -> Self {
514 Self { extent, context }
515 }
516
517 pub(crate) fn to_native(&self) -> sys::mln_metal_owned_texture_descriptor {
518 maplibre_core::render::metal_owned_texture_descriptor_to_native(
519 maplibre_core::render::MetalOwnedTextureDescriptorFields {
520 extent: self.extent.to_core(),
521 context: self.context.to_core(),
522 },
523 )
524 }
525}
526
527#[derive(Debug, Clone, PartialEq)]
528#[non_exhaustive]
529pub struct MetalBorrowedTextureDescriptor {
530 pub extent: RenderTargetExtent,
531 pub texture: NativePointer,
532}
533
534impl MetalBorrowedTextureDescriptor {
535 pub fn new(extent: RenderTargetExtent, texture: NativePointer) -> Self {
536 Self { extent, texture }
537 }
538
539 pub(crate) fn to_native(&self) -> sys::mln_metal_borrowed_texture_descriptor {
540 maplibre_core::render::metal_borrowed_texture_descriptor_to_native(
541 maplibre_core::render::MetalBorrowedTextureDescriptorFields {
542 extent: self.extent.to_core(),
543 texture: self.texture.as_void_ptr(),
544 },
545 )
546 }
547}
548
549#[derive(Debug, Clone, PartialEq)]
550#[non_exhaustive]
551pub struct VulkanOwnedTextureDescriptor {
552 pub extent: RenderTargetExtent,
553 pub context: VulkanContextDescriptor,
554}
555
556impl VulkanOwnedTextureDescriptor {
557 pub fn new(extent: RenderTargetExtent, context: VulkanContextDescriptor) -> Self {
558 Self { extent, context }
559 }
560
561 pub(crate) fn to_native(&self) -> sys::mln_vulkan_owned_texture_descriptor {
562 maplibre_core::render::vulkan_owned_texture_descriptor_to_native(
563 maplibre_core::render::VulkanOwnedTextureDescriptorFields {
564 extent: self.extent.to_core(),
565 context: self.context.to_core(),
566 },
567 )
568 }
569}
570
571#[derive(Debug, Clone, PartialEq)]
572#[non_exhaustive]
573pub struct VulkanBorrowedTextureDescriptor {
574 pub extent: RenderTargetExtent,
575 pub context: VulkanContextDescriptor,
576 pub image: NativePointer,
577 pub image_view: NativePointer,
578 pub format: u32,
579 pub initial_layout: u32,
580 pub final_layout: u32,
581}
582
583impl VulkanBorrowedTextureDescriptor {
584 #[allow(clippy::too_many_arguments)]
585 pub fn new(
586 extent: RenderTargetExtent,
587 context: VulkanContextDescriptor,
588 image: NativePointer,
589 image_view: NativePointer,
590 format: u32,
591 initial_layout: u32,
592 final_layout: u32,
593 ) -> Self {
594 Self {
595 extent,
596 context,
597 image,
598 image_view,
599 format,
600 initial_layout,
601 final_layout,
602 }
603 }
604
605 pub(crate) fn to_native(&self) -> sys::mln_vulkan_borrowed_texture_descriptor {
606 maplibre_core::render::vulkan_borrowed_texture_descriptor_to_native(
607 maplibre_core::render::VulkanBorrowedTextureDescriptorFields {
608 extent: self.extent.to_core(),
609 context: self.context.to_core(),
610 image: self.image.as_void_ptr(),
611 image_view: self.image_view.as_void_ptr(),
612 format: self.format,
613 initial_layout: self.initial_layout,
614 final_layout: self.final_layout,
615 },
616 )
617 }
618}
619
620#[derive(Debug, Clone, PartialEq)]
621#[non_exhaustive]
622pub struct OpenGLOwnedTextureDescriptor {
623 pub extent: RenderTargetExtent,
624 pub context: OpenGLContextDescriptor,
625}
626
627impl OpenGLOwnedTextureDescriptor {
628 pub fn new(extent: RenderTargetExtent, context: OpenGLContextDescriptor) -> Self {
629 Self { extent, context }
630 }
631
632 pub(crate) fn to_native(&self) -> sys::mln_opengl_owned_texture_descriptor {
633 maplibre_core::render::opengl_owned_texture_descriptor_to_native(
634 maplibre_core::render::OpenGLOwnedTextureDescriptorFields {
635 extent: self.extent.to_core(),
636 context: self.context.to_core(),
637 },
638 )
639 }
640}
641
642#[derive(Debug, Clone, PartialEq)]
643#[non_exhaustive]
644pub struct OpenGLBorrowedTextureDescriptor {
645 pub extent: RenderTargetExtent,
646 pub context: OpenGLContextDescriptor,
647 pub texture: u32,
648 pub target: u32,
649}
650
651impl OpenGLBorrowedTextureDescriptor {
652 pub fn new(
653 extent: RenderTargetExtent,
654 context: OpenGLContextDescriptor,
655 texture: u32,
656 target: u32,
657 ) -> Self {
658 Self {
659 extent,
660 context,
661 texture,
662 target,
663 }
664 }
665
666 pub(crate) fn to_native(&self) -> sys::mln_opengl_borrowed_texture_descriptor {
667 maplibre_core::render::opengl_borrowed_texture_descriptor_to_native(
668 maplibre_core::render::OpenGLBorrowedTextureDescriptorFields {
669 extent: self.extent.to_core(),
670 context: self.context.to_core(),
671 texture: self.texture,
672 target: self.target,
673 },
674 )
675 }
676}
677
678#[derive(Debug)]
679struct RenderSessionState {
680 handle: ThreadAffineNativeHandle<sys::mln_render_session>,
681 map: RefCell<Option<Rc<MapState>>>,
682 detached: Cell<bool>,
683 frame_acquired: Cell<bool>,
684}
685
686impl RenderSessionState {
687 fn new(ptr: NonNull<sys::mln_render_session>, map: Rc<MapState>) -> Self {
688 let handle = unsafe {
691 ThreadAffineNativeHandle::from_raw(
692 ptr,
693 sys::mln_render_session_destroy,
694 "mln_render_session",
695 )
696 };
697 Self {
698 handle,
699 map: RefCell::new(Some(map)),
700 detached: Cell::new(false),
701 frame_acquired: Cell::new(false),
702 }
703 }
704
705 fn ensure_no_frame_acquired(&self) -> Result<()> {
706 if self.frame_acquired.get() {
707 Err(frame_acquired_error())
708 } else {
709 Ok(())
710 }
711 }
712
713 fn as_ptr(&self) -> Result<*mut sys::mln_render_session> {
714 let ptr = self.handle.as_ptr();
715 if ptr.is_null() {
716 Err(closed_handle_error("RenderSessionHandle"))
717 } else {
718 Ok(ptr)
719 }
720 }
721
722 fn close(&self) -> Result<()> {
723 self.handle.close()?;
724 self.map.borrow_mut().take();
725 Ok(())
726 }
727}
728
729pub struct RenderSessionHandle {
731 inner: Rc<RenderSessionState>,
732}
733
734impl fmt::Debug for RenderSessionHandle {
735 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
736 f.debug_struct("RenderSessionHandle")
737 .field("closed", &self.inner.handle.is_closed())
738 .field("detached", &self.inner.detached.get())
739 .finish()
740 }
741}
742
743pub struct DetachedRenderSessionHandle {
745 inner: Rc<RenderSessionState>,
746}
747
748impl fmt::Debug for DetachedRenderSessionHandle {
749 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
750 f.debug_struct("DetachedRenderSessionHandle")
751 .field("closed", &self.inner.handle.is_closed())
752 .finish()
753 }
754}
755
756impl DetachedRenderSessionHandle {
757 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
759 if let Err(error) = self.inner.close() {
760 return Err(HandleOperationError::new(error, self));
761 }
762 Ok(())
763 }
764}
765
766fn frame_acquired_error() -> crate::Error {
767 crate::Error::new(
768 crate::ErrorKind::InvalidState,
769 None,
770 "render session has an acquired texture frame",
771 )
772}
773
774#[derive(Debug, Clone, Copy, PartialEq)]
779#[non_exhaustive]
780pub struct MetalOwnedTextureFrame {
781 pub generation: u64,
782 pub width: u32,
783 pub height: u32,
784 pub scale_factor: f64,
785 pub frame_id: u64,
786 pub pixel_format: u64,
787}
788
789impl MetalOwnedTextureFrame {
790 fn from_native(raw: &sys::mln_metal_owned_texture_frame) -> Self {
791 Self {
792 generation: raw.generation,
793 width: raw.width,
794 height: raw.height,
795 scale_factor: raw.scale_factor,
796 frame_id: raw.frame_id,
797 pixel_format: raw.pixel_format,
798 }
799 }
800}
801
802#[derive(Debug, Clone, Copy, PartialEq)]
807#[non_exhaustive]
808pub struct VulkanOwnedTextureFrame {
809 pub generation: u64,
810 pub width: u32,
811 pub height: u32,
812 pub scale_factor: f64,
813 pub frame_id: u64,
814 pub format: u32,
815 pub layout: u32,
816}
817
818impl VulkanOwnedTextureFrame {
819 fn from_native(raw: &sys::mln_vulkan_owned_texture_frame) -> Self {
820 Self {
821 generation: raw.generation,
822 width: raw.width,
823 height: raw.height,
824 scale_factor: raw.scale_factor,
825 frame_id: raw.frame_id,
826 format: raw.format,
827 layout: raw.layout,
828 }
829 }
830}
831
832#[derive(Debug, Clone, Copy, PartialEq)]
837#[non_exhaustive]
838pub struct OpenGLOwnedTextureFrame {
839 pub generation: u64,
840 pub width: u32,
841 pub height: u32,
842 pub scale_factor: f64,
843 pub frame_id: u64,
844 pub target: u32,
845 pub internal_format: u32,
846 pub format: u32,
847 pub type_: u32,
848}
849
850impl OpenGLOwnedTextureFrame {
851 fn from_native(raw: &sys::mln_opengl_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 target: raw.target,
859 internal_format: raw.internal_format,
860 format: raw.format,
861 type_: raw.type_,
862 }
863 }
864}
865
866pub struct MetalOwnedTextureFrameHandle {
870 session: Rc<RenderSessionState>,
871 raw: sys::mln_metal_owned_texture_frame,
872 frame: MetalOwnedTextureFrame,
873 closed: Cell<bool>,
874 _thread_affine: PhantomData<Rc<()>>,
875}
876
877impl fmt::Debug for MetalOwnedTextureFrameHandle {
878 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
879 f.debug_struct("MetalOwnedTextureFrameHandle")
880 .field("closed", &self.closed.get())
881 .field("frame", &self.frame)
882 .finish()
883 }
884}
885
886impl MetalOwnedTextureFrameHandle {
887 pub fn frame(&self) -> Result<&MetalOwnedTextureFrame> {
889 if self.closed.get() {
890 Err(closed_handle_error("MetalOwnedTextureFrameHandle"))
891 } else {
892 Ok(&self.frame)
893 }
894 }
895 pub unsafe fn texture(&self) -> Result<FrameNativePointer<'_>> {
903 if self.closed.get() {
904 Err(closed_handle_error("MetalOwnedTextureFrameHandle"))
905 } else {
906 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.texture) })
909 }
910 }
911
912 pub unsafe fn device(&self) -> Result<FrameNativePointer<'_>> {
919 if self.closed.get() {
920 Err(closed_handle_error("MetalOwnedTextureFrameHandle"))
921 } else {
922 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.device) })
924 }
925 }
926
927 #[allow(clippy::result_large_err)]
929 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
930 self.close_with_release(sys::mln_metal_owned_texture_release_frame)
931 }
932
933 #[allow(clippy::result_large_err)]
934 fn close_with_release(
935 self,
936 release: unsafe extern "C" fn(
937 *mut sys::mln_render_session,
938 *const sys::mln_metal_owned_texture_frame,
939 ) -> sys::mln_status,
940 ) -> std::result::Result<(), HandleOperationError<Self>> {
941 if self.closed.get() {
942 return Ok(());
943 }
944 let session = match self.session.as_ptr() {
945 Ok(session) => session,
946 Err(error) => return Err(HandleOperationError::new(error, self)),
947 };
948 if let Err(error) = maplibre_core::check(unsafe { release(session, &self.raw) }) {
951 return Err(HandleOperationError::new(error, self));
952 }
953 self.closed.set(true);
954 self.session.frame_acquired.set(false);
955 Ok(())
956 }
957}
958
959impl Drop for MetalOwnedTextureFrameHandle {
960 fn drop(&mut self) {
961 if self.closed.get() {
962 return;
963 }
964 if let Ok(session) = self.session.as_ptr() {
965 let status = unsafe { sys::mln_metal_owned_texture_release_frame(session, &self.raw) };
968 if status == sys::MLN_STATUS_OK {
969 self.closed.set(true);
970 self.session.frame_acquired.set(false);
971 }
972 }
973 }
974}
975
976pub struct VulkanOwnedTextureFrameHandle {
981 session: Rc<RenderSessionState>,
982 raw: sys::mln_vulkan_owned_texture_frame,
983 frame: VulkanOwnedTextureFrame,
984 closed: Cell<bool>,
985 _thread_affine: PhantomData<Rc<()>>,
986}
987
988impl fmt::Debug for VulkanOwnedTextureFrameHandle {
989 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
990 f.debug_struct("VulkanOwnedTextureFrameHandle")
991 .field("closed", &self.closed.get())
992 .field("frame", &self.frame)
993 .finish()
994 }
995}
996
997impl VulkanOwnedTextureFrameHandle {
998 pub fn frame(&self) -> Result<&VulkanOwnedTextureFrame> {
1000 if self.closed.get() {
1001 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1002 } else {
1003 Ok(&self.frame)
1004 }
1005 }
1006 pub unsafe fn image(&self) -> Result<FrameNativePointer<'_>> {
1014 if self.closed.get() {
1015 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1016 } else {
1017 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.image) })
1020 }
1021 }
1022
1023 pub unsafe fn image_view(&self) -> Result<FrameNativePointer<'_>> {
1030 if self.closed.get() {
1031 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1032 } else {
1033 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.image_view) })
1035 }
1036 }
1037
1038 pub unsafe fn device(&self) -> Result<FrameNativePointer<'_>> {
1045 if self.closed.get() {
1046 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1047 } else {
1048 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.device) })
1050 }
1051 }
1052
1053 #[allow(clippy::result_large_err)]
1055 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1056 if self.closed.get() {
1057 return Ok(());
1058 }
1059 let session = match self.session.as_ptr() {
1060 Ok(session) => session,
1061 Err(error) => return Err(HandleOperationError::new(error, self)),
1062 };
1063 if let Err(error) = maplibre_core::check(unsafe {
1066 sys::mln_vulkan_owned_texture_release_frame(session, &self.raw)
1067 }) {
1068 return Err(HandleOperationError::new(error, self));
1069 }
1070 self.closed.set(true);
1071 self.session.frame_acquired.set(false);
1072 Ok(())
1073 }
1074}
1075
1076impl Drop for VulkanOwnedTextureFrameHandle {
1077 fn drop(&mut self) {
1078 if self.closed.get() {
1079 return;
1080 }
1081 if let Ok(session) = self.session.as_ptr() {
1082 let status = unsafe { sys::mln_vulkan_owned_texture_release_frame(session, &self.raw) };
1085 if status == sys::MLN_STATUS_OK {
1086 self.closed.set(true);
1087 self.session.frame_acquired.set(false);
1088 }
1089 }
1090 }
1091}
1092
1093pub struct OpenGLOwnedTextureFrameHandle {
1097 session: Rc<RenderSessionState>,
1098 raw: sys::mln_opengl_owned_texture_frame,
1099 frame: OpenGLOwnedTextureFrame,
1100 closed: Cell<bool>,
1101 _thread_affine: PhantomData<Rc<()>>,
1102}
1103
1104impl fmt::Debug for OpenGLOwnedTextureFrameHandle {
1105 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1106 f.debug_struct("OpenGLOwnedTextureFrameHandle")
1107 .field("closed", &self.closed.get())
1108 .field("frame", &self.frame)
1109 .finish()
1110 }
1111}
1112
1113impl OpenGLOwnedTextureFrameHandle {
1114 pub fn frame(&self) -> Result<&OpenGLOwnedTextureFrame> {
1116 if self.closed.get() {
1117 Err(closed_handle_error("OpenGLOwnedTextureFrameHandle"))
1118 } else {
1119 Ok(&self.frame)
1120 }
1121 }
1122 pub fn texture(&self) -> Result<FrameOpenGLTextureName<'_>> {
1124 if self.closed.get() {
1125 Err(closed_handle_error("OpenGLOwnedTextureFrameHandle"))
1126 } else {
1127 Ok(FrameOpenGLTextureName::new(self.raw.texture))
1128 }
1129 }
1130
1131 #[allow(clippy::result_large_err)]
1133 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1134 if self.closed.get() {
1135 return Ok(());
1136 }
1137 let session = match self.session.as_ptr() {
1138 Ok(session) => session,
1139 Err(error) => return Err(HandleOperationError::new(error, self)),
1140 };
1141 if let Err(error) = maplibre_core::check(unsafe {
1144 sys::mln_opengl_owned_texture_release_frame(session, &self.raw)
1145 }) {
1146 return Err(HandleOperationError::new(error, self));
1147 }
1148 self.closed.set(true);
1149 self.session.frame_acquired.set(false);
1150 Ok(())
1151 }
1152}
1153
1154impl Drop for OpenGLOwnedTextureFrameHandle {
1155 fn drop(&mut self) {
1156 if self.closed.get() {
1157 return;
1158 }
1159 if let Ok(session) = self.session.as_ptr() {
1160 let status = unsafe { sys::mln_opengl_owned_texture_release_frame(session, &self.raw) };
1163 if status == sys::MLN_STATUS_OK {
1164 self.closed.set(true);
1165 self.session.frame_acquired.set(false);
1166 }
1167 }
1168 }
1169}
1170
1171impl RenderSessionHandle {
1172 pub(crate) fn attach<F>(map: &MapHandle, attach: F) -> Result<Self>
1173 where
1174 F: FnOnce(*mut sys::mln_map, *mut *mut sys::mln_render_session) -> sys::mln_status,
1175 {
1176 let map_ptr = map.inner.as_ptr()?;
1177 let mut out = maplibre_core::ptr::OutPtr::<sys::mln_render_session>::new();
1178 let status = attach(map_ptr, out.as_mut_ptr());
1179 maplibre_core::check(status)?;
1180 let ptr = out_handle(out, "mln_render_session")?;
1181 Ok(Self {
1182 inner: Rc::new(RenderSessionState::new(ptr, Rc::clone(&map.inner))),
1183 })
1184 }
1185
1186 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1191 if let Err(error) = self.inner.ensure_no_frame_acquired() {
1192 return Err(HandleOperationError::new(error, self));
1193 }
1194 if let Err(error) = self.inner.close() {
1195 return Err(HandleOperationError::new(error, self));
1196 }
1197 Ok(())
1198 }
1199 pub fn resize(&self, width: u32, height: u32, scale_factor: f64) -> Result<()> {
1201 self.inner.ensure_no_frame_acquired()?;
1202 let session = self.inner.as_ptr()?;
1203 maplibre_core::check(unsafe {
1205 sys::mln_render_session_resize(session, width, height, scale_factor)
1206 })
1207 }
1208
1209 pub fn render_update(&self) -> Result<()> {
1211 self.inner.ensure_no_frame_acquired()?;
1212 let session = self.inner.as_ptr()?;
1213 maplibre_core::check(unsafe { sys::mln_render_session_render_update(session) })
1215 }
1216
1217 pub fn detach(
1222 self,
1223 ) -> std::result::Result<DetachedRenderSessionHandle, HandleOperationError<Self>> {
1224 if let Err(error) = self.inner.ensure_no_frame_acquired() {
1225 return Err(HandleOperationError::new(error, self));
1226 }
1227 let session = match self.inner.as_ptr() {
1228 Ok(session) => session,
1229 Err(error) => return Err(HandleOperationError::new(error, self)),
1230 };
1231 if let Err(error) = maplibre_core::check(unsafe { sys::mln_render_session_detach(session) })
1233 {
1234 return Err(HandleOperationError::new(error, self));
1235 }
1236 self.inner.detached.set(true);
1237 Ok(DetachedRenderSessionHandle {
1238 inner: Rc::clone(&self.inner),
1239 })
1240 }
1241
1242 pub fn reduce_memory_use(&self) -> Result<()> {
1244 self.inner.ensure_no_frame_acquired()?;
1245 let session = self.inner.as_ptr()?;
1246 maplibre_core::check(unsafe { sys::mln_render_session_reduce_memory_use(session) })
1248 }
1249
1250 pub fn clear_data(&self) -> Result<()> {
1252 self.inner.ensure_no_frame_acquired()?;
1253 let session = self.inner.as_ptr()?;
1254 maplibre_core::check(unsafe { sys::mln_render_session_clear_data(session) })
1256 }
1257
1258 pub fn dump_debug_logs(&self) -> Result<()> {
1260 self.inner.ensure_no_frame_acquired()?;
1261 let session = self.inner.as_ptr()?;
1262 maplibre_core::check(unsafe { sys::mln_render_session_dump_debug_logs(session) })
1264 }
1265
1266 pub fn texture_image_info(&self) -> Result<TextureImageInfo> {
1268 self.inner.ensure_no_frame_acquired()?;
1269 let session = self.inner.as_ptr()?;
1270 let mut info = unsafe { sys::mln_texture_image_info_default() };
1272 let status = unsafe {
1275 sys::mln_texture_read_premultiplied_rgba8(session, std::ptr::null_mut(), 0, &mut info)
1276 };
1277 if status == sys::MLN_STATUS_OK
1278 || (status == sys::MLN_STATUS_INVALID_ARGUMENT && info.byte_length > 0)
1279 {
1280 Ok(maplibre_core::values::texture_image_info_from_native(&info))
1281 } else {
1282 Err(crate::Error::from_status(status))
1283 }
1284 }
1285
1286 pub fn read_premultiplied_rgba8_into(&self, data: &mut [u8]) -> Result<TextureImageInfo> {
1288 self.inner.ensure_no_frame_acquired()?;
1289 let session = self.inner.as_ptr()?;
1290 let mut info = unsafe { sys::mln_texture_image_info_default() };
1292 let data_ptr = if data.is_empty() {
1293 std::ptr::null_mut()
1294 } else {
1295 data.as_mut_ptr()
1296 };
1297 maplibre_core::check(unsafe {
1301 sys::mln_texture_read_premultiplied_rgba8(session, data_ptr, data.len(), &mut info)
1302 })?;
1303 Ok(maplibre_core::values::texture_image_info_from_native(&info))
1304 }
1305
1306 pub fn acquire_metal_owned_texture_frame(&self) -> Result<MetalOwnedTextureFrameHandle> {
1308 self.inner.ensure_no_frame_acquired()?;
1309 let session = self.inner.as_ptr()?;
1310 let mut raw = empty_metal_owned_texture_frame();
1311 maplibre_core::check(unsafe {
1313 sys::mln_metal_owned_texture_acquire_frame(session, &mut raw)
1314 })?;
1315 self.inner.frame_acquired.set(true);
1316 Ok(MetalOwnedTextureFrameHandle {
1317 session: Rc::clone(&self.inner),
1318 frame: MetalOwnedTextureFrame::from_native(&raw),
1319 raw,
1320 closed: Cell::new(false),
1321 _thread_affine: PhantomData,
1322 })
1323 }
1324
1325 pub fn acquire_vulkan_owned_texture_frame(&self) -> Result<VulkanOwnedTextureFrameHandle> {
1327 self.inner.ensure_no_frame_acquired()?;
1328 let session = self.inner.as_ptr()?;
1329 let mut raw = empty_vulkan_owned_texture_frame();
1330 maplibre_core::check(unsafe {
1332 sys::mln_vulkan_owned_texture_acquire_frame(session, &mut raw)
1333 })?;
1334 self.inner.frame_acquired.set(true);
1335 Ok(VulkanOwnedTextureFrameHandle {
1336 session: Rc::clone(&self.inner),
1337 frame: VulkanOwnedTextureFrame::from_native(&raw),
1338 raw,
1339 closed: Cell::new(false),
1340 _thread_affine: PhantomData,
1341 })
1342 }
1343
1344 pub fn acquire_opengl_owned_texture_frame(&self) -> Result<OpenGLOwnedTextureFrameHandle> {
1346 self.inner.ensure_no_frame_acquired()?;
1347 let session = self.inner.as_ptr()?;
1348 let mut raw = empty_opengl_owned_texture_frame();
1349 maplibre_core::check(unsafe {
1351 sys::mln_opengl_owned_texture_acquire_frame(session, &mut raw)
1352 })?;
1353 self.inner.frame_acquired.set(true);
1354 Ok(OpenGLOwnedTextureFrameHandle {
1355 session: Rc::clone(&self.inner),
1356 frame: OpenGLOwnedTextureFrame::from_native(&raw),
1357 raw,
1358 closed: Cell::new(false),
1359 _thread_affine: PhantomData,
1360 })
1361 }
1362}
1363
1364fn empty_metal_owned_texture_frame() -> sys::mln_metal_owned_texture_frame {
1365 sys::mln_metal_owned_texture_frame {
1366 size: mem::size_of::<sys::mln_metal_owned_texture_frame>() as u32,
1367 generation: 0,
1368 width: 0,
1369 height: 0,
1370 scale_factor: 0.0,
1371 frame_id: 0,
1372 texture: std::ptr::null_mut(),
1373 device: std::ptr::null_mut(),
1374 pixel_format: 0,
1375 }
1376}
1377
1378fn empty_vulkan_owned_texture_frame() -> sys::mln_vulkan_owned_texture_frame {
1379 sys::mln_vulkan_owned_texture_frame {
1380 size: mem::size_of::<sys::mln_vulkan_owned_texture_frame>() as u32,
1381 generation: 0,
1382 width: 0,
1383 height: 0,
1384 scale_factor: 0.0,
1385 frame_id: 0,
1386 image: std::ptr::null_mut(),
1387 image_view: std::ptr::null_mut(),
1388 device: std::ptr::null_mut(),
1389 format: 0,
1390 layout: 0,
1391 }
1392}
1393
1394fn empty_opengl_owned_texture_frame() -> sys::mln_opengl_owned_texture_frame {
1395 sys::mln_opengl_owned_texture_frame {
1396 size: mem::size_of::<sys::mln_opengl_owned_texture_frame>() as u32,
1397 generation: 0,
1398 width: 0,
1399 height: 0,
1400 scale_factor: 0.0,
1401 frame_id: 0,
1402 texture: 0,
1403 target: 0,
1404 internal_format: 0,
1405 format: 0,
1406 type_: 0,
1407 }
1408}
1409
1410#[cfg(test)]
1411mod tests;