mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Support for webxr layer management
This commit is contained in:
parent
af110ac21f
commit
349619ed2d
34 changed files with 949 additions and 642 deletions
29
Cargo.lock
generated
29
Cargo.lock
generated
|
@ -529,6 +529,7 @@ dependencies = [
|
|||
"webrender_api",
|
||||
"webrender_surfman",
|
||||
"webrender_traits",
|
||||
"webxr",
|
||||
"webxr-api",
|
||||
]
|
||||
|
||||
|
@ -1952,15 +1953,6 @@ dependencies = [
|
|||
"gl_generator 0.13.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gleam"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "332d1f4e6c6181ed07178f84a552b2387d43ecf6821a86c22cfb3883ea3fb1b9"
|
||||
dependencies = [
|
||||
"gl_generator 0.14.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gleam"
|
||||
version = "0.11.0"
|
||||
|
@ -5546,8 +5538,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "surfman"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/servo/surfman#2283acaa3a856c2f76028cb23b5dde7dc0030cdf"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3d85bf0eb91b66b93dda5c04627f00074ea1fa008c2980b132a065fafe7a1ab"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cfg_aliases",
|
||||
|
@ -5557,7 +5550,7 @@ dependencies = [
|
|||
"core-graphics 0.17.3",
|
||||
"display-link",
|
||||
"euclid",
|
||||
"gl_generator 0.13.1",
|
||||
"gl_generator 0.14.0",
|
||||
"io-surface",
|
||||
"lazy_static",
|
||||
"libc",
|
||||
|
@ -5575,8 +5568,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "surfman-chains"
|
||||
version = "0.3.0"
|
||||
source = "git+https://github.com/asajeffrey/surfman-chains#b949a240d73ef86d3c4bd22bc3d93933fac21ee9"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d51598e1772bda3dbb1b81a9dc4b46725896948ea58d0f128e5b492a92f297af"
|
||||
dependencies = [
|
||||
"euclid",
|
||||
"fnv",
|
||||
|
@ -6526,18 +6520,18 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webxr"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/webxr#0d8d2affc4da259b88d251ab49c0bbcbe96acf4d"
|
||||
source = "git+https://github.com/servo/webxr#e507076cc6f55ea6daa58c3ecbb1867847854722"
|
||||
dependencies = [
|
||||
"android_injected_glue",
|
||||
"bindgen",
|
||||
"crossbeam-channel",
|
||||
"euclid",
|
||||
"gl_generator 0.13.1",
|
||||
"gleam 0.9.2",
|
||||
"gvr-sys",
|
||||
"log",
|
||||
"openxr",
|
||||
"serde",
|
||||
"sparkle",
|
||||
"surfman",
|
||||
"surfman-chains",
|
||||
"time",
|
||||
|
@ -6549,13 +6543,12 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "webxr-api"
|
||||
version = "0.0.1"
|
||||
source = "git+https://github.com/servo/webxr#0d8d2affc4da259b88d251ab49c0bbcbe96acf4d"
|
||||
source = "git+https://github.com/servo/webxr#e507076cc6f55ea6daa58c3ecbb1867847854722"
|
||||
dependencies = [
|
||||
"euclid",
|
||||
"ipc-channel",
|
||||
"log",
|
||||
"serde",
|
||||
"surfman-chains-api",
|
||||
"time",
|
||||
]
|
||||
|
||||
|
|
|
@ -28,5 +28,3 @@ opt-level = 3
|
|||
|
||||
# This is here to dedupe winapi since mio 0.6 is still using winapi 0.2.
|
||||
mio = { git = "https://github.com/servo/mio.git", branch = "servo" }
|
||||
surfman = { git = "https://github.com/servo/surfman" }
|
||||
surfman-chains = { git = "https://github.com/asajeffrey/surfman-chains" }
|
||||
|
|
|
@ -38,9 +38,9 @@ servo_config = { path = "../config" }
|
|||
sparkle = "0.1.25"
|
||||
style = { path = "../style" }
|
||||
style_traits = { path = "../style_traits" }
|
||||
# NOTE: the sm-angle feature only enables ANGLE on Windows, not other platforms!
|
||||
surfman = { version = "0.2", features = ["sm-angle", "sm-angle-default"] }
|
||||
surfman-chains = "0.3"
|
||||
# NOTE: the sm-angle feature only enables angle on windows, not other platforms!
|
||||
surfman = { version = "0.3", features = ["sm-angle","sm-angle-default"] }
|
||||
surfman-chains = "0.4"
|
||||
surfman-chains-api = "0.2"
|
||||
time = { version = "0.1.0", optional = true }
|
||||
webrender = { git = "https://github.com/servo/webrender" }
|
||||
|
@ -48,3 +48,4 @@ webrender_api = { git = "https://github.com/servo/webrender" }
|
|||
webrender_surfman = { path = "../webrender_surfman" }
|
||||
webrender_traits = { path = "../webrender_traits" }
|
||||
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
|
||||
webxr = { git = "https://github.com/servo/webxr", features = ["ipc"] }
|
||||
|
|
|
@ -12,9 +12,6 @@ extern crate log;
|
|||
mod raqote_backend;
|
||||
|
||||
pub use webgl_mode::WebGLComm;
|
||||
pub use webgl_thread::SurfaceProvider;
|
||||
pub use webgl_thread::SurfaceProviders;
|
||||
pub use webgl_thread::WebGlExecutor;
|
||||
|
||||
pub mod canvas_data;
|
||||
pub mod canvas_paint_thread;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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 crate::webgl_thread::{SurfaceProviders, WebGLThread, WebGLThreadInit, WebGlExecutor};
|
||||
use crate::webgl_thread::{WebGLThread, WebGLThreadInit, WebXRBridgeInit};
|
||||
use canvas_traits::webgl::webgl_channel;
|
||||
use canvas_traits::webgl::{WebGLContextId, WebGLMsg, WebGLThreads};
|
||||
use euclid::default::Size2D;
|
||||
|
@ -11,7 +11,6 @@ use gleam;
|
|||
use servo_config::pref;
|
||||
use sparkle::gl;
|
||||
use sparkle::gl::GlType;
|
||||
use std::collections::HashMap;
|
||||
use std::default::Default;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
@ -25,15 +24,14 @@ use webrender_surfman::WebrenderSurfman;
|
|||
use webrender_traits::{
|
||||
WebrenderExternalImageApi, WebrenderExternalImageRegistry, WebrenderImageSource,
|
||||
};
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
use webxr::SurfmanGL as WebXRSurfman;
|
||||
use webxr_api::LayerGrandManager as WebXRLayerGrandManager;
|
||||
|
||||
pub struct WebGLComm {
|
||||
pub webgl_threads: WebGLThreads,
|
||||
pub webxr_swap_chains: SwapChains<WebXRSwapChainId, Device>,
|
||||
pub webxr_surface_providers: SurfaceProviders,
|
||||
pub image_handler: Box<dyn WebrenderExternalImageApi>,
|
||||
pub output_handler: Option<Box<dyn webrender_api::OutputImageHandler>>,
|
||||
pub webgl_executor: WebGlExecutor,
|
||||
pub webxr_layer_grand_manager: WebXRLayerGrandManager<WebXRSurfman>,
|
||||
}
|
||||
|
||||
impl WebGLComm {
|
||||
|
@ -49,9 +47,8 @@ impl WebGLComm {
|
|||
debug!("WebGLThreads::new()");
|
||||
let (sender, receiver) = webgl_channel::<WebGLMsg>().unwrap();
|
||||
let webrender_swap_chains = SwapChains::new();
|
||||
let webxr_swap_chains = SwapChains::new();
|
||||
let webxr_surface_providers = Arc::new(Mutex::new(HashMap::new()));
|
||||
let (runnable_sender, runnable_receiver) = crossbeam_channel::unbounded();
|
||||
let webxr_init = WebXRBridgeInit::new(sender.clone());
|
||||
let webxr_layer_grand_manager = webxr_init.layer_grand_manager();
|
||||
|
||||
// This implementation creates a single `WebGLThread` for all the pipelines.
|
||||
let init = WebGLThreadInit {
|
||||
|
@ -61,12 +58,10 @@ impl WebGLComm {
|
|||
sender: sender.clone(),
|
||||
receiver,
|
||||
webrender_swap_chains: webrender_swap_chains.clone(),
|
||||
webxr_swap_chains: webxr_swap_chains.clone(),
|
||||
webxr_surface_providers: webxr_surface_providers.clone(),
|
||||
connection: surfman.connection(),
|
||||
adapter: surfman.adapter(),
|
||||
api_type,
|
||||
runnable_receiver,
|
||||
webxr_init,
|
||||
};
|
||||
|
||||
let output_handler = if pref!(dom.webgl.dom_to_texture.enabled) {
|
||||
|
@ -81,11 +76,9 @@ impl WebGLComm {
|
|||
|
||||
WebGLComm {
|
||||
webgl_threads: WebGLThreads(sender),
|
||||
webxr_swap_chains,
|
||||
webxr_surface_providers,
|
||||
image_handler: Box::new(external),
|
||||
output_handler: output_handler.map(|b| b as Box<_>),
|
||||
webgl_executor: runnable_sender,
|
||||
webxr_layer_grand_manager: webxr_layer_grand_manager,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use crate::webgl_limits::GLLimitsDetect;
|
||||
use byteorder::{ByteOrder, NativeEndian, WriteBytesExt};
|
||||
use canvas_traits::webgl;
|
||||
use canvas_traits::webgl::webgl_channel;
|
||||
use canvas_traits::webgl::ActiveAttribInfo;
|
||||
use canvas_traits::webgl::ActiveUniformBlockInfo;
|
||||
use canvas_traits::webgl::ActiveUniformInfo;
|
||||
|
@ -15,7 +16,6 @@ use canvas_traits::webgl::GLLimits;
|
|||
use canvas_traits::webgl::GlType;
|
||||
use canvas_traits::webgl::InternalFormatIntVec;
|
||||
use canvas_traits::webgl::ProgramLinkInfo;
|
||||
use canvas_traits::webgl::SwapChainId;
|
||||
use canvas_traits::webgl::TexDataType;
|
||||
use canvas_traits::webgl::TexFormat;
|
||||
use canvas_traits::webgl::WebGLBufferId;
|
||||
|
@ -28,7 +28,6 @@ use canvas_traits::webgl::WebGLFramebufferBindingRequest;
|
|||
use canvas_traits::webgl::WebGLFramebufferId;
|
||||
use canvas_traits::webgl::WebGLMsg;
|
||||
use canvas_traits::webgl::WebGLMsgSender;
|
||||
use canvas_traits::webgl::WebGLOpaqueFramebufferId;
|
||||
use canvas_traits::webgl::WebGLProgramId;
|
||||
use canvas_traits::webgl::WebGLQueryId;
|
||||
use canvas_traits::webgl::WebGLReceiver;
|
||||
|
@ -39,9 +38,10 @@ use canvas_traits::webgl::WebGLSender;
|
|||
use canvas_traits::webgl::WebGLShaderId;
|
||||
use canvas_traits::webgl::WebGLSyncId;
|
||||
use canvas_traits::webgl::WebGLTextureId;
|
||||
use canvas_traits::webgl::WebGLTransparentFramebufferId;
|
||||
use canvas_traits::webgl::WebGLVersion;
|
||||
use canvas_traits::webgl::WebGLVertexArrayId;
|
||||
use canvas_traits::webgl::WebXRCommand;
|
||||
use canvas_traits::webgl::WebXRLayerManagerId;
|
||||
use canvas_traits::webgl::YAxisTreatment;
|
||||
use euclid::default::Size2D;
|
||||
use fnv::FnvHashMap;
|
||||
|
@ -68,11 +68,22 @@ use surfman::GLVersion;
|
|||
use surfman::SurfaceAccess;
|
||||
use surfman::SurfaceInfo;
|
||||
use surfman::SurfaceType;
|
||||
use surfman_chains::{SurfmanProvider, SwapChains};
|
||||
use surfman_chains::SwapChains;
|
||||
use surfman_chains_api::SwapChainsAPI;
|
||||
use webrender_traits::{WebrenderExternalImageRegistry, WebrenderImageHandlerType};
|
||||
use webxr_api::SessionId;
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
use webxr::SurfmanGL as WebXRSurfman;
|
||||
use webxr_api::ContextId as WebXRContextId;
|
||||
use webxr_api::Error as WebXRError;
|
||||
use webxr_api::GLContexts as WebXRContexts;
|
||||
use webxr_api::GLTypes as WebXRTypes;
|
||||
use webxr_api::LayerGrandManager as WebXRLayerGrandManager;
|
||||
use webxr_api::LayerGrandManagerAPI as WebXRLayerGrandManagerAPI;
|
||||
use webxr_api::LayerId as WebXRLayerId;
|
||||
use webxr_api::LayerInit as WebXRLayerInit;
|
||||
use webxr_api::LayerManager as WebXRLayerManager;
|
||||
use webxr_api::LayerManagerAPI as WebXRLayerManagerAPI;
|
||||
use webxr_api::LayerManagerFactory as WebXRLayerManagerFactory;
|
||||
use webxr_api::SubImages as WebXRSubImages;
|
||||
|
||||
#[cfg(feature = "xr-profile")]
|
||||
fn to_ms(ns: u64) -> f64 {
|
||||
|
@ -239,35 +250,24 @@ pub(crate) struct WebGLThread {
|
|||
sender: WebGLSender<WebGLMsg>,
|
||||
/// The swap chains used by webrender
|
||||
webrender_swap_chains: SwapChains<WebGLContextId, Device>,
|
||||
/// The swap chains used by webxr
|
||||
webxr_swap_chains: SwapChains<WebXRSwapChainId, Device>,
|
||||
/// The set of all surface providers corresponding to WebXR sessions.
|
||||
webxr_surface_providers: SurfaceProviders,
|
||||
/// A channel to allow arbitrary threads to execute tasks that run in the WebGL thread.
|
||||
runnable_receiver: crossbeam_channel::Receiver<WebGlRunnable>,
|
||||
/// Whether this context is a GL or GLES context.
|
||||
api_type: gl::GlType,
|
||||
/// The bridge to WebXR
|
||||
pub webxr_bridge: WebXRBridge,
|
||||
}
|
||||
|
||||
pub type WebGlExecutor = crossbeam_channel::Sender<WebGlRunnable>;
|
||||
pub type WebGlRunnable = Box<dyn FnOnce(&Device) + Send>;
|
||||
pub type SurfaceProviders = Arc<Mutex<HashMap<SessionId, SurfaceProvider>>>;
|
||||
pub type SurfaceProvider = Box<dyn surfman_chains::SurfaceProvider<Device> + Send>;
|
||||
|
||||
/// The data required to initialize an instance of the WebGLThread type.
|
||||
pub(crate) struct WebGLThreadInit {
|
||||
pub webxr_surface_providers: SurfaceProviders,
|
||||
pub webrender_api_sender: webrender_api::RenderApiSender,
|
||||
pub webrender_doc: webrender_api::DocumentId,
|
||||
pub external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
||||
pub sender: WebGLSender<WebGLMsg>,
|
||||
pub receiver: WebGLReceiver<WebGLMsg>,
|
||||
pub webrender_swap_chains: SwapChains<WebGLContextId, Device>,
|
||||
pub webxr_swap_chains: SwapChains<WebXRSwapChainId, Device>,
|
||||
pub connection: Connection,
|
||||
pub adapter: Adapter,
|
||||
pub api_type: gl::GlType,
|
||||
pub runnable_receiver: crossbeam_channel::Receiver<WebGlRunnable>,
|
||||
pub webxr_init: WebXRBridgeInit,
|
||||
}
|
||||
|
||||
// A size at which it should be safe to create GL contexts
|
||||
|
@ -283,12 +283,10 @@ impl WebGLThread {
|
|||
sender,
|
||||
receiver,
|
||||
webrender_swap_chains,
|
||||
webxr_swap_chains,
|
||||
webxr_surface_providers,
|
||||
connection,
|
||||
adapter,
|
||||
api_type,
|
||||
runnable_receiver,
|
||||
webxr_init,
|
||||
}: WebGLThreadInit,
|
||||
) -> Self {
|
||||
WebGLThread {
|
||||
|
@ -305,10 +303,8 @@ impl WebGLThread {
|
|||
sender,
|
||||
receiver: receiver.into_inner(),
|
||||
webrender_swap_chains,
|
||||
webxr_swap_chains,
|
||||
webxr_surface_providers,
|
||||
runnable_receiver,
|
||||
api_type,
|
||||
webxr_bridge: WebXRBridge::new(webxr_init),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -326,34 +322,18 @@ impl WebGLThread {
|
|||
|
||||
fn process(&mut self) {
|
||||
let webgl_chan = WebGLChan(self.sender.clone());
|
||||
loop {
|
||||
crossbeam_channel::select! {
|
||||
recv(self.receiver) -> msg => {
|
||||
match msg {
|
||||
Ok(msg) => {
|
||||
let exit = self.handle_msg(msg, &webgl_chan);
|
||||
if exit {
|
||||
// Call remove_context functions in order to correctly delete WebRender image keys.
|
||||
let context_ids: Vec<WebGLContextId> = self.contexts.keys().map(|id| *id).collect();
|
||||
for id in context_ids {
|
||||
self.remove_webgl_context(id);
|
||||
}
|
||||
while let Ok(msg) = self.receiver.recv() {
|
||||
let exit = self.handle_msg(msg, &webgl_chan);
|
||||
if exit {
|
||||
// Call remove_context functions in order to correctly delete WebRender image keys.
|
||||
let context_ids: Vec<WebGLContextId> = self.contexts.keys().map(|id| *id).collect();
|
||||
for id in context_ids {
|
||||
self.remove_webgl_context(id);
|
||||
}
|
||||
|
||||
// Block on shutting-down WebRender.
|
||||
self.webrender_api.shut_down(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => break,
|
||||
}
|
||||
}
|
||||
recv(self.runnable_receiver) -> msg => {
|
||||
if let Ok(msg) = msg {
|
||||
msg(&self.device);
|
||||
} else {
|
||||
self.runnable_receiver = crossbeam_channel::never();
|
||||
}
|
||||
}
|
||||
// Block on shutting-down WebRender.
|
||||
self.webrender_api.shut_down(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -424,8 +404,8 @@ impl WebGLThread {
|
|||
WebGLMsg::WebGLCommand(ctx_id, command, backtrace) => {
|
||||
self.handle_webgl_command(ctx_id, command, backtrace);
|
||||
},
|
||||
WebGLMsg::CreateWebXRSwapChain(ctx_id, size, sender, id) => {
|
||||
let _ = sender.send(self.create_webxr_swap_chain(ctx_id, size, id));
|
||||
WebGLMsg::WebXRCommand(command) => {
|
||||
self.handle_webxr_command(command);
|
||||
},
|
||||
WebGLMsg::SwapBuffers(swap_ids, sender, sent_time) => {
|
||||
self.handle_swap_buffers(swap_ids, sender, sent_time);
|
||||
|
@ -441,6 +421,63 @@ impl WebGLThread {
|
|||
false
|
||||
}
|
||||
|
||||
/// Handles a WebXR message
|
||||
fn handle_webxr_command(&mut self, command: WebXRCommand) {
|
||||
trace!("processing {:?}", command);
|
||||
let mut contexts = WebXRBridgeContexts {
|
||||
contexts: &mut self.contexts,
|
||||
bound_context_id: &mut self.bound_context_id,
|
||||
};
|
||||
match command {
|
||||
WebXRCommand::CreateLayerManager(sender) => {
|
||||
let result = self
|
||||
.webxr_bridge
|
||||
.create_layer_manager(&mut self.device, &mut contexts);
|
||||
let _ = sender.send(result);
|
||||
},
|
||||
WebXRCommand::DestroyLayerManager(manager_id) => {
|
||||
self.webxr_bridge.destroy_layer_manager(manager_id);
|
||||
},
|
||||
WebXRCommand::CreateLayer(manager_id, context_id, layer_init, sender) => {
|
||||
let result = self.webxr_bridge.create_layer(
|
||||
manager_id,
|
||||
&mut self.device,
|
||||
&mut contexts,
|
||||
context_id,
|
||||
layer_init,
|
||||
);
|
||||
let _ = sender.send(result);
|
||||
},
|
||||
WebXRCommand::DestroyLayer(manager_id, context_id, layer_id) => {
|
||||
self.webxr_bridge.destroy_layer(
|
||||
manager_id,
|
||||
&mut self.device,
|
||||
&mut contexts,
|
||||
context_id,
|
||||
layer_id,
|
||||
);
|
||||
},
|
||||
WebXRCommand::BeginFrame(manager_id, layers, sender) => {
|
||||
let result = self.webxr_bridge.begin_frame(
|
||||
manager_id,
|
||||
&mut self.device,
|
||||
&mut contexts,
|
||||
&layers[..],
|
||||
);
|
||||
let _ = sender.send(result);
|
||||
},
|
||||
WebXRCommand::EndFrame(manager_id, layers, sender) => {
|
||||
let result = self.webxr_bridge.end_frame(
|
||||
manager_id,
|
||||
&mut self.device,
|
||||
&mut contexts,
|
||||
&layers[..],
|
||||
);
|
||||
let _ = sender.send(result);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles a WebGLCommand for a specific WebGLContext
|
||||
fn handle_webgl_command(
|
||||
&mut self,
|
||||
|
@ -457,36 +494,7 @@ impl WebGLThread {
|
|||
&mut self.contexts,
|
||||
&mut self.bound_context_id,
|
||||
);
|
||||
|
||||
if let Some(data) = data {
|
||||
match command {
|
||||
// We have to handle framebuffer binding differently, because `apply`
|
||||
// assumes that the currently attached surface is the right one for binding
|
||||
// the framebuffer, and since it doesn't get passed the swap buffers
|
||||
// it casn't do that itself. At some point we could refactor apply so
|
||||
// it takes a self parameter, at which point that won't be necessary.
|
||||
WebGLCommand::BindFramebuffer(_, request) => {
|
||||
WebGLImpl::attach_surface(
|
||||
context_id,
|
||||
&self.webrender_swap_chains,
|
||||
&self.webxr_swap_chains,
|
||||
request,
|
||||
&mut data.ctx,
|
||||
&mut self.device,
|
||||
);
|
||||
},
|
||||
// Similarly, dropping a WebGL framebuffer needs access to the swap chains,
|
||||
// in order to delete the entry.
|
||||
WebGLCommand::DeleteFramebuffer(WebGLFramebufferId::Opaque(
|
||||
WebGLOpaqueFramebufferId::WebXR(id),
|
||||
)) => {
|
||||
let _ = self
|
||||
.webxr_swap_chains
|
||||
.destroy(id, &mut self.device, &mut data.ctx);
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
|
||||
WebGLImpl::apply(
|
||||
&self.device,
|
||||
&data.ctx,
|
||||
|
@ -545,11 +553,10 @@ impl WebGLThread {
|
|||
size: safe_size.to_i32(),
|
||||
};
|
||||
let surface_access = self.surface_access();
|
||||
let surface_provider = Box::new(SurfmanProvider::new(surface_access));
|
||||
|
||||
let mut ctx = self
|
||||
.device
|
||||
.create_context(&context_descriptor)
|
||||
.create_context(&context_descriptor, None)
|
||||
.map_err(|err| format!("Failed to create the GL context: {:?}", err))?;
|
||||
let surface = self
|
||||
.device
|
||||
|
@ -572,7 +579,7 @@ impl WebGLThread {
|
|||
);
|
||||
|
||||
self.webrender_swap_chains
|
||||
.create_attached_swap_chain(id, &mut self.device, &mut ctx, surface_provider)
|
||||
.create_attached_swap_chain(id, &mut self.device, &mut ctx, surface_access)
|
||||
.map_err(|err| format!("Failed to create swap chain: {:?}", err))?;
|
||||
|
||||
let swap_chain = self
|
||||
|
@ -766,9 +773,11 @@ impl WebGLThread {
|
|||
self.webrender_swap_chains
|
||||
.destroy(context_id, &mut self.device, &mut data.ctx)
|
||||
.unwrap();
|
||||
self.webxr_swap_chains
|
||||
.destroy_all(&mut self.device, &mut data.ctx)
|
||||
.unwrap();
|
||||
|
||||
// Destroy WebXR layers associated with this context
|
||||
let webxr_context_id = WebXRContextId::from(context_id);
|
||||
self.webxr_bridge
|
||||
.destroy_all_layers(&mut self.device, &mut data.ctx, webxr_context_id);
|
||||
|
||||
// Destroy the context
|
||||
self.device.destroy_context(&mut data.ctx).unwrap();
|
||||
|
@ -779,21 +788,12 @@ impl WebGLThread {
|
|||
|
||||
fn handle_swap_buffers(
|
||||
&mut self,
|
||||
swap_ids: Vec<SwapChainId>,
|
||||
context_ids: Vec<WebGLContextId>,
|
||||
completed_sender: WebGLSender<u64>,
|
||||
_sent_time: u64,
|
||||
) {
|
||||
#[cfg(feature = "xr-profile")]
|
||||
let start_swap = time::precise_time_ns();
|
||||
#[cfg(feature = "xr-profile")]
|
||||
println!(
|
||||
"WEBXR PROFILING [swap request]:\t{}ms",
|
||||
to_ms(start_swap - _sent_time)
|
||||
);
|
||||
debug!("handle_swap_buffers()");
|
||||
for swap_id in swap_ids {
|
||||
let context_id = swap_id.context_id();
|
||||
|
||||
for context_id in context_ids {
|
||||
let data = Self::make_current_if_needed_mut(
|
||||
&self.device,
|
||||
context_id,
|
||||
|
@ -811,16 +811,13 @@ impl WebGLThread {
|
|||
FramebufferRebindingInfo::detect(&self.device, &data.ctx, &*data.gl);
|
||||
debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR);
|
||||
|
||||
debug!("Getting swap chain for {:?}", swap_id);
|
||||
let swap_chain = match swap_id {
|
||||
SwapChainId::Context(id) => self.webrender_swap_chains.get(id),
|
||||
SwapChainId::Framebuffer(_, WebGLOpaqueFramebufferId::WebXR(id)) => {
|
||||
self.webxr_swap_chains.get(id)
|
||||
},
|
||||
}
|
||||
.expect("Where's the swap chain?");
|
||||
debug!("Getting swap chain for {:?}", context_id);
|
||||
let swap_chain = self
|
||||
.webrender_swap_chains
|
||||
.get(context_id)
|
||||
.expect("Where's the swap chain?");
|
||||
|
||||
debug!("Swapping {:?}", swap_id);
|
||||
debug!("Swapping {:?}", context_id);
|
||||
swap_chain
|
||||
.swap_buffers(&mut self.device, &mut data.ctx)
|
||||
.unwrap();
|
||||
|
@ -828,7 +825,7 @@ impl WebGLThread {
|
|||
|
||||
// TODO: if preserveDrawingBuffer is true, then blit the front buffer to the back buffer
|
||||
// https://github.com/servo/servo/issues/24604
|
||||
debug!("Clearing {:?}", swap_id);
|
||||
debug!("Clearing {:?}", context_id);
|
||||
let alpha = data
|
||||
.state
|
||||
.requested_flags
|
||||
|
@ -840,7 +837,7 @@ impl WebGLThread {
|
|||
debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR);
|
||||
|
||||
// Rebind framebuffers as appropriate.
|
||||
debug!("Rebinding {:?}", swap_id);
|
||||
debug!("Rebinding {:?}", context_id);
|
||||
framebuffer_rebinding_info.apply(&self.device, &data.ctx, &*data.gl);
|
||||
debug_assert_eq!(data.gl.get_error(), gl::NO_ERROR);
|
||||
|
||||
|
@ -872,36 +869,6 @@ impl WebGLThread {
|
|||
completed_sender.send(end_swap).unwrap();
|
||||
}
|
||||
|
||||
/// Creates a new WebXR swap chain
|
||||
#[allow(unsafe_code)]
|
||||
fn create_webxr_swap_chain(
|
||||
&mut self,
|
||||
context_id: WebGLContextId,
|
||||
size: Size2D<i32>,
|
||||
session_id: SessionId,
|
||||
) -> Option<WebXRSwapChainId> {
|
||||
debug!("WebGLThread::create_webxr_swap_chain()");
|
||||
let id = WebXRSwapChainId::new();
|
||||
let surface_access = self.surface_access();
|
||||
let data = Self::make_current_if_needed_mut(
|
||||
&self.device,
|
||||
context_id,
|
||||
&mut self.contexts,
|
||||
&mut self.bound_context_id,
|
||||
)?;
|
||||
let surface_provider = self
|
||||
.webxr_surface_providers
|
||||
.lock()
|
||||
.unwrap()
|
||||
.remove(&session_id)
|
||||
.unwrap_or_else(|| Box::new(SurfmanProvider::new(surface_access)));
|
||||
self.webxr_swap_chains
|
||||
.create_detached_swap_chain(id, size, &mut self.device, &mut data.ctx, surface_provider)
|
||||
.ok()?;
|
||||
debug!("Created swap chain {:?}", id);
|
||||
Some(id)
|
||||
}
|
||||
|
||||
/// Which access mode to use
|
||||
fn surface_access(&self) -> SurfaceAccess {
|
||||
SurfaceAccess::GPUOnly
|
||||
|
@ -1459,10 +1426,7 @@ impl WebGLImpl {
|
|||
Self::create_shader(gl, shader_type, chan)
|
||||
},
|
||||
WebGLCommand::DeleteBuffer(id) => gl.delete_buffers(&[id.get()]),
|
||||
WebGLCommand::DeleteFramebuffer(WebGLFramebufferId::Transparent(id)) => {
|
||||
gl.delete_framebuffers(&[id.get()])
|
||||
},
|
||||
WebGLCommand::DeleteFramebuffer(WebGLFramebufferId::Opaque(_)) => {},
|
||||
WebGLCommand::DeleteFramebuffer(id) => gl.delete_framebuffers(&[id.get()]),
|
||||
WebGLCommand::DeleteRenderbuffer(id) => gl.delete_renderbuffers(&[id.get()]),
|
||||
WebGLCommand::DeleteTexture(id) => gl.delete_textures(&[id.get()]),
|
||||
WebGLCommand::DeleteProgram(id) => gl.delete_program(id.get()),
|
||||
|
@ -2498,12 +2462,12 @@ impl WebGLImpl {
|
|||
}
|
||||
|
||||
#[allow(unsafe_code)]
|
||||
fn create_framebuffer(gl: &Gl, chan: &WebGLSender<Option<WebGLTransparentFramebufferId>>) {
|
||||
fn create_framebuffer(gl: &Gl, chan: &WebGLSender<Option<WebGLFramebufferId>>) {
|
||||
let framebuffer = gl.gen_framebuffers(1)[0];
|
||||
let framebuffer = if framebuffer == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { WebGLTransparentFramebufferId::new(framebuffer) })
|
||||
Some(unsafe { WebGLFramebufferId::new(framebuffer) })
|
||||
};
|
||||
chan.send(framebuffer).unwrap();
|
||||
}
|
||||
|
@ -2611,54 +2575,6 @@ impl WebGLImpl {
|
|||
debug_assert_eq!(gl.get_error(), gl::NO_ERROR);
|
||||
}
|
||||
|
||||
/// Updates the swap buffers if the context surface needs to be changed
|
||||
fn attach_surface(
|
||||
context_id: WebGLContextId,
|
||||
webrender_swap_chains: &SwapChains<WebGLContextId, Device>,
|
||||
webxr_swap_chains: &SwapChains<WebXRSwapChainId, Device>,
|
||||
request: WebGLFramebufferBindingRequest,
|
||||
ctx: &mut Context,
|
||||
device: &mut Device,
|
||||
) -> Option<()> {
|
||||
debug!(
|
||||
"WebGLImpl::attach_surface({:?} in {:?})",
|
||||
request, context_id
|
||||
);
|
||||
let requested_framebuffer = match request {
|
||||
WebGLFramebufferBindingRequest::Explicit(WebGLFramebufferId::Opaque(id)) => Some(id),
|
||||
WebGLFramebufferBindingRequest::Explicit(WebGLFramebufferId::Transparent(_)) => {
|
||||
return None
|
||||
},
|
||||
WebGLFramebufferBindingRequest::Default => None,
|
||||
};
|
||||
let attached_framebuffer = webxr_swap_chains
|
||||
.iter(device, ctx)
|
||||
.filter_map(|(id, swap_chain)| {
|
||||
if swap_chain.is_attached() {
|
||||
Some(id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.map(WebGLOpaqueFramebufferId::WebXR)
|
||||
.next();
|
||||
if requested_framebuffer == attached_framebuffer {
|
||||
return None;
|
||||
}
|
||||
let requested_swap_chain = match requested_framebuffer {
|
||||
Some(WebGLOpaqueFramebufferId::WebXR(id)) => webxr_swap_chains.get(id)?,
|
||||
None => webrender_swap_chains.get(context_id)?,
|
||||
};
|
||||
let current_swap_chain = match attached_framebuffer {
|
||||
Some(WebGLOpaqueFramebufferId::WebXR(id)) => webxr_swap_chains.get(id)?,
|
||||
None => webrender_swap_chains.get(context_id)?,
|
||||
};
|
||||
requested_swap_chain
|
||||
.take_attachment_from(device, ctx, ¤t_swap_chain)
|
||||
.unwrap();
|
||||
Some(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn bind_framebuffer(
|
||||
gl: &Gl,
|
||||
|
@ -2669,10 +2585,7 @@ impl WebGLImpl {
|
|||
state: &mut GLState,
|
||||
) {
|
||||
let id = match request {
|
||||
WebGLFramebufferBindingRequest::Explicit(WebGLFramebufferId::Transparent(id)) => {
|
||||
id.get()
|
||||
},
|
||||
WebGLFramebufferBindingRequest::Explicit(WebGLFramebufferId::Opaque(_)) |
|
||||
WebGLFramebufferBindingRequest::Explicit(id) => id.get(),
|
||||
WebGLFramebufferBindingRequest::Default => {
|
||||
device
|
||||
.context_surface_info(ctx)
|
||||
|
@ -3223,3 +3136,317 @@ impl FramebufferRebindingInfo {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Bridge between WebGL and WebXR
|
||||
pub(crate) struct WebXRBridge {
|
||||
factory_receiver: crossbeam_channel::Receiver<WebXRLayerManagerFactory<WebXRSurfman>>,
|
||||
managers: HashMap<WebXRLayerManagerId, Box<dyn WebXRLayerManagerAPI<WebXRSurfman>>>,
|
||||
next_manager_id: u32,
|
||||
}
|
||||
|
||||
impl WebXRBridge {
|
||||
pub(crate) fn new(init: WebXRBridgeInit) -> WebXRBridge {
|
||||
let WebXRBridgeInit {
|
||||
factory_receiver, ..
|
||||
} = init;
|
||||
let managers = HashMap::new();
|
||||
let next_manager_id = 1;
|
||||
WebXRBridge {
|
||||
factory_receiver,
|
||||
managers,
|
||||
next_manager_id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl WebXRBridge {
|
||||
#[allow(unsafe_code)]
|
||||
fn create_layer_manager(
|
||||
&mut self,
|
||||
device: &mut Device,
|
||||
contexts: &mut dyn WebXRContexts<WebXRSurfman>,
|
||||
) -> Result<WebXRLayerManagerId, WebXRError> {
|
||||
let factory = self
|
||||
.factory_receiver
|
||||
.recv()
|
||||
.map_err(|_| WebXRError::CommunicationError)?;
|
||||
let manager = factory.build(device, contexts)?;
|
||||
let manager_id = unsafe { WebXRLayerManagerId::new(self.next_manager_id) };
|
||||
self.next_manager_id = self.next_manager_id + 1;
|
||||
self.managers.insert(manager_id, manager);
|
||||
Ok(manager_id)
|
||||
}
|
||||
|
||||
fn destroy_layer_manager(&mut self, manager_id: WebXRLayerManagerId) {
|
||||
self.managers.remove(&manager_id);
|
||||
}
|
||||
|
||||
fn create_layer(
|
||||
&mut self,
|
||||
manager_id: WebXRLayerManagerId,
|
||||
device: &mut Device,
|
||||
contexts: &mut dyn WebXRContexts<WebXRSurfman>,
|
||||
context_id: WebXRContextId,
|
||||
layer_init: WebXRLayerInit,
|
||||
) -> Result<WebXRLayerId, WebXRError> {
|
||||
let manager = self
|
||||
.managers
|
||||
.get_mut(&manager_id)
|
||||
.ok_or(WebXRError::NoMatchingDevice)?;
|
||||
let context = contexts
|
||||
.context(device, context_id)
|
||||
.ok_or(WebXRError::NoMatchingDevice)?;
|
||||
manager.create_layer(device, context, context_id, layer_init)
|
||||
}
|
||||
|
||||
fn destroy_layer(
|
||||
&mut self,
|
||||
manager_id: WebXRLayerManagerId,
|
||||
device: &mut Device,
|
||||
contexts: &mut dyn WebXRContexts<WebXRSurfman>,
|
||||
context_id: WebXRContextId,
|
||||
layer_id: WebXRLayerId,
|
||||
) {
|
||||
if let Some(manager) = self.managers.get_mut(&manager_id) {
|
||||
if let Some(context) = contexts.context(device, context_id) {
|
||||
manager.destroy_layer(device, context, context_id, layer_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn destroy_all_layers(
|
||||
&mut self,
|
||||
device: &mut Device,
|
||||
context: &mut Context,
|
||||
context_id: WebXRContextId,
|
||||
) {
|
||||
for (_, manager) in &mut self.managers {
|
||||
for (other_id, layer_id) in manager.layers().to_vec() {
|
||||
if other_id == context_id {
|
||||
manager.destroy_layer(device, context, context_id, layer_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn begin_frame(
|
||||
&mut self,
|
||||
manager_id: WebXRLayerManagerId,
|
||||
device: &mut Device,
|
||||
contexts: &mut dyn WebXRContexts<WebXRSurfman>,
|
||||
layers: &[(WebXRContextId, WebXRLayerId)],
|
||||
) -> Result<Vec<WebXRSubImages>, WebXRError> {
|
||||
let manager = self
|
||||
.managers
|
||||
.get_mut(&manager_id)
|
||||
.ok_or(WebXRError::NoMatchingDevice)?;
|
||||
manager.begin_frame(device, contexts, layers)
|
||||
}
|
||||
|
||||
fn end_frame(
|
||||
&mut self,
|
||||
manager_id: WebXRLayerManagerId,
|
||||
device: &mut Device,
|
||||
contexts: &mut dyn WebXRContexts<WebXRSurfman>,
|
||||
layers: &[(WebXRContextId, WebXRLayerId)],
|
||||
) -> Result<(), WebXRError> {
|
||||
let manager = self
|
||||
.managers
|
||||
.get_mut(&manager_id)
|
||||
.ok_or(WebXRError::NoMatchingDevice)?;
|
||||
manager.end_frame(device, contexts, layers)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct WebXRBridgeInit {
|
||||
sender: WebGLSender<WebGLMsg>,
|
||||
factory_receiver: crossbeam_channel::Receiver<WebXRLayerManagerFactory<WebXRSurfman>>,
|
||||
factory_sender: crossbeam_channel::Sender<WebXRLayerManagerFactory<WebXRSurfman>>,
|
||||
}
|
||||
|
||||
impl WebXRBridgeInit {
|
||||
pub(crate) fn new(sender: WebGLSender<WebGLMsg>) -> WebXRBridgeInit {
|
||||
let (factory_sender, factory_receiver) = crossbeam_channel::unbounded();
|
||||
WebXRBridgeInit {
|
||||
sender,
|
||||
factory_sender,
|
||||
factory_receiver,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn layer_grand_manager(&self) -> WebXRLayerGrandManager<WebXRSurfman> {
|
||||
WebXRLayerGrandManager::new(WebXRBridgeGrandManager {
|
||||
sender: self.sender.clone(),
|
||||
factory_sender: self.factory_sender.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct WebXRBridgeGrandManager {
|
||||
sender: WebGLSender<WebGLMsg>,
|
||||
// WebXR layer manager factories use generic trait objects under the
|
||||
// hood, which aren't deserializable (even using typetag)
|
||||
// so we can't send them over the regular webgl channel.
|
||||
// Fortunately, the webgl thread runs in the same process as
|
||||
// the webxr threads, so we can use a crossbeam channel to send
|
||||
// factories.
|
||||
factory_sender: crossbeam_channel::Sender<WebXRLayerManagerFactory<WebXRSurfman>>,
|
||||
}
|
||||
|
||||
impl WebXRLayerGrandManagerAPI<WebXRSurfman> for WebXRBridgeGrandManager {
|
||||
fn create_layer_manager(
|
||||
&self,
|
||||
factory: WebXRLayerManagerFactory<WebXRSurfman>,
|
||||
) -> Result<WebXRLayerManager, WebXRError> {
|
||||
let (sender, receiver) = webgl_channel().map_err(|_| WebXRError::CommunicationError)?;
|
||||
let _ = self.factory_sender.send(factory);
|
||||
let _ = self
|
||||
.sender
|
||||
.send(WebGLMsg::WebXRCommand(WebXRCommand::CreateLayerManager(
|
||||
sender,
|
||||
)));
|
||||
let sender = self.sender.clone();
|
||||
let manager_id = receiver
|
||||
.recv()
|
||||
.map_err(|_| WebXRError::CommunicationError)??;
|
||||
let layers = Vec::new();
|
||||
Ok(WebXRLayerManager::new(WebXRBridgeManager {
|
||||
manager_id,
|
||||
sender,
|
||||
layers,
|
||||
}))
|
||||
}
|
||||
|
||||
fn clone_layer_grand_manager(&self) -> WebXRLayerGrandManager<WebXRSurfman> {
|
||||
WebXRLayerGrandManager::new(WebXRBridgeGrandManager {
|
||||
sender: self.sender.clone(),
|
||||
factory_sender: self.factory_sender.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
struct WebXRBridgeManager {
|
||||
sender: WebGLSender<WebGLMsg>,
|
||||
manager_id: WebXRLayerManagerId,
|
||||
layers: Vec<(WebXRContextId, WebXRLayerId)>,
|
||||
}
|
||||
|
||||
impl<GL: WebXRTypes> WebXRLayerManagerAPI<GL> for WebXRBridgeManager {
|
||||
fn create_layer(
|
||||
&mut self,
|
||||
_: &mut GL::Device,
|
||||
_: &mut GL::Context,
|
||||
context_id: WebXRContextId,
|
||||
init: WebXRLayerInit,
|
||||
) -> Result<WebXRLayerId, WebXRError> {
|
||||
let (sender, receiver) = webgl_channel().map_err(|_| WebXRError::CommunicationError)?;
|
||||
let _ = self
|
||||
.sender
|
||||
.send(WebGLMsg::WebXRCommand(WebXRCommand::CreateLayer(
|
||||
self.manager_id,
|
||||
context_id,
|
||||
init,
|
||||
sender,
|
||||
)));
|
||||
let layer_id = receiver
|
||||
.recv()
|
||||
.map_err(|_| WebXRError::CommunicationError)??;
|
||||
self.layers.push((context_id, layer_id));
|
||||
Ok(layer_id)
|
||||
}
|
||||
|
||||
fn destroy_layer(
|
||||
&mut self,
|
||||
_: &mut GL::Device,
|
||||
_: &mut GL::Context,
|
||||
context_id: WebXRContextId,
|
||||
layer_id: WebXRLayerId,
|
||||
) {
|
||||
self.layers.retain(|&ids| ids != (context_id, layer_id));
|
||||
let _ = self
|
||||
.sender
|
||||
.send(WebGLMsg::WebXRCommand(WebXRCommand::DestroyLayer(
|
||||
self.manager_id,
|
||||
context_id,
|
||||
layer_id,
|
||||
)));
|
||||
}
|
||||
|
||||
fn layers(&self) -> &[(WebXRContextId, WebXRLayerId)] {
|
||||
&self.layers[..]
|
||||
}
|
||||
|
||||
fn begin_frame(
|
||||
&mut self,
|
||||
_: &mut GL::Device,
|
||||
_: &mut dyn WebXRContexts<GL>,
|
||||
layers: &[(WebXRContextId, WebXRLayerId)],
|
||||
) -> Result<Vec<WebXRSubImages>, WebXRError> {
|
||||
let (sender, receiver) = webgl_channel().map_err(|_| WebXRError::CommunicationError)?;
|
||||
let _ = self
|
||||
.sender
|
||||
.send(WebGLMsg::WebXRCommand(WebXRCommand::BeginFrame(
|
||||
self.manager_id,
|
||||
layers.to_vec(),
|
||||
sender,
|
||||
)));
|
||||
receiver
|
||||
.recv()
|
||||
.map_err(|_| WebXRError::CommunicationError)?
|
||||
}
|
||||
|
||||
fn end_frame(
|
||||
&mut self,
|
||||
_: &mut GL::Device,
|
||||
_: &mut dyn WebXRContexts<GL>,
|
||||
layers: &[(WebXRContextId, WebXRLayerId)],
|
||||
) -> Result<(), WebXRError> {
|
||||
let (sender, receiver) = webgl_channel().map_err(|_| WebXRError::CommunicationError)?;
|
||||
let _ = self
|
||||
.sender
|
||||
.send(WebGLMsg::WebXRCommand(WebXRCommand::EndFrame(
|
||||
self.manager_id,
|
||||
layers.to_vec(),
|
||||
sender,
|
||||
)));
|
||||
receiver
|
||||
.recv()
|
||||
.map_err(|_| WebXRError::CommunicationError)?
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WebXRBridgeManager {
|
||||
fn drop(&mut self) {
|
||||
let _ = self
|
||||
.sender
|
||||
.send(WebGLMsg::WebXRCommand(WebXRCommand::DestroyLayerManager(
|
||||
self.manager_id,
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
struct WebXRBridgeContexts<'a> {
|
||||
contexts: &'a mut FnvHashMap<WebGLContextId, GLContextData>,
|
||||
bound_context_id: &'a mut Option<WebGLContextId>,
|
||||
}
|
||||
|
||||
impl<'a> WebXRContexts<WebXRSurfman> for WebXRBridgeContexts<'a> {
|
||||
fn context(&mut self, device: &Device, context_id: WebXRContextId) -> Option<&mut Context> {
|
||||
let data = WebGLThread::make_current_if_needed_mut(
|
||||
device,
|
||||
WebGLContextId::from(context_id),
|
||||
&mut self.contexts,
|
||||
&mut self.bound_context_id,
|
||||
)?;
|
||||
Some(&mut data.ctx)
|
||||
}
|
||||
fn bindings(&mut self, device: &Device, context_id: WebXRContextId) -> Option<&Gl> {
|
||||
let data = WebGLThread::make_current_if_needed(
|
||||
device,
|
||||
WebGLContextId::from(context_id),
|
||||
&self.contexts,
|
||||
&mut self.bound_context_id,
|
||||
)?;
|
||||
Some(&data.gl)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,8 +12,11 @@ use std::fmt;
|
|||
use std::num::{NonZeroU32, NonZeroU64};
|
||||
use std::ops::Deref;
|
||||
use webrender_api::{DocumentId, ImageKey, PipelineId};
|
||||
use webxr_api::SessionId;
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
use webxr_api::ContextId as WebXRContextId;
|
||||
use webxr_api::Error as WebXRError;
|
||||
use webxr_api::LayerId as WebXRLayerId;
|
||||
use webxr_api::LayerInit as WebXRLayerInit;
|
||||
use webxr_api::SubImages as WebXRSubImages;
|
||||
|
||||
/// Helper function that creates a WebGL channel (WebGLSender, WebGLReceiver) to be used in WebGLCommands.
|
||||
pub use crate::webgl_channel::webgl_channel;
|
||||
|
@ -70,21 +73,17 @@ pub enum WebGLMsg {
|
|||
RemoveContext(WebGLContextId),
|
||||
/// Runs a WebGLCommand in a specific WebGLContext.
|
||||
WebGLCommand(WebGLContextId, WebGLCommand, WebGLCommandBacktrace),
|
||||
/// Runs a WebXRCommand (WebXR layers need to be created in the WebGL
|
||||
/// thread, as they may have thread affinity).
|
||||
WebXRCommand(WebXRCommand),
|
||||
/// Commands used for the DOMToTexture feature.
|
||||
DOMToTextureCommand(DOMToTextureCommand),
|
||||
/// Creates a new opaque framebuffer for WebXR.
|
||||
CreateWebXRSwapChain(
|
||||
WebGLContextId,
|
||||
Size2D<i32>,
|
||||
WebGLSender<Option<WebXRSwapChainId>>,
|
||||
SessionId,
|
||||
),
|
||||
/// Performs a buffer swap.
|
||||
///
|
||||
/// The third field contains the time (in ns) when the request
|
||||
/// was initiated. The u64 in the second field will be the time the
|
||||
/// request is fulfilled
|
||||
SwapBuffers(Vec<SwapChainId>, WebGLSender<u64>, u64),
|
||||
SwapBuffers(Vec<WebGLContextId>, WebGLSender<u64>, u64),
|
||||
/// Frees all resources and closes the thread.
|
||||
Exit,
|
||||
}
|
||||
|
@ -176,47 +175,6 @@ impl WebGLMsgSender {
|
|||
self.sender.send(WebGLMsg::RemoveContext(self.ctx_id))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn send_create_webxr_swap_chain(
|
||||
&self,
|
||||
size: Size2D<i32>,
|
||||
sender: WebGLSender<Option<WebXRSwapChainId>>,
|
||||
id: SessionId,
|
||||
) -> WebGLSendResult {
|
||||
self.sender.send(WebGLMsg::CreateWebXRSwapChain(
|
||||
self.ctx_id,
|
||||
size,
|
||||
sender,
|
||||
id,
|
||||
))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn send_swap_buffers(&self, id: Option<WebGLOpaqueFramebufferId>) -> WebGLSendResult {
|
||||
let swap_id = id
|
||||
.map(|id| SwapChainId::Framebuffer(self.ctx_id, id))
|
||||
.unwrap_or_else(|| SwapChainId::Context(self.ctx_id));
|
||||
let (sender, receiver) = webgl_channel()?;
|
||||
#[allow(unused)]
|
||||
let mut time = 0;
|
||||
#[cfg(feature = "xr-profile")]
|
||||
{
|
||||
time = time::precise_time_ns();
|
||||
}
|
||||
|
||||
self.sender
|
||||
.send(WebGLMsg::SwapBuffers(vec![swap_id], sender, time))?;
|
||||
|
||||
#[allow(unused)]
|
||||
let sent_time = receiver.recv()?;
|
||||
#[cfg(feature = "xr-profile")]
|
||||
println!(
|
||||
"WEBXR PROFILING [swap complete]:\t{}ms",
|
||||
(time::precise_time_ns() - sent_time) as f64 / 1_000_000.
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn send_dom_to_texture(&self, command: DOMToTextureCommand) -> WebGLSendResult {
|
||||
self.sender.send(WebGLMsg::DOMToTextureCommand(command))
|
||||
}
|
||||
|
@ -282,7 +240,7 @@ pub enum WebGLCommand {
|
|||
CopyTexImage2D(u32, i32, u32, i32, i32, i32, i32, i32),
|
||||
CopyTexSubImage2D(u32, i32, i32, i32, i32, i32, i32, i32),
|
||||
CreateBuffer(WebGLSender<Option<WebGLBufferId>>),
|
||||
CreateFramebuffer(WebGLSender<Option<WebGLTransparentFramebufferId>>),
|
||||
CreateFramebuffer(WebGLSender<Option<WebGLFramebufferId>>),
|
||||
CreateRenderbuffer(WebGLSender<Option<WebGLRenderbufferId>>),
|
||||
CreateTexture(WebGLSender<Option<WebGLTextureId>>),
|
||||
CreateProgram(WebGLSender<Option<WebGLProgramId>>),
|
||||
|
@ -555,6 +513,30 @@ pub enum WebGLCommand {
|
|||
DrawBuffers(Vec<u32>),
|
||||
}
|
||||
|
||||
/// WebXR layer management
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
pub enum WebXRCommand {
|
||||
CreateLayerManager(WebGLSender<Result<WebXRLayerManagerId, WebXRError>>),
|
||||
DestroyLayerManager(WebXRLayerManagerId),
|
||||
CreateLayer(
|
||||
WebXRLayerManagerId,
|
||||
WebXRContextId,
|
||||
WebXRLayerInit,
|
||||
WebGLSender<Result<WebXRLayerId, WebXRError>>,
|
||||
),
|
||||
DestroyLayer(WebXRLayerManagerId, WebXRContextId, WebXRLayerId),
|
||||
BeginFrame(
|
||||
WebXRLayerManagerId,
|
||||
Vec<(WebXRContextId, WebXRLayerId)>,
|
||||
WebGLSender<Result<Vec<WebXRSubImages>, WebXRError>>,
|
||||
),
|
||||
EndFrame(
|
||||
WebXRLayerManagerId,
|
||||
Vec<(WebXRContextId, WebXRLayerId)>,
|
||||
WebGLSender<Result<(), WebXRError>>,
|
||||
),
|
||||
}
|
||||
|
||||
macro_rules! nonzero_type {
|
||||
(u32) => {
|
||||
NonZeroU32
|
||||
|
@ -576,6 +558,11 @@ macro_rules! define_resource_id {
|
|||
$name(<nonzero_type!($type)>::new_unchecked(id))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn maybe_new(id: $type) -> Option<Self> {
|
||||
<nonzero_type!($type)>::new(id).map($name)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get(self) -> $type {
|
||||
self.0.get()
|
||||
|
@ -629,7 +616,7 @@ macro_rules! define_resource_id {
|
|||
}
|
||||
|
||||
define_resource_id!(WebGLBufferId, u32);
|
||||
define_resource_id!(WebGLTransparentFramebufferId, u32);
|
||||
define_resource_id!(WebGLFramebufferId, u32);
|
||||
define_resource_id!(WebGLRenderbufferId, u32);
|
||||
define_resource_id!(WebGLTextureId, u32);
|
||||
define_resource_id!(WebGLProgramId, u32);
|
||||
|
@ -638,24 +625,22 @@ define_resource_id!(WebGLSamplerId, u32);
|
|||
define_resource_id!(WebGLShaderId, u32);
|
||||
define_resource_id!(WebGLSyncId, u64);
|
||||
define_resource_id!(WebGLVertexArrayId, u32);
|
||||
define_resource_id!(WebXRLayerManagerId, u32);
|
||||
|
||||
#[derive(
|
||||
Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, Ord, PartialEq, PartialOrd, Serialize,
|
||||
)]
|
||||
pub struct WebGLContextId(pub u64);
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
pub enum SwapChainId {
|
||||
Context(WebGLContextId),
|
||||
Framebuffer(WebGLContextId, WebGLOpaqueFramebufferId),
|
||||
impl From<WebXRContextId> for WebGLContextId {
|
||||
fn from(id: WebXRContextId) -> Self {
|
||||
Self(id.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl SwapChainId {
|
||||
pub fn context_id(&self) -> WebGLContextId {
|
||||
match *self {
|
||||
SwapChainId::Context(id) => id,
|
||||
SwapChainId::Framebuffer(id, _) => id,
|
||||
}
|
||||
impl From<WebGLContextId> for WebXRContextId {
|
||||
fn from(id: WebGLContextId) -> Self {
|
||||
Self(id.0)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -669,18 +654,6 @@ pub enum WebGLError {
|
|||
ContextLost,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum WebGLOpaqueFramebufferId {
|
||||
// At the moment the only source of opaque framebuffers is webxr
|
||||
WebXR(#[ignore_malloc_size_of = "ids don't malloc"] WebXRSwapChainId),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
|
||||
pub enum WebGLFramebufferId {
|
||||
Transparent(WebGLTransparentFramebufferId),
|
||||
Opaque(WebGLOpaqueFramebufferId),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
|
||||
pub enum WebGLFramebufferBindingRequest {
|
||||
Explicit(WebGLFramebufferId),
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
//! Abstract windowing methods. The concrete implementations of these can be found in `platform/`.
|
||||
|
||||
use canvas::{SurfaceProviders, WebGlExecutor};
|
||||
use embedder_traits::{EmbedderProxy, EventLoopWaker};
|
||||
use euclid::Scale;
|
||||
use keyboard_types::KeyboardEvent;
|
||||
|
@ -171,14 +170,7 @@ pub trait EmbedderMethods {
|
|||
fn create_event_loop_waker(&mut self) -> Box<dyn EventLoopWaker>;
|
||||
|
||||
/// Register services with a WebXR Registry.
|
||||
fn register_webxr(
|
||||
&mut self,
|
||||
_: &mut webxr::MainThreadRegistry,
|
||||
_: WebGlExecutor,
|
||||
_: SurfaceProviders,
|
||||
_: EmbedderProxy,
|
||||
) {
|
||||
}
|
||||
fn register_webxr(&mut self, _: &mut webxr::MainThreadRegistry, _: EmbedderProxy) {}
|
||||
|
||||
/// Returns the user agent string to report in network requests.
|
||||
fn get_user_agent_string(&self) -> Option<String> {
|
||||
|
|
|
@ -60,7 +60,6 @@ use canvas_traits::webgl::{
|
|||
use canvas_traits::webgl::{GLLimits, WebGLQueryId, WebGLSamplerId};
|
||||
use canvas_traits::webgl::{WebGLBufferId, WebGLChan, WebGLContextId, WebGLError};
|
||||
use canvas_traits::webgl::{WebGLFramebufferId, WebGLMsgSender, WebGLPipeline, WebGLProgramId};
|
||||
use canvas_traits::webgl::{WebGLOpaqueFramebufferId, WebGLTransparentFramebufferId};
|
||||
use canvas_traits::webgl::{WebGLReceiver, WebGLRenderbufferId, WebGLSLVersion, WebGLSender};
|
||||
use canvas_traits::webgl::{WebGLShaderId, WebGLSyncId, WebGLTextureId, WebGLVersion};
|
||||
use content_security_policy::CspList;
|
||||
|
@ -172,7 +171,6 @@ use webgpu::{
|
|||
WebGPUTexture, WebGPUTextureView,
|
||||
};
|
||||
use webrender_api::{DocumentId, ExternalImageId, ImageKey};
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
use webxr_api::{Finger, Hand, Ray, View};
|
||||
|
||||
unsafe_no_jsmanaged_fields!(Tm);
|
||||
|
@ -550,8 +548,6 @@ unsafe_no_jsmanaged_fields!(ExternalImageId);
|
|||
unsafe_no_jsmanaged_fields!(WebGLBufferId);
|
||||
unsafe_no_jsmanaged_fields!(WebGLChan);
|
||||
unsafe_no_jsmanaged_fields!(WebGLFramebufferId);
|
||||
unsafe_no_jsmanaged_fields!(WebGLOpaqueFramebufferId);
|
||||
unsafe_no_jsmanaged_fields!(WebGLTransparentFramebufferId);
|
||||
unsafe_no_jsmanaged_fields!(WebGLMsgSender);
|
||||
unsafe_no_jsmanaged_fields!(WebGLPipeline);
|
||||
unsafe_no_jsmanaged_fields!(WebGLProgramId);
|
||||
|
@ -587,12 +583,12 @@ unsafe_no_jsmanaged_fields!(Option<ComputePass>);
|
|||
unsafe_no_jsmanaged_fields!(GPUBufferState);
|
||||
unsafe_no_jsmanaged_fields!(GPUCommandEncoderState);
|
||||
unsafe_no_jsmanaged_fields!(Range<u64>);
|
||||
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
|
||||
unsafe_no_jsmanaged_fields!(MediaList);
|
||||
unsafe_no_jsmanaged_fields!(
|
||||
webxr_api::Registry,
|
||||
webxr_api::Session,
|
||||
webxr_api::Frame,
|
||||
webxr_api::LayerId,
|
||||
webxr_api::InputSource,
|
||||
webxr_api::InputId,
|
||||
webxr_api::Joint,
|
||||
|
|
|
@ -106,7 +106,7 @@ use crate::stylesheet_set::StylesheetSetRef;
|
|||
use crate::task::TaskBox;
|
||||
use crate::task_source::{TaskSource, TaskSourceName};
|
||||
use crate::timers::OneshotTimerCallback;
|
||||
use canvas_traits::webgl::{self, SwapChainId, WebGLContextId, WebGLMsg};
|
||||
use canvas_traits::webgl::{self, WebGLContextId, WebGLMsg};
|
||||
use content_security_policy::{self as csp, CspList};
|
||||
use cookie::Cookie;
|
||||
use devtools_traits::ScriptToDevtoolsControlMsg;
|
||||
|
@ -2707,7 +2707,7 @@ impl Document {
|
|||
.borrow_mut()
|
||||
.drain()
|
||||
.filter(|(_, context)| context.onscreen())
|
||||
.map(|(id, _)| SwapChainId::Context(id))
|
||||
.map(|(id, _)| id)
|
||||
.collect();
|
||||
|
||||
if dirty_context_ids.is_empty() {
|
||||
|
|
|
@ -14,14 +14,13 @@ use crate::dom::webglrenderbuffer::WebGLRenderbuffer;
|
|||
use crate::dom::webglrenderingcontext::{Operation, WebGLRenderingContext};
|
||||
use crate::dom::webgltexture::WebGLTexture;
|
||||
use crate::dom::xrsession::XRSession;
|
||||
use canvas_traits::webgl::WebGLFramebufferId;
|
||||
use canvas_traits::webgl::{webgl_channel, WebGLError, WebGLResult, WebGLVersion};
|
||||
use canvas_traits::webgl::{WebGLCommand, WebGLFramebufferBindingRequest};
|
||||
use canvas_traits::webgl::{WebGLFramebufferId, WebGLOpaqueFramebufferId};
|
||||
use canvas_traits::webgl::{WebGLRenderbufferId, WebGLTextureId};
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::Size2D;
|
||||
use std::cell::Cell;
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
use webxr_api::Viewport;
|
||||
|
||||
pub enum CompleteForRendering {
|
||||
|
@ -134,7 +133,7 @@ impl WebGLFramebuffer {
|
|||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
context.send_command(WebGLCommand::CreateFramebuffer(sender));
|
||||
let id = receiver.recv().unwrap()?;
|
||||
let framebuffer = WebGLFramebuffer::new(context, WebGLFramebufferId::Transparent(id));
|
||||
let framebuffer = WebGLFramebuffer::new(context, id);
|
||||
Some(framebuffer)
|
||||
}
|
||||
|
||||
|
@ -144,25 +143,16 @@ impl WebGLFramebuffer {
|
|||
session: &XRSession,
|
||||
context: &XRWebGLRenderingContext,
|
||||
size: Size2D<i32, Viewport>,
|
||||
) -> Option<(WebXRSwapChainId, DomRoot<Self>)> {
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
) -> Option<DomRoot<Self>> {
|
||||
let context = match context {
|
||||
XRWebGLRenderingContext::WebGLRenderingContext(ref ctx) => DomRoot::from_ref(&**ctx),
|
||||
XRWebGLRenderingContext::WebGL2RenderingContext(ref ctx) => ctx.base_context(),
|
||||
};
|
||||
let _ = context.webgl_sender().send_create_webxr_swap_chain(
|
||||
size.to_untyped(),
|
||||
sender,
|
||||
session.session_id(),
|
||||
);
|
||||
let swap_chain_id = receiver.recv().unwrap()?;
|
||||
let framebuffer_id =
|
||||
WebGLFramebufferId::Opaque(WebGLOpaqueFramebufferId::WebXR(swap_chain_id));
|
||||
let framebuffer = WebGLFramebuffer::new(&*context, framebuffer_id);
|
||||
let framebuffer = Self::maybe_new(&*context)?;
|
||||
framebuffer.size.set(Some((size.width, size.height)));
|
||||
framebuffer.status.set(constants::FRAMEBUFFER_COMPLETE);
|
||||
framebuffer.xr_session.set(Some(session));
|
||||
Some((swap_chain_id, framebuffer))
|
||||
Some(framebuffer)
|
||||
}
|
||||
|
||||
pub fn new(context: &WebGLRenderingContext, id: WebGLFramebufferId) -> DomRoot<Self> {
|
||||
|
@ -655,7 +645,57 @@ impl WebGLFramebuffer {
|
|||
// Opaque framebuffers cannot have their attachments changed
|
||||
// https://immersive-web.github.io/webxr/#opaque-framebuffer
|
||||
self.validate_transparent()?;
|
||||
if let Some(texture) = texture {
|
||||
// "If texture is not zero, then texture must either
|
||||
// name an existing texture object with an target of
|
||||
// textarget, or texture must name an existing cube
|
||||
// map texture and textarget must be one of:
|
||||
// TEXTURE_CUBE_MAP_POSITIVE_X,
|
||||
// TEXTURE_CUBE_MAP_POSITIVE_Y,
|
||||
// TEXTURE_CUBE_MAP_POSITIVE_Z,
|
||||
// TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||
// TEXTURE_CUBE_MAP_NEGATIVE_Y, or
|
||||
// TEXTURE_CUBE_MAP_NEGATIVE_Z. Otherwise,
|
||||
// INVALID_OPERATION is generated."
|
||||
let is_cube = match textarget {
|
||||
constants::TEXTURE_2D => false,
|
||||
|
||||
constants::TEXTURE_CUBE_MAP_POSITIVE_X => true,
|
||||
constants::TEXTURE_CUBE_MAP_POSITIVE_Y => true,
|
||||
constants::TEXTURE_CUBE_MAP_POSITIVE_Z => true,
|
||||
constants::TEXTURE_CUBE_MAP_NEGATIVE_X => true,
|
||||
constants::TEXTURE_CUBE_MAP_NEGATIVE_Y => true,
|
||||
constants::TEXTURE_CUBE_MAP_NEGATIVE_Z => true,
|
||||
|
||||
_ => return Err(WebGLError::InvalidEnum),
|
||||
};
|
||||
|
||||
match texture.target() {
|
||||
Some(constants::TEXTURE_CUBE_MAP) if is_cube => {},
|
||||
Some(_) if !is_cube => {},
|
||||
_ => return Err(WebGLError::InvalidOperation),
|
||||
}
|
||||
|
||||
let context = self.upcast::<WebGLObject>().context();
|
||||
let max_tex_size = if is_cube {
|
||||
context.limits().max_cube_map_tex_size
|
||||
} else {
|
||||
context.limits().max_tex_size
|
||||
};
|
||||
if level < 0 || level as u32 > log2(max_tex_size) {
|
||||
return Err(WebGLError::InvalidValue);
|
||||
}
|
||||
}
|
||||
self.texture2d_even_if_opaque(attachment, textarget, texture, level)
|
||||
}
|
||||
|
||||
pub fn texture2d_even_if_opaque(
|
||||
&self,
|
||||
attachment: u32,
|
||||
textarget: u32,
|
||||
texture: Option<&WebGLTexture>,
|
||||
level: i32,
|
||||
) -> WebGLResult<()> {
|
||||
let binding = self
|
||||
.attachment_binding(attachment)
|
||||
.ok_or(WebGLError::InvalidEnum)?;
|
||||
|
@ -664,46 +704,6 @@ impl WebGLFramebuffer {
|
|||
// Note, from the GLES 2.0.25 spec, page 113:
|
||||
// "If texture is zero, then textarget and level are ignored."
|
||||
Some(texture) => {
|
||||
// "If texture is not zero, then texture must either
|
||||
// name an existing texture object with an target of
|
||||
// textarget, or texture must name an existing cube
|
||||
// map texture and textarget must be one of:
|
||||
// TEXTURE_CUBE_MAP_POSITIVE_X,
|
||||
// TEXTURE_CUBE_MAP_POSITIVE_Y,
|
||||
// TEXTURE_CUBE_MAP_POSITIVE_Z,
|
||||
// TEXTURE_CUBE_MAP_NEGATIVE_X,
|
||||
// TEXTURE_CUBE_MAP_NEGATIVE_Y, or
|
||||
// TEXTURE_CUBE_MAP_NEGATIVE_Z. Otherwise,
|
||||
// INVALID_OPERATION is generated."
|
||||
let is_cube = match textarget {
|
||||
constants::TEXTURE_2D => false,
|
||||
|
||||
constants::TEXTURE_CUBE_MAP_POSITIVE_X => true,
|
||||
constants::TEXTURE_CUBE_MAP_POSITIVE_Y => true,
|
||||
constants::TEXTURE_CUBE_MAP_POSITIVE_Z => true,
|
||||
constants::TEXTURE_CUBE_MAP_NEGATIVE_X => true,
|
||||
constants::TEXTURE_CUBE_MAP_NEGATIVE_Y => true,
|
||||
constants::TEXTURE_CUBE_MAP_NEGATIVE_Z => true,
|
||||
|
||||
_ => return Err(WebGLError::InvalidEnum),
|
||||
};
|
||||
|
||||
match texture.target() {
|
||||
Some(constants::TEXTURE_CUBE_MAP) if is_cube => {},
|
||||
Some(_) if !is_cube => {},
|
||||
_ => return Err(WebGLError::InvalidOperation),
|
||||
}
|
||||
|
||||
let context = self.upcast::<WebGLObject>().context();
|
||||
let max_tex_size = if is_cube {
|
||||
context.limits().max_cube_map_tex_size
|
||||
} else {
|
||||
context.limits().max_tex_size
|
||||
};
|
||||
if level < 0 || level as u32 > log2(max_tex_size) {
|
||||
return Err(WebGLError::InvalidValue);
|
||||
}
|
||||
|
||||
*binding.borrow_mut() = Some(WebGLFramebufferAttachment::Texture {
|
||||
texture: Dom::from_ref(texture),
|
||||
level: level,
|
||||
|
|
|
@ -60,8 +60,8 @@ use canvas_traits::webgl::{
|
|||
webgl_channel, AlphaTreatment, DOMToTextureCommand, GLContextAttributes, GLLimits, GlType,
|
||||
Parameter, SizedDataType, TexDataType, TexFormat, TexParameter, WebGLChan, WebGLCommand,
|
||||
WebGLCommandBacktrace, WebGLContextId, WebGLError, WebGLFramebufferBindingRequest, WebGLMsg,
|
||||
WebGLMsgSender, WebGLOpaqueFramebufferId, WebGLProgramId, WebGLResult, WebGLSLVersion,
|
||||
WebGLSendResult, WebGLSender, WebGLVersion, YAxisTreatment,
|
||||
WebGLMsgSender, WebGLProgramId, WebGLResult, WebGLSLVersion, WebGLSendResult, WebGLSender,
|
||||
WebGLVersion, YAxisTreatment,
|
||||
};
|
||||
use dom_struct::dom_struct;
|
||||
use embedder_traits::EventLoopWaker;
|
||||
|
@ -84,8 +84,6 @@ use std::cell::Cell;
|
|||
use std::cmp;
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::rc::Rc;
|
||||
use webxr_api::SessionId;
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
|
||||
// From the GLES 2.0.25 spec, page 85:
|
||||
//
|
||||
|
@ -406,10 +404,6 @@ impl WebGLRenderingContext {
|
|||
.send(command, capture_webgl_backtrace(self));
|
||||
}
|
||||
|
||||
pub fn swap_buffers(&self, id: Option<WebGLOpaqueFramebufferId>) {
|
||||
let _ = self.webgl_sender.send_swap_buffers(id);
|
||||
}
|
||||
|
||||
pub fn webgl_error(&self, err: WebGLError) {
|
||||
// TODO(emilio): Add useful debug messages to this
|
||||
warn!(
|
||||
|
@ -5003,19 +4997,6 @@ impl WebGLMessageSender {
|
|||
self.wake_after_send(|| self.sender.send(msg, backtrace))
|
||||
}
|
||||
|
||||
pub fn send_swap_buffers(&self, id: Option<WebGLOpaqueFramebufferId>) -> WebGLSendResult {
|
||||
self.wake_after_send(|| self.sender.send_swap_buffers(id))
|
||||
}
|
||||
|
||||
pub fn send_create_webxr_swap_chain(
|
||||
&self,
|
||||
size: Size2D<i32>,
|
||||
sender: WebGLSender<Option<WebXRSwapChainId>>,
|
||||
id: SessionId,
|
||||
) -> WebGLSendResult {
|
||||
self.wake_after_send(|| self.sender.send_create_webxr_swap_chain(size, sender, id))
|
||||
}
|
||||
|
||||
pub fn send_resize(
|
||||
&self,
|
||||
size: Size2D<u32>,
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
// https://immersive-web.github.io/layers/#xrlayertype
|
||||
[SecureContext, Exposed=Window, Pref="dom.webxr.layers.enabled"]
|
||||
interface XRLayer {
|
||||
readonly attribute unsigned long pixelWidth;
|
||||
readonly attribute unsigned long pixelHeight;
|
||||
|
||||
// attribute boolean blendTextureSourceAlpha;
|
||||
// attribute boolean chromaticAberrationCorrection;
|
||||
|
||||
|
|
|
@ -12,7 +12,8 @@ dictionary XRWebGLLayerInit {
|
|||
boolean depth = true;
|
||||
boolean stencil = false;
|
||||
boolean alpha = true;
|
||||
// double framebufferScaleFactor = 1.0;
|
||||
boolean ignoreDepthValues = false;
|
||||
double framebufferScaleFactor = 1.0;
|
||||
};
|
||||
|
||||
[SecureContext, Exposed=Window, Pref="dom.webxr.enabled"]
|
||||
|
|
|
@ -5,7 +5,9 @@
|
|||
// https://immersive-web.github.io/layers/#xrwebglsubimagetype
|
||||
[SecureContext, Exposed=Window, Pref="dom.webxr.layers.enabled"]
|
||||
interface XRWebGLSubImage : XRSubImage {
|
||||
readonly attribute WebGLTexture colorTexture;
|
||||
readonly attribute WebGLTexture? depthStencilTexture;
|
||||
[SameObject] readonly attribute WebGLTexture colorTexture;
|
||||
[SameObject] readonly attribute WebGLTexture? depthStencilTexture;
|
||||
readonly attribute unsigned long? imageIndex;
|
||||
readonly attribute unsigned long textureWidth;
|
||||
readonly attribute unsigned long textureHeight;
|
||||
};
|
||||
|
|
|
@ -20,6 +20,8 @@ use crate::dom::xrviewerpose::XRViewerPose;
|
|||
use dom_struct::dom_struct;
|
||||
use std::cell::Cell;
|
||||
use webxr_api::Frame;
|
||||
use webxr_api::LayerId;
|
||||
use webxr_api::SubImages;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct XRFrame {
|
||||
|
@ -59,6 +61,14 @@ impl XRFrame {
|
|||
pub fn get_pose(&self, space: &XRSpace) -> Option<ApiPose> {
|
||||
space.get_pose(&self.data)
|
||||
}
|
||||
|
||||
pub fn get_sub_images(&self, layer_id: LayerId) -> Option<&SubImages> {
|
||||
self.data
|
||||
.sub_images
|
||||
.iter()
|
||||
.filter(|sub_images| sub_images.layer_id == layer_id)
|
||||
.next()
|
||||
}
|
||||
}
|
||||
|
||||
impl XRFrameMethods for XRFrame {
|
||||
|
|
|
@ -6,30 +6,22 @@ use crate::dom::bindings::codegen::Bindings::XRLayerBinding::XRLayerBinding::XRL
|
|||
use crate::dom::bindings::reflector::Reflector;
|
||||
use crate::dom::bindings::root::Dom;
|
||||
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use crate::dom::xrframe::XRFrame;
|
||||
use crate::dom::xrsession::XRSession;
|
||||
use canvas_traits::webgl::WebGLContextId;
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::Size2D;
|
||||
use webxr_api::Viewport;
|
||||
use webxr_api::LayerId;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct XRLayer {
|
||||
reflector: Reflector,
|
||||
session: Dom<XRSession>,
|
||||
context: Dom<WebGLRenderingContext>,
|
||||
size: Size2D<u32, Viewport>,
|
||||
#[ignore_malloc_size_of = "Layers don't heap-allocate"]
|
||||
layer_id: LayerId,
|
||||
}
|
||||
|
||||
impl XRLayerMethods for XRLayer {
|
||||
/// https://immersive-web.github.io/layers/#dom-xrlayer-pixelwidth
|
||||
fn PixelWidth(&self) -> u32 {
|
||||
self.size.width
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/layers/#dom-xrlayer-pixelheight
|
||||
fn PixelHeight(&self) -> u32 {
|
||||
self.size.height
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/layers/#dom-xrlayer-destroy
|
||||
fn Destroy(&self) {
|
||||
// TODO: Implement this
|
||||
|
@ -41,13 +33,31 @@ impl XRLayer {
|
|||
pub fn new_inherited(
|
||||
session: &XRSession,
|
||||
context: &WebGLRenderingContext,
|
||||
size: Size2D<u32, Viewport>,
|
||||
layer_id: LayerId,
|
||||
) -> XRLayer {
|
||||
XRLayer {
|
||||
reflector: Reflector::new(),
|
||||
session: Dom::from_ref(session),
|
||||
context: Dom::from_ref(context),
|
||||
size: size,
|
||||
layer_id,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn layer_id(&self) -> LayerId {
|
||||
self.layer_id
|
||||
}
|
||||
|
||||
pub(crate) fn context_id(&self) -> WebGLContextId {
|
||||
self.context.context_id()
|
||||
}
|
||||
|
||||
pub fn begin_frame(&self, _frame: &XRFrame) -> Option<()> {
|
||||
// TODO: Implement this
|
||||
None
|
||||
}
|
||||
|
||||
pub fn end_frame(&self, _frame: &XRFrame) -> Option<()> {
|
||||
// TODO: Implement this
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,9 +11,11 @@ use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
|||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::xrlayer::XRLayer;
|
||||
use crate::dom::xrwebgllayer::XRWebGLLayer;
|
||||
use canvas_traits::webgl::WebGLContextId;
|
||||
use dom_struct::dom_struct;
|
||||
use std::cell::Cell;
|
||||
use webxr_api::SwapChainId;
|
||||
use webxr_api::LayerId;
|
||||
use webxr_api::SubImages;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct XRRenderState {
|
||||
|
@ -21,7 +23,7 @@ pub struct XRRenderState {
|
|||
depth_near: Cell<f64>,
|
||||
depth_far: Cell<f64>,
|
||||
inline_vertical_fov: Cell<Option<f64>>,
|
||||
layer: MutNullableDom<XRWebGLLayer>,
|
||||
base_layer: MutNullableDom<XRWebGLLayer>,
|
||||
layers: DomRefCell<Vec<XRWebGLLayerOrXRLayer>>,
|
||||
}
|
||||
|
||||
|
@ -45,17 +47,26 @@ impl XRWebGLLayerOrXRLayer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn swap_chain_id(&self) -> Option<SwapChainId> {
|
||||
pub(crate) fn layer_id(&self) -> Option<LayerId> {
|
||||
match self {
|
||||
XRWebGLLayerOrXRLayer::XRWebGLLayer(layer) => Some(layer.swap_chain_id()),
|
||||
XRWebGLLayerOrXRLayer::XRLayer(_) => None,
|
||||
XRWebGLLayerOrXRLayer::XRWebGLLayer(ref layer) => layer.layer_id(),
|
||||
XRWebGLLayerOrXRLayer::XRLayer(ref layer) => Some(layer.layer_id()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RootedXRWebGLLayerOrXRLayer {
|
||||
pub(crate) fn layer_id(&self) -> Option<LayerId> {
|
||||
match self {
|
||||
RootedXRWebGLLayerOrXRLayer::XRWebGLLayer(ref layer) => layer.layer_id(),
|
||||
RootedXRWebGLLayerOrXRLayer::XRLayer(ref layer) => Some(layer.layer_id()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn swap_buffers(&self) {
|
||||
pub(crate) fn context_id(&self) -> WebGLContextId {
|
||||
match self {
|
||||
XRWebGLLayerOrXRLayer::XRWebGLLayer(layer) => layer.swap_buffers(),
|
||||
XRWebGLLayerOrXRLayer::XRLayer(_) => (),
|
||||
RootedXRWebGLLayerOrXRLayer::XRWebGLLayer(ref layer) => layer.context_id(),
|
||||
RootedXRWebGLLayerOrXRLayer::XRLayer(ref layer) => layer.context_id(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +85,7 @@ impl XRRenderState {
|
|||
depth_near: Cell::new(depth_near),
|
||||
depth_far: Cell::new(depth_far),
|
||||
inline_vertical_fov: Cell::new(inline_vertical_fov),
|
||||
layer: MutNullableDom::new(layer),
|
||||
base_layer: MutNullableDom::new(layer),
|
||||
layers: DomRefCell::new(layers.iter().cloned().collect()),
|
||||
}
|
||||
}
|
||||
|
@ -106,7 +117,7 @@ impl XRRenderState {
|
|||
self.depth_near.get(),
|
||||
self.depth_far.get(),
|
||||
self.inline_vertical_fov.get(),
|
||||
self.layer.get().as_ref().map(|x| &**x),
|
||||
self.base_layer.get().as_ref().map(|x| &**x),
|
||||
&layers,
|
||||
)
|
||||
}
|
||||
|
@ -121,8 +132,8 @@ impl XRRenderState {
|
|||
debug_assert!(self.inline_vertical_fov.get().is_some());
|
||||
self.inline_vertical_fov.set(Some(fov))
|
||||
}
|
||||
pub fn set_layer(&self, layer: Option<&XRWebGLLayer>) {
|
||||
self.layer.set(layer)
|
||||
pub fn set_base_layer(&self, layer: Option<&XRWebGLLayer>) {
|
||||
self.base_layer.set(layer)
|
||||
}
|
||||
pub fn set_layers(&self, layers: &[RootedXRWebGLLayerOrXRLayer]) {
|
||||
*self.layers.borrow_mut() = layers.iter().map(XRWebGLLayerOrXRLayer::from_ref).collect();
|
||||
|
@ -134,8 +145,25 @@ impl XRRenderState {
|
|||
let layers = self.layers.borrow();
|
||||
f(&*layers)
|
||||
}
|
||||
pub fn has_layer(&self) -> bool {
|
||||
self.layer.get().is_some() || !self.layers.borrow().is_empty()
|
||||
pub fn has_sub_images(&self, sub_images: &[SubImages]) -> bool {
|
||||
if let Some(base_layer) = self.base_layer.get() {
|
||||
match sub_images.len() {
|
||||
// For inline sessions, there may be a base layer, but it won't have a framebuffer
|
||||
0 => base_layer.layer_id() == None,
|
||||
// For immersive sessions, the base layer will have a framebuffer,
|
||||
// so we make sure the layer id's match up
|
||||
1 => base_layer.layer_id() == Some(sub_images[0].layer_id),
|
||||
_ => false,
|
||||
}
|
||||
} else {
|
||||
// The layers API is only for immersive sessions
|
||||
let layers = self.layers.borrow();
|
||||
sub_images.len() == layers.len() &&
|
||||
sub_images
|
||||
.iter()
|
||||
.zip(layers.iter())
|
||||
.all(|(sub_image, layer)| Some(sub_image.layer_id) == layer.layer_id())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -157,6 +185,6 @@ impl XRRenderStateMethods for XRRenderState {
|
|||
|
||||
/// https://immersive-web.github.io/webxr/#dom-xrrenderstate-baselayer
|
||||
fn GetBaseLayer(&self) -> Option<DomRoot<XRWebGLLayer>> {
|
||||
self.layer.get()
|
||||
self.base_layer.get()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ use crate::dom::xrinputsourcearray::XRInputSourceArray;
|
|||
use crate::dom::xrinputsourceevent::XRInputSourceEvent;
|
||||
use crate::dom::xrreferencespace::XRReferenceSpace;
|
||||
use crate::dom::xrrenderstate::XRRenderState;
|
||||
use crate::dom::xrrenderstate::XRWebGLLayerOrXRLayer;
|
||||
use crate::dom::xrsessionevent::XRSessionEvent;
|
||||
use crate::dom::xrspace::XRSpace;
|
||||
use crate::realms::InRealm;
|
||||
|
@ -50,6 +51,7 @@ use std::collections::HashMap;
|
|||
use std::f64::consts::{FRAC_PI_2, PI};
|
||||
use std::mem;
|
||||
use std::rc::Rc;
|
||||
use webxr_api::ContextId as WebXRContextId;
|
||||
use webxr_api::{
|
||||
self, util, ApiSpace, Display, EntityTypes, EnvironmentBlendMode, Event as XREvent, Frame,
|
||||
FrameUpdateEvent, HitTestId, HitTestSource, Ray, SelectEvent, SelectKind, Session, SessionId,
|
||||
|
@ -354,7 +356,7 @@ impl XRSession {
|
|||
|
||||
/// https://immersive-web.github.io/webxr/#xr-animation-frame
|
||||
fn raf_callback(&self, mut frame: Frame) {
|
||||
debug!("WebXR RAF callback");
|
||||
debug!("WebXR RAF callback {:?}", frame);
|
||||
#[cfg(feature = "xr-profile")]
|
||||
let raf_start = time::precise_time_ns();
|
||||
#[cfg(feature = "xr-profile")]
|
||||
|
@ -363,7 +365,9 @@ impl XRSession {
|
|||
(raf_start - frame.sent_time) as f64 / 1_000_000.
|
||||
);
|
||||
|
||||
// Step 1
|
||||
// Step 1-2 happen in the xebxr device thread
|
||||
|
||||
// Step 3
|
||||
if let Some(pending) = self.pending_render_state.take() {
|
||||
// https://immersive-web.github.io/webxr/#apply-the-pending-render-state
|
||||
// (Steps 1-4 are implicit)
|
||||
|
@ -371,33 +375,38 @@ impl XRSession {
|
|||
self.active_render_state.set(&pending);
|
||||
// Step 6-7: XXXManishearth handle inlineVerticalFieldOfView
|
||||
|
||||
if self.is_immersive() {
|
||||
let swap_chain_id = pending
|
||||
.GetBaseLayer()
|
||||
.map(|layer| layer.swap_chain_id())
|
||||
.or_else(|| {
|
||||
self.active_render_state.get().with_layers(|layers| {
|
||||
layers.get(0).and_then(|layer| layer.swap_chain_id())
|
||||
})
|
||||
});
|
||||
self.session.borrow_mut().set_swap_chain(swap_chain_id);
|
||||
} else {
|
||||
if !self.is_immersive() {
|
||||
self.update_inline_projection_matrix()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: how does this fit the webxr spec?
|
||||
for event in frame.events.drain(..) {
|
||||
self.handle_frame_update(event);
|
||||
self.handle_frame_event(event);
|
||||
}
|
||||
|
||||
// Step 2
|
||||
if !self.active_render_state.get().has_layer() {
|
||||
// Step 4
|
||||
// TODO: what should this check be?
|
||||
// This is checking that the new render state has the same
|
||||
// layers as the frame.
|
||||
// Related to https://github.com/immersive-web/webxr/issues/1051
|
||||
if !self
|
||||
.active_render_state
|
||||
.get()
|
||||
.has_sub_images(&frame.sub_images[..])
|
||||
{
|
||||
// If the frame has different layers than the render state,
|
||||
// we just return early, drawing a blank frame.
|
||||
// This can result in flickering when the render state is changed.
|
||||
// TODO: it would be better to not render anything until the next frame.
|
||||
warn!("Rendering blank XR frame");
|
||||
self.session.borrow_mut().render_animation_frame();
|
||||
return;
|
||||
}
|
||||
|
||||
// Step 3: XXXManishearth handle inline session
|
||||
// Step 5: XXXManishearth handle inline session
|
||||
|
||||
// Step 4-5
|
||||
// Step 6-7
|
||||
{
|
||||
let mut current = self.current_raf_callback_list.borrow_mut();
|
||||
assert!(current.is_empty());
|
||||
|
@ -407,11 +416,17 @@ impl XRSession {
|
|||
let time = reduce_timing_resolution((frame.time_ns - start).to_ms());
|
||||
|
||||
let frame = XRFrame::new(&self.global(), self, frame);
|
||||
// Step 6,7
|
||||
// Step 8-9
|
||||
frame.set_active(true);
|
||||
frame.set_animation_frame(true);
|
||||
|
||||
// Step 8
|
||||
// Step 10
|
||||
self.apply_frame_updates(&*frame);
|
||||
|
||||
// TODO: how does this fit with the webxr and xr layers specs?
|
||||
self.layers_begin_frame(&*frame);
|
||||
|
||||
// Step 11-12
|
||||
self.outside_raf.set(false);
|
||||
let len = self.current_raf_callback_list.borrow().len();
|
||||
for i in 0..len {
|
||||
|
@ -426,21 +441,14 @@ impl XRSession {
|
|||
self.outside_raf.set(true);
|
||||
*self.current_raf_callback_list.borrow_mut() = vec![];
|
||||
|
||||
// TODO: how does this fit with the webxr and xr layers specs?
|
||||
self.layers_end_frame(&*frame);
|
||||
|
||||
// Step 13
|
||||
frame.set_active(false);
|
||||
if self.is_immersive() {
|
||||
if let Some(base_layer) = self.active_render_state.get().GetBaseLayer() {
|
||||
base_layer.swap_buffers();
|
||||
} else {
|
||||
self.active_render_state.get().with_layers(|layers| {
|
||||
for layer in layers {
|
||||
layer.swap_buffers();
|
||||
}
|
||||
});
|
||||
}
|
||||
self.session.borrow_mut().render_animation_frame();
|
||||
} else {
|
||||
self.session.borrow_mut().start_render_loop();
|
||||
}
|
||||
|
||||
// TODO: how does this fit the webxr spec?
|
||||
self.session.borrow_mut().render_animation_frame();
|
||||
|
||||
#[cfg(feature = "xr-profile")]
|
||||
println!(
|
||||
|
@ -498,7 +506,50 @@ impl XRSession {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_frame_update(&self, event: FrameUpdateEvent) {
|
||||
// TODO: how does this align with the layers spec?
|
||||
fn layers_begin_frame(&self, frame: &XRFrame) {
|
||||
if let Some(layer) = self.active_render_state.get().GetBaseLayer() {
|
||||
layer.begin_frame(frame);
|
||||
}
|
||||
self.active_render_state.get().with_layers(|layers| {
|
||||
for layer in layers {
|
||||
match layer {
|
||||
XRWebGLLayerOrXRLayer::XRWebGLLayer(layer) => {
|
||||
layer.begin_frame(frame);
|
||||
},
|
||||
XRWebGLLayerOrXRLayer::XRLayer(layer) => {
|
||||
layer.begin_frame(frame);
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: how does this align with the layers spec?
|
||||
fn layers_end_frame(&self, frame: &XRFrame) {
|
||||
if let Some(layer) = self.active_render_state.get().GetBaseLayer() {
|
||||
layer.end_frame(frame);
|
||||
}
|
||||
self.active_render_state.get().with_layers(|layers| {
|
||||
for layer in layers {
|
||||
match layer {
|
||||
XRWebGLLayerOrXRLayer::XRWebGLLayer(layer) => {
|
||||
layer.end_frame(frame);
|
||||
},
|
||||
XRWebGLLayerOrXRLayer::XRLayer(layer) => {
|
||||
layer.end_frame(frame);
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/webxr/#xrframe-apply-frame-updates
|
||||
fn apply_frame_updates(&self, _frame: &XRFrame) {
|
||||
// TODO: add a comment about why this is empty right now!
|
||||
}
|
||||
|
||||
fn handle_frame_event(&self, event: FrameUpdateEvent) {
|
||||
match event {
|
||||
FrameUpdateEvent::HitTestSourceAdded(id) => {
|
||||
if let Some(promise) = self.pending_hit_test_promises.borrow_mut().remove(&id) {
|
||||
|
@ -624,8 +675,16 @@ impl XRSessionMethods for XRSession {
|
|||
pending.set_inline_vertical_fov(fov);
|
||||
}
|
||||
if let Some(ref layer) = init.baseLayer {
|
||||
pending.set_layer(Some(&layer));
|
||||
pending.set_base_layer(Some(&layer));
|
||||
pending.set_layers(&[]);
|
||||
let layers = std::iter::once(layer)
|
||||
.filter_map(|layer| {
|
||||
let context_id = WebXRContextId::from(layer.context_id());
|
||||
let layer_id = layer.layer_id()?;
|
||||
Some((context_id, layer_id))
|
||||
})
|
||||
.collect();
|
||||
self.session.borrow_mut().set_layers(layers);
|
||||
}
|
||||
|
||||
if init.depthFar.is_some() || init.depthNear.is_some() {
|
||||
|
@ -637,8 +696,17 @@ impl XRSessionMethods for XRSession {
|
|||
// TODO: add spec link for this step once XR layers has settled down
|
||||
// https://immersive-web.github.io/layers/
|
||||
if let Some(ref layers) = init.layers {
|
||||
pending.set_layer(None);
|
||||
pending.set_base_layer(None);
|
||||
pending.set_layers(layers);
|
||||
let layers = layers
|
||||
.iter()
|
||||
.filter_map(|layer| {
|
||||
let context_id = WebXRContextId::from(layer.context_id());
|
||||
let layer_id = layer.layer_id()?;
|
||||
Some((context_id, layer_id))
|
||||
})
|
||||
.collect();
|
||||
self.session.borrow_mut().set_layers(layers);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -16,6 +16,7 @@ use crate::dom::xrlayer::XRLayer;
|
|||
use crate::dom::xrsession::XRSession;
|
||||
use crate::dom::xrview::XRView;
|
||||
use crate::dom::xrwebglsubimage::XRWebGLSubImage;
|
||||
use canvas_traits::webgl::WebGLContextId;
|
||||
use dom_struct::dom_struct;
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -53,6 +54,19 @@ impl WebGLRenderingContextOrWebGL2RenderingContext {
|
|||
}
|
||||
}
|
||||
|
||||
impl RootedWebGLRenderingContextOrWebGL2RenderingContext {
|
||||
pub(crate) fn context_id(&self) -> WebGLContextId {
|
||||
match self {
|
||||
RootedWebGLRenderingContextOrWebGL2RenderingContext::WebGLRenderingContext(
|
||||
ref context,
|
||||
) => context.context_id(),
|
||||
RootedWebGLRenderingContextOrWebGL2RenderingContext::WebGL2RenderingContext(
|
||||
ref context,
|
||||
) => context.base_context().context_id(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl XRWebGLBindingMethods for XRWebGLBinding {
|
||||
/// https://immersive-web.github.io/layers/#dom-xrwebglbinding-getsubimage
|
||||
fn GetSubImage(&self, _layer: &XRLayer, _frame: &XRFrame) -> Option<DomRoot<XRWebGLSubImage>> {
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* 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 crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextBinding::WebGL2RenderingContextMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerInit;
|
||||
|
@ -13,17 +15,24 @@ use crate::dom::bindings::reflector::{reflect_dom_object, DomObject, Reflector};
|
|||
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::webglframebuffer::WebGLFramebuffer;
|
||||
use crate::dom::webglobject::WebGLObject;
|
||||
use crate::dom::webgltexture::WebGLTexture;
|
||||
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use crate::dom::webgl2renderingcontext::WebGL2RenderingContext;
|
||||
use crate::dom::window::Window;
|
||||
use crate::dom::xrframe::XRFrame;
|
||||
use crate::dom::xrsession::XRSession;
|
||||
use crate::dom::xrview::XRView;
|
||||
use crate::dom::xrviewport::XRViewport;
|
||||
use canvas_traits::webgl::WebGLFramebufferId;
|
||||
use canvas_traits::webgl::WebGLContextId;
|
||||
use canvas_traits::webgl::WebGLCommand;
|
||||
use canvas_traits::webgl::WebGLTextureId;
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::{Rect, Size2D};
|
||||
use std::convert::TryInto;
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
use webxr_api::ContextId as WebXRContextId;
|
||||
use webxr_api::LayerId;
|
||||
use webxr_api::LayerInit;
|
||||
use webxr_api::Viewport;
|
||||
|
||||
#[derive(JSTraceable, MallocSizeOf)]
|
||||
|
@ -33,6 +42,28 @@ pub enum RenderingContext {
|
|||
WebGL2(Dom<WebGL2RenderingContext>),
|
||||
}
|
||||
|
||||
impl RenderingContext {
|
||||
fn context_id(&self) -> WebGLContextId {
|
||||
match self {
|
||||
RenderingContext::WebGL1(ref ctx) => ctx.context_id(),
|
||||
RenderingContext::WebGL2(ref ctx) => ctx.base_context().context_id(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a XRWebGLLayerInit> for LayerInit {
|
||||
fn from(init: &'a XRWebGLLayerInit) -> LayerInit {
|
||||
LayerInit::WebGLLayer {
|
||||
alpha: init.alpha,
|
||||
antialias: init.antialias,
|
||||
depth: init.depth,
|
||||
stencil: init.stencil,
|
||||
framebuffer_scale_factor: *init.framebufferScaleFactor as f32,
|
||||
ignore_depth_values: init.ignoreDepthValues,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[dom_struct]
|
||||
pub struct XRWebGLLayer {
|
||||
reflector_: Reflector,
|
||||
|
@ -40,21 +71,22 @@ pub struct XRWebGLLayer {
|
|||
depth: bool,
|
||||
stencil: bool,
|
||||
alpha: bool,
|
||||
#[ignore_malloc_size_of = "ids don't malloc"]
|
||||
swap_chain_id: Option<WebXRSwapChainId>,
|
||||
context: RenderingContext,
|
||||
session: Dom<XRSession>,
|
||||
/// If none, this is an inline session (the composition disabled flag is true)
|
||||
framebuffer: Option<Dom<WebGLFramebuffer>>,
|
||||
/// If none, this is an inline session (the composition disabled flag is true)
|
||||
#[ignore_malloc_size_of = "Layer ids don't heap-allocate"]
|
||||
layer_id: Option<LayerId>,
|
||||
}
|
||||
|
||||
impl XRWebGLLayer {
|
||||
pub fn new_inherited(
|
||||
swap_chain_id: Option<WebXRSwapChainId>,
|
||||
session: &XRSession,
|
||||
context: XRWebGLRenderingContext,
|
||||
init: &XRWebGLLayerInit,
|
||||
framebuffer: Option<&WebGLFramebuffer>,
|
||||
layer_id: Option<LayerId>,
|
||||
) -> XRWebGLLayer {
|
||||
XRWebGLLayer {
|
||||
reflector_: Reflector::new(),
|
||||
|
@ -62,7 +94,7 @@ impl XRWebGLLayer {
|
|||
depth: init.depth,
|
||||
stencil: init.stencil,
|
||||
alpha: init.alpha,
|
||||
swap_chain_id,
|
||||
layer_id,
|
||||
context: match context {
|
||||
XRWebGLRenderingContext::WebGLRenderingContext(ctx) => {
|
||||
RenderingContext::WebGL1(Dom::from_ref(&*ctx))
|
||||
|
@ -78,19 +110,19 @@ impl XRWebGLLayer {
|
|||
|
||||
pub fn new(
|
||||
global: &GlobalScope,
|
||||
swap_chain_id: Option<WebXRSwapChainId>,
|
||||
session: &XRSession,
|
||||
context: XRWebGLRenderingContext,
|
||||
init: &XRWebGLLayerInit,
|
||||
framebuffer: Option<&WebGLFramebuffer>,
|
||||
layer_id: Option<LayerId>,
|
||||
) -> DomRoot<XRWebGLLayer> {
|
||||
reflect_dom_object(
|
||||
Box::new(XRWebGLLayer::new_inherited(
|
||||
swap_chain_id,
|
||||
session,
|
||||
context,
|
||||
init,
|
||||
framebuffer,
|
||||
layer_id,
|
||||
)),
|
||||
global,
|
||||
)
|
||||
|
@ -104,7 +136,6 @@ impl XRWebGLLayer {
|
|||
context: XRWebGLRenderingContext,
|
||||
init: &XRWebGLLayerInit,
|
||||
) -> Fallible<DomRoot<Self>> {
|
||||
let framebuffer;
|
||||
// Step 2
|
||||
if session.is_ended() {
|
||||
return Err(Error::InvalidState);
|
||||
|
@ -112,27 +143,29 @@ impl XRWebGLLayer {
|
|||
// XXXManishearth step 3: throw error if context is lost
|
||||
// XXXManishearth step 4: check XR compat flag for immersive sessions
|
||||
|
||||
// Step 9.2. "Initialize layer’s framebuffer to a new opaque framebuffer created with context."
|
||||
let (swap_chain_id, framebuffer) = if session.is_immersive() {
|
||||
let size = session.with_session(|session| {
|
||||
session
|
||||
.recommended_framebuffer_resolution()
|
||||
.expect("immersive session must have viewports")
|
||||
});
|
||||
let (swap_chain_id, fb) = WebGLFramebuffer::maybe_new_webxr(session, &context, size)
|
||||
let (framebuffer, layer_id) = if session.is_immersive() {
|
||||
// Step 9.2. "Initialize layer’s framebuffer to a new opaque framebuffer created with context."
|
||||
let size = session
|
||||
.with_session(|session| session.recommended_framebuffer_resolution())
|
||||
.ok_or(Error::Operation)?;
|
||||
framebuffer = fb;
|
||||
(Some(swap_chain_id), Some(&*framebuffer))
|
||||
let framebuffer = WebGLFramebuffer::maybe_new_webxr(session, &context, size)
|
||||
.ok_or(Error::Operation)?;
|
||||
|
||||
// Step 9.3. "Allocate and initialize resources compatible with session’s XR device,
|
||||
// including GPU accessible memory buffers, as required to support the compositing of layer."
|
||||
let context_id = WebXRContextId::from(context.context_id());
|
||||
let layer_init = LayerInit::from(init);
|
||||
let layer_id = session
|
||||
.with_session(|session| session.create_layer(context_id, layer_init))
|
||||
.map_err(|_| Error::Operation)?;
|
||||
|
||||
// Step 9.4: "If layer’s resources were unable to be created for any reason,
|
||||
// throw an OperationError and abort these steps."
|
||||
(Some(framebuffer), Some(layer_id))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
// Step 9.3. "Allocate and initialize resources compatible with session’s XR device,
|
||||
// including GPU accessible memory buffers, as required to support the compositing of layer."
|
||||
|
||||
// Step 9.4: "If layer’s resources were unable to be created for any reason,
|
||||
// throw an OperationError and abort these steps."
|
||||
|
||||
// Ensure that we finish setting up this layer before continuing.
|
||||
match context {
|
||||
XRWebGLRenderingContext::WebGLRenderingContext(ref ctx) => ctx.Finish(),
|
||||
|
@ -142,37 +175,26 @@ impl XRWebGLLayer {
|
|||
// Step 10. "Return layer."
|
||||
Ok(XRWebGLLayer::new(
|
||||
&global.global(),
|
||||
swap_chain_id,
|
||||
session,
|
||||
context,
|
||||
init,
|
||||
framebuffer,
|
||||
framebuffer.as_deref(),
|
||||
layer_id,
|
||||
))
|
||||
}
|
||||
|
||||
pub fn swap_chain_id(&self) -> WebXRSwapChainId {
|
||||
self.swap_chain_id
|
||||
.expect("swap_chain_id must not be called for inline sessions")
|
||||
pub fn layer_id(&self) -> Option<LayerId> {
|
||||
self.layer_id
|
||||
}
|
||||
|
||||
pub fn context_id(&self) -> WebGLContextId {
|
||||
self.context.context_id()
|
||||
}
|
||||
|
||||
pub fn session(&self) -> &XRSession {
|
||||
&self.session
|
||||
}
|
||||
|
||||
pub fn swap_buffers(&self) {
|
||||
if let WebGLFramebufferId::Opaque(id) = self
|
||||
.framebuffer
|
||||
.as_ref()
|
||||
.expect("swap_buffers must not be called for inline sessions")
|
||||
.id()
|
||||
{
|
||||
match self.context {
|
||||
RenderingContext::WebGL1(ref ctx) => ctx.swap_buffers(Some(id)),
|
||||
RenderingContext::WebGL2(ref ctx) => ctx.base_context().swap_buffers(Some(id)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Size2D<u32, Viewport> {
|
||||
if let Some(framebuffer) = self.framebuffer.as_ref() {
|
||||
let size = framebuffer.size().unwrap_or((0, 0));
|
||||
|
@ -188,6 +210,52 @@ impl XRWebGLLayer {
|
|||
Size2D::from_untyped(size)
|
||||
}
|
||||
}
|
||||
|
||||
fn texture_target(&self) -> u32 {
|
||||
if cfg!(target_os = "macos") {
|
||||
sparkle::gl::TEXTURE_RECTANGLE
|
||||
} else {
|
||||
sparkle::gl::TEXTURE_2D
|
||||
}
|
||||
}
|
||||
|
||||
pub fn begin_frame(&self, frame: &XRFrame) -> Option<()> {
|
||||
debug!("XRWebGLLayer begin frame");
|
||||
let framebuffer = self.framebuffer.as_ref()?;
|
||||
let context = framebuffer.upcast::<WebGLObject>().context();
|
||||
let sub_images = frame.get_sub_images(self.layer_id?)?;
|
||||
// TODO: Cache this texture
|
||||
let color_texture_id =
|
||||
WebGLTextureId::maybe_new(sub_images.sub_image.as_ref()?.color_texture)?;
|
||||
let color_texture = WebGLTexture::new(context, color_texture_id);
|
||||
let target = self.texture_target();
|
||||
// TODO: rebind the current bindings
|
||||
context.send_command(WebGLCommand::BindTexture(target, Some(color_texture_id)));
|
||||
framebuffer.bind(constants::FRAMEBUFFER);
|
||||
framebuffer
|
||||
.texture2d_even_if_opaque(
|
||||
constants::COLOR_ATTACHMENT0,
|
||||
self.texture_target(),
|
||||
Some(&color_texture),
|
||||
0,
|
||||
)
|
||||
.ok()?;
|
||||
// TODO: depth/stencil
|
||||
Some(())
|
||||
}
|
||||
|
||||
pub fn end_frame(&self, _frame: &XRFrame) -> Option<()> {
|
||||
debug!("XRWebGLLayer end frame");
|
||||
// TODO: invalidate the old texture
|
||||
let framebuffer = self.framebuffer.as_ref()?;
|
||||
// TODO: rebind the current bindings
|
||||
framebuffer.bind(constants::FRAMEBUFFER);
|
||||
framebuffer
|
||||
.texture2d_even_if_opaque(constants::COLOR_ATTACHMENT0, self.texture_target(), None, 0)
|
||||
.ok()?;
|
||||
framebuffer.upcast::<WebGLObject>().context().Flush();
|
||||
Some(())
|
||||
}
|
||||
}
|
||||
|
||||
impl XRWebGLLayerMethods for XRWebGLLayer {
|
||||
|
|
|
@ -8,6 +8,8 @@ use crate::dom::bindings::root::DomRoot;
|
|||
use crate::dom::webgltexture::WebGLTexture;
|
||||
use crate::dom::xrsubimage::XRSubImage;
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::Size2D;
|
||||
use webxr_api::Viewport;
|
||||
|
||||
#[dom_struct]
|
||||
pub struct XRWebGLSubImage {
|
||||
|
@ -15,6 +17,7 @@ pub struct XRWebGLSubImage {
|
|||
color_texture: Dom<WebGLTexture>,
|
||||
depth_stencil_texture: Option<Dom<WebGLTexture>>,
|
||||
image_index: Option<u32>,
|
||||
size: Size2D<u32, Viewport>,
|
||||
}
|
||||
|
||||
impl XRWebGLSubImageMethods for XRWebGLSubImage {
|
||||
|
@ -32,4 +35,14 @@ impl XRWebGLSubImageMethods for XRWebGLSubImage {
|
|||
fn GetImageIndex(&self) -> Option<u32> {
|
||||
self.image_index
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/layers/#dom-xrwebglsubimage-texturewidth
|
||||
fn TextureWidth(&self) -> u32 {
|
||||
self.size.width
|
||||
}
|
||||
|
||||
/// https://immersive-web.github.io/layers/#dom-xrwebglsubimage-textureheight
|
||||
fn TextureHeight(&self) -> u32 {
|
||||
self.size.height
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@ servo_url = { path = "../url" }
|
|||
sparkle = "0.1"
|
||||
style = { path = "../style", features = ["servo"] }
|
||||
style_traits = { path = "../style_traits", features = ["servo"] }
|
||||
surfman = "0.2"
|
||||
surfman = "0.3"
|
||||
webdriver_server = { path = "../webdriver_server", optional = true }
|
||||
webgpu = { path = "../webgpu" }
|
||||
webrender = { git = "https://github.com/servo/webrender" }
|
||||
|
|
|
@ -65,7 +65,7 @@ fn webdriver(_port: u16, _constellation: Sender<ConstellationMsg>) {}
|
|||
use bluetooth::BluetoothThreadFactory;
|
||||
use bluetooth_traits::BluetoothRequest;
|
||||
use canvas::canvas_paint_thread::{self, CanvasPaintThread};
|
||||
use canvas::{SurfaceProviders, WebGLComm, WebGlExecutor};
|
||||
use canvas::WebGLComm;
|
||||
use canvas_traits::webgl::WebGLThreads;
|
||||
use compositing::compositor_thread::{
|
||||
CompositorProxy, CompositorReceiver, InitialCompositorState, Msg, WebrenderCanvasMsg,
|
||||
|
@ -118,12 +118,13 @@ use std::cmp::max;
|
|||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use surfman::GLApi;
|
||||
use webrender::ShaderPrecacheFlags;
|
||||
use webrender_surfman::WebrenderSurfman;
|
||||
use webrender_traits::WebrenderExternalImageHandlers;
|
||||
use webrender_traits::WebrenderExternalImageRegistry;
|
||||
use webrender_traits::WebrenderImageHandlerType;
|
||||
use webrender_traits::{WebrenderExternalImageHandlers, WebrenderExternalImageRegistry};
|
||||
|
||||
pub use gleam::gl;
|
||||
pub use keyboard_types;
|
||||
|
@ -446,32 +447,43 @@ where
|
|||
None
|
||||
};
|
||||
|
||||
// Create the webgl thread
|
||||
let gl_type = match webrender_gl.get_type() {
|
||||
gleam::gl::GlType::Gl => sparkle::gl::GlType::Gl,
|
||||
gleam::gl::GlType::Gles => sparkle::gl::GlType::Gles,
|
||||
};
|
||||
|
||||
let (external_image_handlers, external_images) = WebrenderExternalImageHandlers::new();
|
||||
let mut external_image_handlers = Box::new(external_image_handlers);
|
||||
|
||||
let mut webxr_main_thread = webxr::MainThreadRegistry::new(event_loop_waker)
|
||||
.expect("Failed to create WebXR device registry");
|
||||
|
||||
let (webgl_threads, webgl_extras) = create_webgl_threads(
|
||||
let WebGLComm {
|
||||
webgl_threads,
|
||||
webxr_layer_grand_manager,
|
||||
image_handler,
|
||||
output_handler,
|
||||
} = WebGLComm::new(
|
||||
webrender_surfman.clone(),
|
||||
webrender_gl.clone(),
|
||||
&mut webrender,
|
||||
webrender_api.create_sender(),
|
||||
webrender_document,
|
||||
&mut webxr_main_thread,
|
||||
&mut external_image_handlers,
|
||||
external_images.clone(),
|
||||
gl_type,
|
||||
);
|
||||
|
||||
// Set webrender external image handler for WebGL textures
|
||||
external_image_handlers.set_handler(image_handler, WebrenderImageHandlerType::WebGL);
|
||||
|
||||
// Set DOM to texture handler, if enabled.
|
||||
if let Some(output_handler) = output_handler {
|
||||
webrender.set_output_image_handler(output_handler);
|
||||
}
|
||||
|
||||
// Create the WebXR main thread
|
||||
let mut webxr_main_thread =
|
||||
webxr::MainThreadRegistry::new(event_loop_waker, webxr_layer_grand_manager)
|
||||
.expect("Failed to create WebXR device registry");
|
||||
if pref!(dom.webxr.enabled) {
|
||||
if let Some((webxr_surface_providers, webgl_executor)) = webgl_extras {
|
||||
embedder.register_webxr(
|
||||
&mut webxr_main_thread,
|
||||
webgl_executor,
|
||||
webxr_surface_providers,
|
||||
embedder_proxy.clone(),
|
||||
);
|
||||
}
|
||||
embedder.register_webxr(&mut webxr_main_thread, embedder_proxy.clone());
|
||||
}
|
||||
|
||||
let glplayer_threads = match window.get_gl_context() {
|
||||
|
@ -526,7 +538,7 @@ where
|
|||
webrender_api_sender,
|
||||
webxr_main_thread.registry(),
|
||||
player_context,
|
||||
webgl_threads,
|
||||
Some(webgl_threads),
|
||||
glplayer_threads,
|
||||
event_loop_waker,
|
||||
window_size,
|
||||
|
@ -1095,58 +1107,6 @@ fn create_sandbox() {
|
|||
panic!("Sandboxing is not supported on Windows, iOS, ARM targets and android.");
|
||||
}
|
||||
|
||||
// Initializes the WebGL thread.
|
||||
fn create_webgl_threads(
|
||||
webrender_surfman: WebrenderSurfman,
|
||||
webrender_gl: Rc<dyn gl::Gl>,
|
||||
webrender: &mut webrender::Renderer,
|
||||
webrender_api_sender: webrender_api::RenderApiSender,
|
||||
webrender_doc: webrender_api::DocumentId,
|
||||
webxr_main_thread: &mut webxr::MainThreadRegistry,
|
||||
external_image_handlers: &mut WebrenderExternalImageHandlers,
|
||||
external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,
|
||||
) -> (
|
||||
Option<WebGLThreads>,
|
||||
Option<(SurfaceProviders, WebGlExecutor)>,
|
||||
) {
|
||||
let gl_type = match webrender_gl.get_type() {
|
||||
gleam::gl::GlType::Gl => sparkle::gl::GlType::Gl,
|
||||
gleam::gl::GlType::Gles => sparkle::gl::GlType::Gles,
|
||||
};
|
||||
|
||||
let WebGLComm {
|
||||
webgl_threads,
|
||||
webxr_swap_chains,
|
||||
webxr_surface_providers,
|
||||
image_handler,
|
||||
output_handler,
|
||||
webgl_executor,
|
||||
} = WebGLComm::new(
|
||||
webrender_surfman,
|
||||
webrender_gl,
|
||||
webrender_api_sender,
|
||||
webrender_doc,
|
||||
external_images,
|
||||
gl_type,
|
||||
);
|
||||
|
||||
// Set webrender external image handler for WebGL textures
|
||||
external_image_handlers.set_handler(image_handler, WebrenderImageHandlerType::WebGL);
|
||||
|
||||
// Set webxr external image handler for WebGL textures
|
||||
webxr_main_thread.set_swap_chains(webxr_swap_chains);
|
||||
|
||||
// Set DOM to texture handler, if enabled.
|
||||
if let Some(output_handler) = output_handler {
|
||||
webrender.set_output_image_handler(output_handler);
|
||||
}
|
||||
|
||||
(
|
||||
Some(webgl_threads),
|
||||
Some((webxr_surface_providers, webgl_executor)),
|
||||
)
|
||||
}
|
||||
|
||||
enum UserAgent {
|
||||
Desktop,
|
||||
Android,
|
||||
|
|
17
components/webrender_surfman/#Cargo.toml#
Normal file
17
components/webrender_surfman/#Cargo.toml#
Normal file
|
@ -0,0 +1,17 @@
|
|||
[package]
|
||||
name = "webrender_surfman"
|
||||
version = "0.0.1"
|
||||
authors = ["The Servo Project Developers"]
|
||||
license = "MPL-2.0"
|
||||
edition = "2018"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
name = "webrender_surfman"
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies]
|
||||
euclid = "0.20"
|
||||
surfman = "0.3"
|
||||
surfman-chains = "0.4i"
|
||||
|
1
components/webrender_surfman/.#Cargo.toml
Symbolic link
1
components/webrender_surfman/.#Cargo.toml
Symbolic link
|
@ -0,0 +1 @@
|
|||
ajeffrey@ajeffrey-home.4753:1592856534
|
|
@ -12,6 +12,6 @@ path = "lib.rs"
|
|||
|
||||
[dependencies]
|
||||
euclid = "0.20"
|
||||
surfman = "0.2"
|
||||
surfman-chains = "0.3"
|
||||
surfman = "0.3"
|
||||
surfman-chains = "0.4"
|
||||
|
||||
|
|
|
@ -26,7 +26,6 @@ use surfman::SurfaceAccess;
|
|||
use surfman::SurfaceInfo;
|
||||
use surfman::SurfaceTexture;
|
||||
use surfman::SurfaceType;
|
||||
use surfman_chains::SurfmanProvider;
|
||||
use surfman_chains::SwapChain;
|
||||
|
||||
/// A bridge between webrender and surfman
|
||||
|
@ -68,7 +67,7 @@ impl WebrenderSurfman {
|
|||
};
|
||||
let context_attributes = ContextAttributes { flags, version };
|
||||
let context_descriptor = device.create_context_descriptor(&context_attributes)?;
|
||||
let mut context = device.create_context(&context_descriptor)?;
|
||||
let mut context = device.create_context(&context_descriptor, None)?;
|
||||
let surface_access = SurfaceAccess::GPUOnly;
|
||||
let headless = match surface_type {
|
||||
SurfaceType::Widget { .. } => false,
|
||||
|
@ -82,11 +81,10 @@ impl WebrenderSurfman {
|
|||
err
|
||||
})?;
|
||||
let swap_chain = if headless {
|
||||
let surface_provider = Box::new(SurfmanProvider::new(surface_access));
|
||||
Some(SwapChain::create_attached(
|
||||
&mut device,
|
||||
&mut context,
|
||||
surface_provider,
|
||||
surface_access,
|
||||
)?)
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -29,8 +29,8 @@ libservo = { path = "../../components/servo" }
|
|||
log = "0.4"
|
||||
servo-media = { git = "https://github.com/servo/media" }
|
||||
sparkle = "0.1"
|
||||
surfman = { git = "https://github.com/servo/surfman" }
|
||||
surfman-chains = { git = "https://github.com/asajeffrey/surfman-chains" }
|
||||
surfman = "0.3"
|
||||
surfman-chains = "0.4"
|
||||
surfman-chains-api = "0.2"
|
||||
|
||||
[build-dependencies]
|
||||
|
|
|
@ -12,7 +12,7 @@ ipc-channel = "0.14"
|
|||
libservo = { path = "../../../components/servo" }
|
||||
log = "0.4"
|
||||
servo-media = { git = "https://github.com/servo/media" }
|
||||
surfman = { version = "0.2", features = ["sm-angle-default"] }
|
||||
surfman = { version = "0.3", features = ["sm-angle-default"] }
|
||||
webxr = { git = "https://github.com/servo/webxr"}
|
||||
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }
|
||||
|
||||
|
|
|
@ -15,7 +15,6 @@ pub use servo::script_traits::{MediaSessionActionType, MouseButton};
|
|||
|
||||
use getopts::Options;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use servo::canvas::{SurfaceProviders, WebGlExecutor};
|
||||
use servo::compositing::windowing::{
|
||||
AnimationState, EmbedderCoordinates, EmbedderMethods, MouseWindowEvent, WindowEvent,
|
||||
WindowMethods,
|
||||
|
@ -794,8 +793,6 @@ impl EmbedderMethods for ServoEmbedderCallbacks {
|
|||
fn register_webxr(
|
||||
&mut self,
|
||||
registry: &mut webxr::MainThreadRegistry,
|
||||
executor: WebGlExecutor,
|
||||
surface_providers: SurfaceProviders,
|
||||
embedder_proxy: EmbedderProxy,
|
||||
) {
|
||||
use ipc_channel::ipc::{self, IpcReceiver};
|
||||
|
@ -806,16 +803,6 @@ impl EmbedderMethods for ServoEmbedderCallbacks {
|
|||
"UWP builds should not be initialized with a WebXR Discovery object"
|
||||
);
|
||||
|
||||
struct ProviderRegistration(SurfaceProviders);
|
||||
impl openxr::SurfaceProviderRegistration for ProviderRegistration {
|
||||
fn register(&self, id: webxr_api::SessionId, provider: servo::canvas::SurfaceProvider) {
|
||||
self.0.lock().unwrap().insert(id, provider);
|
||||
}
|
||||
fn clone(&self) -> Box<dyn openxr::SurfaceProviderRegistration> {
|
||||
Box::new(ProviderRegistration(self.0.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct ContextMenuCallback(EmbedderProxy);
|
||||
|
||||
|
@ -854,22 +841,9 @@ impl EmbedderMethods for ServoEmbedderCallbacks {
|
|||
}
|
||||
}
|
||||
|
||||
struct GlThread(WebGlExecutor);
|
||||
impl openxr::GlThread for GlThread {
|
||||
fn execute(&self, runnable: Box<dyn FnOnce(&surfman::Device) + Send>) {
|
||||
let _ = self.0.send(runnable);
|
||||
}
|
||||
fn clone(&self) -> Box<dyn webxr::openxr::GlThread> {
|
||||
Box::new(GlThread(self.0.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
if openxr::create_instance(false).is_ok() {
|
||||
let discovery = openxr::OpenXrDiscovery::new(
|
||||
Box::new(GlThread(executor)),
|
||||
Box::new(ProviderRegistration(surface_providers)),
|
||||
Box::new(ContextMenuCallback(embedder_proxy)),
|
||||
);
|
||||
let discovery =
|
||||
openxr::OpenXrDiscovery::new(Box::new(ContextMenuCallback(embedder_proxy)));
|
||||
registry.register(discovery);
|
||||
} else {
|
||||
let msg =
|
||||
|
@ -891,8 +865,6 @@ impl EmbedderMethods for ServoEmbedderCallbacks {
|
|||
fn register_webxr(
|
||||
&mut self,
|
||||
registry: &mut webxr::MainThreadRegistry,
|
||||
_executor: WebGlExecutor,
|
||||
_surface_provider_registration: SurfaceProviders,
|
||||
_embedder_proxy: EmbedderProxy,
|
||||
) {
|
||||
debug!("EmbedderMethods::register_xr");
|
||||
|
|
|
@ -18,7 +18,7 @@ env_logger = "0.7"
|
|||
lazy_static = "1"
|
||||
log = "0.4"
|
||||
simpleservo = { path = "../api" }
|
||||
surfman = "0.2"
|
||||
surfman = "0.3"
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
libc = "0.2"
|
||||
|
|
|
@ -57,7 +57,7 @@ libservo = { path = "../../components/servo" }
|
|||
log = "0.4"
|
||||
servo-media = { git = "https://github.com/servo/media" }
|
||||
shellwords = "1.0.0"
|
||||
surfman = { version = "0.2", features = ["sm-winit", "sm-x11"] }
|
||||
surfman = { version = "0.3", features = ["sm-winit", "sm-x11"] }
|
||||
tinyfiledialogs = "3.0"
|
||||
webxr = { git = "https://github.com/servo/webxr", features = ["ipc", "glwindow", "headless"] }
|
||||
winit = "0.19"
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
//! Implements the global methods required by Servo (not window/gl/compositor related).
|
||||
|
||||
use crate::events_loop::EventsLoop;
|
||||
use servo::canvas::{SurfaceProviders, WebGlExecutor};
|
||||
use servo::compositing::windowing::EmbedderMethods;
|
||||
use servo::embedder_traits::{EmbedderProxy, EventLoopWaker};
|
||||
use servo::servo_config::pref;
|
||||
|
@ -38,8 +37,6 @@ impl EmbedderMethods for EmbedderCallbacks {
|
|||
fn register_webxr(
|
||||
&mut self,
|
||||
xr: &mut webxr::MainThreadRegistry,
|
||||
_executor: WebGlExecutor,
|
||||
_surface_provider_registration: SurfaceProviders,
|
||||
_embedder_proxy: EmbedderProxy,
|
||||
) {
|
||||
if pref!(dom.webxr.test) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue