Skip to content

Add VRCompositor commands for WebVR #603

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion webrender/src/render_backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use webrender_traits::{ApiMsg, AuxiliaryLists, BuiltDisplayList, IdNamespace, Im
use webrender_traits::{FlushNotifier, RenderNotifier, RenderDispatcher, WebGLCommand, WebGLContextId};
use webrender_traits::{DeviceIntSize};
use webrender_traits::channel::{PayloadHelperMethods, PayloadReceiver, PayloadSender, MsgReceiver};
use webrender_traits::{VRCompositorCommand, VRCompositorHandler};
use tiling::FrameBuilderConfig;
use offscreen_gl_context::GLContextDispatcher;

Expand Down Expand Up @@ -50,6 +51,8 @@ pub struct RenderBackend {
main_thread_dispatcher: Arc<Mutex<Option<Box<RenderDispatcher>>>>,

next_webgl_id: usize,

vr_compositor_handler: Arc<Mutex<Option<Box<VRCompositorHandler>>>>
}

impl RenderBackend {
Expand All @@ -66,7 +69,8 @@ impl RenderBackend {
config: FrameBuilderConfig,
debug: bool,
enable_recording:bool,
main_thread_dispatcher: Arc<Mutex<Option<Box<RenderDispatcher>>>>) -> RenderBackend {
main_thread_dispatcher: Arc<Mutex<Option<Box<RenderDispatcher>>>>,
vr_compositor_handler: Arc<Mutex<Option<Box<VRCompositorHandler>>>>) -> RenderBackend {

let resource_cache = ResourceCache::new(texture_cache,
enable_aa);
Expand All @@ -89,6 +93,7 @@ impl RenderBackend {
enable_recording:enable_recording,
main_thread_dispatcher: main_thread_dispatcher,
next_webgl_id: 0,
vr_compositor_handler: vr_compositor_handler
}
}

Expand Down Expand Up @@ -336,6 +341,10 @@ impl RenderBackend {
ctx.make_current();
ctx.apply_command(command);
self.current_bound_webgl_context_id = Some(context_id);
},

ApiMsg::VRCompositorCommand(context_id, command) => {
self.handle_vr_compositor_command(context_id, command);
}
ApiMsg::GenerateFrame => {
let frame = profile_counters.total_time.profile(|| {
Expand Down Expand Up @@ -469,6 +478,20 @@ impl RenderBackend {
let mut notifier = self.notifier.lock();
notifier.as_mut().unwrap().as_mut().unwrap().new_scroll_frame_ready(composite_needed);
}

fn handle_vr_compositor_command(&mut self, ctx_id: WebGLContextId, cmd: VRCompositorCommand) {
let texture = match cmd {
VRCompositorCommand::SubmitFrame(..) => {
match self.resource_cache.get_webgl_texture(&ctx_id).texture_id {
SourceTexture::WebGL(texture_id) => Some(texture_id),
_=> None
}
},
_ => None
};
let mut handler = self.vr_compositor_handler.lock();
handler.as_mut().unwrap().as_mut().unwrap().handle(cmd, texture);
}
}

struct WebRenderGLDispatcher {
Expand Down
21 changes: 20 additions & 1 deletion webrender/src/renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ use webrender_traits::{ColorF, Epoch, FlushNotifier, PipelineId, RenderNotifier,
use webrender_traits::{ExternalImageId, ImageFormat, RenderApiSender, RendererKind};
use webrender_traits::{DeviceSize, DevicePoint, DeviceIntPoint, DeviceIntSize, DeviceUintSize};
use webrender_traits::channel;
use webrender_traits::VRCompositorHandler;

pub const MAX_VERTEX_TEXTURE_WIDTH: usize = 1024;

Expand Down Expand Up @@ -419,6 +420,10 @@ pub struct Renderer {

/// Map of external image IDs to native textures.
external_images: HashMap<ExternalImageId, TextureId, BuildHasherDefault<FnvHasher>>,

// Optional trait object that handles WebVR commands.
// Some WebVR commands such as SubmitFrame must be synced with the WebGL render thread.
vr_compositor_handler: Arc<Mutex<Option<Box<VRCompositorHandler>>>>
}

impl Renderer {
Expand Down Expand Up @@ -680,6 +685,9 @@ impl Renderer {
let backend_main_thread_dispatcher = main_thread_dispatcher.clone();
let backend_flush_notifier = flush_notifier.clone();

let vr_compositor = Arc::new(Mutex::new(None));
let backend_vr_compositor = vr_compositor.clone();

// We need a reference to the webrender context from the render backend in order to share
// texture ids
let context_handle = match options.renderer_kind {
Expand Down Expand Up @@ -708,7 +716,8 @@ impl Renderer {
config,
debug,
enable_recording,
backend_main_thread_dispatcher);
backend_main_thread_dispatcher,
backend_vr_compositor);
backend.run();
});

Expand Down Expand Up @@ -770,6 +779,7 @@ impl Renderer {
cache_texture_id_map: Vec::new(),
external_image_handler: None,
external_images: HashMap::with_hasher(Default::default()),
vr_compositor_handler: vr_compositor
};

let sender = RenderApiSender::new(api_tx, payload_tx);
Expand Down Expand Up @@ -803,6 +813,15 @@ impl Renderer {
*dispatcher_arc = Some(dispatcher);
}

/// Sets the VRCompositorHandler.
///
/// It's used to handle WebVR render commands.
/// Some WebVR commands such as Vsync and SubmitFrame must be called in the WebGL render thread.
pub fn set_vr_compositor_handler(&self, creator: Box<VRCompositorHandler>) {
let mut handler_arc = self.vr_compositor_handler.lock().unwrap();
*handler_arc = Some(creator);
}

/// Returns the Epoch of the current frame in a pipeline.
pub fn current_epoch(&self, pipeline_id: PipelineId) -> Option<Epoch> {
self.pipeline_epoch_map.get(&pipeline_id).map(|epoch| *epoch)
Expand Down
6 changes: 6 additions & 0 deletions webrender_traits/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use {ApiMsg, ColorF, DisplayListBuilder, Epoch};
use {FontKey, IdNamespace, ImageFormat, ImageKey, NativeFontHandle, PipelineId};
use {RenderApiSender, ResourceId, ScrollEventPhase, ScrollLayerState, ScrollLocation, ServoScrollRootId};
use {GlyphKey, GlyphDimensions, ImageData, WebGLContextId, WebGLCommand};
use VRCompositorCommand;

impl RenderApiSender {
pub fn new(api_sender: MsgSender<ApiMsg>,
Expand Down Expand Up @@ -245,6 +246,11 @@ impl RenderApi {
self.api_sender.send(msg).unwrap();
}

pub fn send_vr_compositor_command(&self, context_id: WebGLContextId, command: VRCompositorCommand) {
let msg = ApiMsg::VRCompositorCommand(context_id, command);
self.api_sender.send(msg).unwrap();
}

#[inline]
fn next_unique_id(&self) -> (u32, u32) {
let IdNamespace(namespace) = self.id_namespace;
Expand Down
19 changes: 19 additions & 0 deletions webrender_traits/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ pub enum ApiMsg {
ResizeWebGLContext(WebGLContextId, Size2D<i32>),
WebGLCommand(WebGLContextId, WebGLCommand),
GenerateFrame,
// WebVR commands that must be called in the WebGL render thread.
VRCompositorCommand(WebGLContextId, VRCompositorCommand)
}

#[derive(Copy, Clone, Deserialize, Serialize, Debug)]
Expand Down Expand Up @@ -792,3 +794,20 @@ pub enum WebGLShaderParameter {
Bool(bool),
Invalid,
}

pub type VRCompositorId = u64;

// WebVR commands that must be called in the WebGL render thread.
#[derive(Clone, Deserialize, Serialize)]
pub enum VRCompositorCommand {
Create(VRCompositorId),
SyncPoses(VRCompositorId, f64, f64, MsgSender<Result<Vec<u8>,()>>),
SubmitFrame(VRCompositorId, [f32; 4], [f32; 4]),
Release(VRCompositorId)
}

// Trait object that handles WebVR commands.
// Receives the texture_id associated to the WebGLContext.
pub trait VRCompositorHandler: Send {
fn handle(&mut self, command: VRCompositorCommand, texture_id: Option<u32>);
}