Auto merge of #27538 - asajeffrey:webxr-texture-invalidation, r=Manishearth

Make textures that come from webxr invalid outside an rAF

<!-- Please describe your changes on the following line: -->

Implements "The colorTexture and depthStencilTexture objects MUST only be used during the XR animation frame of the current session and MUST be made invalid once the XR animation frame completes." from https://immersive-web.github.io/layers/#xrwebglsubimagetype

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `___` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] There are no tests for these changes because we can't test this until we have projection layers

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
This commit is contained in:
bors-servo 2020-08-06 22:57:35 -04:00 committed by GitHub
commit 080e9dc6df
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 40 additions and 21 deletions

View file

@ -205,6 +205,9 @@ impl WebGLFramebuffer {
}
pub fn is_deleted(&self) -> bool {
// TODO: if a framebuffer has an attachment which is invalid due to
// being outside a webxr rAF, should this make the framebuffer invalid?
// https://github.com/immersive-web/layers/issues/196
self.is_deleted.get()
}
@ -447,6 +450,9 @@ impl WebGLFramebuffer {
} else {
self.status.get()
}
// TODO: if a framebuffer has an attachment which is invalid due to
// being outside a webxr rAF, should this make the framebuffer incomplete?
// https://github.com/immersive-web/layers/issues/196
}
pub fn check_status_for_rendering(&self) -> CompleteForRendering {
@ -497,6 +503,10 @@ impl WebGLFramebuffer {
self.is_initialized.set(true);
}
// TODO: if a framebuffer has an attachment which is invalid due to
// being outside a webxr rAF, should this make the framebuffer incomplete?
// https://github.com/immersive-web/layers/issues/196
CompleteForRendering::Complete
}

View file

@ -3563,7 +3563,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
// https://www.khronos.org/registry/webgl/specs/latest/1.0/#5.14.8
fn IsTexture(&self, texture: Option<&WebGLTexture>) -> bool {
texture.map_or(false, |tex| {
self.validate_ownership(tex).is_ok() && tex.target().is_some() && !tex.is_deleted()
self.validate_ownership(tex).is_ok() && tex.target().is_some() && !tex.is_invalid()
})
}

View file

@ -9,11 +9,13 @@ use crate::dom::bindings::codegen::Bindings::EXTTextureFilterAnisotropicBinding:
use crate::dom::bindings::codegen::Bindings::WebGL2RenderingContextBinding::WebGL2RenderingContextConstants as constants;
use crate::dom::bindings::inheritance::Castable;
use crate::dom::bindings::reflector::{reflect_dom_object, DomObject};
use crate::dom::bindings::root::Dom;
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
use crate::dom::webgl_validations::types::TexImageTarget;
use crate::dom::webglframebuffer::WebGLFramebuffer;
use crate::dom::webglobject::WebGLObject;
use crate::dom::webglrenderingcontext::{Operation, WebGLRenderingContext};
use crate::dom::xrsession::XRSession;
use canvas_traits::webgl::{
webgl_channel, TexDataType, TexFormat, TexParameter, TexParameterBool, TexParameterInt,
WebGLResult, WebGLTextureId,
@ -31,10 +33,11 @@ pub enum TexParameterValue {
// Textures generated for WebXR are owned by the WebXR device, not by the WebGL thread
// so the GL texture should not be deleted when the texture is garbage collected.
#[derive(Clone, Copy, Debug, Eq, JSTraceable, MallocSizeOf, PartialEq)]
#[unrooted_must_root_lint::must_root]
#[derive(JSTraceable, MallocSizeOf)]
enum WebGLTextureOwner {
WebGL,
WebXR,
WebXR(Dom<XRSession>),
}
const MAX_LEVEL_COUNT: usize = 31;
@ -71,14 +74,16 @@ impl WebGLTexture {
fn new_inherited(
context: &WebGLRenderingContext,
id: WebGLTextureId,
owner: WebGLTextureOwner,
owner: Option<&XRSession>,
) -> Self {
Self {
webgl_object: WebGLObject::new_inherited(context),
id: id,
target: Cell::new(None),
is_deleted: Cell::new(false),
owner: owner,
owner: owner
.map(|session| WebGLTextureOwner::WebXR(Dom::from_ref(session)))
.unwrap_or(WebGLTextureOwner::WebGL),
immutable_levels: Cell::new(None),
face_count: Cell::new(0),
base_mipmap_level: 0,
@ -101,22 +106,18 @@ impl WebGLTexture {
pub fn new(context: &WebGLRenderingContext, id: WebGLTextureId) -> DomRoot<Self> {
reflect_dom_object(
Box::new(WebGLTexture::new_inherited(
context,
id,
WebGLTextureOwner::WebGL,
)),
Box::new(WebGLTexture::new_inherited(context, id, None)),
&*context.global(),
)
}
pub fn new_webxr(context: &WebGLRenderingContext, id: WebGLTextureId) -> DomRoot<Self> {
pub fn new_webxr(
context: &WebGLRenderingContext,
id: WebGLTextureId,
session: &XRSession,
) -> DomRoot<Self> {
reflect_dom_object(
Box::new(WebGLTexture::new_inherited(
context,
id,
WebGLTextureOwner::WebXR,
)),
Box::new(WebGLTexture::new_inherited(context, id, Some(session))),
&*context.global(),
)
}
@ -129,7 +130,7 @@ impl WebGLTexture {
// NB: Only valid texture targets come here
pub fn bind(&self, target: u32) -> WebGLResult<()> {
if self.is_deleted.get() {
if self.is_invalid() {
return Err(WebGLError::InvalidOperation);
}
@ -246,7 +247,7 @@ impl WebGLTexture {
}
// We don't delete textures owned by WebXR
if self.owner == WebGLTextureOwner::WebXR {
if let WebGLTextureOwner::WebXR(_) = self.owner {
return;
}
@ -258,7 +259,13 @@ impl WebGLTexture {
}
}
pub fn is_deleted(&self) -> bool {
pub fn is_invalid(&self) -> bool {
// https://immersive-web.github.io/layers/#xrwebglsubimagetype
if let WebGLTextureOwner::WebXR(ref session) = self.owner {
if session.is_outside_raf() {
return true;
}
}
self.is_deleted.get()
}

View file

@ -193,10 +193,11 @@ impl XRWebGLLayer {
let framebuffer = self.framebuffer.as_ref()?;
let context = framebuffer.upcast::<WebGLObject>().context();
let sub_images = frame.get_sub_images(self.layer_id()?)?;
let session = self.session();
// TODO: Cache this texture
let color_texture_id =
WebGLTextureId::maybe_new(sub_images.sub_image.as_ref()?.color_texture)?;
let color_texture = WebGLTexture::new_webxr(context, color_texture_id);
let color_texture = WebGLTexture::new_webxr(context, color_texture_id, session);
let target = self.texture_target();
// Save the current bindings
@ -230,7 +231,8 @@ impl XRWebGLLayer {
if let Some(id) = sub_images.sub_image.as_ref()?.depth_stencil_texture {
// TODO: Cache this texture
let depth_stencil_texture_id = WebGLTextureId::maybe_new(id)?;
let depth_stencil_texture = WebGLTexture::new_webxr(context, depth_stencil_texture_id);
let depth_stencil_texture =
WebGLTexture::new_webxr(context, depth_stencil_texture_id, session);
framebuffer
.texture2d_even_if_opaque(
constants::DEPTH_STENCIL_ATTACHMENT,