mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Use surfman for managing GL surfaces
Co-authored-by: Alan Jeffrey <ajeffrey@mozilla.com> Co-authored-by: Zakor Gyula <gyula.zakor@h-lab.eu> Co-authored-by: Josh Matthews <josh@joshmatthews.net>
This commit is contained in:
parent
48d918dcde
commit
a358bca766
52 changed files with 1929 additions and 2195 deletions
|
@ -47,11 +47,10 @@ use canvas_traits::canvas::{
|
|||
use canvas_traits::canvas::{CompositionOrBlending, LineCapStyle, LineJoinStyle, RepetitionStyle};
|
||||
use canvas_traits::webgl::WebGLVertexArrayId;
|
||||
use canvas_traits::webgl::{ActiveAttribInfo, ActiveUniformInfo, GlType, TexDataType, TexFormat};
|
||||
use canvas_traits::webgl::{GLFormats, GLLimits, WebGLQueryId, WebGLSamplerId};
|
||||
use canvas_traits::webgl::{
|
||||
WebGLBufferId, WebGLChan, WebGLContextId, WebGLContextShareMode, WebGLError,
|
||||
};
|
||||
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;
|
||||
|
@ -147,6 +146,7 @@ use time::{Duration, Timespec};
|
|||
use uuid::Uuid;
|
||||
use webrender_api::{DocumentId, ImageKey, RenderApiSender};
|
||||
use webvr_traits::{WebVRGamepadData, WebVRGamepadHand, WebVRGamepadState};
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
|
||||
/// A trait to allow tracing (only) DOM objects.
|
||||
pub unsafe trait JSTraceable {
|
||||
|
@ -451,7 +451,7 @@ unsafe_no_jsmanaged_fields!(StorageType);
|
|||
unsafe_no_jsmanaged_fields!(CanvasGradientStop, LinearGradientStyle, RadialGradientStyle);
|
||||
unsafe_no_jsmanaged_fields!(LineCapStyle, LineJoinStyle, CompositionOrBlending);
|
||||
unsafe_no_jsmanaged_fields!(RepetitionStyle);
|
||||
unsafe_no_jsmanaged_fields!(WebGLError, GLFormats, GLLimits, GlType);
|
||||
unsafe_no_jsmanaged_fields!(WebGLError, GLLimits, GlType);
|
||||
unsafe_no_jsmanaged_fields!(TimeProfilerChan);
|
||||
unsafe_no_jsmanaged_fields!(MemProfilerChan);
|
||||
unsafe_no_jsmanaged_fields!(PseudoElement);
|
||||
|
@ -486,8 +486,9 @@ unsafe_no_jsmanaged_fields!(DocumentId);
|
|||
unsafe_no_jsmanaged_fields!(ImageKey);
|
||||
unsafe_no_jsmanaged_fields!(WebGLBufferId);
|
||||
unsafe_no_jsmanaged_fields!(WebGLChan);
|
||||
unsafe_no_jsmanaged_fields!(WebGLContextShareMode);
|
||||
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);
|
||||
|
@ -500,6 +501,7 @@ unsafe_no_jsmanaged_fields!(WebGLTextureId);
|
|||
unsafe_no_jsmanaged_fields!(WebGLVertexArrayId);
|
||||
unsafe_no_jsmanaged_fields!(WebGLVersion);
|
||||
unsafe_no_jsmanaged_fields!(WebGLSLVersion);
|
||||
unsafe_no_jsmanaged_fields!(WebXRSwapChainId);
|
||||
unsafe_no_jsmanaged_fields!(MediaList);
|
||||
unsafe_no_jsmanaged_fields!(WebVRGamepadData, WebVRGamepadState, WebVRGamepadHand);
|
||||
unsafe_no_jsmanaged_fields!(
|
||||
|
|
|
@ -98,6 +98,7 @@ use crate::dom::treewalker::TreeWalker;
|
|||
use crate::dom::uievent::UIEvent;
|
||||
use crate::dom::virtualmethods::vtable_for;
|
||||
use crate::dom::webglcontextevent::WebGLContextEvent;
|
||||
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use crate::dom::wheelevent::WheelEvent;
|
||||
use crate::dom::window::{ReflowReason, Window};
|
||||
use crate::dom::windowproxy::WindowProxy;
|
||||
|
@ -109,7 +110,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, WebGLContextId, WebGLMsg};
|
||||
use canvas_traits::webgl::{self, SwapChainId, WebGLContextId, WebGLMsg};
|
||||
use content_security_policy::{self as csp, CspList};
|
||||
use cookie::Cookie;
|
||||
use devtools_traits::ScriptToDevtoolsControlMsg;
|
||||
|
@ -399,7 +400,7 @@ pub struct Document {
|
|||
/// hosting the media controls UI.
|
||||
media_controls: DomRefCell<HashMap<String, Dom<ShadowRoot>>>,
|
||||
/// List of all WebGL context IDs that need flushing.
|
||||
dirty_webgl_contexts: DomRefCell<HashSet<WebGLContextId>>,
|
||||
dirty_webgl_contexts: DomRefCell<HashMap<WebGLContextId, Dom<WebGLRenderingContext>>>,
|
||||
/// https://html.spec.whatwg.org/multipage/#concept-document-csp-list
|
||||
#[ignore_malloc_size_of = "Defined in rust-content-security-policy"]
|
||||
csp_list: DomRefCell<Option<CspList>>,
|
||||
|
@ -2486,15 +2487,26 @@ impl Document {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn add_dirty_canvas(&self, context_id: WebGLContextId) {
|
||||
self.dirty_webgl_contexts.borrow_mut().insert(context_id);
|
||||
pub fn add_dirty_canvas(&self, context: &WebGLRenderingContext) {
|
||||
self.dirty_webgl_contexts
|
||||
.borrow_mut()
|
||||
.entry(context.context_id())
|
||||
.or_insert_with(|| Dom::from_ref(context));
|
||||
}
|
||||
|
||||
pub fn flush_dirty_canvases(&self) {
|
||||
let dirty_context_ids: Vec<_> = self.dirty_webgl_contexts.borrow_mut().drain().collect();
|
||||
let dirty_context_ids: Vec<_> = self
|
||||
.dirty_webgl_contexts
|
||||
.borrow_mut()
|
||||
.drain()
|
||||
.filter(|(_, context)| context.onscreen())
|
||||
.map(|(id, _)| SwapChainId::Context(id))
|
||||
.collect();
|
||||
|
||||
if dirty_context_ids.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
let (sender, receiver) = webgl::webgl_channel().unwrap();
|
||||
self.window
|
||||
.webgl_chan()
|
||||
|
@ -2797,7 +2809,7 @@ impl Document {
|
|||
shadow_roots: DomRefCell::new(HashSet::new()),
|
||||
shadow_roots_styles_changed: Cell::new(false),
|
||||
media_controls: DomRefCell::new(HashMap::new()),
|
||||
dirty_webgl_contexts: DomRefCell::new(HashSet::new()),
|
||||
dirty_webgl_contexts: DomRefCell::new(HashMap::new()),
|
||||
csp_list: DomRefCell::new(None),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1426,6 +1426,6 @@ impl LayoutCanvasWebGLRenderingContextHelpers for LayoutDom<WebGL2RenderingConte
|
|||
#[allow(unsafe_code)]
|
||||
unsafe fn canvas_data_source(&self) -> HTMLCanvasDataSource {
|
||||
let this = &*self.unsafe_get();
|
||||
HTMLCanvasDataSource::WebGL((*this.base.to_layout().unsafe_get()).layout_handle())
|
||||
(*this.base.to_layout().unsafe_get()).layout_handle()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,15 +8,20 @@ use crate::dom::bindings::codegen::Bindings::WebGLFramebufferBinding;
|
|||
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||
use crate::dom::bindings::inheritance::Castable;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot};
|
||||
use crate::dom::bindings::root::{Dom, DomRoot, MutNullableDom};
|
||||
use crate::dom::webglobject::WebGLObject;
|
||||
use crate::dom::webglrenderbuffer::WebGLRenderbuffer;
|
||||
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use crate::dom::webgltexture::WebGLTexture;
|
||||
use crate::dom::xrsession::XRSession;
|
||||
use canvas_traits::webgl::{webgl_channel, WebGLError, WebGLResult};
|
||||
use canvas_traits::webgl::{WebGLCommand, WebGLFramebufferBindingRequest, WebGLFramebufferId};
|
||||
use canvas_traits::webgl::{WebGLCommand, WebGLFramebufferBindingRequest};
|
||||
use canvas_traits::webgl::{WebGLFramebufferId, WebGLOpaqueFramebufferId};
|
||||
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 {
|
||||
Complete,
|
||||
|
@ -92,6 +97,9 @@ pub struct WebGLFramebuffer {
|
|||
stencil: DomRefCell<Option<WebGLFramebufferAttachment>>,
|
||||
depthstencil: DomRefCell<Option<WebGLFramebufferAttachment>>,
|
||||
is_initialized: Cell<bool>,
|
||||
// Framebuffers for XR keep a reference to the XR session.
|
||||
// https://github.com/immersive-web/webxr/issues/856
|
||||
xr_session: MutNullableDom<XRSession>,
|
||||
}
|
||||
|
||||
impl WebGLFramebuffer {
|
||||
|
@ -108,16 +116,37 @@ impl WebGLFramebuffer {
|
|||
stencil: DomRefCell::new(None),
|
||||
depthstencil: DomRefCell::new(None),
|
||||
is_initialized: Cell::new(false),
|
||||
xr_session: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn maybe_new(context: &WebGLRenderingContext) -> Option<DomRoot<Self>> {
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
context.send_command(WebGLCommand::CreateFramebuffer(sender));
|
||||
receiver
|
||||
.recv()
|
||||
.unwrap()
|
||||
.map(|id| WebGLFramebuffer::new(context, id))
|
||||
let id = receiver.recv().unwrap()?;
|
||||
let framebuffer = WebGLFramebuffer::new(context, WebGLFramebufferId::Transparent(id));
|
||||
Some(framebuffer)
|
||||
}
|
||||
|
||||
// TODO: depth, stencil and alpha
|
||||
// https://github.com/servo/servo/issues/24498
|
||||
pub fn maybe_new_webxr(
|
||||
session: &XRSession,
|
||||
context: &WebGLRenderingContext,
|
||||
size: Size2D<i32, Viewport>,
|
||||
) -> Option<(WebXRSwapChainId, DomRoot<Self>)> {
|
||||
let (sender, receiver) = webgl_channel().unwrap();
|
||||
let _ = context
|
||||
.webgl_sender()
|
||||
.send_create_webxr_swap_chain(size.to_untyped(), sender);
|
||||
let swap_chain_id = receiver.recv().unwrap()?;
|
||||
let framebuffer_id =
|
||||
WebGLFramebufferId::Opaque(WebGLOpaqueFramebufferId::WebXR(swap_chain_id));
|
||||
let framebuffer = WebGLFramebuffer::new(context, framebuffer_id);
|
||||
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))
|
||||
}
|
||||
|
||||
pub fn new(context: &WebGLRenderingContext, id: WebGLFramebufferId) -> DomRoot<Self> {
|
||||
|
@ -134,11 +163,25 @@ impl WebGLFramebuffer {
|
|||
self.id
|
||||
}
|
||||
|
||||
fn is_in_xr_session(&self) -> bool {
|
||||
self.xr_session.get().is_some()
|
||||
}
|
||||
|
||||
pub fn validate_transparent(&self) -> WebGLResult<()> {
|
||||
if self.is_in_xr_session() {
|
||||
Err(WebGLError::InvalidOperation)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn bind(&self, target: u32) {
|
||||
// Update the framebuffer status on binding. It may have
|
||||
// changed if its attachments were resized or deleted while
|
||||
// we've been unbound.
|
||||
self.update_status();
|
||||
if !self.is_in_xr_session() {
|
||||
// Update the framebuffer status on binding. It may have
|
||||
// changed if its attachments were resized or deleted while
|
||||
// we've been unbound.
|
||||
self.update_status();
|
||||
}
|
||||
|
||||
self.target.set(Some(target));
|
||||
self.upcast::<WebGLObject>()
|
||||
|
@ -267,7 +310,17 @@ impl WebGLFramebuffer {
|
|||
}
|
||||
|
||||
pub fn check_status(&self) -> u32 {
|
||||
return self.status.get();
|
||||
// For opaque framebuffers, check to see if the XR session is currently processing an rAF
|
||||
// https://immersive-web.github.io/webxr/#opaque-framebuffer
|
||||
if let Some(xr_session) = self.xr_session.get() {
|
||||
if xr_session.is_outside_raf() {
|
||||
constants::FRAMEBUFFER_UNSUPPORTED
|
||||
} else {
|
||||
constants::FRAMEBUFFER_COMPLETE
|
||||
}
|
||||
} else {
|
||||
self.status.get()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check_status_for_rendering(&self) -> CompleteForRendering {
|
||||
|
@ -276,6 +329,12 @@ impl WebGLFramebuffer {
|
|||
return CompleteForRendering::Incomplete;
|
||||
}
|
||||
|
||||
// XR framebuffers are complete inside an rAF
|
||||
// https://github.com/immersive-web/webxr/issues/854
|
||||
if self.xr_session.get().is_some() {
|
||||
return CompleteForRendering::Complete;
|
||||
}
|
||||
|
||||
if self.color.borrow().is_none() {
|
||||
return CompleteForRendering::MissingColorAttachment;
|
||||
}
|
||||
|
@ -309,6 +368,10 @@ impl WebGLFramebuffer {
|
|||
}
|
||||
|
||||
pub fn renderbuffer(&self, attachment: u32, rb: Option<&WebGLRenderbuffer>) -> WebGLResult<()> {
|
||||
// Opaque framebuffers cannot have their attachments changed
|
||||
// https://immersive-web.github.io/webxr/#opaque-framebuffer
|
||||
self.validate_transparent()?;
|
||||
|
||||
let binding = self
|
||||
.attachment_binding(attachment)
|
||||
.ok_or(WebGLError::InvalidEnum)?;
|
||||
|
@ -337,7 +400,7 @@ impl WebGLFramebuffer {
|
|||
));
|
||||
|
||||
if rb.is_none() {
|
||||
self.detach_binding(binding, attachment);
|
||||
self.detach_binding(binding, attachment)?;
|
||||
}
|
||||
|
||||
self.update_status();
|
||||
|
@ -349,14 +412,19 @@ impl WebGLFramebuffer {
|
|||
&self,
|
||||
binding: &DomRefCell<Option<WebGLFramebufferAttachment>>,
|
||||
attachment: u32,
|
||||
) {
|
||||
) -> WebGLResult<()> {
|
||||
// Opaque framebuffers cannot have their attachments changed
|
||||
// https://immersive-web.github.io/webxr/#opaque-framebuffer
|
||||
self.validate_transparent()?;
|
||||
|
||||
if let Some(att) = &*binding.borrow() {
|
||||
att.detach();
|
||||
}
|
||||
*binding.borrow_mut() = None;
|
||||
if INTERESTING_ATTACHMENT_POINTS.contains(&attachment) {
|
||||
self.reattach_depth_stencil();
|
||||
self.reattach_depth_stencil()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn attachment_binding(
|
||||
|
@ -372,7 +440,11 @@ impl WebGLFramebuffer {
|
|||
}
|
||||
}
|
||||
|
||||
fn reattach_depth_stencil(&self) {
|
||||
fn reattach_depth_stencil(&self) -> WebGLResult<()> {
|
||||
// Opaque framebuffers cannot have their attachments changed
|
||||
// https://immersive-web.github.io/webxr/#opaque-framebuffer
|
||||
self.validate_transparent()?;
|
||||
|
||||
let reattach = |attachment: &WebGLFramebufferAttachment, attachment_point| {
|
||||
let context = self.upcast::<WebGLObject>().context();
|
||||
match *attachment {
|
||||
|
@ -411,6 +483,7 @@ impl WebGLFramebuffer {
|
|||
if let Some(ref depth_stencil) = *self.depthstencil.borrow() {
|
||||
reattach(depth_stencil, constants::DEPTH_STENCIL_ATTACHMENT);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn attachment(&self, attachment: u32) -> Option<WebGLFramebufferAttachmentRoot> {
|
||||
|
@ -428,6 +501,10 @@ impl WebGLFramebuffer {
|
|||
texture: Option<&WebGLTexture>,
|
||||
level: i32,
|
||||
) -> WebGLResult<()> {
|
||||
// Opaque framebuffers cannot have their attachments changed
|
||||
// https://immersive-web.github.io/webxr/#opaque-framebuffer
|
||||
self.validate_transparent()?;
|
||||
|
||||
let binding = self
|
||||
.attachment_binding(attachment)
|
||||
.ok_or(WebGLError::InvalidEnum)?;
|
||||
|
@ -498,7 +575,7 @@ impl WebGLFramebuffer {
|
|||
));
|
||||
|
||||
if texture.is_none() {
|
||||
self.detach_binding(binding, attachment);
|
||||
self.detach_binding(binding, attachment)?;
|
||||
}
|
||||
|
||||
self.update_status();
|
||||
|
@ -563,7 +640,11 @@ impl WebGLFramebuffer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn detach_renderbuffer(&self, rb: &WebGLRenderbuffer) {
|
||||
pub fn detach_renderbuffer(&self, rb: &WebGLRenderbuffer) -> WebGLResult<()> {
|
||||
// Opaque framebuffers cannot have their attachments changed
|
||||
// https://immersive-web.github.io/webxr/#opaque-framebuffer
|
||||
self.validate_transparent()?;
|
||||
|
||||
let mut depth_or_stencil_updated = false;
|
||||
self.with_matching_renderbuffers(rb, |att, name| {
|
||||
depth_or_stencil_updated |= INTERESTING_ATTACHMENT_POINTS.contains(&name);
|
||||
|
@ -575,11 +656,16 @@ impl WebGLFramebuffer {
|
|||
});
|
||||
|
||||
if depth_or_stencil_updated {
|
||||
self.reattach_depth_stencil();
|
||||
self.reattach_depth_stencil()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn detach_texture(&self, texture: &WebGLTexture) {
|
||||
pub fn detach_texture(&self, texture: &WebGLTexture) -> WebGLResult<()> {
|
||||
// Opaque framebuffers cannot have their attachments changed
|
||||
// https://immersive-web.github.io/webxr/#opaque-framebuffer
|
||||
self.validate_transparent()?;
|
||||
|
||||
let mut depth_or_stencil_updated = false;
|
||||
self.with_matching_textures(texture, |att, name| {
|
||||
depth_or_stencil_updated |= INTERESTING_ATTACHMENT_POINTS.contains(&name);
|
||||
|
@ -591,8 +677,9 @@ impl WebGLFramebuffer {
|
|||
});
|
||||
|
||||
if depth_or_stencil_updated {
|
||||
self.reattach_depth_stencil();
|
||||
self.reattach_depth_stencil()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn invalidate_renderbuffer(&self, rb: &WebGLRenderbuffer) {
|
||||
|
@ -615,7 +702,7 @@ impl WebGLFramebuffer {
|
|||
|
||||
impl Drop for WebGLFramebuffer {
|
||||
fn drop(&mut self) {
|
||||
self.delete(true);
|
||||
let _ = self.delete(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -392,10 +392,12 @@ impl WebGLProgram {
|
|||
sender,
|
||||
));
|
||||
let location = receiver.recv().unwrap();
|
||||
let context_id = self.upcast::<WebGLObject>().context().context_id();
|
||||
|
||||
Ok(Some(WebGLUniformLocation::new(
|
||||
self.global().as_window(),
|
||||
location,
|
||||
context_id,
|
||||
self.id,
|
||||
self.link_generation.get(),
|
||||
size,
|
||||
|
|
|
@ -106,7 +106,7 @@ impl WebGLRenderbuffer {
|
|||
let currently_bound_framebuffer =
|
||||
self.upcast::<WebGLObject>().context().bound_framebuffer();
|
||||
if let Some(fb) = currently_bound_framebuffer {
|
||||
fb.detach_renderbuffer(self);
|
||||
let _ = fb.detach_renderbuffer(self);
|
||||
}
|
||||
|
||||
let context = self.upcast::<WebGLObject>().context();
|
||||
|
|
|
@ -54,11 +54,11 @@ use crate::script_runtime::JSContext as SafeJSContext;
|
|||
use backtrace::Backtrace;
|
||||
use canvas_traits::webgl::WebGLError::*;
|
||||
use canvas_traits::webgl::{
|
||||
webgl_channel, AlphaTreatment, DOMToTextureCommand, GLContextAttributes, GLFormats, GLLimits,
|
||||
GlType, Parameter, TexDataType, TexFormat, TexParameter, WebGLChan, WebGLCommand,
|
||||
WebGLCommandBacktrace, WebGLContextId, WebGLContextShareMode, WebGLError,
|
||||
WebGLFramebufferBindingRequest, WebGLMsg, WebGLMsgSender, WebGLProgramId, WebGLResult,
|
||||
WebGLSLVersion, WebGLSendResult, WebGLSender, WebGLVersion, WebVRCommand, YAxisTreatment,
|
||||
webgl_channel, AlphaTreatment, DOMToTextureCommand, GLContextAttributes, GLLimits, GlType,
|
||||
Parameter, TexDataType, TexFormat, TexParameter, WebGLChan, WebGLCommand,
|
||||
WebGLCommandBacktrace, WebGLContextId, WebGLError, WebGLFramebufferBindingRequest, WebGLMsg,
|
||||
WebGLMsgSender, WebGLOpaqueFramebufferId, WebGLProgramId, WebGLResult, WebGLSLVersion,
|
||||
WebGLSendResult, WebGLSender, WebGLVersion, WebVRCommand, YAxisTreatment,
|
||||
};
|
||||
use dom_struct::dom_struct;
|
||||
use embedder_traits::EventLoopWaker;
|
||||
|
@ -81,6 +81,7 @@ use std::cell::Cell;
|
|||
use std::cmp;
|
||||
use std::ptr::{self, NonNull};
|
||||
use std::rc::Rc;
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
|
||||
// From the GLES 2.0.25 spec, page 85:
|
||||
//
|
||||
|
@ -130,10 +131,9 @@ pub struct WebGLRenderingContext {
|
|||
webgl_sender: WebGLMessageSender,
|
||||
#[ignore_malloc_size_of = "Defined in webrender"]
|
||||
webrender_image: webrender_api::ImageKey,
|
||||
share_mode: WebGLContextShareMode,
|
||||
webgl_version: WebGLVersion,
|
||||
glsl_version: WebGLSLVersion,
|
||||
#[ignore_malloc_size_of = "Defined in offscreen_gl_context"]
|
||||
#[ignore_malloc_size_of = "Defined in surfman"]
|
||||
limits: GLLimits,
|
||||
canvas: Dom<HTMLCanvasElement>,
|
||||
#[ignore_malloc_size_of = "Defined in canvas_traits"]
|
||||
|
@ -160,7 +160,6 @@ pub struct WebGLRenderingContext {
|
|||
current_vao: MutNullableDom<WebGLVertexArrayObjectOES>,
|
||||
textures: Textures,
|
||||
api_type: GlType,
|
||||
framebuffer_format: GLFormats,
|
||||
}
|
||||
|
||||
impl WebGLRenderingContext {
|
||||
|
@ -195,7 +194,6 @@ impl WebGLRenderingContext {
|
|||
window.get_event_loop_waker(),
|
||||
),
|
||||
webrender_image: ctx_data.image_key,
|
||||
share_mode: ctx_data.share_mode,
|
||||
webgl_version,
|
||||
glsl_version: ctx_data.glsl_version,
|
||||
limits: ctx_data.limits,
|
||||
|
@ -220,7 +218,6 @@ impl WebGLRenderingContext {
|
|||
current_vao: Default::default(),
|
||||
textures: Textures::new(max_combined_texture_image_units),
|
||||
api_type: ctx_data.api_type,
|
||||
framebuffer_format: ctx_data.framebuffer_format,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -292,7 +289,7 @@ impl WebGLRenderingContext {
|
|||
self.send_command(WebGLCommand::Scissor(rect.0, rect.1, rect.2, rect.3));
|
||||
|
||||
// Bound texture must not change when the canvas is resized.
|
||||
// Right now offscreen_gl_context generates a new FBO and the bound texture is changed
|
||||
// Right now surfman generates a new FBO and the bound texture is changed
|
||||
// in order to create a new render to texture attachment.
|
||||
// Send a command to re-bind the TEXTURE_2D, if any.
|
||||
if let Some(texture) = self
|
||||
|
@ -308,7 +305,7 @@ impl WebGLRenderingContext {
|
|||
}
|
||||
|
||||
// Bound framebuffer must not change when the canvas is resized.
|
||||
// Right now offscreen_gl_context generates a new FBO on resize.
|
||||
// Right now surfman generates a new FBO on resize.
|
||||
// Send a command to re-bind the framebuffer, if any.
|
||||
if let Some(fbo) = self.bound_framebuffer.get() {
|
||||
let id = WebGLFramebufferBindingRequest::Explicit(fbo.id());
|
||||
|
@ -324,6 +321,10 @@ impl WebGLRenderingContext {
|
|||
self.webgl_sender.context_id()
|
||||
}
|
||||
|
||||
pub fn onscreen(&self) -> bool {
|
||||
self.canvas.upcast::<Node>().is_connected()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn send_command(&self, command: WebGLCommand) {
|
||||
self.webgl_sender
|
||||
|
@ -337,6 +338,10 @@ impl WebGLRenderingContext {
|
|||
.send(command, capture_webgl_backtrace(self));
|
||||
}
|
||||
|
||||
pub fn swap_buffers(&self, id: Option<WebGLOpaqueFramebufferId>) {
|
||||
let _ = self.webgl_sender.send_swap_buffers(id);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn send_vr_command(&self, command: WebVRCommand) {
|
||||
self.webgl_sender.send_vr(command).unwrap();
|
||||
|
@ -462,7 +467,7 @@ impl WebGLRenderingContext {
|
|||
.dirty(NodeDamage::OtherNodeDamage);
|
||||
|
||||
let document = document_from_node(&*self.canvas);
|
||||
document.add_dirty_canvas(self.context_id());
|
||||
document.add_dirty_canvas(self);
|
||||
}
|
||||
|
||||
fn vertex_attrib(&self, indx: u32, x: f32, y: f32, z: f32, w: f32) {
|
||||
|
@ -810,8 +815,9 @@ impl WebGLRenderingContext {
|
|||
receiver.recv().unwrap()
|
||||
}
|
||||
|
||||
pub fn layout_handle(&self) -> webrender_api::ImageKey {
|
||||
self.webrender_image
|
||||
pub(crate) fn layout_handle(&self) -> HTMLCanvasDataSource {
|
||||
let image_key = self.webrender_image;
|
||||
HTMLCanvasDataSource::WebGL(image_key)
|
||||
}
|
||||
|
||||
// https://www.khronos.org/registry/webgl/extensions/ANGLE_instanced_arrays/
|
||||
|
@ -1086,17 +1092,9 @@ impl WebGLRenderingContext {
|
|||
self.bound_framebuffer.get()
|
||||
}
|
||||
|
||||
pub fn bound_renderbuffer(&self) -> Option<DomRoot<WebGLRenderbuffer>> {
|
||||
self.bound_renderbuffer.get()
|
||||
}
|
||||
|
||||
pub fn extension_manager(&self) -> &WebGLExtensions {
|
||||
&self.extension_manager
|
||||
}
|
||||
|
||||
pub fn formats(&self) -> &GLFormats {
|
||||
&self.framebuffer_format
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "webgl_backtrace"))]
|
||||
|
@ -2225,6 +2223,10 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.6
|
||||
fn DeleteFramebuffer(&self, framebuffer: Option<&WebGLFramebuffer>) {
|
||||
if let Some(framebuffer) = framebuffer {
|
||||
// https://immersive-web.github.io/webxr/#opaque-framebuffer
|
||||
// Can opaque framebuffers be deleted?
|
||||
// https://github.com/immersive-web/webxr/issues/855
|
||||
handle_potential_webgl_error!(self, framebuffer.validate_transparent(), return);
|
||||
handle_potential_webgl_error!(self, self.validate_ownership(framebuffer), return);
|
||||
handle_object_deletion!(
|
||||
self,
|
||||
|
@ -2384,7 +2386,11 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
pname: u32,
|
||||
) -> JSVal {
|
||||
// Check if currently bound framebuffer is non-zero as per spec.
|
||||
if self.bound_framebuffer.get().is_none() {
|
||||
if let Some(fb) = self.bound_framebuffer.get() {
|
||||
// Opaque framebuffers cannot have their attachments inspected
|
||||
// https://immersive-web.github.io/webxr/#opaque-framebuffer
|
||||
handle_potential_webgl_error!(self, fb.validate_transparent(), return NullValue());
|
||||
} else {
|
||||
self.webgl_error(InvalidOperation);
|
||||
return NullValue();
|
||||
}
|
||||
|
@ -2487,6 +2493,8 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
|
||||
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.7
|
||||
fn GetRenderbufferParameter(&self, _cx: SafeJSContext, target: u32, pname: u32) -> JSVal {
|
||||
// We do not check to see if the renderbuffer came from an opaque framebuffer
|
||||
// https://github.com/immersive-web/webxr/issues/862
|
||||
let target_matches = target == constants::RENDERBUFFER;
|
||||
|
||||
let pname_matches = match pname {
|
||||
|
@ -3477,6 +3485,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
|
||||
if program.is_deleted() ||
|
||||
!program.is_linked() ||
|
||||
self.context_id() != location.context_id() ||
|
||||
program.id() != location.program_id() ||
|
||||
program.link_generation() != location.link_generation()
|
||||
{
|
||||
|
@ -4153,7 +4162,7 @@ pub trait LayoutCanvasWebGLRenderingContextHelpers {
|
|||
impl LayoutCanvasWebGLRenderingContextHelpers for LayoutDom<WebGLRenderingContext> {
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn canvas_data_source(&self) -> HTMLCanvasDataSource {
|
||||
HTMLCanvasDataSource::WebGL((*self.unsafe_get()).layout_handle())
|
||||
(*self.unsafe_get()).layout_handle()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4347,7 +4356,7 @@ impl TexPixels {
|
|||
}
|
||||
|
||||
#[derive(JSTraceable)]
|
||||
pub(crate) struct WebGLCommandSender {
|
||||
pub struct WebGLCommandSender {
|
||||
sender: WebGLChan,
|
||||
waker: Option<Box<dyn EventLoopWaker>>,
|
||||
}
|
||||
|
@ -4410,6 +4419,18 @@ impl WebGLMessageSender {
|
|||
self.wake_after_send(|| self.sender.send_vr(command))
|
||||
}
|
||||
|
||||
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>>,
|
||||
) -> WebGLSendResult {
|
||||
self.wake_after_send(|| self.sender.send_create_webxr_swap_chain(size, sender))
|
||||
}
|
||||
|
||||
pub fn send_resize(
|
||||
&self,
|
||||
size: Size2D<u32>,
|
||||
|
|
|
@ -210,7 +210,7 @@ impl WebGLTexture {
|
|||
let currently_bound_framebuffer =
|
||||
self.upcast::<WebGLObject>().context().bound_framebuffer();
|
||||
if let Some(fb) = currently_bound_framebuffer {
|
||||
fb.detach_texture(self);
|
||||
let _ = fb.detach_texture(self);
|
||||
}
|
||||
|
||||
let cmd = WebGLCommand::DeleteTexture(self.id);
|
||||
|
|
|
@ -7,6 +7,7 @@ use crate::dom::bindings::codegen::Bindings::WebGLUniformLocationBinding;
|
|||
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector};
|
||||
use crate::dom::bindings::root::DomRoot;
|
||||
use crate::dom::window::Window;
|
||||
use canvas_traits::webgl::WebGLContextId;
|
||||
use canvas_traits::webgl::WebGLProgramId;
|
||||
use dom_struct::dom_struct;
|
||||
|
||||
|
@ -14,6 +15,7 @@ use dom_struct::dom_struct;
|
|||
pub struct WebGLUniformLocation {
|
||||
reflector_: Reflector,
|
||||
id: i32,
|
||||
context_id: WebGLContextId,
|
||||
program_id: WebGLProgramId,
|
||||
link_generation: u64,
|
||||
size: Option<i32>,
|
||||
|
@ -23,6 +25,7 @@ pub struct WebGLUniformLocation {
|
|||
impl WebGLUniformLocation {
|
||||
fn new_inherited(
|
||||
id: i32,
|
||||
context_id: WebGLContextId,
|
||||
program_id: WebGLProgramId,
|
||||
link_generation: u64,
|
||||
size: Option<i32>,
|
||||
|
@ -31,6 +34,7 @@ impl WebGLUniformLocation {
|
|||
Self {
|
||||
reflector_: Reflector::new(),
|
||||
id,
|
||||
context_id,
|
||||
program_id,
|
||||
link_generation,
|
||||
size,
|
||||
|
@ -41,6 +45,7 @@ impl WebGLUniformLocation {
|
|||
pub fn new(
|
||||
window: &Window,
|
||||
id: i32,
|
||||
context_id: WebGLContextId,
|
||||
program_id: WebGLProgramId,
|
||||
link_generation: u64,
|
||||
size: Option<i32>,
|
||||
|
@ -49,6 +54,7 @@ impl WebGLUniformLocation {
|
|||
reflect_dom_object(
|
||||
Box::new(Self::new_inherited(
|
||||
id,
|
||||
context_id,
|
||||
program_id,
|
||||
link_generation,
|
||||
size,
|
||||
|
@ -67,6 +73,10 @@ impl WebGLUniformLocation {
|
|||
self.program_id
|
||||
}
|
||||
|
||||
pub fn context_id(&self) -> WebGLContextId {
|
||||
self.context_id
|
||||
}
|
||||
|
||||
pub fn link_generation(&self) -> u64 {
|
||||
self.link_generation
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ use crate::compartments::InCompartment;
|
|||
use crate::dom::bindings::callback::ExceptionHandling;
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::NavigatorBinding::NavigatorBinding::NavigatorMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::WindowBinding::WindowBinding::WindowMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::XRReferenceSpaceBinding::XRReferenceSpaceType;
|
||||
|
@ -30,7 +29,6 @@ use crate::dom::globalscope::GlobalScope;
|
|||
use crate::dom::node::Node;
|
||||
use crate::dom::node::NodeDamage;
|
||||
use crate::dom::promise::Promise;
|
||||
use crate::dom::webglframebuffer::WebGLFramebufferAttachmentRoot;
|
||||
use crate::dom::xrframe::XRFrame;
|
||||
use crate::dom::xrinputsourcearray::XRInputSourceArray;
|
||||
use crate::dom::xrinputsourceevent::XRInputSourceEvent;
|
||||
|
@ -41,7 +39,6 @@ use crate::dom::xrspace::XRSpace;
|
|||
use crate::dom::xrwebgllayer::XRWebGLLayer;
|
||||
use crate::task_source::TaskSource;
|
||||
use dom_struct::dom_struct;
|
||||
use euclid::default::Size2D;
|
||||
use euclid::RigidTransform3D;
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use ipc_channel::router::ROUTER;
|
||||
|
@ -77,6 +74,9 @@ pub struct XRSession {
|
|||
end_promises: DomRefCell<Vec<Rc<Promise>>>,
|
||||
/// https://immersive-web.github.io/webxr/#ended
|
||||
ended: Cell<bool>,
|
||||
/// Opaque framebuffers need to know the session is "outside of a requestAnimationFrame"
|
||||
/// https://immersive-web.github.io/webxr/#opaque-framebuffer
|
||||
outside_raf: Cell<bool>,
|
||||
}
|
||||
|
||||
impl XRSession {
|
||||
|
@ -102,6 +102,7 @@ impl XRSession {
|
|||
input_sources: Dom::from_ref(input_sources),
|
||||
end_promises: DomRefCell::new(vec![]),
|
||||
ended: Cell::new(false),
|
||||
outside_raf: Cell::new(true),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,6 +170,10 @@ impl XRSession {
|
|||
self.session.borrow_mut().request_animation_frame(sender);
|
||||
}
|
||||
|
||||
pub fn is_outside_raf(&self) -> bool {
|
||||
self.outside_raf.get()
|
||||
}
|
||||
|
||||
fn attach_event_handler(&self) {
|
||||
let this = Trusted::new(self);
|
||||
let global = self.global();
|
||||
|
@ -276,6 +281,8 @@ impl XRSession {
|
|||
|
||||
/// https://immersive-web.github.io/webxr/#xr-animation-frame
|
||||
fn raf_callback(&self, (time, mut frame): (f64, Frame)) {
|
||||
debug!("WebXR RAF callback");
|
||||
|
||||
// Step 1
|
||||
if let Some(pending) = self.pending_render_state.take() {
|
||||
// https://immersive-web.github.io/webxr/#apply-the-pending-render-state
|
||||
|
@ -285,19 +292,8 @@ impl XRSession {
|
|||
// Step 6-7: XXXManishearth handle inlineVerticalFieldOfView
|
||||
|
||||
// XXXManishearth handle inline sessions and composition disabled flag
|
||||
if let Some(layer) = pending.GetBaseLayer() {
|
||||
let attachment = layer.framebuffer().attachment(constants::COLOR_ATTACHMENT0);
|
||||
if let Some(WebGLFramebufferAttachmentRoot::Texture(texture)) = attachment {
|
||||
let context = layer.Context().context_id().0;
|
||||
let texture_id = texture.id().get();
|
||||
if let Some((width, height)) = layer.framebuffer().size() {
|
||||
let size = Size2D::new(width, height);
|
||||
self.session
|
||||
.borrow_mut()
|
||||
.set_texture(context, texture_id, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
let swap_chain_id = pending.GetBaseLayer().map(|layer| layer.swap_chain_id());
|
||||
self.session.borrow_mut().set_swap_chain(swap_chain_id);
|
||||
}
|
||||
|
||||
for event in frame.events.drain(..) {
|
||||
|
@ -321,13 +317,16 @@ impl XRSession {
|
|||
frame.set_animation_frame(true);
|
||||
|
||||
// Step 8
|
||||
self.outside_raf.set(false);
|
||||
for (_, callback) in callbacks.drain(..) {
|
||||
if let Some(callback) = callback {
|
||||
let _ = callback.Call__(Finite::wrap(time), &frame, ExceptionHandling::Report);
|
||||
}
|
||||
}
|
||||
self.outside_raf.set(true);
|
||||
|
||||
frame.set_active(false);
|
||||
base_layer.swap_buffers();
|
||||
self.session.borrow_mut().render_animation_frame();
|
||||
self.request_new_xr_frame();
|
||||
|
||||
|
|
|
@ -2,27 +2,26 @@
|
|||
* 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::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::XRViewBinding::{XREye, XRViewMethods};
|
||||
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding;
|
||||
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerInit;
|
||||
use crate::dom::bindings::codegen::Bindings::XRWebGLLayerBinding::XRWebGLLayerMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextBinding::WebGLRenderingContextMethods;
|
||||
use crate::dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLRenderingContextConstants as constants;
|
||||
use crate::dom::bindings::error::Error;
|
||||
use crate::dom::bindings::error::Fallible;
|
||||
use crate::dom::bindings::reflector::{reflect_dom_object, Reflector, DomObject};
|
||||
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::webgl_validations::types::TexImageTarget;
|
||||
use crate::dom::webglframebuffer::WebGLFramebuffer;
|
||||
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use crate::dom::window::Window;
|
||||
use crate::dom::xrsession::XRSession;
|
||||
use crate::dom::xrview::XRView;
|
||||
use crate::dom::xrviewport::XRViewport;
|
||||
use canvas_traits::webgl::WebGLFramebufferId;
|
||||
use dom_struct::dom_struct;
|
||||
use js::rust::CustomAutoRooter;
|
||||
use std::convert::TryInto;
|
||||
use webxr_api::SwapChainId as WebXRSwapChainId;
|
||||
use webxr_api::Views;
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -32,6 +31,8 @@ pub struct XRWebGLLayer {
|
|||
depth: bool,
|
||||
stencil: bool,
|
||||
alpha: bool,
|
||||
#[ignore_malloc_size_of = "ids don't malloc"]
|
||||
swap_chain_id: WebXRSwapChainId,
|
||||
context: Dom<WebGLRenderingContext>,
|
||||
session: Dom<XRSession>,
|
||||
framebuffer: Dom<WebGLFramebuffer>,
|
||||
|
@ -39,6 +40,7 @@ pub struct XRWebGLLayer {
|
|||
|
||||
impl XRWebGLLayer {
|
||||
pub fn new_inherited(
|
||||
swap_chain_id: WebXRSwapChainId,
|
||||
session: &XRSession,
|
||||
context: &WebGLRenderingContext,
|
||||
init: &XRWebGLLayerInit,
|
||||
|
@ -50,6 +52,7 @@ impl XRWebGLLayer {
|
|||
depth: init.depth,
|
||||
stencil: init.stencil,
|
||||
alpha: init.alpha,
|
||||
swap_chain_id,
|
||||
context: Dom::from_ref(context),
|
||||
session: Dom::from_ref(session),
|
||||
framebuffer: Dom::from_ref(framebuffer),
|
||||
|
@ -58,6 +61,7 @@ impl XRWebGLLayer {
|
|||
|
||||
pub fn new(
|
||||
global: &GlobalScope,
|
||||
swap_chain_id: WebXRSwapChainId,
|
||||
session: &XRSession,
|
||||
context: &WebGLRenderingContext,
|
||||
init: &XRWebGLLayerInit,
|
||||
|
@ -65,6 +69,7 @@ impl XRWebGLLayer {
|
|||
) -> DomRoot<XRWebGLLayer> {
|
||||
reflect_dom_object(
|
||||
Box::new(XRWebGLLayer::new_inherited(
|
||||
swap_chain_id,
|
||||
session,
|
||||
context,
|
||||
init,
|
||||
|
@ -89,108 +94,16 @@ impl XRWebGLLayer {
|
|||
// XXXManishearth step 3: throw error if context is lost
|
||||
// XXXManishearth step 4: check XR compat flag for immersive sessions
|
||||
|
||||
let cx = global.get_cx();
|
||||
let old_fbo = context.bound_framebuffer();
|
||||
let old_rbo = context.bound_renderbuffer();
|
||||
let old_texture = context
|
||||
.textures()
|
||||
.active_texture_for_image_target(TexImageTarget::Texture2D);
|
||||
|
||||
// Step 9.2. "Initialize layer’s framebuffer to a new opaque framebuffer created with
|
||||
// context and layerInit’s depth, stencil, and alpha values."
|
||||
let framebuffer = context.CreateFramebuffer().ok_or(Error::Operation)?;
|
||||
// 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());
|
||||
let (swap_chain_id, 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."
|
||||
|
||||
// Create a new texture with size given by the session's recommended resolution
|
||||
let texture = context.CreateTexture().ok_or(Error::Operation)?;
|
||||
let render_buffer = context.CreateRenderbuffer().ok_or(Error::Operation)?;
|
||||
let resolution = session.with_session(|s| s.recommended_framebuffer_resolution());
|
||||
let mut pixels = CustomAutoRooter::new(None);
|
||||
let mut clear_bits = constants::COLOR_BUFFER_BIT;
|
||||
|
||||
let formats = context.formats();
|
||||
|
||||
context.BindTexture(constants::TEXTURE_2D, Some(&texture));
|
||||
let sc = context.TexImage2D(
|
||||
constants::TEXTURE_2D,
|
||||
0,
|
||||
formats.texture_format,
|
||||
resolution.width,
|
||||
resolution.height,
|
||||
0,
|
||||
formats.texture_format,
|
||||
formats.texture_type,
|
||||
pixels.root(*cx),
|
||||
);
|
||||
|
||||
// Bind the new texture to the framebuffer
|
||||
context.BindFramebuffer(constants::FRAMEBUFFER, Some(&framebuffer));
|
||||
context.FramebufferTexture2D(
|
||||
constants::FRAMEBUFFER,
|
||||
constants::COLOR_ATTACHMENT0,
|
||||
constants::TEXTURE_2D,
|
||||
Some(&texture),
|
||||
0,
|
||||
);
|
||||
|
||||
// Create backing store and bind a renderbuffer if requested
|
||||
if init.depth || init.stencil {
|
||||
let (internal_format, attachment) = if init.depth && init.stencil {
|
||||
clear_bits |= constants::DEPTH_BUFFER_BIT | constants::STENCIL_BUFFER_BIT;
|
||||
(
|
||||
constants::DEPTH_STENCIL,
|
||||
constants::DEPTH_STENCIL_ATTACHMENT,
|
||||
)
|
||||
} else if init.depth {
|
||||
clear_bits |= constants::DEPTH_BUFFER_BIT;
|
||||
(constants::DEPTH_COMPONENT16, constants::DEPTH_ATTACHMENT)
|
||||
} else {
|
||||
clear_bits |= constants::STENCIL_BUFFER_BIT;
|
||||
(constants::STENCIL_INDEX8, constants::STENCIL_ATTACHMENT)
|
||||
};
|
||||
context.BindRenderbuffer(constants::RENDERBUFFER, Some(&render_buffer));
|
||||
context.RenderbufferStorage(
|
||||
constants::RENDERBUFFER,
|
||||
internal_format,
|
||||
resolution.width,
|
||||
resolution.height,
|
||||
);
|
||||
context.FramebufferRenderbuffer(
|
||||
constants::FRAMEBUFFER,
|
||||
attachment,
|
||||
constants::RENDERBUFFER,
|
||||
Some(&render_buffer),
|
||||
);
|
||||
}
|
||||
|
||||
context.initialize_framebuffer(clear_bits);
|
||||
|
||||
// Restore the WebGL state while complaining about global mutable state
|
||||
let fb_status = context.CheckFramebufferStatus(constants::FRAMEBUFFER);
|
||||
let gl_status = context.GetError();
|
||||
context.BindTexture(constants::TEXTURE_2D, old_texture.as_ref().map(|t| &**t));
|
||||
context.BindFramebuffer(constants::FRAMEBUFFER, old_fbo.as_ref().map(|f| &**f));
|
||||
context.BindRenderbuffer(constants::RENDERBUFFER, old_rbo.as_ref().map(|f| &**f));
|
||||
|
||||
// Step 9.4: "If layer’s resources were unable to be created for any reason,
|
||||
// throw an OperationError and abort these steps."
|
||||
if let Err(err) = sc {
|
||||
error!("TexImage2D error {:?} while creating XR context", err);
|
||||
return Err(Error::Operation);
|
||||
}
|
||||
if fb_status != constants::FRAMEBUFFER_COMPLETE {
|
||||
error!(
|
||||
"Framebuffer error {:x} while creating XR context",
|
||||
fb_status
|
||||
);
|
||||
return Err(Error::Operation);
|
||||
}
|
||||
if gl_status != constants::NO_ERROR {
|
||||
error!("GL error {:x} while creating XR context", gl_status);
|
||||
return Err(Error::Operation);
|
||||
}
|
||||
|
||||
// Ensure that we finish setting up this layer before continuing.
|
||||
context.Finish();
|
||||
|
@ -198,6 +111,7 @@ impl XRWebGLLayer {
|
|||
// Step 10. "Return layer."
|
||||
Ok(XRWebGLLayer::new(
|
||||
&global.global(),
|
||||
swap_chain_id,
|
||||
session,
|
||||
context,
|
||||
init,
|
||||
|
@ -205,12 +119,18 @@ impl XRWebGLLayer {
|
|||
))
|
||||
}
|
||||
|
||||
pub fn swap_chain_id(&self) -> WebXRSwapChainId {
|
||||
self.swap_chain_id
|
||||
}
|
||||
|
||||
pub fn session(&self) -> &XRSession {
|
||||
&self.session
|
||||
}
|
||||
|
||||
pub fn framebuffer(&self) -> &WebGLFramebuffer {
|
||||
&self.framebuffer
|
||||
pub fn swap_buffers(&self) {
|
||||
if let WebGLFramebufferId::Opaque(id) = self.framebuffer.id() {
|
||||
self.context.swap_buffers(Some(id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue