From d4a27db9eeb95608c31efa3e2aab68d0aed5e288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fernando=20Jim=C3=A9nez=20Moreno?= Date: Tue, 28 Jul 2020 11:34:01 +0200 Subject: [PATCH] captureStream for WebGL content --- components/canvas/webgl_thread.rs | 20 +++++++++++++++++-- components/canvas_traits/webgl.rs | 2 ++ components/script/dom/gpucanvascontext.rs | 6 ++++++ components/script/dom/htmlcanvaselement.rs | 18 ++++++++++++++--- .../script/dom/webgl2renderingcontext.rs | 6 ++++++ .../script/dom/webglrenderingcontext.rs | 5 +++++ 6 files changed, 52 insertions(+), 5 deletions(-) diff --git a/components/canvas/webgl_thread.rs b/components/canvas/webgl_thread.rs index 3c27c52386668..c9648753763f0 100644 --- a/components/canvas/webgl_thread.rs +++ b/components/canvas/webgl_thread.rs @@ -47,6 +47,7 @@ use euclid::default::Size2D; use fnv::FnvHashMap; use half::f16; use pixels::{self, PixelFormat}; +use servo_media::ServoMedia; use sparkle::gl; use sparkle::gl::GLint; use sparkle::gl::GLuint; @@ -800,7 +801,6 @@ impl WebGLThread { completed_sender: WebGLSender, _sent_time: u64, ) { - debug!("handle_swap_buffers()"); for context_id in context_ids { let data = Self::make_current_if_needed_mut( &self.device, @@ -1069,7 +1069,7 @@ impl WebGLThread { /// Gets the GLSL Version supported by a GLContext. fn get_glsl_version(gl: &Gl) -> WebGLSLVersion { let version = gl.get_string(gl::SHADING_LANGUAGE_VERSION); - // Fomat used by SHADING_LANGUAGE_VERSION query : major.minor[.release] [vendor info] + // Format used by SHADING_LANGUAGE_VERSION query : major.minor[.release] [vendor info] let mut values = version.split(&['.', ' '][..]); let major = values .next() @@ -2208,6 +2208,22 @@ impl WebGLImpl { }, WebGLCommand::ReadBuffer(buffer) => gl.read_buffer(buffer), WebGLCommand::DrawBuffers(ref buffers) => gl.draw_buffers(buffers), + WebGLCommand::PushCapturedStreamsData(ref captured_streams, size) => { + // XXX(ferjm) This is currently returning all 0's. + // I suspect this requires https://github.com/servo/servo/issues/2460 + let pixels = gl.read_pixels( + 0, + 0, + size.width as gl::GLsizei, + size.height as gl::GLsizei, + gl::RGB, + gl::UNSIGNED_BYTE, + ); + let media = ServoMedia::get().unwrap(); + for stream in captured_streams.iter() { + media.push_stream_data(stream, pixels.clone()); + } + }, } // If debug asertions are enabled, then check the error state. diff --git a/components/canvas_traits/webgl.rs b/components/canvas_traits/webgl.rs index 175e5ab0937c2..2e92976d096d4 100644 --- a/components/canvas_traits/webgl.rs +++ b/components/canvas_traits/webgl.rs @@ -6,6 +6,7 @@ use euclid::default::{Rect, Size2D}; use ipc_channel::ipc::{IpcBytesReceiver, IpcBytesSender, IpcSharedMemory}; use pixels::PixelFormat; use serde::{Deserialize, Serialize}; +use servo_media::streams::registry::MediaStreamId; use sparkle::gl; use std::borrow::Cow; use std::fmt; @@ -511,6 +512,7 @@ pub enum WebGLCommand { FramebufferTextureLayer(u32, u32, Option, i32, i32), ReadBuffer(u32), DrawBuffers(Vec), + PushCapturedStreamsData(Vec, Size2D), } /// WebXR layer management diff --git a/components/script/dom/gpucanvascontext.rs b/components/script/dom/gpucanvascontext.rs index ca059fdec979a..6764d1e922249 100644 --- a/components/script/dom/gpucanvascontext.rs +++ b/components/script/dom/gpucanvascontext.rs @@ -19,6 +19,7 @@ use crate::dom::gpuswapchain::GPUSwapChain; use crate::dom::htmlcanvaselement::{HTMLCanvasElement, LayoutCanvasRenderingContextHelpers}; use crate::dom::node::{document_from_node, Node, NodeDamage}; use arrayvec::ArrayVec; +use canvas_traits::webgl::WebGLCommand; use dom_struct::dom_struct; use euclid::default::Size2D; use ipc_channel::ipc; @@ -119,6 +120,11 @@ impl LayoutCanvasRenderingContextHelpers for LayoutDom<'_, GPUCanvasContext> { unsafe fn canvas_data_source(self) -> HTMLCanvasDataSource { (*self.unsafe_get()).layout_handle() } + + #[allow(unsafe_code)] + unsafe fn send_command(self, _: WebGLCommand) { + unimplemented!(); + } } impl GPUCanvasContextMethods for GPUCanvasContext { diff --git a/components/script/dom/htmlcanvaselement.rs b/components/script/dom/htmlcanvaselement.rs index 698a7f97ea693..92904148671fc 100644 --- a/components/script/dom/htmlcanvaselement.rs +++ b/components/script/dom/htmlcanvaselement.rs @@ -31,7 +31,7 @@ use crate::dom::webglrenderingcontext::WebGLRenderingContext; use crate::script_runtime::JSContext; use base64; use canvas_traits::canvas::{CanvasId, CanvasMsg, FromScriptMsg}; -use canvas_traits::webgl::{GLContextAttributes, WebGLVersion}; +use canvas_traits::webgl::{GLContextAttributes, WebGLCommand, WebGLVersion}; use dom_struct::dom_struct; use euclid::default::{Rect, Size2D}; use html5ever::{LocalName, Prefix}; @@ -123,6 +123,8 @@ impl HTMLCanvasElement { pub trait LayoutCanvasRenderingContextHelpers { #[allow(unsafe_code)] unsafe fn canvas_data_source(self) -> HTMLCanvasDataSource; + #[allow(unsafe_code)] + unsafe fn send_command(self, command: WebGLCommand); } pub trait LayoutHTMLCanvasElementHelpers { @@ -164,10 +166,20 @@ impl LayoutHTMLCanvasElementHelpers for LayoutDom<'_, HTMLCanvasElement> { HTMLCanvasDataSource::Image(Some(renderer)) }, Some(&CanvasContext::WebGL(ref context)) => { - context.to_layout().canvas_data_source() + let context = context.to_layout(); + context.send_command(WebGLCommand::PushCapturedStreamsData( + self.get_captured_streams(), + Size2D::new(width.into(), height.into()), + )); + context.canvas_data_source() }, Some(&CanvasContext::WebGL2(ref context)) => { - context.to_layout().canvas_data_source() + let context = context.to_layout(); + context.send_command(WebGLCommand::PushCapturedStreamsData( + self.get_captured_streams(), + Size2D::new(width.into(), height.into()), + )); + context.canvas_data_source() }, Some(&CanvasContext::WebGPU(ref context)) => { context.to_layout().canvas_data_source() diff --git a/components/script/dom/webgl2renderingcontext.rs b/components/script/dom/webgl2renderingcontext.rs index b6a34dbc60a92..6c5332ee6752d 100644 --- a/components/script/dom/webgl2renderingcontext.rs +++ b/components/script/dom/webgl2renderingcontext.rs @@ -4469,4 +4469,10 @@ impl LayoutCanvasRenderingContextHelpers for LayoutDom<'_, WebGL2RenderingContex let this = &*self.unsafe_get(); (*this.base.to_layout().unsafe_get()).layout_handle() } + + #[allow(unsafe_code)] + unsafe fn send_command(self, command: WebGLCommand) { + let this = &*self.unsafe_get(); + (*this.base.to_layout().unsafe_get()).send_command(command); + } } diff --git a/components/script/dom/webglrenderingcontext.rs b/components/script/dom/webglrenderingcontext.rs index 168d31fdf5d21..c4d65a8118622 100644 --- a/components/script/dom/webglrenderingcontext.rs +++ b/components/script/dom/webglrenderingcontext.rs @@ -4723,6 +4723,11 @@ impl LayoutCanvasRenderingContextHelpers for LayoutDom<'_, WebGLRenderingContext unsafe fn canvas_data_source(self) -> HTMLCanvasDataSource { (*self.unsafe_get()).layout_handle() } + + #[allow(unsafe_code)] + unsafe fn send_command(self, command: WebGLCommand) { + (*self.unsafe_get()).send_command(command); + } } #[derive(Default, JSTraceable, MallocSizeOf)]