1use std::cell::Cell;
2use std::fmt;
3use std::marker::PhantomData;
4use std::mem;
5use std::rc::Rc;
6
7pub use maplibre_core::{PremultipliedRgba8Image, TextureImageInfo};
8use maplibre_native_ffi_core as maplibre_core;
9use maplibre_native_ffi_core::{OpenGLClientApi, OpenGLContextOwnership, RenderResult};
10use maplibre_native_ffi_sys as sys;
11
12use crate::handle::{ThreadAffineNativeHandle, closed_handle_error, out_handle};
13use crate::map::MapAttachRef;
14use crate::{HandleOperationError, Result};
15
16#[derive(Clone, Copy, PartialEq, Eq, Hash)]
20pub struct NativePointer {
21 address: usize,
22 _thread_affine: PhantomData<Rc<()>>,
23}
24
25impl NativePointer {
26 pub const NULL: Self = Self {
28 address: 0,
29 _thread_affine: PhantomData,
30 };
31
32 pub unsafe fn from_address(address: usize) -> Self {
40 if address == 0 {
41 Self::NULL
42 } else {
43 Self {
44 address,
45 _thread_affine: PhantomData,
46 }
47 }
48 }
49
50 pub unsafe fn from_ptr<T>(ptr: *mut T) -> Self {
57 unsafe { Self::from_address(ptr as usize) }
60 }
61
62 pub fn address(self) -> usize {
64 self.address
65 }
66
67 pub fn is_null(self) -> bool {
69 self.address == 0
70 }
71
72 pub unsafe fn as_ptr<T>(self) -> *mut T {
80 self.address as *mut T
81 }
82
83 fn as_void_ptr(self) -> *mut std::ffi::c_void {
84 self.address as *mut std::ffi::c_void
85 }
86}
87
88impl fmt::Debug for NativePointer {
89 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
90 write!(f, "NativePointer(0x{:x})", self.address)
91 }
92}
93
94#[derive(Clone, Copy, PartialEq, Eq, Hash)]
98pub struct FrameNativePointer<'frame> {
99 address: usize,
100 _frame: PhantomData<&'frame ()>,
101 _thread_affine: PhantomData<Rc<()>>,
102}
103
104impl<'frame> FrameNativePointer<'frame> {
105 unsafe fn from_ptr<T>(ptr: *mut T) -> Self {
106 Self {
107 address: ptr as usize,
108 _frame: PhantomData,
109 _thread_affine: PhantomData,
110 }
111 }
112
113 pub unsafe fn address(self) -> usize {
122 self.address
123 }
124
125 pub fn is_null(self) -> bool {
127 self.address == 0
128 }
129
130 pub unsafe fn as_ptr<T>(self) -> *mut T {
138 self.address as *mut T
139 }
140}
141
142impl fmt::Debug for FrameNativePointer<'_> {
143 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
144 write!(f, "FrameNativePointer(0x{:x})", self.address)
145 }
146}
147
148#[derive(Clone, Copy, PartialEq, Eq, Hash)]
150pub struct FrameOpenGLTextureName<'frame> {
151 name: u32,
152 _frame: PhantomData<&'frame ()>,
153 _thread_affine: PhantomData<Rc<()>>,
154}
155
156impl<'frame> FrameOpenGLTextureName<'frame> {
157 fn new(name: u32) -> Self {
158 Self {
159 name,
160 _frame: PhantomData,
161 _thread_affine: PhantomData,
162 }
163 }
164
165 pub fn is_zero(self) -> bool {
167 self.name == 0
168 }
169
170 pub unsafe fn value(self) -> u32 {
178 self.name
179 }
180}
181
182impl fmt::Debug for FrameOpenGLTextureName<'_> {
183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184 write!(f, "FrameOpenGLTextureName({})", self.name)
185 }
186}
187
188mod query;
189pub use query::{
190 FeatureStateSelector, QueriedFeature, RenderedFeatureQueryOptions, RenderedQueryGeometry,
191 SourceFeatureQueryOptions,
192};
193#[derive(Debug, Clone, PartialEq)]
194#[non_exhaustive]
195pub struct RenderTargetExtent {
196 pub width: u32,
197 pub height: u32,
198 pub scale_factor: f64,
199}
200
201impl RenderTargetExtent {
202 pub fn new(width: u32, height: u32, scale_factor: f64) -> Self {
203 Self {
204 width,
205 height,
206 scale_factor,
207 }
208 }
209
210 pub(crate) fn to_core(&self) -> maplibre_core::render::RenderTargetExtentFields {
211 maplibre_core::render::RenderTargetExtentFields {
212 width: self.width,
213 height: self.height,
214 scale_factor: self.scale_factor,
215 }
216 }
217
218 pub fn physical_size(&self) -> Result<(u32, u32)> {
223 let native = maplibre_core::render::render_target_extent_to_native(self.to_core());
224 let mut width = 0u32;
225 let mut height = 0u32;
226 maplibre_core::check(unsafe {
229 sys::mln_render_target_extent_physical_size(&native, &mut width, &mut height)
230 })?;
231 Ok((width, height))
232 }
233}
234
235impl Default for RenderTargetExtent {
236 fn default() -> Self {
237 Self::new(256, 256, 1.0)
238 }
239}
240
241#[derive(Debug, Clone, PartialEq)]
242#[non_exhaustive]
243pub struct MetalContextDescriptor {
244 pub device: NativePointer,
245}
246
247impl MetalContextDescriptor {
248 pub fn new(device: NativePointer) -> Self {
249 Self { device }
250 }
251
252 pub(crate) fn to_core(&self) -> maplibre_core::render::MetalContextDescriptorFields {
253 maplibre_core::render::MetalContextDescriptorFields {
254 device: self.device.as_void_ptr(),
255 }
256 }
257}
258
259impl Default for MetalContextDescriptor {
260 fn default() -> Self {
261 Self::new(NativePointer::NULL)
262 }
263}
264
265#[derive(Debug, Clone, PartialEq)]
266#[non_exhaustive]
267pub struct VulkanContextDescriptor {
268 pub instance: NativePointer,
269 pub physical_device: NativePointer,
270 pub device: NativePointer,
271 pub graphics_queue: NativePointer,
272 pub graphics_queue_family_index: u32,
273 pub get_instance_proc_addr: NativePointer,
274 pub get_device_proc_addr: NativePointer,
275}
276
277impl VulkanContextDescriptor {
278 #[allow(clippy::too_many_arguments)]
279 pub fn new(
280 instance: NativePointer,
281 physical_device: NativePointer,
282 device: NativePointer,
283 graphics_queue: NativePointer,
284 graphics_queue_family_index: u32,
285 ) -> Self {
286 Self {
287 instance,
288 physical_device,
289 device,
290 graphics_queue,
291 graphics_queue_family_index,
292 get_instance_proc_addr: NativePointer::NULL,
293 get_device_proc_addr: NativePointer::NULL,
294 }
295 }
296
297 pub(crate) fn to_core(&self) -> maplibre_core::render::VulkanContextDescriptorFields {
298 maplibre_core::render::VulkanContextDescriptorFields {
299 instance: self.instance.as_void_ptr(),
300 physical_device: self.physical_device.as_void_ptr(),
301 device: self.device.as_void_ptr(),
302 graphics_queue: self.graphics_queue.as_void_ptr(),
303 graphics_queue_family_index: self.graphics_queue_family_index,
304 get_instance_proc_addr: self.get_instance_proc_addr.as_void_ptr(),
305 get_device_proc_addr: self.get_device_proc_addr.as_void_ptr(),
306 }
307 }
308}
309
310impl Default for VulkanContextDescriptor {
311 fn default() -> Self {
312 Self::new(
313 NativePointer::NULL,
314 NativePointer::NULL,
315 NativePointer::NULL,
316 NativePointer::NULL,
317 0,
318 )
319 }
320}
321
322#[derive(Debug, Clone, PartialEq)]
328#[non_exhaustive]
329pub struct WebGpuContextDescriptor {
330 pub instance: NativePointer,
332 pub device: NativePointer,
333 pub queue: NativePointer,
336}
337
338impl WebGpuContextDescriptor {
339 pub fn new(device: NativePointer) -> Self {
340 Self {
341 instance: NativePointer::NULL,
342 device,
343 queue: NativePointer::NULL,
344 }
345 }
346
347 pub(crate) fn to_core(&self) -> maplibre_core::render::WebGpuContextDescriptorFields {
348 maplibre_core::render::WebGpuContextDescriptorFields {
349 instance: self.instance.as_void_ptr(),
350 device: self.device.as_void_ptr(),
351 queue: self.queue.as_void_ptr(),
352 }
353 }
354}
355
356impl Default for WebGpuContextDescriptor {
357 fn default() -> Self {
358 Self::new(NativePointer::NULL)
359 }
360}
361
362#[derive(Debug, Clone, PartialEq)]
363#[non_exhaustive]
364pub struct WglContextDescriptor {
365 pub device_context: NativePointer,
366 pub share_context: NativePointer,
370 pub get_proc_address: NativePointer,
371 pub ownership: OpenGLContextOwnership,
373}
374
375impl WglContextDescriptor {
376 pub fn new(device_context: NativePointer, share_context: NativePointer) -> Self {
377 Self {
378 device_context,
379 share_context,
380 get_proc_address: NativePointer::NULL,
381 ownership: OpenGLContextOwnership::Shared,
382 }
383 }
384
385 pub(crate) fn to_core(&self) -> maplibre_core::render::WglContextDescriptorFields {
386 maplibre_core::render::WglContextDescriptorFields {
387 device_context: self.device_context.as_void_ptr(),
388 share_context: self.share_context.as_void_ptr(),
389 get_proc_address: self.get_proc_address.as_void_ptr(),
390 ownership: self.ownership.as_raw(),
391 }
392 }
393}
394
395impl Default for WglContextDescriptor {
396 fn default() -> Self {
397 Self::new(NativePointer::NULL, NativePointer::NULL)
398 }
399}
400
401#[derive(Debug, Clone, PartialEq)]
402#[non_exhaustive]
403pub struct EglContextDescriptor {
404 pub display: NativePointer,
405 pub config: NativePointer,
406 pub share_context: NativePointer,
411 pub client_api: OpenGLClientApi,
415 pub get_proc_address: NativePointer,
416 pub ownership: OpenGLContextOwnership,
418}
419
420impl EglContextDescriptor {
421 pub fn new(
422 display: NativePointer,
423 config: NativePointer,
424 share_context: NativePointer,
425 ) -> Self {
426 Self {
427 display,
428 config,
429 share_context,
430 client_api: OpenGLClientApi::Unspecified,
431 get_proc_address: NativePointer::NULL,
432 ownership: OpenGLContextOwnership::Shared,
433 }
434 }
435
436 pub(crate) fn to_core(&self) -> maplibre_core::render::EglContextDescriptorFields {
437 maplibre_core::render::EglContextDescriptorFields {
438 display: self.display.as_void_ptr(),
439 config: self.config.as_void_ptr(),
440 share_context: self.share_context.as_void_ptr(),
441 client_api: self.client_api.as_raw(),
442 get_proc_address: self.get_proc_address.as_void_ptr(),
443 ownership: self.ownership.as_raw(),
444 }
445 }
446}
447
448impl Default for EglContextDescriptor {
449 fn default() -> Self {
450 Self::new(
451 NativePointer::NULL,
452 NativePointer::NULL,
453 NativePointer::NULL,
454 )
455 }
456}
457
458#[derive(Debug, Clone, PartialEq)]
465#[non_exhaustive]
466pub struct WebGlContextDescriptor {
467 pub context: i32,
468}
469
470impl WebGlContextDescriptor {
471 pub fn new(context: i32) -> Self {
472 Self { context }
473 }
474
475 pub(crate) fn to_core(&self) -> maplibre_core::render::WebGlContextDescriptorFields {
476 maplibre_core::render::WebGlContextDescriptorFields {
477 context: self.context,
478 }
479 }
480}
481
482#[derive(Debug, Clone, PartialEq)]
487#[non_exhaustive]
488pub enum OpenGLContextDescriptor {
489 Wgl(WglContextDescriptor),
490 Egl(EglContextDescriptor),
491 WebGl(WebGlContextDescriptor),
492}
493
494impl OpenGLContextDescriptor {
495 pub(crate) fn to_core(&self) -> maplibre_core::render::OpenGLContextDescriptorFields {
496 match self {
497 Self::Wgl(descriptor) => {
498 maplibre_core::render::OpenGLContextDescriptorFields::Wgl(descriptor.to_core())
499 }
500 Self::Egl(descriptor) => {
501 maplibre_core::render::OpenGLContextDescriptorFields::Egl(descriptor.to_core())
502 }
503 Self::WebGl(descriptor) => {
504 maplibre_core::render::OpenGLContextDescriptorFields::WebGl(descriptor.to_core())
505 }
506 }
507 }
508}
509
510#[derive(Debug, Clone, PartialEq)]
511#[non_exhaustive]
512pub struct MetalSurfaceDescriptor {
513 pub extent: RenderTargetExtent,
514 pub context: MetalContextDescriptor,
515 pub layer: NativePointer,
516}
517
518impl MetalSurfaceDescriptor {
519 pub fn new(
520 extent: RenderTargetExtent,
521 context: MetalContextDescriptor,
522 layer: NativePointer,
523 ) -> Self {
524 Self {
525 extent,
526 context,
527 layer,
528 }
529 }
530
531 pub(crate) fn to_native(&self) -> sys::mln_metal_surface_descriptor {
532 maplibre_core::render::metal_surface_descriptor_to_native(
533 maplibre_core::render::MetalSurfaceDescriptorFields {
534 extent: self.extent.to_core(),
535 context: self.context.to_core(),
536 layer: self.layer.as_void_ptr(),
537 },
538 )
539 }
540}
541
542#[derive(Debug, Clone, PartialEq)]
543#[non_exhaustive]
544pub struct VulkanSurfaceDescriptor {
545 pub extent: RenderTargetExtent,
546 pub context: VulkanContextDescriptor,
547 pub surface: NativePointer,
548}
549
550impl VulkanSurfaceDescriptor {
551 pub fn new(
552 extent: RenderTargetExtent,
553 context: VulkanContextDescriptor,
554 surface: NativePointer,
555 ) -> Self {
556 Self {
557 extent,
558 context,
559 surface,
560 }
561 }
562
563 pub(crate) fn to_native(&self) -> sys::mln_vulkan_surface_descriptor {
564 maplibre_core::render::vulkan_surface_descriptor_to_native(
565 maplibre_core::render::VulkanSurfaceDescriptorFields {
566 extent: self.extent.to_core(),
567 context: self.context.to_core(),
568 surface: self.surface.as_void_ptr(),
569 },
570 )
571 }
572}
573
574#[derive(Debug, Clone, PartialEq)]
581#[non_exhaustive]
582pub struct WebGpuSurfaceDescriptor {
583 pub extent: RenderTargetExtent,
584 pub context: WebGpuContextDescriptor,
585 pub surface: NativePointer,
586 pub format: u32,
587}
588
589impl WebGpuSurfaceDescriptor {
590 pub fn new(
591 extent: RenderTargetExtent,
592 context: WebGpuContextDescriptor,
593 surface: NativePointer,
594 format: u32,
595 ) -> Self {
596 Self {
597 extent,
598 context,
599 surface,
600 format,
601 }
602 }
603
604 pub(crate) fn to_native(&self) -> sys::mln_webgpu_surface_descriptor {
605 maplibre_core::render::webgpu_surface_descriptor_to_native(
606 maplibre_core::render::WebGpuSurfaceDescriptorFields {
607 extent: self.extent.to_core(),
608 context: self.context.to_core(),
609 surface: self.surface.as_void_ptr(),
610 format: self.format,
611 },
612 )
613 }
614}
615
616#[derive(Debug, Clone, PartialEq)]
617#[non_exhaustive]
618pub struct OpenGLSurfaceDescriptor {
619 pub extent: RenderTargetExtent,
620 pub context: OpenGLContextDescriptor,
621 pub surface: NativePointer,
622}
623
624impl OpenGLSurfaceDescriptor {
625 pub fn new(
626 extent: RenderTargetExtent,
627 context: OpenGLContextDescriptor,
628 surface: NativePointer,
629 ) -> Self {
630 Self {
631 extent,
632 context,
633 surface,
634 }
635 }
636
637 pub(crate) fn to_native(&self) -> sys::mln_opengl_surface_descriptor {
638 maplibre_core::render::opengl_surface_descriptor_to_native(
639 maplibre_core::render::OpenGLSurfaceDescriptorFields {
640 extent: self.extent.to_core(),
641 context: self.context.to_core(),
642 surface: self.surface.as_void_ptr(),
643 },
644 )
645 }
646}
647
648#[derive(Debug, Clone, PartialEq)]
649#[non_exhaustive]
650pub struct MetalOwnedTextureDescriptor {
651 pub extent: RenderTargetExtent,
652 pub context: MetalContextDescriptor,
653}
654
655impl MetalOwnedTextureDescriptor {
656 pub fn new(extent: RenderTargetExtent, context: MetalContextDescriptor) -> Self {
657 Self { extent, context }
658 }
659
660 pub(crate) fn to_native(&self) -> sys::mln_metal_owned_texture_descriptor {
661 maplibre_core::render::metal_owned_texture_descriptor_to_native(
662 maplibre_core::render::MetalOwnedTextureDescriptorFields {
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 MetalBorrowedTextureDescriptor {
673 pub extent: RenderTargetExtent,
674 pub physical_width: u32,
677 pub physical_height: u32,
678 pub texture: NativePointer,
679}
680
681impl MetalBorrowedTextureDescriptor {
682 pub fn new(
683 extent: RenderTargetExtent,
684 physical_width: u32,
685 physical_height: u32,
686 texture: NativePointer,
687 ) -> Self {
688 Self {
689 extent,
690 physical_width,
691 physical_height,
692 texture,
693 }
694 }
695
696 pub(crate) fn to_native(&self) -> sys::mln_metal_borrowed_texture_descriptor {
697 maplibre_core::render::metal_borrowed_texture_descriptor_to_native(
698 maplibre_core::render::MetalBorrowedTextureDescriptorFields {
699 extent: self.extent.to_core(),
700 physical_width: self.physical_width,
701 physical_height: self.physical_height,
702 texture: self.texture.as_void_ptr(),
703 },
704 )
705 }
706}
707
708#[derive(Debug, Clone, PartialEq)]
709#[non_exhaustive]
710pub struct VulkanOwnedTextureDescriptor {
711 pub extent: RenderTargetExtent,
712 pub context: VulkanContextDescriptor,
713}
714
715impl VulkanOwnedTextureDescriptor {
716 pub fn new(extent: RenderTargetExtent, context: VulkanContextDescriptor) -> Self {
717 Self { extent, context }
718 }
719
720 pub(crate) fn to_native(&self) -> sys::mln_vulkan_owned_texture_descriptor {
721 maplibre_core::render::vulkan_owned_texture_descriptor_to_native(
722 maplibre_core::render::VulkanOwnedTextureDescriptorFields {
723 extent: self.extent.to_core(),
724 context: self.context.to_core(),
725 },
726 )
727 }
728}
729
730#[derive(Debug, Clone, PartialEq)]
731#[non_exhaustive]
732pub struct VulkanBorrowedTextureDescriptor {
733 pub extent: RenderTargetExtent,
734 pub physical_width: u32,
737 pub physical_height: u32,
738 pub context: VulkanContextDescriptor,
739 pub image: NativePointer,
740 pub image_view: NativePointer,
741 pub format: u32,
742 pub initial_layout: u32,
743 pub final_layout: u32,
744}
745
746impl VulkanBorrowedTextureDescriptor {
747 #[allow(clippy::too_many_arguments)]
748 pub fn new(
749 extent: RenderTargetExtent,
750 physical_width: u32,
751 physical_height: u32,
752 context: VulkanContextDescriptor,
753 image: NativePointer,
754 image_view: NativePointer,
755 format: u32,
756 initial_layout: u32,
757 final_layout: u32,
758 ) -> Self {
759 Self {
760 extent,
761 physical_width,
762 physical_height,
763 context,
764 image,
765 image_view,
766 format,
767 initial_layout,
768 final_layout,
769 }
770 }
771
772 pub(crate) fn to_native(&self) -> sys::mln_vulkan_borrowed_texture_descriptor {
773 maplibre_core::render::vulkan_borrowed_texture_descriptor_to_native(
774 maplibre_core::render::VulkanBorrowedTextureDescriptorFields {
775 extent: self.extent.to_core(),
776 physical_width: self.physical_width,
777 physical_height: self.physical_height,
778 context: self.context.to_core(),
779 image: self.image.as_void_ptr(),
780 image_view: self.image_view.as_void_ptr(),
781 format: self.format,
782 initial_layout: self.initial_layout,
783 final_layout: self.final_layout,
784 },
785 )
786 }
787}
788
789#[derive(Debug, Clone, PartialEq)]
790#[non_exhaustive]
791pub struct WebGpuOwnedTextureDescriptor {
792 pub extent: RenderTargetExtent,
793 pub context: WebGpuContextDescriptor,
794}
795
796impl WebGpuOwnedTextureDescriptor {
797 pub fn new(extent: RenderTargetExtent, context: WebGpuContextDescriptor) -> Self {
798 Self { extent, context }
799 }
800
801 pub(crate) fn to_native(&self) -> sys::mln_webgpu_owned_texture_descriptor {
802 maplibre_core::render::webgpu_owned_texture_descriptor_to_native(
803 maplibre_core::render::WebGpuOwnedTextureDescriptorFields {
804 extent: self.extent.to_core(),
805 context: self.context.to_core(),
806 },
807 )
808 }
809}
810
811#[derive(Debug, Clone, PartialEq)]
812#[non_exhaustive]
813pub struct WebGpuBorrowedTextureDescriptor {
814 pub extent: RenderTargetExtent,
815 pub physical_width: u32,
818 pub physical_height: u32,
819 pub context: WebGpuContextDescriptor,
820 pub texture: NativePointer,
821 pub texture_view: NativePointer,
822 pub format: u32,
824}
825
826impl WebGpuBorrowedTextureDescriptor {
827 #[allow(clippy::too_many_arguments)]
828 pub fn new(
829 extent: RenderTargetExtent,
830 physical_width: u32,
831 physical_height: u32,
832 context: WebGpuContextDescriptor,
833 texture: NativePointer,
834 texture_view: NativePointer,
835 format: u32,
836 ) -> Self {
837 Self {
838 extent,
839 physical_width,
840 physical_height,
841 context,
842 texture,
843 texture_view,
844 format,
845 }
846 }
847
848 pub(crate) fn to_native(&self) -> sys::mln_webgpu_borrowed_texture_descriptor {
849 maplibre_core::render::webgpu_borrowed_texture_descriptor_to_native(
850 maplibre_core::render::WebGpuBorrowedTextureDescriptorFields {
851 extent: self.extent.to_core(),
852 physical_width: self.physical_width,
853 physical_height: self.physical_height,
854 context: self.context.to_core(),
855 texture: self.texture.as_void_ptr(),
856 texture_view: self.texture_view.as_void_ptr(),
857 format: self.format,
858 },
859 )
860 }
861}
862
863#[derive(Debug, Clone, PartialEq)]
864#[non_exhaustive]
865pub struct OpenGLOwnedTextureDescriptor {
866 pub extent: RenderTargetExtent,
867 pub context: OpenGLContextDescriptor,
868}
869
870impl OpenGLOwnedTextureDescriptor {
871 pub fn new(extent: RenderTargetExtent, context: OpenGLContextDescriptor) -> Self {
872 Self { extent, context }
873 }
874
875 pub(crate) fn to_native(&self) -> sys::mln_opengl_owned_texture_descriptor {
876 maplibre_core::render::opengl_owned_texture_descriptor_to_native(
877 maplibre_core::render::OpenGLOwnedTextureDescriptorFields {
878 extent: self.extent.to_core(),
879 context: self.context.to_core(),
880 },
881 )
882 }
883}
884
885#[derive(Debug, Clone, PartialEq)]
886#[non_exhaustive]
887pub struct OpenGLBorrowedTextureDescriptor {
888 pub extent: RenderTargetExtent,
889 pub physical_width: u32,
892 pub physical_height: u32,
893 pub context: OpenGLContextDescriptor,
894 pub texture: u32,
895 pub target: u32,
896}
897
898impl OpenGLBorrowedTextureDescriptor {
899 pub fn new(
900 extent: RenderTargetExtent,
901 physical_width: u32,
902 physical_height: u32,
903 context: OpenGLContextDescriptor,
904 texture: u32,
905 target: u32,
906 ) -> Self {
907 Self {
908 extent,
909 physical_width,
910 physical_height,
911 context,
912 texture,
913 target,
914 }
915 }
916
917 pub(crate) fn to_native(&self) -> sys::mln_opengl_borrowed_texture_descriptor {
918 maplibre_core::render::opengl_borrowed_texture_descriptor_to_native(
919 maplibre_core::render::OpenGLBorrowedTextureDescriptorFields {
920 extent: self.extent.to_core(),
921 physical_width: self.physical_width,
922 physical_height: self.physical_height,
923 context: self.context.to_core(),
924 texture: self.texture,
925 target: self.target,
926 },
927 )
928 }
929}
930
931#[derive(Debug)]
932struct RenderSessionState {
933 handle: ThreadAffineNativeHandle<sys::mln_render_session>,
934 detached: Cell<bool>,
935 frame_acquired: Cell<bool>,
936}
937
938impl RenderSessionState {
939 fn new(native: sys::mln_render_session) -> Result<Self> {
940 let handle = unsafe {
943 ThreadAffineNativeHandle::from_handle(
944 native,
945 sys::mln_render_session_destroy,
946 "mln_render_session",
947 )
948 }?;
949 Ok(Self {
950 handle,
951 detached: Cell::new(false),
952 frame_acquired: Cell::new(false),
953 })
954 }
955
956 fn ensure_no_frame_acquired(&self) -> Result<()> {
957 if self.frame_acquired.get() {
958 Err(frame_acquired_error())
959 } else {
960 Ok(())
961 }
962 }
963
964 fn native(&self) -> Result<sys::mln_render_session> {
965 self.handle
966 .live_handle()
967 .ok_or_else(|| closed_handle_error("RenderSessionHandle"))
968 }
969
970 fn close(&self) -> Result<()> {
971 self.handle.close()
972 }
973}
974
975#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
977#[non_exhaustive]
978pub struct RenderUpdate {
979 pub result: RenderResult,
982 pub needs_repaint: bool,
989}
990
991pub struct RenderSessionHandle {
996 inner: Rc<RenderSessionState>,
997}
998
999impl fmt::Debug for RenderSessionHandle {
1000 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1001 f.debug_struct("RenderSessionHandle")
1002 .field("closed", &self.inner.handle.is_closed())
1003 .field("detached", &self.inner.detached.get())
1004 .finish()
1005 }
1006}
1007
1008pub struct DetachedRenderSessionHandle {
1013 inner: Rc<RenderSessionState>,
1014}
1015
1016impl fmt::Debug for DetachedRenderSessionHandle {
1017 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1018 f.debug_struct("DetachedRenderSessionHandle")
1019 .field("closed", &self.inner.handle.is_closed())
1020 .finish()
1021 }
1022}
1023
1024impl DetachedRenderSessionHandle {
1025 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1027 if let Err(error) = self.inner.close() {
1028 return Err(HandleOperationError::new(error, self));
1029 }
1030 Ok(())
1031 }
1032}
1033
1034fn frame_acquired_error() -> crate::Error {
1035 crate::Error::new(
1036 crate::ErrorKind::InvalidState,
1037 None,
1038 "render session has an acquired texture frame",
1039 )
1040}
1041
1042#[derive(Debug, Clone, Copy, PartialEq)]
1047#[non_exhaustive]
1048pub struct MetalOwnedTextureFrame {
1049 pub generation: u64,
1050 pub width: u32,
1051 pub height: u32,
1052 pub scale_factor: f64,
1053 pub frame_id: u64,
1054 pub pixel_format: u64,
1055}
1056
1057impl MetalOwnedTextureFrame {
1058 fn from_native(raw: &sys::mln_metal_owned_texture_frame) -> Self {
1059 Self {
1060 generation: raw.generation,
1061 width: raw.width,
1062 height: raw.height,
1063 scale_factor: raw.scale_factor,
1064 frame_id: raw.frame_id,
1065 pixel_format: raw.pixel_format,
1066 }
1067 }
1068}
1069
1070#[derive(Debug, Clone, Copy, PartialEq)]
1075#[non_exhaustive]
1076pub struct VulkanOwnedTextureFrame {
1077 pub generation: u64,
1078 pub width: u32,
1079 pub height: u32,
1080 pub scale_factor: f64,
1081 pub frame_id: u64,
1082 pub format: u32,
1083 pub layout: u32,
1084}
1085
1086impl VulkanOwnedTextureFrame {
1087 fn from_native(raw: &sys::mln_vulkan_owned_texture_frame) -> Self {
1088 Self {
1089 generation: raw.generation,
1090 width: raw.width,
1091 height: raw.height,
1092 scale_factor: raw.scale_factor,
1093 frame_id: raw.frame_id,
1094 format: raw.format,
1095 layout: raw.layout,
1096 }
1097 }
1098}
1099
1100#[derive(Debug, Clone, Copy, PartialEq)]
1105#[non_exhaustive]
1106pub struct WebGpuOwnedTextureFrame {
1107 pub generation: u64,
1108 pub width: u32,
1109 pub height: u32,
1110 pub scale_factor: f64,
1111 pub frame_id: u64,
1112 pub format: u32,
1113}
1114
1115impl WebGpuOwnedTextureFrame {
1116 fn from_native(raw: &sys::mln_webgpu_owned_texture_frame) -> Self {
1117 Self {
1118 generation: raw.generation,
1119 width: raw.width,
1120 height: raw.height,
1121 scale_factor: raw.scale_factor,
1122 frame_id: raw.frame_id,
1123 format: raw.format,
1124 }
1125 }
1126}
1127
1128#[derive(Debug, Clone, Copy, PartialEq)]
1133#[non_exhaustive]
1134pub struct OpenGLOwnedTextureFrame {
1135 pub generation: u64,
1136 pub width: u32,
1137 pub height: u32,
1138 pub scale_factor: f64,
1139 pub frame_id: u64,
1140 pub target: u32,
1141 pub internal_format: u32,
1142 pub format: u32,
1143 pub type_: u32,
1144}
1145
1146impl OpenGLOwnedTextureFrame {
1147 fn from_native(raw: &sys::mln_opengl_owned_texture_frame) -> Self {
1148 Self {
1149 generation: raw.generation,
1150 width: raw.width,
1151 height: raw.height,
1152 scale_factor: raw.scale_factor,
1153 frame_id: raw.frame_id,
1154 target: raw.target,
1155 internal_format: raw.internal_format,
1156 format: raw.format,
1157 type_: raw.type_,
1158 }
1159 }
1160}
1161
1162pub struct MetalOwnedTextureFrameHandle {
1166 session: Rc<RenderSessionState>,
1167 raw: sys::mln_metal_owned_texture_frame,
1168 frame: MetalOwnedTextureFrame,
1169 closed: Cell<bool>,
1170 _thread_affine: PhantomData<Rc<()>>,
1171}
1172
1173impl fmt::Debug for MetalOwnedTextureFrameHandle {
1174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1175 f.debug_struct("MetalOwnedTextureFrameHandle")
1176 .field("closed", &self.closed.get())
1177 .field("frame", &self.frame)
1178 .finish()
1179 }
1180}
1181
1182impl MetalOwnedTextureFrameHandle {
1183 pub fn frame(&self) -> Result<&MetalOwnedTextureFrame> {
1185 if self.closed.get() {
1186 Err(closed_handle_error("MetalOwnedTextureFrameHandle"))
1187 } else {
1188 Ok(&self.frame)
1189 }
1190 }
1191 pub unsafe fn texture(&self) -> Result<FrameNativePointer<'_>> {
1199 if self.closed.get() {
1200 Err(closed_handle_error("MetalOwnedTextureFrameHandle"))
1201 } else {
1202 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.texture) })
1205 }
1206 }
1207
1208 pub unsafe fn device(&self) -> Result<FrameNativePointer<'_>> {
1215 if self.closed.get() {
1216 Err(closed_handle_error("MetalOwnedTextureFrameHandle"))
1217 } else {
1218 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.device) })
1220 }
1221 }
1222
1223 #[allow(clippy::result_large_err)]
1225 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1226 self.close_with_release(sys::mln_metal_owned_texture_release_frame)
1227 }
1228
1229 #[allow(clippy::result_large_err)]
1230 fn close_with_release(
1231 self,
1232 release: unsafe extern "C" fn(
1233 sys::mln_render_session,
1234 *const sys::mln_metal_owned_texture_frame,
1235 ) -> sys::mln_status,
1236 ) -> std::result::Result<(), HandleOperationError<Self>> {
1237 if self.closed.get() {
1238 return Ok(());
1239 }
1240 let session = match self.session.native() {
1241 Ok(session) => session,
1242 Err(error) => return Err(HandleOperationError::new(error, self)),
1243 };
1244 if let Err(error) = maplibre_core::check(unsafe { release(session, &self.raw) }) {
1247 return Err(HandleOperationError::new(error, self));
1248 }
1249 self.closed.set(true);
1250 self.session.frame_acquired.set(false);
1251 Ok(())
1252 }
1253}
1254
1255impl Drop for MetalOwnedTextureFrameHandle {
1256 fn drop(&mut self) {
1257 if self.closed.get() {
1258 return;
1259 }
1260 if let Ok(session) = self.session.native() {
1261 let status = unsafe { sys::mln_metal_owned_texture_release_frame(session, &self.raw) };
1264 if status == sys::MLN_STATUS_OK {
1265 self.closed.set(true);
1266 self.session.frame_acquired.set(false);
1267 }
1268 }
1269 }
1270}
1271
1272pub struct VulkanOwnedTextureFrameHandle {
1277 session: Rc<RenderSessionState>,
1278 raw: sys::mln_vulkan_owned_texture_frame,
1279 frame: VulkanOwnedTextureFrame,
1280 closed: Cell<bool>,
1281 _thread_affine: PhantomData<Rc<()>>,
1282}
1283
1284impl fmt::Debug for VulkanOwnedTextureFrameHandle {
1285 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1286 f.debug_struct("VulkanOwnedTextureFrameHandle")
1287 .field("closed", &self.closed.get())
1288 .field("frame", &self.frame)
1289 .finish()
1290 }
1291}
1292
1293impl VulkanOwnedTextureFrameHandle {
1294 pub fn frame(&self) -> Result<&VulkanOwnedTextureFrame> {
1296 if self.closed.get() {
1297 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1298 } else {
1299 Ok(&self.frame)
1300 }
1301 }
1302 pub unsafe fn image(&self) -> Result<FrameNativePointer<'_>> {
1310 if self.closed.get() {
1311 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1312 } else {
1313 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.image) })
1316 }
1317 }
1318
1319 pub unsafe fn image_view(&self) -> Result<FrameNativePointer<'_>> {
1326 if self.closed.get() {
1327 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1328 } else {
1329 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.image_view) })
1331 }
1332 }
1333
1334 pub unsafe fn device(&self) -> Result<FrameNativePointer<'_>> {
1341 if self.closed.get() {
1342 Err(closed_handle_error("VulkanOwnedTextureFrameHandle"))
1343 } else {
1344 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.device) })
1346 }
1347 }
1348
1349 #[allow(clippy::result_large_err)]
1351 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1352 if self.closed.get() {
1353 return Ok(());
1354 }
1355 let session = match self.session.native() {
1356 Ok(session) => session,
1357 Err(error) => return Err(HandleOperationError::new(error, self)),
1358 };
1359 if let Err(error) = maplibre_core::check(unsafe {
1362 sys::mln_vulkan_owned_texture_release_frame(session, &self.raw)
1363 }) {
1364 return Err(HandleOperationError::new(error, self));
1365 }
1366 self.closed.set(true);
1367 self.session.frame_acquired.set(false);
1368 Ok(())
1369 }
1370}
1371
1372impl Drop for VulkanOwnedTextureFrameHandle {
1373 fn drop(&mut self) {
1374 if self.closed.get() {
1375 return;
1376 }
1377 if let Ok(session) = self.session.native() {
1378 let status = unsafe { sys::mln_vulkan_owned_texture_release_frame(session, &self.raw) };
1381 if status == sys::MLN_STATUS_OK {
1382 self.closed.set(true);
1383 self.session.frame_acquired.set(false);
1384 }
1385 }
1386 }
1387}
1388
1389pub struct WebGpuOwnedTextureFrameHandle {
1394 session: Rc<RenderSessionState>,
1395 raw: sys::mln_webgpu_owned_texture_frame,
1396 frame: WebGpuOwnedTextureFrame,
1397 closed: Cell<bool>,
1398 _thread_affine: PhantomData<Rc<()>>,
1399}
1400
1401impl fmt::Debug for WebGpuOwnedTextureFrameHandle {
1402 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1403 f.debug_struct("WebGpuOwnedTextureFrameHandle")
1404 .field("closed", &self.closed.get())
1405 .field("frame", &self.frame)
1406 .finish()
1407 }
1408}
1409
1410impl WebGpuOwnedTextureFrameHandle {
1411 pub fn frame(&self) -> Result<&WebGpuOwnedTextureFrame> {
1413 if self.closed.get() {
1414 Err(closed_handle_error("WebGpuOwnedTextureFrameHandle"))
1415 } else {
1416 Ok(&self.frame)
1417 }
1418 }
1419
1420 pub unsafe fn texture(&self) -> Result<FrameNativePointer<'_>> {
1428 if self.closed.get() {
1429 Err(closed_handle_error("WebGpuOwnedTextureFrameHandle"))
1430 } else {
1431 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.texture) })
1434 }
1435 }
1436
1437 pub unsafe fn texture_view(&self) -> Result<FrameNativePointer<'_>> {
1444 if self.closed.get() {
1445 Err(closed_handle_error("WebGpuOwnedTextureFrameHandle"))
1446 } else {
1447 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.texture_view) })
1449 }
1450 }
1451
1452 pub unsafe fn device(&self) -> Result<FrameNativePointer<'_>> {
1459 if self.closed.get() {
1460 Err(closed_handle_error("WebGpuOwnedTextureFrameHandle"))
1461 } else {
1462 Ok(unsafe { FrameNativePointer::from_ptr(self.raw.device) })
1464 }
1465 }
1466
1467 #[allow(clippy::result_large_err)]
1469 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1470 if self.closed.get() {
1471 return Ok(());
1472 }
1473 let session = match self.session.native() {
1474 Ok(session) => session,
1475 Err(error) => return Err(HandleOperationError::new(error, self)),
1476 };
1477 if let Err(error) = maplibre_core::check(unsafe {
1480 sys::mln_webgpu_owned_texture_release_frame(session, &self.raw)
1481 }) {
1482 return Err(HandleOperationError::new(error, self));
1483 }
1484 self.closed.set(true);
1485 self.session.frame_acquired.set(false);
1486 Ok(())
1487 }
1488}
1489
1490impl Drop for WebGpuOwnedTextureFrameHandle {
1491 fn drop(&mut self) {
1492 if self.closed.get() {
1493 return;
1494 }
1495 if let Ok(session) = self.session.native() {
1496 let status = unsafe { sys::mln_webgpu_owned_texture_release_frame(session, &self.raw) };
1499 if status == sys::MLN_STATUS_OK {
1500 self.closed.set(true);
1501 self.session.frame_acquired.set(false);
1502 }
1503 }
1504 }
1505}
1506
1507pub struct OpenGLOwnedTextureFrameHandle {
1511 session: Rc<RenderSessionState>,
1512 raw: sys::mln_opengl_owned_texture_frame,
1513 frame: OpenGLOwnedTextureFrame,
1514 closed: Cell<bool>,
1515 _thread_affine: PhantomData<Rc<()>>,
1516}
1517
1518impl fmt::Debug for OpenGLOwnedTextureFrameHandle {
1519 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1520 f.debug_struct("OpenGLOwnedTextureFrameHandle")
1521 .field("closed", &self.closed.get())
1522 .field("frame", &self.frame)
1523 .finish()
1524 }
1525}
1526
1527impl OpenGLOwnedTextureFrameHandle {
1528 pub fn frame(&self) -> Result<&OpenGLOwnedTextureFrame> {
1530 if self.closed.get() {
1531 Err(closed_handle_error("OpenGLOwnedTextureFrameHandle"))
1532 } else {
1533 Ok(&self.frame)
1534 }
1535 }
1536 pub fn texture(&self) -> Result<FrameOpenGLTextureName<'_>> {
1538 if self.closed.get() {
1539 Err(closed_handle_error("OpenGLOwnedTextureFrameHandle"))
1540 } else {
1541 Ok(FrameOpenGLTextureName::new(self.raw.texture))
1542 }
1543 }
1544
1545 #[allow(clippy::result_large_err)]
1547 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1548 if self.closed.get() {
1549 return Ok(());
1550 }
1551 let session = match self.session.native() {
1552 Ok(session) => session,
1553 Err(error) => return Err(HandleOperationError::new(error, self)),
1554 };
1555 if let Err(error) = maplibre_core::check(unsafe {
1558 sys::mln_opengl_owned_texture_release_frame(session, &self.raw)
1559 }) {
1560 return Err(HandleOperationError::new(error, self));
1561 }
1562 self.closed.set(true);
1563 self.session.frame_acquired.set(false);
1564 Ok(())
1565 }
1566}
1567
1568impl Drop for OpenGLOwnedTextureFrameHandle {
1569 fn drop(&mut self) {
1570 if self.closed.get() {
1571 return;
1572 }
1573 if let Ok(session) = self.session.native() {
1574 let status = unsafe { sys::mln_opengl_owned_texture_release_frame(session, &self.raw) };
1577 if status == sys::MLN_STATUS_OK {
1578 self.closed.set(true);
1579 self.session.frame_acquired.set(false);
1580 }
1581 }
1582 }
1583}
1584
1585impl RenderSessionHandle {
1586 pub(crate) fn attach<F>(map: &MapAttachRef, attach: F) -> Result<Self>
1587 where
1588 F: FnOnce(sys::mln_map, *mut sys::mln_render_session) -> sys::mln_status,
1589 {
1590 let mut out = maplibre_core::ptr::OutHandle::<sys::mln_render_session>::new();
1591 let status = attach(map.map(), out.as_mut_ptr());
1594 maplibre_core::check(status)?;
1595 let ptr = out_handle(out, "mln_render_session")?;
1596 Ok(Self {
1597 inner: Rc::new(RenderSessionState::new(ptr)?),
1598 })
1599 }
1600
1601 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
1606 if let Err(error) = self.inner.ensure_no_frame_acquired() {
1607 return Err(HandleOperationError::new(error, self));
1608 }
1609 if let Err(error) = self.inner.close() {
1610 return Err(HandleOperationError::new(error, self));
1611 }
1612 Ok(())
1613 }
1614 pub fn resize(&self, width: u32, height: u32, scale_factor: f64) -> Result<()> {
1622 self.inner.ensure_no_frame_acquired()?;
1623 let session = self.inner.native()?;
1624 maplibre_core::check(unsafe {
1626 sys::mln_render_session_resize(session, width, height, scale_factor)
1627 })
1628 }
1629
1630 pub fn set_metal_surface_target(&self, descriptor: &MetalSurfaceDescriptor) -> Result<()> {
1637 self.set_target(descriptor.to_native(), |session, raw| {
1638 unsafe { sys::mln_metal_surface_set_target(session, raw) }
1641 })
1642 }
1643
1644 pub fn set_vulkan_surface_target(&self, descriptor: &VulkanSurfaceDescriptor) -> Result<()> {
1651 self.set_target(descriptor.to_native(), |session, raw| {
1652 unsafe { sys::mln_vulkan_surface_set_target(session, raw) }
1655 })
1656 }
1657
1658 pub fn set_webgpu_surface_target(&self, descriptor: &WebGpuSurfaceDescriptor) -> Result<()> {
1664 self.set_target(descriptor.to_native(), |session, raw| {
1665 unsafe { sys::mln_webgpu_surface_set_target(session, raw) }
1668 })
1669 }
1670
1671 pub fn set_opengl_surface_target(&self, descriptor: &OpenGLSurfaceDescriptor) -> Result<()> {
1679 self.set_target(descriptor.to_native(), |session, raw| {
1680 unsafe { sys::mln_opengl_surface_set_target(session, raw) }
1683 })
1684 }
1685
1686 pub fn set_metal_borrowed_texture_target(
1696 &self,
1697 descriptor: &MetalBorrowedTextureDescriptor,
1698 ) -> Result<()> {
1699 self.set_target(descriptor.to_native(), |session, raw| {
1700 unsafe { sys::mln_metal_borrowed_texture_set_target(session, raw) }
1703 })
1704 }
1705
1706 pub fn set_vulkan_borrowed_texture_target(
1713 &self,
1714 descriptor: &VulkanBorrowedTextureDescriptor,
1715 ) -> Result<()> {
1716 self.set_target(descriptor.to_native(), |session, raw| {
1717 unsafe { sys::mln_vulkan_borrowed_texture_set_target(session, raw) }
1720 })
1721 }
1722
1723 pub fn set_webgpu_borrowed_texture_target(
1729 &self,
1730 descriptor: &WebGpuBorrowedTextureDescriptor,
1731 ) -> Result<()> {
1732 self.set_target(descriptor.to_native(), |session, raw| {
1733 unsafe { sys::mln_webgpu_borrowed_texture_set_target(session, raw) }
1736 })
1737 }
1738
1739 pub fn set_opengl_borrowed_texture_target(
1746 &self,
1747 descriptor: &OpenGLBorrowedTextureDescriptor,
1748 ) -> Result<()> {
1749 self.set_target(descriptor.to_native(), |session, raw| {
1750 unsafe { sys::mln_opengl_borrowed_texture_set_target(session, raw) }
1753 })
1754 }
1755
1756 fn set_target<D>(
1760 &self,
1761 raw: D,
1762 set_target: impl FnOnce(sys::mln_render_session, &D) -> sys::mln_status,
1763 ) -> Result<()> {
1764 self.inner.ensure_no_frame_acquired()?;
1765 let session = self.inner.native()?;
1766 maplibre_core::check(set_target(session, &raw))
1767 }
1768
1769 pub fn render_update(&self) -> Result<RenderUpdate> {
1782 self.inner.ensure_no_frame_acquired()?;
1783 let session = self.inner.native()?;
1784 let mut result = sys::MLN_RENDER_RESULT_NO_UPDATE;
1785 let mut needs_repaint = false;
1786 maplibre_core::check(unsafe {
1789 sys::mln_render_session_render_update(session, &raw mut result, &raw mut needs_repaint)
1790 })?;
1791 Ok(RenderUpdate {
1792 result: RenderResult::from_raw(result),
1793 needs_repaint,
1794 })
1795 }
1796
1797 pub fn detach(
1803 self,
1804 ) -> std::result::Result<DetachedRenderSessionHandle, HandleOperationError<Self>> {
1805 if let Err(error) = self.inner.ensure_no_frame_acquired() {
1806 return Err(HandleOperationError::new(error, self));
1807 }
1808 let session = match self.inner.native() {
1809 Ok(session) => session,
1810 Err(error) => return Err(HandleOperationError::new(error, self)),
1811 };
1812 if let Err(error) = maplibre_core::check(unsafe { sys::mln_render_session_detach(session) })
1814 {
1815 return Err(HandleOperationError::new(error, self));
1816 }
1817 self.inner.detached.set(true);
1818 Ok(DetachedRenderSessionHandle {
1819 inner: Rc::clone(&self.inner),
1820 })
1821 }
1822
1823 pub fn reduce_memory_use(&self) -> Result<()> {
1825 self.inner.ensure_no_frame_acquired()?;
1826 let session = self.inner.native()?;
1827 maplibre_core::check(unsafe { sys::mln_render_session_reduce_memory_use(session) })
1829 }
1830
1831 pub fn clear_data(&self) -> Result<()> {
1833 self.inner.ensure_no_frame_acquired()?;
1834 let session = self.inner.native()?;
1835 maplibre_core::check(unsafe { sys::mln_render_session_clear_data(session) })
1837 }
1838
1839 pub fn dump_debug_logs(&self) -> Result<()> {
1841 self.inner.ensure_no_frame_acquired()?;
1842 let session = self.inner.native()?;
1843 maplibre_core::check(unsafe { sys::mln_render_session_dump_debug_logs(session) })
1845 }
1846
1847 pub fn texture_image_info(&self) -> Result<TextureImageInfo> {
1849 self.inner.ensure_no_frame_acquired()?;
1850 let session = self.inner.native()?;
1851 let mut info = unsafe { sys::mln_texture_image_info_default() };
1853 maplibre_core::check(unsafe {
1856 sys::mln_texture_read_premultiplied_rgba8(session, std::ptr::null_mut(), 0, &mut info)
1857 })?;
1858 Ok(maplibre_core::values::texture_image_info_from_native(&info))
1859 }
1860
1861 pub fn read_premultiplied_rgba8_into(&self, data: &mut [u8]) -> Result<TextureImageInfo> {
1863 self.inner.ensure_no_frame_acquired()?;
1864 let session = self.inner.native()?;
1865 let mut info = unsafe { sys::mln_texture_image_info_default() };
1867 let data_ptr = if data.is_empty() {
1868 std::ptr::null_mut()
1869 } else {
1870 data.as_mut_ptr()
1871 };
1872 maplibre_core::check(unsafe {
1876 sys::mln_texture_read_premultiplied_rgba8(session, data_ptr, data.len(), &mut info)
1877 })?;
1878 if data.is_empty() && info.byte_length > 0 {
1881 return Err(crate::Error::invalid_argument(format!(
1882 "buffer length 0 is smaller than the required {} bytes",
1883 info.byte_length
1884 )));
1885 }
1886 Ok(maplibre_core::values::texture_image_info_from_native(&info))
1887 }
1888
1889 pub fn acquire_metal_owned_texture_frame(&self) -> Result<MetalOwnedTextureFrameHandle> {
1891 self.inner.ensure_no_frame_acquired()?;
1892 let session = self.inner.native()?;
1893 let mut raw = empty_metal_owned_texture_frame();
1894 maplibre_core::check(unsafe {
1896 sys::mln_metal_owned_texture_acquire_frame(session, &mut raw)
1897 })?;
1898 self.inner.frame_acquired.set(true);
1899 Ok(MetalOwnedTextureFrameHandle {
1900 session: Rc::clone(&self.inner),
1901 frame: MetalOwnedTextureFrame::from_native(&raw),
1902 raw,
1903 closed: Cell::new(false),
1904 _thread_affine: PhantomData,
1905 })
1906 }
1907
1908 pub fn acquire_vulkan_owned_texture_frame(&self) -> Result<VulkanOwnedTextureFrameHandle> {
1910 self.inner.ensure_no_frame_acquired()?;
1911 let session = self.inner.native()?;
1912 let mut raw = empty_vulkan_owned_texture_frame();
1913 maplibre_core::check(unsafe {
1915 sys::mln_vulkan_owned_texture_acquire_frame(session, &mut raw)
1916 })?;
1917 self.inner.frame_acquired.set(true);
1918 Ok(VulkanOwnedTextureFrameHandle {
1919 session: Rc::clone(&self.inner),
1920 frame: VulkanOwnedTextureFrame::from_native(&raw),
1921 raw,
1922 closed: Cell::new(false),
1923 _thread_affine: PhantomData,
1924 })
1925 }
1926
1927 pub fn acquire_webgpu_owned_texture_frame(&self) -> Result<WebGpuOwnedTextureFrameHandle> {
1929 self.inner.ensure_no_frame_acquired()?;
1930 let session = self.inner.native()?;
1931 let mut raw = empty_webgpu_owned_texture_frame();
1932 maplibre_core::check(unsafe {
1934 sys::mln_webgpu_owned_texture_acquire_frame(session, &mut raw)
1935 })?;
1936 self.inner.frame_acquired.set(true);
1937 Ok(WebGpuOwnedTextureFrameHandle {
1938 session: Rc::clone(&self.inner),
1939 frame: WebGpuOwnedTextureFrame::from_native(&raw),
1940 raw,
1941 closed: Cell::new(false),
1942 _thread_affine: PhantomData,
1943 })
1944 }
1945
1946 pub fn acquire_opengl_owned_texture_frame(&self) -> Result<OpenGLOwnedTextureFrameHandle> {
1948 self.inner.ensure_no_frame_acquired()?;
1949 let session = self.inner.native()?;
1950 let mut raw = empty_opengl_owned_texture_frame();
1951 maplibre_core::check(unsafe {
1953 sys::mln_opengl_owned_texture_acquire_frame(session, &mut raw)
1954 })?;
1955 self.inner.frame_acquired.set(true);
1956 Ok(OpenGLOwnedTextureFrameHandle {
1957 session: Rc::clone(&self.inner),
1958 frame: OpenGLOwnedTextureFrame::from_native(&raw),
1959 raw,
1960 closed: Cell::new(false),
1961 _thread_affine: PhantomData,
1962 })
1963 }
1964}
1965
1966fn empty_metal_owned_texture_frame() -> sys::mln_metal_owned_texture_frame {
1967 sys::mln_metal_owned_texture_frame {
1968 size: mem::size_of::<sys::mln_metal_owned_texture_frame>() as u32,
1969 generation: 0,
1970 width: 0,
1971 height: 0,
1972 scale_factor: 0.0,
1973 frame_id: 0,
1974 texture: std::ptr::null_mut(),
1975 device: std::ptr::null_mut(),
1976 pixel_format: 0,
1977 }
1978}
1979
1980fn empty_webgpu_owned_texture_frame() -> sys::mln_webgpu_owned_texture_frame {
1981 sys::mln_webgpu_owned_texture_frame {
1982 size: mem::size_of::<sys::mln_webgpu_owned_texture_frame>() as u32,
1983 generation: 0,
1984 width: 0,
1985 height: 0,
1986 scale_factor: 0.0,
1987 frame_id: 0,
1988 texture: std::ptr::null_mut(),
1989 texture_view: std::ptr::null_mut(),
1990 device: std::ptr::null_mut(),
1991 format: 0,
1992 }
1993}
1994
1995fn empty_vulkan_owned_texture_frame() -> sys::mln_vulkan_owned_texture_frame {
1996 sys::mln_vulkan_owned_texture_frame {
1997 size: mem::size_of::<sys::mln_vulkan_owned_texture_frame>() as u32,
1998 generation: 0,
1999 width: 0,
2000 height: 0,
2001 scale_factor: 0.0,
2002 frame_id: 0,
2003 image: std::ptr::null_mut(),
2004 image_view: std::ptr::null_mut(),
2005 device: std::ptr::null_mut(),
2006 format: 0,
2007 layout: 0,
2008 }
2009}
2010
2011fn empty_opengl_owned_texture_frame() -> sys::mln_opengl_owned_texture_frame {
2012 sys::mln_opengl_owned_texture_frame {
2013 size: mem::size_of::<sys::mln_opengl_owned_texture_frame>() as u32,
2014 generation: 0,
2015 width: 0,
2016 height: 0,
2017 scale_factor: 0.0,
2018 frame_id: 0,
2019 texture: 0,
2020 target: 0,
2021 internal_format: 0,
2022 format: 0,
2023 type_: 0,
2024 }
2025}
2026
2027#[cfg(test)]
2028mod tests;