aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock29
-rw-r--r--Cargo.toml2
-rw-r--r--components/canvas/Cargo.toml7
-rw-r--r--components/canvas/lib.rs3
-rw-r--r--components/canvas/webgl_mode/inprocess.rs23
-rw-r--r--components/canvas/webgl_thread.rs627
-rw-r--r--components/canvas_traits/webgl.rs123
-rw-r--r--components/compositing/windowing.rs10
-rw-r--r--components/script/dom/bindings/trace.rs6
-rw-r--r--components/script/dom/document.rs4
-rw-r--r--components/script/dom/webglframebuffer.rs110
-rw-r--r--components/script/dom/webglrenderingcontext.rs23
-rw-r--r--components/script/dom/webidls/XRLayer.webidl3
-rw-r--r--components/script/dom/webidls/XRWebGLLayer.webidl3
-rw-r--r--components/script/dom/webidls/XRWebGLSubImage.webidl6
-rw-r--r--components/script/dom/xrframe.rs10
-rw-r--r--components/script/dom/xrlayer.rs40
-rw-r--r--components/script/dom/xrrenderstate.rs58
-rw-r--r--components/script/dom/xrsession.rs142
-rw-r--r--components/script/dom/xrwebglbinding.rs14
-rw-r--r--components/script/dom/xrwebgllayer.rs156
-rw-r--r--components/script/dom/xrwebglsubimage.rs13
-rw-r--r--components/servo/Cargo.toml2
-rw-r--r--components/servo/lib.rs104
-rw-r--r--components/webrender_surfman/#Cargo.toml#17
l---------components/webrender_surfman/.#Cargo.toml1
-rw-r--r--components/webrender_surfman/Cargo.toml4
-rw-r--r--components/webrender_surfman/lib.rs6
-rw-r--r--ports/gstplugin/Cargo.toml4
-rw-r--r--ports/libsimpleservo/api/Cargo.toml2
-rw-r--r--ports/libsimpleservo/api/src/lib.rs32
-rw-r--r--ports/libsimpleservo/capi/Cargo.toml2
-rw-r--r--ports/winit/Cargo.toml2
-rw-r--r--ports/winit/embedder.rs3
34 files changed, 949 insertions, 642 deletions
diff --git a/Cargo.lock b/Cargo.lock
index bba68728820..fef028c035c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -529,6 +529,7 @@ dependencies = [
"webrender_api",
"webrender_surfman",
"webrender_traits",
+ "webxr",
"webxr-api",
]
@@ -1954,15 +1955,6 @@ dependencies = [
[[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"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9a13b5bb12ab457c15400b43cbba5971df5c1898b6a9c30cc8c52cb01baa112"
@@ -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",
]
diff --git a/Cargo.toml b/Cargo.toml
index cf04bfa64c8..5ad9325baf8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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" }
diff --git a/components/canvas/Cargo.toml b/components/canvas/Cargo.toml
index 782e9fba4f0..2281ea30242 100644
--- a/components/canvas/Cargo.toml
+++ b/components/canvas/Cargo.toml
@@ -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"] }
diff --git a/components/canvas/lib.rs b/components/canvas/lib.rs
index 074a4a00bcb..1e5872420bc 100644
--- a/components/canvas/lib.rs
+++ b/components/canvas/lib.rs
@@ -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;
diff --git a/components/canvas/webgl_mode/inprocess.rs b/components/canvas/webgl_mode/inprocess.rs
index c7b25b69d12..ca9188aee54 100644
--- a/components/canvas/webgl_mode/inprocess.rs
+++ b/components/canvas/webgl_mode/inprocess.rs
@@ -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,
}
}
}
diff --git a/components/canvas/webgl_thread.rs b/components/canvas/webgl_thread.rs
index d113f0aca85..a9a76d71960 100644
--- a/components/canvas/webgl_thread.rs
+++ b/components/canvas/webgl_thread.rs
@@ -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);
- }
-
- // 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();
- }
+ 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;
}
}
}
@@ -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, &current_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)
+ }
+}
diff --git a/components/canvas_traits/webgl.rs b/components/canvas_traits/webgl.rs
index 2b4b9dda482..175e5ab0937 100644
--- a/components/canvas_traits/webgl.rs
+++ b/components/canvas_traits/webgl.rs
@@ -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
@@ -577,6 +559,11 @@ macro_rules! define_resource_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),
diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs
index 7a2784e08fd..ac481486d37 100644
--- a/components/compositing/windowing.rs
+++ b/components/compositing/windowing.rs
@@ -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> {
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index d6216cdad48..5a540f3e912 100644
--- a/components/script/dom/bindings/trace.rs
+++ b/components/script/dom/bindings/trace.rs
@@ -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,
diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs
index ce3204d3797..09b802b20e5 100644
--- a/components/script/dom/document.rs
+++ b/components/script/dom/document.rs
@@ -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() {
diff --git a/components/script/dom/webglframebuffer.rs b/components/script/dom/webglframebuffer.rs
index 9f38365c4c7..a0d8025a131 100644
--- a/components/script/dom/webglframebuffer.rs
+++ b/components/script/dom/webglframebuffer.rs
@@ -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,
diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs
index a3f78e64c91..b4efd86033b 100644
--- a/components/script/dom/webglrenderingcontext.rs
+++ b/components/script/dom/webglrenderingcontext.rs
@@ -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>,
diff --git a/components/script/dom/webidls/XRLayer.webidl b/components/script/dom/webidls/XRLayer.webidl
index eb967abf091..d78e220b5f5 100644
--- a/components/script/dom/webidls/XRLayer.webidl
+++ b/components/script/dom/webidls/XRLayer.webidl
@@ -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;
diff --git a/components/script/dom/webidls/XRWebGLLayer.webidl b/components/script/dom/webidls/XRWebGLLayer.webidl
index 4d98e506765..995f6b25bf2 100644
--- a/components/script/dom/webidls/XRWebGLLayer.webidl
+++ b/components/script/dom/webidls/XRWebGLLayer.webidl
@@ -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"]
diff --git a/components/script/dom/webidls/XRWebGLSubImage.webidl b/components/script/dom/webidls/XRWebGLSubImage.webidl
index f25552d533e..2682206cc0a 100644
--- a/components/script/dom/webidls/XRWebGLSubImage.webidl
+++ b/components/script/dom/webidls/XRWebGLSubImage.webidl
@@ -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;
};
diff --git a/components/script/dom/xrframe.rs b/components/script/dom/xrframe.rs
index 2381d4864d9..914d96333b5 100644
--- a/components/script/dom/xrframe.rs
+++ b/components/script/dom/xrframe.rs
@@ -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 {
diff --git a/components/script/dom/xrlayer.rs b/components/script/dom/xrlayer.rs
index e70cdb5085a..b55df545e37 100644
--- a/components/script/dom/xrlayer.rs
+++ b/components/script/dom/xrlayer.rs
@@ -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
+ }
}
diff --git a/components/script/dom/xrrenderstate.rs b/components/script/dom/xrrenderstate.rs
index d174af531d0..10ab1ba661f 100644
--- a/components/script/dom/xrrenderstate.rs
+++ b/components/script/dom/xrrenderstate.rs
@@ -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()
}
}
diff --git a/components/script/dom/xrsession.rs b/components/script/dom/xrsession.rs
index ee7a865d280..c9f7b108a94 100644
--- a/components/script/dom/xrsession.rs
+++ b/components/script/dom/xrsession.rs
@@ -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(())
diff --git a/components/script/dom/xrwebglbinding.rs b/components/script/dom/xrwebglbinding.rs
index 27435aa3ddc..4f5efaa3cf7 100644
--- a/components/script/dom/xrwebglbinding.rs
+++ b/components/script/dom/xrwebglbinding.rs
@@ -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>> {
diff --git a/components/script/dom/xrwebgllayer.rs b/components/script/dom/xrwebgllayer.rs
index f93c4c22bc2..c4dd5999636 100644
--- a/components/script/dom/xrwebgllayer.rs
+++ b/components/script/dom/xrwebgllayer.rs
@@ -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,35 +175,24 @@ 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 session(&self) -> &XRSession {
- &self.session
+ pub fn context_id(&self) -> WebGLContextId {
+ self.context.context_id()
}
- 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 session(&self) -> &XRSession {
+ &self.session
}
pub fn size(&self) -> Size2D<u32, Viewport> {
@@ -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 {
diff --git a/components/script/dom/xrwebglsubimage.rs b/components/script/dom/xrwebglsubimage.rs
index 0331d36c4c2..0813bd85d9e 100644
--- a/components/script/dom/xrwebglsubimage.rs
+++ b/components/script/dom/xrwebglsubimage.rs
@@ -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
+ }
}
diff --git a/components/servo/Cargo.toml b/components/servo/Cargo.toml
index 2b52339e628..87c5e713f60 100644
--- a/components/servo/Cargo.toml
+++ b/components/servo/Cargo.toml
@@ -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" }
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index e518d1aaa3d..57dee7557dc 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -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,
diff --git a/components/webrender_surfman/#Cargo.toml# b/components/webrender_surfman/#Cargo.toml#
new file mode 100644
index 00000000000..8370ff4457d
--- /dev/null
+++ b/components/webrender_surfman/#Cargo.toml#
@@ -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"
+
diff --git a/components/webrender_surfman/.#Cargo.toml b/components/webrender_surfman/.#Cargo.toml
new file mode 120000
index 00000000000..0ab6459308a
--- /dev/null
+++ b/components/webrender_surfman/.#Cargo.toml
@@ -0,0 +1 @@
+ajeffrey@ajeffrey-home.4753:1592856534 \ No newline at end of file
diff --git a/components/webrender_surfman/Cargo.toml b/components/webrender_surfman/Cargo.toml
index e82f553d2cc..82ae827cbb7 100644
--- a/components/webrender_surfman/Cargo.toml
+++ b/components/webrender_surfman/Cargo.toml
@@ -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"
diff --git a/components/webrender_surfman/lib.rs b/components/webrender_surfman/lib.rs
index 193298808bc..530ca0ebfc7 100644
--- a/components/webrender_surfman/lib.rs
+++ b/components/webrender_surfman/lib.rs
@@ -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
diff --git a/ports/gstplugin/Cargo.toml b/ports/gstplugin/Cargo.toml
index ad7dc426431..dd45c6225a8 100644
--- a/ports/gstplugin/Cargo.toml
+++ b/ports/gstplugin/Cargo.toml
@@ -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]
diff --git a/ports/libsimpleservo/api/Cargo.toml b/ports/libsimpleservo/api/Cargo.toml
index 9fd37846f8e..17e914f5468 100644
--- a/ports/libsimpleservo/api/Cargo.toml
+++ b/ports/libsimpleservo/api/Cargo.toml
@@ -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"] }
diff --git a/ports/libsimpleservo/api/src/lib.rs b/ports/libsimpleservo/api/src/lib.rs
index cc2d84f9814..e0d2f46e71a 100644
--- a/ports/libsimpleservo/api/src/lib.rs
+++ b/ports/libsimpleservo/api/src/lib.rs
@@ -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");
diff --git a/ports/libsimpleservo/capi/Cargo.toml b/ports/libsimpleservo/capi/Cargo.toml
index ff481da0672..334a77f9198 100644
--- a/ports/libsimpleservo/capi/Cargo.toml
+++ b/ports/libsimpleservo/capi/Cargo.toml
@@ -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"
diff --git a/ports/winit/Cargo.toml b/ports/winit/Cargo.toml
index 5b6cc3b3c37..1091cdc4b17 100644
--- a/ports/winit/Cargo.toml
+++ b/ports/winit/Cargo.toml
@@ -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"
diff --git a/ports/winit/embedder.rs b/ports/winit/embedder.rs
index e770911cff8..039f003da19 100644
--- a/ports/winit/embedder.rs
+++ b/ports/winit/embedder.rs
@@ -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) {