/
githubmirror
/
servo
Обзор
Документация
Войти
/
githubmirror
/
servo
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
components/shared/webxr/layer.rs
279 строк
8 KB
Narfinger
webxr: Implement MallocSizeOf (#42505)
11 фев 2026, 11:39
Не верифицирован
11 фев 2026, 11:39
2f61982
Код
Авторство
О чём код?
/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ use std::fmt::Debug; use std::num::NonZeroU32; use std::sync::atomic::{AtomicUsize, Ordering}; use euclid::{Rect, Size2D}; use malloc_size_of_derive::MallocSizeOf; use serde::{Deserialize, Serialize}; use crate::{Error, Viewport, Viewports}; #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)] pub struct ContextId(pub u64); pub trait GLTypes { type Device; type Context; type Bindings; } pub trait GLContexts<GL: GLTypes> { fn device(&self, context_id: ContextId) -> Option<GL::Device>; fn bindings(&mut self, context_id: ContextId) -> Option<&GL::Bindings>; fn context(&mut self, context_id: ContextId) -> Option<&mut GL::Context>; } impl GLTypes for () { type Bindings = (); type Device = (); type Context = (); } impl GLContexts<()> for () { fn device(&self, _: ContextId) -> Option<()> { Some(()) } fn context(&mut self, _: ContextId) -> Option<&mut ()> { Some(self) } fn bindings(&mut self, _: ContextId) -> Option<&()> { Some(self) } } pub trait LayerGrandManagerAPI<GL: GLTypes> { fn create_layer_manager(&self, factory: LayerManagerFactory<GL>) -> Result<LayerManager, Error>; fn clone_layer_grand_manager(&self) -> LayerGrandManager<GL>; } pub struct LayerGrandManager<GL>(Box<dyn Send + LayerGrandManagerAPI<GL>>); impl<GL: GLTypes> Clone for LayerGrandManager<GL> { fn clone(&self) -> Self { self.0.clone_layer_grand_manager() } } impl<GL> Debug for LayerGrandManager<GL> { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { "LayerGrandManager(...)".fmt(fmt) } } impl<GL: GLTypes> LayerGrandManager<GL> { pub fn new<GM>(grand_manager: GM) -> LayerGrandManager<GL> where GM: 'static + Send + LayerGrandManagerAPI<GL>, { LayerGrandManager(Box::new(grand_manager)) } pub fn create_layer_manager<F, M>(&self, factory: F) -> Result<LayerManager, Error> where F: 'static + Send + FnOnce(&mut dyn GLContexts<GL>) -> Result<M, Error>, M: 'static + LayerManagerAPI<GL>, { self.0 .create_layer_manager(LayerManagerFactory::new(factory)) } } pub trait LayerManagerAPI<GL: GLTypes> { fn create_layer( &mut self, contexts: &mut dyn GLContexts<GL>, context_id: ContextId, init: LayerInit, ) -> Result<LayerId, Error>; fn destroy_layer( &mut self, contexts: &mut dyn GLContexts<GL>, context_id: ContextId, layer_id: LayerId, ); fn layers(&self) -> &[(ContextId, LayerId)]; fn begin_frame( &mut self, contexts: &mut dyn GLContexts<GL>, layers: &[(ContextId, LayerId)], ) -> Result<Vec<SubImages>, Error>; fn end_frame( &mut self, contexts: &mut dyn GLContexts<GL>, layers: &[(ContextId, LayerId)], ) -> Result<(), Error>; } pub struct LayerManager(Box<dyn Send + LayerManagerAPI<()>>); impl Debug for LayerManager { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { "LayerManager(...)".fmt(fmt) } } impl LayerManager { pub fn create_layer( &mut self, context_id: ContextId, init: LayerInit, ) -> Result<LayerId, Error> { self.0.create_layer(&mut (), context_id, init) } pub fn destroy_layer(&mut self, context_id: ContextId, layer_id: LayerId) { self.0.destroy_layer(&mut (), context_id, layer_id); } pub fn begin_frame( &mut self, layers: &[(ContextId, LayerId)], ) -> Result<Vec<SubImages>, Error> { self.0.begin_frame(&mut (), layers) } pub fn end_frame(&mut self, layers: &[(ContextId, LayerId)]) -> Result<(), Error> { self.0.end_frame(&mut (), layers) } } impl LayerManager { pub fn new<M>(manager: M) -> LayerManager where M: 'static + Send + LayerManagerAPI<()>, { LayerManager(Box::new(manager)) } } impl Drop for LayerManager { fn drop(&mut self) { log::debug!("Dropping LayerManager"); let layers: Vec<_> = self.0.layers().to_vec(); for (context_id, layer_id) in layers.into_iter() { self.destroy_layer(context_id, layer_id); } } } #[expect(clippy::type_complexity)] pub struct LayerManagerFactory<GL: GLTypes>( Box<dyn Send + FnOnce(&mut dyn GLContexts<GL>) -> Result<Box<dyn LayerManagerAPI<GL>>, Error>>, ); impl<GL: GLTypes> Debug for LayerManagerFactory<GL> { fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { "LayerManagerFactory(...)".fmt(fmt) } } impl<GL: GLTypes> LayerManagerFactory<GL> { pub fn new<F, M>(factory: F) -> LayerManagerFactory<GL> where F: 'static + Send + FnOnce(&mut dyn GLContexts<GL>) -> Result<M, Error>, M: 'static + LayerManagerAPI<GL>, { LayerManagerFactory(Box::new(move |contexts| Ok(Box::new(factory(contexts)?)))) } pub fn build( self, contexts: &mut dyn GLContexts<GL>, ) -> Result<Box<dyn LayerManagerAPI<GL>>, Error> { (self.0)(contexts) } } #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, Deserialize, Serialize, MallocSizeOf)] pub struct LayerId(usize); static NEXT_LAYER_ID: AtomicUsize = AtomicUsize::new(0); impl Default for LayerId { fn default() -> Self { LayerId(NEXT_LAYER_ID.fetch_add(1, Ordering::SeqCst)) } } #[derive(Clone, Copy, Debug, Deserialize, Serialize)] pub enum LayerInit { /// <https://www.w3.org/TR/webxr/#dictdef-xrwebgllayerinit> WebGLLayer { antialias: bool, depth: bool, stencil: bool, alpha: bool, ignore_depth_values: bool, framebuffer_scale_factor: f32, }, /// <https://immersive-web.github.io/layers/#xrprojectionlayerinittype> ProjectionLayer { depth: bool, stencil: bool, alpha: bool, scale_factor: f32, }, // TODO: other layer types } impl LayerInit { pub fn texture_size(&self, viewports: &Viewports) -> Size2D<i32, Viewport> { match self { LayerInit::WebGLLayer { framebuffer_scale_factor: scale, .. } | LayerInit::ProjectionLayer { scale_factor: scale, .. } => { let native_size = viewports .viewports .iter() .fold(Rect::zero(), |acc, view| acc.union(view)) .size; (native_size.to_f32() * *scale).to_i32() }, } } } /// <https://immersive-web.github.io/layers/#enumdef-xrlayerlayout> #[derive(Clone, Copy, Debug, Deserialize, Serialize)] pub enum LayerLayout { // TODO: Default // Allocates one texture Mono, // Allocates one texture, which is split in half vertically, giving two subimages StereoLeftRight, // Allocates one texture, which is split in half horizonally, giving two subimages StereoTopBottom, } #[derive(Clone, Debug, Deserialize, Serialize, MallocSizeOf)] pub struct SubImages { pub layer_id: LayerId, pub sub_image: Option<SubImage>, pub view_sub_images: Vec<SubImage>, } /// <https://immersive-web.github.io/layers/#xrsubimagetype> #[derive(Clone, Debug, Deserialize, Serialize, MallocSizeOf)] pub struct SubImage { pub color_texture: Option<NonZeroU32>, pub depth_stencil_texture: Option<NonZeroU32>, pub texture_array_index: Option<u32>, pub viewport: Rect<i32, Viewport>, }