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 LocationIndicatorImageKind, RasterDemEncoding, SourceInfo, SourceType, StyleImage,
45 StyleImageInfo, StyleImageOptions, TileScheme, TileSourceOptions, VectorTileEncoding,
46};
47
48#[derive(Debug)]
49pub(crate) struct MapState {
50 handle: ThreadAffineNativeHandle<sys::mln_map>,
51 runtime: RefCell<Option<Rc<RuntimeState>>>,
52 id: MapId,
53 custom_geometry_sources: RefCell<HashMap<String, Box<CustomGeometrySourceState>>>,
54}
55
56impl MapState {
57 fn new(ptr: std::ptr::NonNull<sys::mln_map>, runtime: Rc<RuntimeState>, id: MapId) -> Self {
58 let handle =
61 unsafe { ThreadAffineNativeHandle::from_raw(ptr, sys::mln_map_destroy, "mln_map") };
62 Self {
63 handle,
64 runtime: RefCell::new(Some(runtime)),
65 id,
66 custom_geometry_sources: RefCell::new(HashMap::new()),
67 }
68 }
69
70 pub(crate) fn as_ptr(&self) -> Result<*mut sys::mln_map> {
71 let ptr = self.handle.as_ptr();
72 if ptr.is_null() {
73 Err(closed_handle_error("MapHandle"))
74 } else {
75 Ok(ptr)
76 }
77 }
78
79 fn is_closed(&self) -> bool {
80 self.handle.is_closed()
81 }
82
83 fn close(&self) -> Result<()> {
84 let ptr = self.handle.as_ptr();
85 self.handle.close()?;
86 if let Some(runtime) = self.runtime.borrow_mut().take() {
87 runtime.unregister_map(ptr);
88 }
89 self.clear_custom_geometry_sources();
90 Ok(())
91 }
92
93 pub(crate) fn clear_custom_geometry_sources(&self) {
94 self.custom_geometry_sources.borrow_mut().clear();
95 }
96
97 pub(crate) fn release_detached_custom_geometry_sources(&self) {
98 let map = match self.as_ptr() {
99 Ok(map) => map,
100 Err(_) => return,
101 };
102 let source_ids = self
103 .custom_geometry_sources
104 .borrow()
105 .keys()
106 .cloned()
107 .collect::<Vec<_>>();
108 let mut detached = Vec::new();
109 for source_id in source_ids {
110 let source_id_view = maplibre_core::string::string_view(&source_id);
111 let mut source_type = 0;
112 let mut found = false;
113 let status = unsafe {
116 sys::mln_map_get_style_source_type(
117 map,
118 source_id_view.raw(),
119 &mut source_type,
120 &mut found,
121 )
122 };
123 if status == sys::MLN_STATUS_OK
124 && (!found || source_type != sys::MLN_STYLE_SOURCE_TYPE_CUSTOM_VECTOR)
125 {
126 detached.push(source_id);
127 }
128 }
129 if !detached.is_empty() {
130 let mut sources = self.custom_geometry_sources.borrow_mut();
131 for source_id in detached {
132 sources.remove(&source_id);
133 }
134 }
135 }
136}
137
138impl Drop for MapState {
139 fn drop(&mut self) {
140 if let Some(runtime) = self.runtime.borrow_mut().take() {
141 runtime.unregister_map(self.handle.as_ptr());
142 }
143 }
144}
145
146pub struct MapHandle {
148 pub(crate) inner: Rc<MapState>,
149}
150
151impl fmt::Debug for MapHandle {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 f.debug_struct("MapHandle")
154 .field("closed", &self.inner.is_closed())
155 .finish()
156 }
157}
158
159impl MapHandle {
160 pub fn new(runtime: &RuntimeHandle) -> Result<Self> {
162 Self::with_options(runtime, &MapOptions::default())
163 }
164
165 pub fn with_options(runtime: &RuntimeHandle, options: &MapOptions) -> Result<Self> {
167 let runtime_ptr = runtime.inner.as_ptr()?;
168 let mut out = maplibre_core::ptr::OutPtr::<sys::mln_map>::new();
169 let raw_options = options.to_native();
170
171 maplibre_core::check(unsafe {
175 sys::mln_map_create(runtime_ptr, &raw_options, out.as_mut_ptr())
176 })?;
177 let ptr = out_handle(out, "mln_map")?;
178 let id = runtime.inner.register_map(ptr.as_ptr());
179 let state = Rc::new(MapState::new(ptr, Rc::clone(&runtime.inner), id));
180 runtime
181 .inner
182 .register_map_state(ptr.as_ptr(), Rc::downgrade(&state));
183
184 Ok(Self { inner: state })
185 }
186
187 pub fn id(&self) -> MapId {
189 self.inner.id
190 }
191
192 #[cfg(test)]
193 fn custom_geometry_source_count_for_testing(&self) -> usize {
194 self.inner.custom_geometry_sources.borrow().len()
195 }
196
197 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
203 if self.inner.is_closed() {
204 return Ok(());
205 }
206 if Rc::strong_count(&self.inner) > 1 {
207 return Err(HandleOperationError::new(
208 Error::new(
209 ErrorKind::InvalidState,
210 None,
211 "MapHandle cannot close while child handles are live",
212 ),
213 self,
214 ));
215 }
216 self.inner
217 .close()
218 .map_err(|error| HandleOperationError::new(error, self))
219 }
220
221 pub fn request_repaint(&self) -> Result<()> {
223 let map = self.inner.as_ptr()?;
224 maplibre_core::check(unsafe { sys::mln_map_request_repaint(map) })
226 }
227
228 pub fn request_still_image(&self) -> Result<()> {
230 let map = self.inner.as_ptr()?;
231 maplibre_core::check(unsafe { sys::mln_map_request_still_image(map) })
233 }
234
235 pub fn set_debug_options(&self, options: MapDebugOptions) -> Result<()> {
237 let map = self.inner.as_ptr()?;
238 maplibre_core::check(unsafe { sys::mln_map_set_debug_options(map, options.bits()) })
240 }
241
242 pub fn debug_options(&self) -> Result<MapDebugOptions> {
244 let map = self.inner.as_ptr()?;
245 let mut raw = 0;
246 maplibre_core::check(unsafe { sys::mln_map_get_debug_options(map, &mut raw) })?;
248 Ok(MapDebugOptions::from_bits_retain(raw))
249 }
250
251 pub fn set_rendering_stats_view_enabled(&self, enabled: bool) -> Result<()> {
253 let map = self.inner.as_ptr()?;
254 maplibre_core::check(unsafe { sys::mln_map_set_rendering_stats_view_enabled(map, enabled) })
256 }
257
258 pub fn rendering_stats_view_enabled(&self) -> Result<bool> {
260 let map = self.inner.as_ptr()?;
261 let mut enabled = false;
262 maplibre_core::check(unsafe {
264 sys::mln_map_get_rendering_stats_view_enabled(map, &mut enabled)
265 })?;
266 Ok(enabled)
267 }
268
269 pub fn is_fully_loaded(&self) -> Result<bool> {
271 let map = self.inner.as_ptr()?;
272 let mut loaded = false;
273 maplibre_core::check(unsafe { sys::mln_map_is_fully_loaded(map, &mut loaded) })?;
275 Ok(loaded)
276 }
277
278 pub fn dump_debug_logs(&self) -> Result<()> {
280 let map = self.inner.as_ptr()?;
281 maplibre_core::check(unsafe { sys::mln_map_dump_debug_logs(map) })
283 }
284
285 pub fn viewport_options(&self) -> Result<MapViewportOptions> {
287 let map = self.inner.as_ptr()?;
288 let mut raw = unsafe { sys::mln_map_viewport_options_default() };
290 maplibre_core::check(unsafe { sys::mln_map_get_viewport_options(map, &mut raw) })?;
292 Ok(MapViewportOptions::from_native(raw))
293 }
294
295 pub fn set_viewport_options(&self, options: &MapViewportOptions) -> Result<()> {
297 let map = self.inner.as_ptr()?;
298 let raw = options.to_native();
299 maplibre_core::check(unsafe { sys::mln_map_set_viewport_options(map, &raw) })
302 }
303
304 pub fn tile_options(&self) -> Result<MapTileOptions> {
306 let map = self.inner.as_ptr()?;
307 let mut raw = unsafe { sys::mln_map_tile_options_default() };
309 maplibre_core::check(unsafe { sys::mln_map_get_tile_options(map, &mut raw) })?;
311 Ok(MapTileOptions::from_native(raw))
312 }
313
314 pub fn set_tile_options(&self, options: &MapTileOptions) -> Result<()> {
316 let map = self.inner.as_ptr()?;
317 let raw = options.to_native();
318 maplibre_core::check(unsafe { sys::mln_map_set_tile_options(map, &raw) })
321 }
322
323 pub fn camera(&self) -> Result<CameraOptions> {
325 let map = self.inner.as_ptr()?;
326 let mut raw = unsafe { sys::mln_camera_options_default() };
328 maplibre_core::check(unsafe { sys::mln_map_get_camera(map, &mut raw) })?;
330 Ok(CameraOptions::from_native(raw))
331 }
332
333 pub fn jump_to(&self, camera: &CameraOptions) -> Result<()> {
335 let map = self.inner.as_ptr()?;
336 let raw = camera.to_native();
337 maplibre_core::check(unsafe { sys::mln_map_jump_to(map, &raw) })
340 }
341
342 pub fn ease_to(
344 &self,
345 camera: &CameraOptions,
346 animation: Option<&AnimationOptions>,
347 ) -> Result<()> {
348 let map = self.inner.as_ptr()?;
349 let raw_camera = camera.to_native();
350 let raw_animation = animation.map(AnimationOptions::to_native);
351 maplibre_core::check(unsafe {
354 sys::mln_map_ease_to(map, &raw_camera, option_ptr(raw_animation.as_ref()))
355 })
356 }
357
358 pub fn fly_to(
360 &self,
361 camera: &CameraOptions,
362 animation: Option<&AnimationOptions>,
363 ) -> Result<()> {
364 let map = self.inner.as_ptr()?;
365 let raw_camera = camera.to_native();
366 let raw_animation = animation.map(AnimationOptions::to_native);
367 maplibre_core::check(unsafe {
370 sys::mln_map_fly_to(map, &raw_camera, option_ptr(raw_animation.as_ref()))
371 })
372 }
373
374 pub fn move_by(&self, delta_x: f64, delta_y: f64) -> Result<()> {
376 let map = self.inner.as_ptr()?;
377 maplibre_core::check(unsafe { sys::mln_map_move_by(map, delta_x, delta_y) })
379 }
380
381 pub fn move_by_animated(
383 &self,
384 delta_x: f64,
385 delta_y: f64,
386 animation: Option<&AnimationOptions>,
387 ) -> Result<()> {
388 let map = self.inner.as_ptr()?;
389 let raw_animation = animation.map(AnimationOptions::to_native);
390 maplibre_core::check(unsafe {
393 sys::mln_map_move_by_animated(map, delta_x, delta_y, option_ptr(raw_animation.as_ref()))
394 })
395 }
396
397 pub fn scale_by(&self, scale: f64, anchor: Option<ScreenPoint>) -> Result<()> {
399 let map = self.inner.as_ptr()?;
400 let raw_anchor = anchor.map(ScreenPoint::to_native);
401 maplibre_core::check(unsafe {
404 sys::mln_map_scale_by(map, scale, option_ptr(raw_anchor.as_ref()))
405 })
406 }
407
408 pub fn scale_by_animated(
410 &self,
411 scale: f64,
412 anchor: Option<ScreenPoint>,
413 animation: Option<&AnimationOptions>,
414 ) -> Result<()> {
415 let map = self.inner.as_ptr()?;
416 let raw_anchor = anchor.map(ScreenPoint::to_native);
417 let raw_animation = animation.map(AnimationOptions::to_native);
418 maplibre_core::check(unsafe {
421 sys::mln_map_scale_by_animated(
422 map,
423 scale,
424 option_ptr(raw_anchor.as_ref()),
425 option_ptr(raw_animation.as_ref()),
426 )
427 })
428 }
429
430 pub fn rotate_by(&self, first: ScreenPoint, second: ScreenPoint) -> Result<()> {
432 let map = self.inner.as_ptr()?;
433 maplibre_core::check(unsafe {
435 sys::mln_map_rotate_by(map, first.to_native(), second.to_native())
436 })
437 }
438
439 pub fn rotate_by_animated(
441 &self,
442 first: ScreenPoint,
443 second: ScreenPoint,
444 animation: Option<&AnimationOptions>,
445 ) -> Result<()> {
446 let map = self.inner.as_ptr()?;
447 let raw_animation = animation.map(AnimationOptions::to_native);
448 maplibre_core::check(unsafe {
451 sys::mln_map_rotate_by_animated(
452 map,
453 first.to_native(),
454 second.to_native(),
455 option_ptr(raw_animation.as_ref()),
456 )
457 })
458 }
459
460 pub fn pitch_by(&self, pitch: f64) -> Result<()> {
462 let map = self.inner.as_ptr()?;
463 maplibre_core::check(unsafe { sys::mln_map_pitch_by(map, pitch) })
465 }
466
467 pub fn pitch_by_animated(
469 &self,
470 pitch: f64,
471 animation: Option<&AnimationOptions>,
472 ) -> Result<()> {
473 let map = self.inner.as_ptr()?;
474 let raw_animation = animation.map(AnimationOptions::to_native);
475 maplibre_core::check(unsafe {
478 sys::mln_map_pitch_by_animated(map, pitch, option_ptr(raw_animation.as_ref()))
479 })
480 }
481
482 pub fn cancel_transitions(&self) -> Result<()> {
484 let map = self.inner.as_ptr()?;
485 maplibre_core::check(unsafe { sys::mln_map_cancel_transitions(map) })
487 }
488
489 pub fn camera_for_lat_lng_bounds(
491 &self,
492 bounds: LatLngBounds,
493 fit_options: Option<&CameraFitOptions>,
494 ) -> Result<CameraOptions> {
495 let map = self.inner.as_ptr()?;
496 let raw_fit = fit_options.map(CameraFitOptions::to_native);
497 let mut raw_camera = unsafe { sys::mln_camera_options_default() };
499 maplibre_core::check(unsafe {
502 sys::mln_map_camera_for_lat_lng_bounds(
503 map,
504 bounds.to_native(),
505 option_ptr(raw_fit.as_ref()),
506 &mut raw_camera,
507 )
508 })?;
509 Ok(CameraOptions::from_native(raw_camera))
510 }
511
512 pub fn camera_for_lat_lngs(
514 &self,
515 coordinates: &[LatLng],
516 fit_options: Option<&CameraFitOptions>,
517 ) -> Result<CameraOptions> {
518 let map = self.inner.as_ptr()?;
519 if coordinates.is_empty() {
520 return Err(Error::invalid_argument(
521 "camera_for_lat_lngs requires at least one coordinate",
522 ));
523 }
524 let raw_coordinates = lat_lngs_to_native(coordinates);
525 let raw_fit = fit_options.map(CameraFitOptions::to_native);
526 let mut raw_camera = unsafe { sys::mln_camera_options_default() };
528 maplibre_core::check(unsafe {
531 sys::mln_map_camera_for_lat_lngs(
532 map,
533 const_ptr_or_null(&raw_coordinates),
534 raw_coordinates.len(),
535 option_ptr(raw_fit.as_ref()),
536 &mut raw_camera,
537 )
538 })?;
539 Ok(CameraOptions::from_native(raw_camera))
540 }
541
542 pub fn camera_for_geometry(
544 &self,
545 geometry: &Geometry,
546 fit_options: Option<&CameraFitOptions>,
547 ) -> Result<CameraOptions> {
548 let map = self.inner.as_ptr()?;
549 let native_geometry = geometry.try_to_native()?;
550 let raw_fit = fit_options.map(CameraFitOptions::to_native);
551 let mut raw_camera = unsafe { sys::mln_camera_options_default() };
553 maplibre_core::check(unsafe {
557 sys::mln_map_camera_for_geometry(
558 map,
559 native_geometry.as_ptr(),
560 option_ptr(raw_fit.as_ref()),
561 &mut raw_camera,
562 )
563 })?;
564 Ok(CameraOptions::from_native(raw_camera))
565 }
566
567 pub fn lat_lng_bounds_for_camera(&self, camera: &CameraOptions) -> Result<LatLngBounds> {
569 let map = self.inner.as_ptr()?;
570 let raw_camera = camera.to_native();
571 let mut raw_bounds = empty_bounds();
572 maplibre_core::check(unsafe {
575 sys::mln_map_lat_lng_bounds_for_camera(map, &raw_camera, &mut raw_bounds)
576 })?;
577 Ok(LatLngBounds::from_native(raw_bounds))
578 }
579
580 pub fn lat_lng_bounds_for_camera_unwrapped(
582 &self,
583 camera: &CameraOptions,
584 ) -> Result<LatLngBounds> {
585 let map = self.inner.as_ptr()?;
586 let raw_camera = camera.to_native();
587 let mut raw_bounds = empty_bounds();
588 maplibre_core::check(unsafe {
591 sys::mln_map_lat_lng_bounds_for_camera_unwrapped(map, &raw_camera, &mut raw_bounds)
592 })?;
593 Ok(LatLngBounds::from_native(raw_bounds))
594 }
595
596 pub fn bounds(&self) -> Result<BoundOptions> {
598 let map = self.inner.as_ptr()?;
599 let mut raw = unsafe { sys::mln_bound_options_default() };
601 maplibre_core::check(unsafe { sys::mln_map_get_bounds(map, &mut raw) })?;
603 Ok(BoundOptions::from_native(raw))
604 }
605
606 pub fn set_bounds(&self, options: &BoundOptions) -> Result<()> {
608 let map = self.inner.as_ptr()?;
609 let raw = options.to_native();
610 maplibre_core::check(unsafe { sys::mln_map_set_bounds(map, &raw) })
612 }
613
614 pub fn free_camera_options(&self) -> Result<FreeCameraOptions> {
616 let map = self.inner.as_ptr()?;
617 let mut raw = unsafe { sys::mln_free_camera_options_default() };
619 maplibre_core::check(unsafe { sys::mln_map_get_free_camera_options(map, &mut raw) })?;
621 Ok(FreeCameraOptions::from_native(raw))
622 }
623
624 pub fn set_free_camera_options(&self, options: &FreeCameraOptions) -> Result<()> {
626 let map = self.inner.as_ptr()?;
627 let raw = options.to_native();
628 maplibre_core::check(unsafe { sys::mln_map_set_free_camera_options(map, &raw) })
630 }
631
632 pub fn projection_mode(&self) -> Result<ProjectionMode> {
634 let map = self.inner.as_ptr()?;
635 let mut raw = unsafe { sys::mln_projection_mode_default() };
637 maplibre_core::check(unsafe { sys::mln_map_get_projection_mode(map, &mut raw) })?;
639 Ok(ProjectionMode::from_native(raw))
640 }
641
642 pub fn set_projection_mode(&self, mode: &ProjectionMode) -> Result<()> {
644 let map = self.inner.as_ptr()?;
645 let raw = mode.to_native();
646 maplibre_core::check(unsafe { sys::mln_map_set_projection_mode(map, &raw) })
648 }
649
650 pub fn pixel_for_lat_lng(&self, coordinate: LatLng) -> Result<ScreenPoint> {
652 let map = self.inner.as_ptr()?;
653 let mut raw_point = empty_screen_point();
654 maplibre_core::check(unsafe {
657 sys::mln_map_pixel_for_lat_lng(map, coordinate.to_native(), &mut raw_point)
658 })?;
659 Ok(ScreenPoint::from_native(raw_point))
660 }
661
662 pub fn lat_lng_for_pixel(&self, point: ScreenPoint) -> Result<LatLng> {
664 let map = self.inner.as_ptr()?;
665 let mut raw_coordinate = empty_lat_lng();
666 maplibre_core::check(unsafe {
669 sys::mln_map_lat_lng_for_pixel(map, point.to_native(), &mut raw_coordinate)
670 })?;
671 Ok(LatLng::from_native(raw_coordinate))
672 }
673
674 pub fn pixels_for_lat_lngs(&self, coordinates: &[LatLng]) -> Result<Vec<ScreenPoint>> {
676 let map = self.inner.as_ptr()?;
677 let raw_coordinates = lat_lngs_to_native(coordinates);
678 let mut raw_points = vec![empty_screen_point(); coordinates.len()];
679 maplibre_core::check(unsafe {
682 sys::mln_map_pixels_for_lat_lngs(
683 map,
684 const_ptr_or_null(&raw_coordinates),
685 raw_coordinates.len(),
686 mut_ptr_or_null(&mut raw_points),
687 )
688 })?;
689 Ok(raw_points
690 .into_iter()
691 .map(ScreenPoint::from_native)
692 .collect())
693 }
694
695 pub fn lat_lngs_for_pixels(&self, points: &[ScreenPoint]) -> Result<Vec<LatLng>> {
697 let map = self.inner.as_ptr()?;
698 let raw_points = screen_points_to_native(points);
699 let mut raw_coordinates = vec![empty_lat_lng(); points.len()];
700 maplibre_core::check(unsafe {
703 sys::mln_map_lat_lngs_for_pixels(
704 map,
705 const_ptr_or_null(&raw_points),
706 raw_points.len(),
707 mut_ptr_or_null(&mut raw_coordinates),
708 )
709 })?;
710 Ok(raw_coordinates
711 .into_iter()
712 .map(LatLng::from_native)
713 .collect())
714 }
715
716 pub fn create_projection(&self) -> Result<MapProjectionHandle> {
718 MapProjectionHandle::new(self)
719 }
720
721 pub fn attach_metal_surface(
727 &self,
728 descriptor: &MetalSurfaceDescriptor,
729 ) -> Result<RenderSessionHandle> {
730 let raw = descriptor.to_native();
731 RenderSessionHandle::attach(self, |map, out| {
732 unsafe { sys::mln_metal_surface_attach(map, &raw, out) }
735 })
736 }
737
738 pub fn attach_vulkan_surface(
743 &self,
744 descriptor: &VulkanSurfaceDescriptor,
745 ) -> Result<RenderSessionHandle> {
746 let raw = descriptor.to_native();
747 RenderSessionHandle::attach(self, |map, out| {
748 unsafe { sys::mln_vulkan_surface_attach(map, &raw, out) }
751 })
752 }
753
754 pub fn attach_opengl_surface(
760 &self,
761 descriptor: &OpenGLSurfaceDescriptor,
762 ) -> Result<RenderSessionHandle> {
763 let raw = descriptor.to_native();
764 RenderSessionHandle::attach(self, |map, out| {
765 unsafe { sys::mln_opengl_surface_attach(map, &raw, out) }
768 })
769 }
770
771 pub fn attach_metal_owned_texture(
776 &self,
777 descriptor: &MetalOwnedTextureDescriptor,
778 ) -> Result<RenderSessionHandle> {
779 let raw = descriptor.to_native();
780 RenderSessionHandle::attach(self, |map, out| {
781 unsafe { sys::mln_metal_owned_texture_attach(map, &raw, out) }
784 })
785 }
786
787 pub fn attach_metal_borrowed_texture(
792 &self,
793 descriptor: &MetalBorrowedTextureDescriptor,
794 ) -> Result<RenderSessionHandle> {
795 let raw = descriptor.to_native();
796 RenderSessionHandle::attach(self, |map, out| {
797 unsafe { sys::mln_metal_borrowed_texture_attach(map, &raw, out) }
800 })
801 }
802
803 pub fn attach_vulkan_owned_texture(
808 &self,
809 descriptor: &VulkanOwnedTextureDescriptor,
810 ) -> Result<RenderSessionHandle> {
811 let raw = descriptor.to_native();
812 RenderSessionHandle::attach(self, |map, out| {
813 unsafe { sys::mln_vulkan_owned_texture_attach(map, &raw, out) }
816 })
817 }
818
819 pub fn attach_vulkan_borrowed_texture(
825 &self,
826 descriptor: &VulkanBorrowedTextureDescriptor,
827 ) -> Result<RenderSessionHandle> {
828 let raw = descriptor.to_native();
829 RenderSessionHandle::attach(self, |map, out| {
830 unsafe { sys::mln_vulkan_borrowed_texture_attach(map, &raw, out) }
833 })
834 }
835
836 pub fn attach_opengl_owned_texture(
842 &self,
843 descriptor: &OpenGLOwnedTextureDescriptor,
844 ) -> Result<RenderSessionHandle> {
845 let raw = descriptor.to_native();
846 RenderSessionHandle::attach(self, |map, out| {
847 unsafe { sys::mln_opengl_owned_texture_attach(map, &raw, out) }
850 })
851 }
852
853 pub fn attach_opengl_borrowed_texture(
859 &self,
860 descriptor: &OpenGLBorrowedTextureDescriptor,
861 ) -> Result<RenderSessionHandle> {
862 let raw = descriptor.to_native();
863 RenderSessionHandle::attach(self, |map, out| {
864 unsafe { sys::mln_opengl_borrowed_texture_attach(map, &raw, out) }
867 })
868 }
869}
870
871#[cfg(test)]
872mod tests;