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 with_options(runtime: &RuntimeHandle, options: &MapOptions) -> Result<Self> {
162 let runtime_ptr = runtime.inner.as_ptr()?;
163 let mut out = maplibre_core::ptr::OutPtr::<sys::mln_map>::new();
164 let raw_options = options.to_native()?;
165
166 maplibre_core::check(unsafe {
170 sys::mln_map_create(runtime_ptr, &raw_options, out.as_mut_ptr())
171 })?;
172 let ptr = out_handle(out, "mln_map")?;
173 let id = runtime.inner.register_map(ptr.as_ptr());
174 let state = Rc::new(MapState::new(ptr, Rc::clone(&runtime.inner), id));
175 runtime
176 .inner
177 .register_map_state(ptr.as_ptr(), Rc::downgrade(&state));
178
179 Ok(Self { inner: state })
180 }
181
182 pub fn id(&self) -> MapId {
184 self.inner.id
185 }
186
187 #[cfg(test)]
188 fn custom_geometry_source_count_for_testing(&self) -> usize {
189 self.inner.custom_geometry_sources.borrow().len()
190 }
191
192 pub fn close(self) -> std::result::Result<(), HandleOperationError<Self>> {
198 if self.inner.is_closed() {
199 return Ok(());
200 }
201 if Rc::strong_count(&self.inner) > 1 {
202 return Err(HandleOperationError::new(
203 Error::new(
204 ErrorKind::InvalidState,
205 None,
206 "MapHandle cannot close while child handles are live",
207 ),
208 self,
209 ));
210 }
211 self.inner
212 .close()
213 .map_err(|error| HandleOperationError::new(error, self))
214 }
215
216 pub fn request_repaint(&self) -> Result<()> {
218 let map = self.inner.as_ptr()?;
219 maplibre_core::check(unsafe { sys::mln_map_request_repaint(map) })
221 }
222
223 pub fn request_still_image(&self) -> Result<()> {
225 let map = self.inner.as_ptr()?;
226 maplibre_core::check(unsafe { sys::mln_map_request_still_image(map) })
228 }
229
230 pub fn set_debug_options(&self, options: MapDebugOptions) -> Result<()> {
232 let map = self.inner.as_ptr()?;
233 maplibre_core::check(unsafe { sys::mln_map_set_debug_options(map, options.bits()) })
235 }
236
237 pub fn debug_options(&self) -> Result<MapDebugOptions> {
239 let map = self.inner.as_ptr()?;
240 let mut raw = 0;
241 maplibre_core::check(unsafe { sys::mln_map_get_debug_options(map, &mut raw) })?;
243 Ok(MapDebugOptions::from_bits_retain(raw))
244 }
245
246 pub fn set_rendering_stats_view_enabled(&self, enabled: bool) -> Result<()> {
248 let map = self.inner.as_ptr()?;
249 maplibre_core::check(unsafe { sys::mln_map_set_rendering_stats_view_enabled(map, enabled) })
251 }
252
253 pub fn rendering_stats_view_enabled(&self) -> Result<bool> {
255 let map = self.inner.as_ptr()?;
256 let mut enabled = false;
257 maplibre_core::check(unsafe {
259 sys::mln_map_get_rendering_stats_view_enabled(map, &mut enabled)
260 })?;
261 Ok(enabled)
262 }
263
264 pub fn is_fully_loaded(&self) -> Result<bool> {
266 let map = self.inner.as_ptr()?;
267 let mut loaded = false;
268 maplibre_core::check(unsafe { sys::mln_map_is_fully_loaded(map, &mut loaded) })?;
270 Ok(loaded)
271 }
272
273 pub fn dump_debug_logs(&self) -> Result<()> {
275 let map = self.inner.as_ptr()?;
276 maplibre_core::check(unsafe { sys::mln_map_dump_debug_logs(map) })
278 }
279
280 pub fn viewport_options(&self) -> Result<MapViewportOptions> {
282 let map = self.inner.as_ptr()?;
283 let mut raw = unsafe { sys::mln_map_viewport_options_default() };
285 maplibre_core::check(unsafe { sys::mln_map_get_viewport_options(map, &mut raw) })?;
287 Ok(MapViewportOptions::from_native(raw))
288 }
289
290 pub fn set_viewport_options(&self, options: &MapViewportOptions) -> Result<()> {
292 let map = self.inner.as_ptr()?;
293 let raw = options.to_native();
294 maplibre_core::check(unsafe { sys::mln_map_set_viewport_options(map, &raw) })
297 }
298
299 pub fn tile_options(&self) -> Result<MapTileOptions> {
301 let map = self.inner.as_ptr()?;
302 let mut raw = unsafe { sys::mln_map_tile_options_default() };
304 maplibre_core::check(unsafe { sys::mln_map_get_tile_options(map, &mut raw) })?;
306 Ok(MapTileOptions::from_native(raw))
307 }
308
309 pub fn set_tile_options(&self, options: &MapTileOptions) -> Result<()> {
311 let map = self.inner.as_ptr()?;
312 let raw = options.to_native();
313 maplibre_core::check(unsafe { sys::mln_map_set_tile_options(map, &raw) })
316 }
317
318 pub fn camera(&self) -> Result<CameraOptions> {
320 let map = self.inner.as_ptr()?;
321 let mut raw = unsafe { sys::mln_camera_options_default() };
323 maplibre_core::check(unsafe { sys::mln_map_get_camera(map, &mut raw) })?;
325 Ok(CameraOptions::from_native(raw))
326 }
327
328 pub fn jump_to(&self, camera: &CameraOptions) -> Result<()> {
330 let map = self.inner.as_ptr()?;
331 let raw = camera.to_native();
332 maplibre_core::check(unsafe { sys::mln_map_jump_to(map, &raw) })
335 }
336
337 pub fn ease_to(
339 &self,
340 camera: &CameraOptions,
341 animation: Option<&AnimationOptions>,
342 ) -> Result<()> {
343 let map = self.inner.as_ptr()?;
344 let raw_camera = camera.to_native();
345 let raw_animation = animation.map(AnimationOptions::to_native);
346 maplibre_core::check(unsafe {
349 sys::mln_map_ease_to(map, &raw_camera, option_ptr(raw_animation.as_ref()))
350 })
351 }
352
353 pub fn fly_to(
355 &self,
356 camera: &CameraOptions,
357 animation: Option<&AnimationOptions>,
358 ) -> Result<()> {
359 let map = self.inner.as_ptr()?;
360 let raw_camera = camera.to_native();
361 let raw_animation = animation.map(AnimationOptions::to_native);
362 maplibre_core::check(unsafe {
365 sys::mln_map_fly_to(map, &raw_camera, option_ptr(raw_animation.as_ref()))
366 })
367 }
368
369 pub fn move_by(&self, delta_x: f64, delta_y: f64) -> Result<()> {
371 let map = self.inner.as_ptr()?;
372 maplibre_core::check(unsafe { sys::mln_map_move_by(map, delta_x, delta_y) })
374 }
375
376 pub fn move_by_animated(
378 &self,
379 delta_x: f64,
380 delta_y: f64,
381 animation: Option<&AnimationOptions>,
382 ) -> Result<()> {
383 let map = self.inner.as_ptr()?;
384 let raw_animation = animation.map(AnimationOptions::to_native);
385 maplibre_core::check(unsafe {
388 sys::mln_map_move_by_animated(map, delta_x, delta_y, option_ptr(raw_animation.as_ref()))
389 })
390 }
391
392 pub fn scale_by(&self, scale: f64, anchor: Option<ScreenPoint>) -> Result<()> {
394 let map = self.inner.as_ptr()?;
395 let raw_anchor = anchor.map(ScreenPoint::to_native);
396 maplibre_core::check(unsafe {
399 sys::mln_map_scale_by(map, scale, option_ptr(raw_anchor.as_ref()))
400 })
401 }
402
403 pub fn scale_by_animated(
405 &self,
406 scale: f64,
407 anchor: Option<ScreenPoint>,
408 animation: Option<&AnimationOptions>,
409 ) -> Result<()> {
410 let map = self.inner.as_ptr()?;
411 let raw_anchor = anchor.map(ScreenPoint::to_native);
412 let raw_animation = animation.map(AnimationOptions::to_native);
413 maplibre_core::check(unsafe {
416 sys::mln_map_scale_by_animated(
417 map,
418 scale,
419 option_ptr(raw_anchor.as_ref()),
420 option_ptr(raw_animation.as_ref()),
421 )
422 })
423 }
424
425 pub fn rotate_by(&self, first: ScreenPoint, second: ScreenPoint) -> Result<()> {
427 let map = self.inner.as_ptr()?;
428 maplibre_core::check(unsafe {
430 sys::mln_map_rotate_by(map, first.to_native(), second.to_native())
431 })
432 }
433
434 pub fn rotate_by_animated(
436 &self,
437 first: ScreenPoint,
438 second: ScreenPoint,
439 animation: Option<&AnimationOptions>,
440 ) -> Result<()> {
441 let map = self.inner.as_ptr()?;
442 let raw_animation = animation.map(AnimationOptions::to_native);
443 maplibre_core::check(unsafe {
446 sys::mln_map_rotate_by_animated(
447 map,
448 first.to_native(),
449 second.to_native(),
450 option_ptr(raw_animation.as_ref()),
451 )
452 })
453 }
454
455 pub fn pitch_by(&self, pitch: f64) -> Result<()> {
457 let map = self.inner.as_ptr()?;
458 maplibre_core::check(unsafe { sys::mln_map_pitch_by(map, pitch) })
460 }
461
462 pub fn pitch_by_animated(
464 &self,
465 pitch: f64,
466 animation: Option<&AnimationOptions>,
467 ) -> Result<()> {
468 let map = self.inner.as_ptr()?;
469 let raw_animation = animation.map(AnimationOptions::to_native);
470 maplibre_core::check(unsafe {
473 sys::mln_map_pitch_by_animated(map, pitch, option_ptr(raw_animation.as_ref()))
474 })
475 }
476
477 pub fn cancel_transitions(&self) -> Result<()> {
479 let map = self.inner.as_ptr()?;
480 maplibre_core::check(unsafe { sys::mln_map_cancel_transitions(map) })
482 }
483
484 pub fn camera_for_lat_lng_bounds(
486 &self,
487 bounds: LatLngBounds,
488 fit_options: Option<&CameraFitOptions>,
489 ) -> Result<CameraOptions> {
490 let map = self.inner.as_ptr()?;
491 let raw_fit = fit_options.map(CameraFitOptions::to_native);
492 let mut raw_camera = unsafe { sys::mln_camera_options_default() };
494 maplibre_core::check(unsafe {
497 sys::mln_map_camera_for_lat_lng_bounds(
498 map,
499 bounds.to_native(),
500 option_ptr(raw_fit.as_ref()),
501 &mut raw_camera,
502 )
503 })?;
504 Ok(CameraOptions::from_native(raw_camera))
505 }
506
507 pub fn camera_for_lat_lngs(
509 &self,
510 coordinates: &[LatLng],
511 fit_options: Option<&CameraFitOptions>,
512 ) -> Result<CameraOptions> {
513 let map = self.inner.as_ptr()?;
514 if coordinates.is_empty() {
515 return Err(Error::invalid_argument(
516 "camera_for_lat_lngs requires at least one coordinate",
517 ));
518 }
519 let raw_coordinates = lat_lngs_to_native(coordinates);
520 let raw_fit = fit_options.map(CameraFitOptions::to_native);
521 let mut raw_camera = unsafe { sys::mln_camera_options_default() };
523 maplibre_core::check(unsafe {
526 sys::mln_map_camera_for_lat_lngs(
527 map,
528 const_ptr_or_null(&raw_coordinates),
529 raw_coordinates.len(),
530 option_ptr(raw_fit.as_ref()),
531 &mut raw_camera,
532 )
533 })?;
534 Ok(CameraOptions::from_native(raw_camera))
535 }
536
537 pub fn camera_for_geometry(
539 &self,
540 geometry: &Geometry,
541 fit_options: Option<&CameraFitOptions>,
542 ) -> Result<CameraOptions> {
543 let map = self.inner.as_ptr()?;
544 let native_geometry = geometry.try_to_native()?;
545 let raw_fit = fit_options.map(CameraFitOptions::to_native);
546 let mut raw_camera = unsafe { sys::mln_camera_options_default() };
548 maplibre_core::check(unsafe {
552 sys::mln_map_camera_for_geometry(
553 map,
554 native_geometry.as_ptr(),
555 option_ptr(raw_fit.as_ref()),
556 &mut raw_camera,
557 )
558 })?;
559 Ok(CameraOptions::from_native(raw_camera))
560 }
561
562 pub fn lat_lng_bounds_for_camera(&self, camera: &CameraOptions) -> Result<LatLngBounds> {
564 let map = self.inner.as_ptr()?;
565 let raw_camera = camera.to_native();
566 let mut raw_bounds = empty_bounds();
567 maplibre_core::check(unsafe {
570 sys::mln_map_lat_lng_bounds_for_camera(map, &raw_camera, &mut raw_bounds)
571 })?;
572 Ok(LatLngBounds::from_native(raw_bounds))
573 }
574
575 pub fn lat_lng_bounds_for_camera_unwrapped(
577 &self,
578 camera: &CameraOptions,
579 ) -> Result<LatLngBounds> {
580 let map = self.inner.as_ptr()?;
581 let raw_camera = camera.to_native();
582 let mut raw_bounds = empty_bounds();
583 maplibre_core::check(unsafe {
586 sys::mln_map_lat_lng_bounds_for_camera_unwrapped(map, &raw_camera, &mut raw_bounds)
587 })?;
588 Ok(LatLngBounds::from_native(raw_bounds))
589 }
590
591 pub fn bounds(&self) -> Result<BoundOptions> {
593 let map = self.inner.as_ptr()?;
594 let mut raw = unsafe { sys::mln_bound_options_default() };
596 maplibre_core::check(unsafe { sys::mln_map_get_bounds(map, &mut raw) })?;
598 Ok(BoundOptions::from_native(raw))
599 }
600
601 pub fn set_bounds(&self, options: &BoundOptions) -> Result<()> {
603 let map = self.inner.as_ptr()?;
604 let raw = options.to_native();
605 maplibre_core::check(unsafe { sys::mln_map_set_bounds(map, &raw) })
607 }
608
609 pub fn free_camera_options(&self) -> Result<FreeCameraOptions> {
611 let map = self.inner.as_ptr()?;
612 let mut raw = unsafe { sys::mln_free_camera_options_default() };
614 maplibre_core::check(unsafe { sys::mln_map_get_free_camera_options(map, &mut raw) })?;
616 Ok(FreeCameraOptions::from_native(raw))
617 }
618
619 pub fn set_free_camera_options(&self, options: &FreeCameraOptions) -> Result<()> {
621 let map = self.inner.as_ptr()?;
622 let raw = options.to_native();
623 maplibre_core::check(unsafe { sys::mln_map_set_free_camera_options(map, &raw) })
625 }
626
627 pub fn projection_mode(&self) -> Result<ProjectionMode> {
629 let map = self.inner.as_ptr()?;
630 let mut raw = unsafe { sys::mln_projection_mode_default() };
632 maplibre_core::check(unsafe { sys::mln_map_get_projection_mode(map, &mut raw) })?;
634 Ok(ProjectionMode::from_native(raw))
635 }
636
637 pub fn set_projection_mode(&self, mode: &ProjectionMode) -> Result<()> {
639 let map = self.inner.as_ptr()?;
640 let raw = mode.to_native();
641 maplibre_core::check(unsafe { sys::mln_map_set_projection_mode(map, &raw) })
643 }
644
645 pub fn pixel_for_lat_lng(&self, coordinate: LatLng) -> Result<ScreenPoint> {
647 let map = self.inner.as_ptr()?;
648 let mut raw_point = empty_screen_point();
649 maplibre_core::check(unsafe {
652 sys::mln_map_pixel_for_lat_lng(map, coordinate.to_native(), &mut raw_point)
653 })?;
654 Ok(ScreenPoint::from_native(raw_point))
655 }
656
657 pub fn lat_lng_for_pixel(&self, point: ScreenPoint) -> Result<LatLng> {
659 let map = self.inner.as_ptr()?;
660 let mut raw_coordinate = empty_lat_lng();
661 maplibre_core::check(unsafe {
664 sys::mln_map_lat_lng_for_pixel(map, point.to_native(), &mut raw_coordinate)
665 })?;
666 Ok(LatLng::from_native(raw_coordinate))
667 }
668
669 pub fn pixels_for_lat_lngs(&self, coordinates: &[LatLng]) -> Result<Vec<ScreenPoint>> {
671 let map = self.inner.as_ptr()?;
672 let raw_coordinates = lat_lngs_to_native(coordinates);
673 let mut raw_points = vec![empty_screen_point(); coordinates.len()];
674 maplibre_core::check(unsafe {
677 sys::mln_map_pixels_for_lat_lngs(
678 map,
679 const_ptr_or_null(&raw_coordinates),
680 raw_coordinates.len(),
681 mut_ptr_or_null(&mut raw_points),
682 )
683 })?;
684 Ok(raw_points
685 .into_iter()
686 .map(ScreenPoint::from_native)
687 .collect())
688 }
689
690 pub fn lat_lngs_for_pixels(&self, points: &[ScreenPoint]) -> Result<Vec<LatLng>> {
692 let map = self.inner.as_ptr()?;
693 let raw_points = screen_points_to_native(points);
694 let mut raw_coordinates = vec![empty_lat_lng(); points.len()];
695 maplibre_core::check(unsafe {
698 sys::mln_map_lat_lngs_for_pixels(
699 map,
700 const_ptr_or_null(&raw_points),
701 raw_points.len(),
702 mut_ptr_or_null(&mut raw_coordinates),
703 )
704 })?;
705 Ok(raw_coordinates
706 .into_iter()
707 .map(LatLng::from_native)
708 .collect())
709 }
710
711 pub fn create_projection(&self) -> Result<MapProjectionHandle> {
713 MapProjectionHandle::new(self)
714 }
715
716 pub fn attach_metal_surface(
722 &self,
723 descriptor: &MetalSurfaceDescriptor,
724 ) -> Result<RenderSessionHandle> {
725 let raw = descriptor.to_native();
726 RenderSessionHandle::attach(self, |map, out| {
727 unsafe { sys::mln_metal_surface_attach(map, &raw, out) }
730 })
731 }
732
733 pub fn attach_vulkan_surface(
738 &self,
739 descriptor: &VulkanSurfaceDescriptor,
740 ) -> Result<RenderSessionHandle> {
741 let raw = descriptor.to_native();
742 RenderSessionHandle::attach(self, |map, out| {
743 unsafe { sys::mln_vulkan_surface_attach(map, &raw, out) }
746 })
747 }
748
749 pub fn attach_opengl_surface(
755 &self,
756 descriptor: &OpenGLSurfaceDescriptor,
757 ) -> Result<RenderSessionHandle> {
758 let raw = descriptor.to_native();
759 RenderSessionHandle::attach(self, |map, out| {
760 unsafe { sys::mln_opengl_surface_attach(map, &raw, out) }
763 })
764 }
765
766 pub fn attach_metal_owned_texture(
771 &self,
772 descriptor: &MetalOwnedTextureDescriptor,
773 ) -> Result<RenderSessionHandle> {
774 let raw = descriptor.to_native();
775 RenderSessionHandle::attach(self, |map, out| {
776 unsafe { sys::mln_metal_owned_texture_attach(map, &raw, out) }
779 })
780 }
781
782 pub fn attach_metal_borrowed_texture(
787 &self,
788 descriptor: &MetalBorrowedTextureDescriptor,
789 ) -> Result<RenderSessionHandle> {
790 let raw = descriptor.to_native();
791 RenderSessionHandle::attach(self, |map, out| {
792 unsafe { sys::mln_metal_borrowed_texture_attach(map, &raw, out) }
795 })
796 }
797
798 pub fn attach_vulkan_owned_texture(
803 &self,
804 descriptor: &VulkanOwnedTextureDescriptor,
805 ) -> Result<RenderSessionHandle> {
806 let raw = descriptor.to_native();
807 RenderSessionHandle::attach(self, |map, out| {
808 unsafe { sys::mln_vulkan_owned_texture_attach(map, &raw, out) }
811 })
812 }
813
814 pub fn attach_vulkan_borrowed_texture(
820 &self,
821 descriptor: &VulkanBorrowedTextureDescriptor,
822 ) -> Result<RenderSessionHandle> {
823 let raw = descriptor.to_native();
824 RenderSessionHandle::attach(self, |map, out| {
825 unsafe { sys::mln_vulkan_borrowed_texture_attach(map, &raw, out) }
828 })
829 }
830
831 pub fn attach_opengl_owned_texture(
837 &self,
838 descriptor: &OpenGLOwnedTextureDescriptor,
839 ) -> Result<RenderSessionHandle> {
840 let raw = descriptor.to_native();
841 RenderSessionHandle::attach(self, |map, out| {
842 unsafe { sys::mln_opengl_owned_texture_attach(map, &raw, out) }
845 })
846 }
847
848 pub fn attach_opengl_borrowed_texture(
854 &self,
855 descriptor: &OpenGLBorrowedTextureDescriptor,
856 ) -> Result<RenderSessionHandle> {
857 let raw = descriptor.to_native();
858 RenderSessionHandle::attach(self, |map, out| {
859 unsafe { sys::mln_opengl_borrowed_texture_attach(map, &raw, out) }
862 })
863 }
864}
865
866#[cfg(test)]
867mod tests;