1use std::cell::RefCell;
2use std::collections::HashMap;
3use std::fmt;
4use std::rc::Rc;
5
6use maplibre_native_core as maplibre_core;
7use maplibre_native_core::ptr::{const_ptr_or_null, mut_ptr_or_null, option_ptr};
8use maplibre_native_core::values::{
9 empty_lat_lng, empty_lat_lng_bounds as empty_bounds, empty_screen_point, lat_lngs_to_native,
10 screen_points_to_native,
11};
12use maplibre_native_sys as sys;
13
14use crate::camera::{
15 AnimationOptionsNativeExt, BoundOptionsNativeExt, CameraFitOptionsNativeExt,
16 CameraOptionsNativeExt, FreeCameraOptionsNativeExt, ProjectionModeNativeExt,
17};
18#[cfg(test)]
19use crate::custom_geometry::CanonicalTileId;
20use crate::custom_geometry::CustomGeometrySourceState;
21use crate::events::MapId;
22use crate::geometry::GeometryNativeExt;
23use crate::handle::{ThreadAffineNativeHandle, closed_handle_error, out_handle};
24use crate::options::{MapOptionsNativeExt, MapTileOptionsNativeExt, MapViewportOptionsNativeExt};
25use crate::render::{
26 MetalBorrowedTextureDescriptor, MetalOwnedTextureDescriptor, MetalSurfaceDescriptor,
27 OpenGLBorrowedTextureDescriptor, OpenGLOwnedTextureDescriptor, OpenGLSurfaceDescriptor,
28 RenderSessionHandle, VulkanBorrowedTextureDescriptor, VulkanOwnedTextureDescriptor,
29 VulkanSurfaceDescriptor,
30};
31use crate::runtime::{RuntimeHandle, RuntimeState};
32use crate::values::NativeValue;
33use crate::{
34 AnimationOptions, BoundOptions, CameraFitOptions, CameraOptions, Error, ErrorKind,
35 FreeCameraOptions, Geometry, HandleOperationError, LatLng, LatLngBounds, MapDebugOptions,
36 MapOptions, MapProjectionHandle, MapTileOptions, MapViewportOptions, ProjectionMode, Result,
37 ScreenPoint,
38};
39#[cfg(test)]
40use crate::{GeoJson, JsonValue, PremultipliedRgba8Image};
41
42mod style;
43pub use style::{
44 GeoJsonSourceOptions, LocationIndicatorImageKind, RasterDemEncoding, SourceInfo, SourceType,
45 StyleImage, StyleImageInfo, StyleImageOptions, TileScheme, TileSourceOptions,
46 VectorTileEncoding,
47};
48
49#[derive(Debug)]
50pub(crate) struct MapState {
51 handle: ThreadAffineNativeHandle<sys::mln_map>,
52 runtime: RefCell<Option<Rc<RuntimeState>>>,
53 id: MapId,
54 custom_geometry_sources: RefCell<HashMap<String, Box<CustomGeometrySourceState>>>,
55}
56
57impl MapState {
58 fn new(ptr: std::ptr::NonNull<sys::mln_map>, runtime: Rc<RuntimeState>, id: MapId) -> Self {
59 let handle =
62 unsafe { ThreadAffineNativeHandle::from_raw(ptr, sys::mln_map_destroy, "mln_map") };
63 Self {
64 handle,
65 runtime: RefCell::new(Some(runtime)),
66 id,
67 custom_geometry_sources: RefCell::new(HashMap::new()),
68 }
69 }
70
71 pub(crate) fn as_ptr(&self) -> Result<*mut sys::mln_map> {
72 let ptr = self.handle.as_ptr();
73 if ptr.is_null() {
74 Err(closed_handle_error("MapHandle"))
75 } else {
76 Ok(ptr)
77 }
78 }
79
80 fn is_closed(&self) -> bool {
81 self.handle.is_closed()
82 }
83
84 fn close(&self) -> Result<()> {
85 let ptr = self.handle.as_ptr();
86 self.handle.close()?;
87 if let Some(runtime) = self.runtime.borrow_mut().take() {
88 runtime.unregister_map(ptr);
89 }
90 self.clear_custom_geometry_sources();
91 Ok(())
92 }
93
94 pub(crate) fn clear_custom_geometry_sources(&self) {
95 self.custom_geometry_sources.borrow_mut().clear();
96 }
97
98 pub(crate) fn release_detached_custom_geometry_sources(&self) {
99 let map = match self.as_ptr() {
100 Ok(map) => map,
101 Err(_) => return,
102 };
103 let source_ids = self
104 .custom_geometry_sources
105 .borrow()
106 .keys()
107 .cloned()
108 .collect::<Vec<_>>();
109 let mut detached = Vec::new();
110 for source_id in source_ids {
111 let source_id_view = maplibre_core::string::string_view(&source_id);
112 let mut source_type = 0;
113 let mut found = false;
114 let status = unsafe {
117 sys::mln_map_get_style_source_type(
118 map,
119 source_id_view.raw(),
120 &mut source_type,
121 &mut found,
122 )
123 };
124 if status == sys::MLN_STATUS_OK
125 && (!found || source_type != sys::MLN_STYLE_SOURCE_TYPE_CUSTOM_VECTOR)
126 {
127 detached.push(source_id);
128 }
129 }
130 if !detached.is_empty() {
131 let mut sources = self.custom_geometry_sources.borrow_mut();
132 for source_id in detached {
133 sources.remove(&source_id);
134 }
135 }
136 }
137}
138
139impl Drop for MapState {
140 fn drop(&mut self) {
141 if let Some(runtime) = self.runtime.borrow_mut().take() {
142 runtime.unregister_map(self.handle.as_ptr());
143 }
144 }
145}
146
147pub struct MapHandle {
149 pub(crate) inner: Rc<MapState>,
150}
151
152impl fmt::Debug for MapHandle {
153 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
154 f.debug_struct("MapHandle")
155 .field("closed", &self.inner.is_closed())
156 .finish()
157 }
158}
159
160impl MapHandle {
161 pub fn with_options(runtime: &RuntimeHandle, options: &MapOptions) -> Result<Self> {
163 let runtime_ptr = runtime.inner.as_ptr()?;
164 let mut out = maplibre_core::ptr::OutPtr::<sys::mln_map>::new();
165 let raw_options = options.to_native()?;
166
167 maplibre_core::check(unsafe {
171 sys::mln_map_create(runtime_ptr, &raw_options, out.as_mut_ptr())
172 })?;
173 let ptr = out_handle(out, "mln_map")?;
174 let id = runtime.inner.register_map(ptr.as_ptr());
175 let state = Rc::new(MapState::new(ptr, Rc::clone(&runtime.inner), id));
176 runtime
177 .inner
178 .register_map_state(ptr.as_ptr(), Rc::downgrade(&state));
179
180 Ok(Self { inner: state })
181 }
182
183 pub fn id(&self) -> MapId {
185 self.inner.id
186 }
187
188 #[cfg(test)]
189 fn custom_geometry_source_count_for_testing(&self) -> usize {
190 self.inner.custom_geometry_sources.borrow().len()
191 }
192
193 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
205 if self.inner.is_closed() {
206 return Ok(());
207 }
208 if Rc::strong_count(&self.inner) > 1 {
209 return Err(HandleOperationError::new(
210 Error::new(
211 ErrorKind::InvalidState,
212 None,
213 "MapHandle cannot close while child handles are live",
214 ),
215 self,
216 ));
217 }
218 self.inner
219 .close()
220 .map_err(|error| HandleOperationError::new(error, self))
221 }
222
223 pub fn request_repaint(&self) -> Result<()> {
225 let map = self.inner.as_ptr()?;
226 maplibre_core::check(unsafe { sys::mln_map_request_repaint(map) })
228 }
229
230 pub fn request_still_image(&self) -> Result<()> {
232 let map = self.inner.as_ptr()?;
233 maplibre_core::check(unsafe { sys::mln_map_request_still_image(map) })
235 }
236
237 pub fn set_debug_options(&self, options: MapDebugOptions) -> Result<()> {
239 let map = self.inner.as_ptr()?;
240 maplibre_core::check(unsafe { sys::mln_map_set_debug_options(map, options.bits()) })
242 }
243
244 pub fn debug_options(&self) -> Result<MapDebugOptions> {
246 let map = self.inner.as_ptr()?;
247 let mut raw = 0;
248 maplibre_core::check(unsafe { sys::mln_map_get_debug_options(map, &mut raw) })?;
250 Ok(MapDebugOptions::from_bits_retain(raw))
251 }
252
253 pub fn set_rendering_stats_view_enabled(&self, enabled: bool) -> Result<()> {
255 let map = self.inner.as_ptr()?;
256 maplibre_core::check(unsafe { sys::mln_map_set_rendering_stats_view_enabled(map, enabled) })
258 }
259
260 pub fn rendering_stats_view_enabled(&self) -> Result<bool> {
262 let map = self.inner.as_ptr()?;
263 let mut enabled = false;
264 maplibre_core::check(unsafe {
266 sys::mln_map_get_rendering_stats_view_enabled(map, &mut enabled)
267 })?;
268 Ok(enabled)
269 }
270
271 pub fn is_fully_loaded(&self) -> Result<bool> {
273 let map = self.inner.as_ptr()?;
274 let mut loaded = false;
275 maplibre_core::check(unsafe { sys::mln_map_is_fully_loaded(map, &mut loaded) })?;
277 Ok(loaded)
278 }
279
280 pub fn dump_debug_logs(&self) -> Result<()> {
282 let map = self.inner.as_ptr()?;
283 maplibre_core::check(unsafe { sys::mln_map_dump_debug_logs(map) })
285 }
286
287 pub fn size(&self) -> Result<(u32, u32, f64)> {
294 let map = self.inner.as_ptr()?;
295 let mut width = 0u32;
296 let mut height = 0u32;
297 let mut scale_factor = 0f64;
298 maplibre_core::check(unsafe {
301 sys::mln_map_get_size(map, &mut width, &mut height, &mut scale_factor)
302 })?;
303 Ok((width, height, scale_factor))
304 }
305
306 pub fn viewport_options(&self) -> Result<MapViewportOptions> {
308 let map = self.inner.as_ptr()?;
309 let mut raw = unsafe { sys::mln_map_viewport_options_default() };
311 maplibre_core::check(unsafe { sys::mln_map_get_viewport_options(map, &mut raw) })?;
313 Ok(MapViewportOptions::from_native(raw))
314 }
315
316 pub fn set_viewport_options(&self, options: &MapViewportOptions) -> Result<()> {
318 let map = self.inner.as_ptr()?;
319 let raw = options.to_native();
320 maplibre_core::check(unsafe { sys::mln_map_set_viewport_options(map, &raw) })
323 }
324
325 pub fn tile_options(&self) -> Result<MapTileOptions> {
327 let map = self.inner.as_ptr()?;
328 let mut raw = unsafe { sys::mln_map_tile_options_default() };
330 maplibre_core::check(unsafe { sys::mln_map_get_tile_options(map, &mut raw) })?;
332 Ok(MapTileOptions::from_native(raw))
333 }
334
335 pub fn set_tile_options(&self, options: &MapTileOptions) -> Result<()> {
337 let map = self.inner.as_ptr()?;
338 let raw = options.to_native();
339 maplibre_core::check(unsafe { sys::mln_map_set_tile_options(map, &raw) })
342 }
343
344 pub fn camera(&self) -> Result<CameraOptions> {
346 let map = self.inner.as_ptr()?;
347 let mut raw = unsafe { sys::mln_camera_options_default() };
349 maplibre_core::check(unsafe { sys::mln_map_get_camera(map, &mut raw) })?;
351 Ok(CameraOptions::from_native(raw))
352 }
353
354 pub fn jump_to(&self, camera: &CameraOptions) -> Result<()> {
356 let map = self.inner.as_ptr()?;
357 let raw = camera.to_native();
358 maplibre_core::check(unsafe { sys::mln_map_jump_to(map, &raw) })
361 }
362
363 pub fn ease_to(
369 &self,
370 camera: &CameraOptions,
371 animation: Option<&AnimationOptions>,
372 ) -> Result<()> {
373 let map = self.inner.as_ptr()?;
374 let raw_camera = camera.to_native();
375 let raw_animation = animation.map(AnimationOptions::to_native);
376 maplibre_core::check(unsafe {
379 sys::mln_map_ease_to(map, &raw_camera, option_ptr(raw_animation.as_ref()))
380 })
381 }
382
383 pub fn fly_to(
391 &self,
392 camera: &CameraOptions,
393 animation: Option<&AnimationOptions>,
394 ) -> Result<()> {
395 let map = self.inner.as_ptr()?;
396 let raw_camera = camera.to_native();
397 let raw_animation = animation.map(AnimationOptions::to_native);
398 maplibre_core::check(unsafe {
401 sys::mln_map_fly_to(map, &raw_camera, option_ptr(raw_animation.as_ref()))
402 })
403 }
404
405 pub fn move_by(&self, delta_x: f64, delta_y: f64) -> Result<()> {
407 let map = self.inner.as_ptr()?;
408 maplibre_core::check(unsafe { sys::mln_map_move_by(map, delta_x, delta_y) })
410 }
411
412 pub fn move_by_animated(
418 &self,
419 delta_x: f64,
420 delta_y: f64,
421 animation: Option<&AnimationOptions>,
422 ) -> Result<()> {
423 let map = self.inner.as_ptr()?;
424 let raw_animation = animation.map(AnimationOptions::to_native);
425 maplibre_core::check(unsafe {
428 sys::mln_map_move_by_animated(map, delta_x, delta_y, option_ptr(raw_animation.as_ref()))
429 })
430 }
431
432 pub fn scale_by(&self, scale: f64, anchor: Option<ScreenPoint>) -> Result<()> {
434 let map = self.inner.as_ptr()?;
435 let raw_anchor = anchor.map(ScreenPoint::to_native);
436 maplibre_core::check(unsafe {
439 sys::mln_map_scale_by(map, scale, option_ptr(raw_anchor.as_ref()))
440 })
441 }
442
443 pub fn scale_by_animated(
449 &self,
450 scale: f64,
451 anchor: Option<ScreenPoint>,
452 animation: Option<&AnimationOptions>,
453 ) -> Result<()> {
454 let map = self.inner.as_ptr()?;
455 let raw_anchor = anchor.map(ScreenPoint::to_native);
456 let raw_animation = animation.map(AnimationOptions::to_native);
457 maplibre_core::check(unsafe {
460 sys::mln_map_scale_by_animated(
461 map,
462 scale,
463 option_ptr(raw_anchor.as_ref()),
464 option_ptr(raw_animation.as_ref()),
465 )
466 })
467 }
468
469 pub fn rotate_by(&self, first: ScreenPoint, second: ScreenPoint) -> Result<()> {
471 let map = self.inner.as_ptr()?;
472 maplibre_core::check(unsafe {
474 sys::mln_map_rotate_by(map, first.to_native(), second.to_native())
475 })
476 }
477
478 pub fn rotate_by_animated(
484 &self,
485 first: ScreenPoint,
486 second: ScreenPoint,
487 animation: Option<&AnimationOptions>,
488 ) -> Result<()> {
489 let map = self.inner.as_ptr()?;
490 let raw_animation = animation.map(AnimationOptions::to_native);
491 maplibre_core::check(unsafe {
494 sys::mln_map_rotate_by_animated(
495 map,
496 first.to_native(),
497 second.to_native(),
498 option_ptr(raw_animation.as_ref()),
499 )
500 })
501 }
502
503 pub fn pitch_by(&self, pitch: f64) -> Result<()> {
505 let map = self.inner.as_ptr()?;
506 maplibre_core::check(unsafe { sys::mln_map_pitch_by(map, pitch) })
508 }
509
510 pub fn pitch_by_animated(
516 &self,
517 pitch: f64,
518 animation: Option<&AnimationOptions>,
519 ) -> Result<()> {
520 let map = self.inner.as_ptr()?;
521 let raw_animation = animation.map(AnimationOptions::to_native);
522 maplibre_core::check(unsafe {
525 sys::mln_map_pitch_by_animated(map, pitch, option_ptr(raw_animation.as_ref()))
526 })
527 }
528
529 pub fn cancel_transitions(&self) -> Result<()> {
531 let map = self.inner.as_ptr()?;
532 maplibre_core::check(unsafe { sys::mln_map_cancel_transitions(map) })
534 }
535
536 pub fn camera_for_lat_lng_bounds(
538 &self,
539 bounds: LatLngBounds,
540 fit_options: Option<&CameraFitOptions>,
541 ) -> Result<CameraOptions> {
542 let map = self.inner.as_ptr()?;
543 let raw_fit = fit_options.map(CameraFitOptions::to_native);
544 let mut raw_camera = unsafe { sys::mln_camera_options_default() };
546 maplibre_core::check(unsafe {
549 sys::mln_map_camera_for_lat_lng_bounds(
550 map,
551 bounds.to_native(),
552 option_ptr(raw_fit.as_ref()),
553 &mut raw_camera,
554 )
555 })?;
556 Ok(CameraOptions::from_native(raw_camera))
557 }
558
559 pub fn camera_for_lat_lngs(
561 &self,
562 coordinates: &[LatLng],
563 fit_options: Option<&CameraFitOptions>,
564 ) -> Result<CameraOptions> {
565 let map = self.inner.as_ptr()?;
566 if coordinates.is_empty() {
567 return Err(Error::invalid_argument(
568 "camera_for_lat_lngs requires at least one coordinate",
569 ));
570 }
571 let raw_coordinates = lat_lngs_to_native(coordinates);
572 let raw_fit = fit_options.map(CameraFitOptions::to_native);
573 let mut raw_camera = unsafe { sys::mln_camera_options_default() };
575 maplibre_core::check(unsafe {
578 sys::mln_map_camera_for_lat_lngs(
579 map,
580 const_ptr_or_null(&raw_coordinates),
581 raw_coordinates.len(),
582 option_ptr(raw_fit.as_ref()),
583 &mut raw_camera,
584 )
585 })?;
586 Ok(CameraOptions::from_native(raw_camera))
587 }
588
589 pub fn camera_for_geometry(
591 &self,
592 geometry: &Geometry,
593 fit_options: Option<&CameraFitOptions>,
594 ) -> Result<CameraOptions> {
595 let map = self.inner.as_ptr()?;
596 let native_geometry = geometry.try_to_native()?;
597 let raw_fit = fit_options.map(CameraFitOptions::to_native);
598 let mut raw_camera = unsafe { sys::mln_camera_options_default() };
600 maplibre_core::check(unsafe {
604 sys::mln_map_camera_for_geometry(
605 map,
606 native_geometry.as_ptr(),
607 option_ptr(raw_fit.as_ref()),
608 &mut raw_camera,
609 )
610 })?;
611 Ok(CameraOptions::from_native(raw_camera))
612 }
613
614 pub fn lat_lng_bounds_for_camera(&self, camera: &CameraOptions) -> Result<LatLngBounds> {
616 let map = self.inner.as_ptr()?;
617 let raw_camera = camera.to_native();
618 let mut raw_bounds = empty_bounds();
619 maplibre_core::check(unsafe {
622 sys::mln_map_lat_lng_bounds_for_camera(map, &raw_camera, &mut raw_bounds)
623 })?;
624 Ok(LatLngBounds::from_native(raw_bounds))
625 }
626
627 pub fn lat_lng_bounds_for_camera_unwrapped(
629 &self,
630 camera: &CameraOptions,
631 ) -> Result<LatLngBounds> {
632 let map = self.inner.as_ptr()?;
633 let raw_camera = camera.to_native();
634 let mut raw_bounds = empty_bounds();
635 maplibre_core::check(unsafe {
638 sys::mln_map_lat_lng_bounds_for_camera_unwrapped(map, &raw_camera, &mut raw_bounds)
639 })?;
640 Ok(LatLngBounds::from_native(raw_bounds))
641 }
642
643 pub fn bounds(&self) -> Result<BoundOptions> {
645 let map = self.inner.as_ptr()?;
646 let mut raw = unsafe { sys::mln_bound_options_default() };
648 maplibre_core::check(unsafe { sys::mln_map_get_bounds(map, &mut raw) })?;
650 Ok(BoundOptions::from_native(raw))
651 }
652
653 pub fn set_bounds(&self, options: &BoundOptions) -> Result<()> {
655 let map = self.inner.as_ptr()?;
656 let raw = options.to_native();
657 maplibre_core::check(unsafe { sys::mln_map_set_bounds(map, &raw) })
659 }
660
661 pub fn free_camera_options(&self) -> Result<FreeCameraOptions> {
663 let map = self.inner.as_ptr()?;
664 let mut raw = unsafe { sys::mln_free_camera_options_default() };
666 maplibre_core::check(unsafe { sys::mln_map_get_free_camera_options(map, &mut raw) })?;
668 Ok(FreeCameraOptions::from_native(raw))
669 }
670
671 pub fn set_free_camera_options(&self, options: &FreeCameraOptions) -> Result<()> {
673 let map = self.inner.as_ptr()?;
674 let raw = options.to_native();
675 maplibre_core::check(unsafe { sys::mln_map_set_free_camera_options(map, &raw) })
677 }
678
679 pub fn projection_mode(&self) -> Result<ProjectionMode> {
681 let map = self.inner.as_ptr()?;
682 let mut raw = unsafe { sys::mln_projection_mode_default() };
684 maplibre_core::check(unsafe { sys::mln_map_get_projection_mode(map, &mut raw) })?;
686 Ok(ProjectionMode::from_native(raw))
687 }
688
689 pub fn set_projection_mode(&self, mode: &ProjectionMode) -> Result<()> {
691 let map = self.inner.as_ptr()?;
692 let raw = mode.to_native();
693 maplibre_core::check(unsafe { sys::mln_map_set_projection_mode(map, &raw) })
695 }
696
697 pub fn pixel_for_lat_lng(&self, coordinate: LatLng) -> Result<ScreenPoint> {
699 let map = self.inner.as_ptr()?;
700 let mut raw_point = empty_screen_point();
701 maplibre_core::check(unsafe {
704 sys::mln_map_pixel_for_lat_lng(map, coordinate.to_native(), &mut raw_point)
705 })?;
706 Ok(ScreenPoint::from_native(raw_point))
707 }
708
709 pub fn lat_lng_for_pixel(&self, point: ScreenPoint) -> Result<LatLng> {
711 let map = self.inner.as_ptr()?;
712 let mut raw_coordinate = empty_lat_lng();
713 maplibre_core::check(unsafe {
716 sys::mln_map_lat_lng_for_pixel(map, point.to_native(), &mut raw_coordinate)
717 })?;
718 Ok(LatLng::from_native(raw_coordinate))
719 }
720
721 pub fn pixels_for_lat_lngs(&self, coordinates: &[LatLng]) -> Result<Vec<ScreenPoint>> {
723 let map = self.inner.as_ptr()?;
724 let raw_coordinates = lat_lngs_to_native(coordinates);
725 let mut raw_points = vec![empty_screen_point(); coordinates.len()];
726 maplibre_core::check(unsafe {
729 sys::mln_map_pixels_for_lat_lngs(
730 map,
731 const_ptr_or_null(&raw_coordinates),
732 raw_coordinates.len(),
733 mut_ptr_or_null(&mut raw_points),
734 )
735 })?;
736 Ok(raw_points
737 .into_iter()
738 .map(ScreenPoint::from_native)
739 .collect())
740 }
741
742 pub fn lat_lngs_for_pixels(&self, points: &[ScreenPoint]) -> Result<Vec<LatLng>> {
744 let map = self.inner.as_ptr()?;
745 let raw_points = screen_points_to_native(points);
746 let mut raw_coordinates = vec![empty_lat_lng(); points.len()];
747 maplibre_core::check(unsafe {
750 sys::mln_map_lat_lngs_for_pixels(
751 map,
752 const_ptr_or_null(&raw_points),
753 raw_points.len(),
754 mut_ptr_or_null(&mut raw_coordinates),
755 )
756 })?;
757 Ok(raw_coordinates
758 .into_iter()
759 .map(LatLng::from_native)
760 .collect())
761 }
762
763 pub fn create_projection(&self) -> Result<MapProjectionHandle> {
765 MapProjectionHandle::new(self)
766 }
767
768 pub fn attach_metal_surface(
774 &self,
775 descriptor: &MetalSurfaceDescriptor,
776 ) -> Result<RenderSessionHandle> {
777 let raw = descriptor.to_native();
778 RenderSessionHandle::attach(self, |map, out| {
779 unsafe { sys::mln_metal_surface_attach(map, &raw, out) }
782 })
783 }
784
785 pub fn attach_vulkan_surface(
790 &self,
791 descriptor: &VulkanSurfaceDescriptor,
792 ) -> Result<RenderSessionHandle> {
793 let raw = descriptor.to_native();
794 RenderSessionHandle::attach(self, |map, out| {
795 unsafe { sys::mln_vulkan_surface_attach(map, &raw, out) }
798 })
799 }
800
801 pub fn attach_opengl_surface(
807 &self,
808 descriptor: &OpenGLSurfaceDescriptor,
809 ) -> Result<RenderSessionHandle> {
810 let raw = descriptor.to_native();
811 RenderSessionHandle::attach(self, |map, out| {
812 unsafe { sys::mln_opengl_surface_attach(map, &raw, out) }
815 })
816 }
817
818 pub fn attach_metal_owned_texture(
823 &self,
824 descriptor: &MetalOwnedTextureDescriptor,
825 ) -> Result<RenderSessionHandle> {
826 let raw = descriptor.to_native();
827 RenderSessionHandle::attach(self, |map, out| {
828 unsafe { sys::mln_metal_owned_texture_attach(map, &raw, out) }
831 })
832 }
833
834 pub fn attach_metal_borrowed_texture(
839 &self,
840 descriptor: &MetalBorrowedTextureDescriptor,
841 ) -> Result<RenderSessionHandle> {
842 let raw = descriptor.to_native();
843 RenderSessionHandle::attach(self, |map, out| {
844 unsafe { sys::mln_metal_borrowed_texture_attach(map, &raw, out) }
847 })
848 }
849
850 pub fn attach_vulkan_owned_texture(
855 &self,
856 descriptor: &VulkanOwnedTextureDescriptor,
857 ) -> Result<RenderSessionHandle> {
858 let raw = descriptor.to_native();
859 RenderSessionHandle::attach(self, |map, out| {
860 unsafe { sys::mln_vulkan_owned_texture_attach(map, &raw, out) }
863 })
864 }
865
866 pub fn attach_vulkan_borrowed_texture(
872 &self,
873 descriptor: &VulkanBorrowedTextureDescriptor,
874 ) -> Result<RenderSessionHandle> {
875 let raw = descriptor.to_native();
876 RenderSessionHandle::attach(self, |map, out| {
877 unsafe { sys::mln_vulkan_borrowed_texture_attach(map, &raw, out) }
880 })
881 }
882
883 pub fn attach_opengl_owned_texture(
889 &self,
890 descriptor: &OpenGLOwnedTextureDescriptor,
891 ) -> Result<RenderSessionHandle> {
892 let raw = descriptor.to_native();
893 RenderSessionHandle::attach(self, |map, out| {
894 unsafe { sys::mln_opengl_owned_texture_attach(map, &raw, out) }
897 })
898 }
899
900 pub fn attach_opengl_borrowed_texture(
906 &self,
907 descriptor: &OpenGLBorrowedTextureDescriptor,
908 ) -> Result<RenderSessionHandle> {
909 let raw = descriptor.to_native();
910 RenderSessionHandle::attach(self, |map, out| {
911 unsafe { sys::mln_opengl_borrowed_texture_attach(map, &raw, out) }
914 })
915 }
916}
917
918#[cfg(test)]
919mod tests;