Skip to content
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

Implement GPUSwapChain and GPUCanvasContext and interface with Webrender #26872

Merged
merged 2 commits into from Jun 15, 2020
Merged
Changes from 1 commit
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Next

Implement GPUSwapChain and GPUCanvasContext and interface with Webrender

  • Loading branch information
kunalmohan committed Jun 13, 2020
commit 71401e0855c24e4cf86a754171f0162ae08d8e55

Some generated files are not rendered by default. Learn more.

@@ -22,7 +22,9 @@ use surfman_chains::SwapChains;
use surfman_chains_api::SwapChainAPI;
use surfman_chains_api::SwapChainsAPI;
use webrender_surfman::WebrenderSurfman;
use webrender_traits::{WebrenderExternalImageApi, WebrenderExternalImageRegistry};
use webrender_traits::{
WebrenderExternalImageApi, WebrenderExternalImageRegistry, WebrenderImageSource,
};
use webxr_api::SwapChainId as WebXRSwapChainId;

pub struct WebGLComm {
@@ -138,9 +140,10 @@ impl WebGLExternalImages {
}

impl WebrenderExternalImageApi for WebGLExternalImages {
fn lock(&mut self, id: u64) -> (u32, Size2D<i32>) {
fn lock(&mut self, id: u64) -> (WebrenderImageSource, Size2D<i32>) {
let id = WebGLContextId(id);
self.lock_swap_chain(id).unwrap_or_default()
let (texture_id, size) = self.lock_swap_chain(id).unwrap_or_default();
(WebrenderImageSource::TextureHandle(texture_id), size)
}

fn unlock(&mut self, id: u64) {
@@ -43,6 +43,7 @@ servo_url = { path = "../url" }
style_traits = { path = "../style_traits" }
webgpu = { path = "../webgpu" }
webrender_api = { git = "https://github.com/servo/webrender" }
webrender_traits = { path = "../webrender_traits" }
webxr-api = { git = "https://github.com/servo/webxr", features = ["ipc"] }

[target.'cfg(all(not(target_os = "windows"), not(target_os = "ios"), not(target_os="android"), not(target_arch="arm"), not(target_arch="aarch64")))'.dependencies]
@@ -172,11 +172,12 @@ use std::marker::PhantomData;
use std::mem::replace;
use std::process;
use std::rc::{Rc, Weak};
use std::sync::Arc;
use std::sync::{Arc, Mutex};
use std::thread;
use style_traits::viewport::ViewportConstraints;
use style_traits::CSSPixel;
use webgpu::{WebGPU, WebGPURequest};
use webgpu::{self, WebGPU, WebGPURequest};
use webrender_traits::WebrenderExternalImageRegistry;

type PendingApprovalNavigations = HashMap<PipelineId, (LoadData, HistoryEntryReplacement)>;

@@ -216,6 +217,18 @@ struct MessagePortInfo {
entangled_with: Option<MessagePortId>,
}

/// Webrender related objects required by WebGPU threads
struct WebrenderWGPU {
/// Webrender API.
webrender_api: webrender_api::RenderApi,

/// List of Webrender external images
webrender_external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,

/// WebGPU data that supplied to Webrender for rendering
wgpu_image_map: Arc<Mutex<HashMap<u64, webgpu::PresentationData>>>,
}

/// Servo supports tabs (referred to as browsers), so `Constellation` needs to
/// store browser specific data for bookkeeping.
struct Browser {
@@ -384,6 +397,9 @@ pub struct Constellation<Message, LTF, STF, SWF> {
/// A single WebRender document the constellation operates on.
webrender_document: webrender_api::DocumentId,

/// Webrender related objects required by WebGPU threads
webrender_wgpu: WebrenderWGPU,

/// A channel for content processes to send messages that will
/// be relayed to the WebRender thread.
webrender_api_ipc_sender: script_traits::WebrenderIpcSender,
@@ -533,6 +549,12 @@ pub struct InitialConstellationState {
/// Webrender document ID.
pub webrender_document: webrender_api::DocumentId,

/// Webrender API.
pub webrender_api_sender: webrender_api::RenderApiSender,

/// Webrender external images
pub webrender_external_images: Arc<Mutex<WebrenderExternalImageRegistry>>,

/// Entry point to create and get channels to a WebGLThread.
pub webgl_threads: Option<WebGLThreads>,

@@ -549,6 +571,8 @@ pub struct InitialConstellationState {

/// User agent string to report in network requests.
pub user_agent: Cow<'static, str>,

pub wgpu_image_map: Arc<Mutex<HashMap<u64, webgpu::PresentationData>>>,
}

/// Data needed for webdriver
@@ -834,6 +858,12 @@ where
}),
);

let webrender_wgpu = WebrenderWGPU {
webrender_api: state.webrender_api_sender.create_api(),
webrender_external_images: state.webrender_external_images,
wgpu_image_map: state.wgpu_image_map,
};

let mut constellation: Constellation<Message, LTF, STF, SWF> = Constellation {
namespace_receiver,
namespace_sender,
@@ -889,6 +919,7 @@ where
webrender_image_api_sender: net_traits::WebrenderIpcSender::new(
webrender_image_ipc_sender,
),
webrender_wgpu,
shutting_down: false,
handled_warnings: VecDeque::new(),
random_pipeline_closure: random_pipeline_closure_probability.map(|prob| {
@@ -1899,12 +1930,16 @@ where
EmbedderMsg::MediaSessionEvent(event),
));
},
FromScriptMsg::RequestAdapter(sender, options, ids) => self
.handle_request_wgpu_adapter(
source_pipeline_id,
BrowsingContextId::from(source_top_ctx_id),
FromScriptMsg::RequestAdapter(sender, options, ids),
),
FromScriptMsg::RequestAdapter(sender, options, ids) => self.handle_wgpu_request(
source_pipeline_id,
BrowsingContextId::from(source_top_ctx_id),
FromScriptMsg::RequestAdapter(sender, options, ids),
),
FromScriptMsg::GetWebGPUChan(sender) => self.handle_wgpu_request(
source_pipeline_id,
BrowsingContextId::from(source_top_ctx_id),
FromScriptMsg::GetWebGPUChan(sender),
),
}
}

@@ -2072,7 +2107,7 @@ where
}
}

fn handle_request_wgpu_adapter(
fn handle_wgpu_request(
&mut self,
source_pipeline_id: PipelineId,
browsing_context_id: BrowsingContextId,
@@ -2090,46 +2125,62 @@ where
Some(host) => host,
None => return warn!("Invalid host url"),
};
match self
let browsing_context_group = if let Some(bcg) = self
.browsing_context_group_set
.get_mut(&browsing_context_group_id)
{
Some(browsing_context_group) => {
let adapter_request =
if let FromScriptMsg::RequestAdapter(sender, options, ids) = request {
WebGPURequest::RequestAdapter {
sender,
options,
ids,
}
} else {
return warn!("Wrong message type in handle_request_wgpu_adapter");
};
let send = match browsing_context_group.webgpus.entry(host) {
Entry::Vacant(v) => v
.insert(match WebGPU::new() {
Some(webgpu) => {
let msg = ConstellationControlMsg::SetWebGPUPort(webgpu.1);
if let Err(e) = source_pipeline.event_loop.send(msg) {
warn!(
"Failed to send SetWebGPUPort to pipeline {} ({:?})",
source_pipeline_id, e
);
}
webgpu.0
},
None => return warn!("Failed to create new WebGPU thread"),
})
.0
.send(adapter_request),
Entry::Occupied(o) => o.get().0.send(adapter_request),
bcg
} else {
return warn!("Browsing context group not found");
};
let webgpu_chan = match browsing_context_group.webgpus.entry(host) {
Entry::Vacant(v) => v
.insert(
match WebGPU::new(
self.webrender_wgpu.webrender_api.create_sender(),
self.webrender_document,
self.webrender_wgpu.webrender_external_images.clone(),
self.webrender_wgpu.wgpu_image_map.clone(),
) {
Some(webgpu) => {
let msg = ConstellationControlMsg::SetWebGPUPort(webgpu.1);
if let Err(e) = source_pipeline.event_loop.send(msg) {
warn!(
"Failed to send SetWebGPUPort to pipeline {} ({:?})",
source_pipeline_id, e
);
}
webgpu.0
},
None => {
return warn!("Failed to create new WebGPU thread");
},
},
)
.clone(),
Entry::Occupied(o) => o.get().clone(),
};
match request {
FromScriptMsg::RequestAdapter(sender, options, ids) => {
let adapter_request = WebGPURequest::RequestAdapter {
sender,
options,
ids,
};
if send.is_err() {
if webgpu_chan.0.send(adapter_request).is_err() {
return warn!("Failed to send request adapter message on WebGPU channel");
}
},
None => return warn!("Browsing context group not found"),
};
FromScriptMsg::GetWebGPUChan(sender) => {
if sender.send(webgpu_chan).is_err() {
return warn!(
"Failed to send WebGPU channel to Pipeline {:?}",
source_pipeline_id
);
}
},
_ => return warn!("Wrong message type in handle_wgpu_request"),
}
}

fn handle_request_from_layout(&mut self, message: FromLayoutMsg) {
@@ -1905,6 +1905,7 @@ impl Fragment {

let image_key = match canvas_fragment_info.source {
CanvasFragmentSource::WebGL(image_key) => image_key,
CanvasFragmentSource::WebGPU(image_key) => image_key,
CanvasFragmentSource::Image(ref ipc_renderer) => match *ipc_renderer {
Some(ref ipc_renderer) => {
let ipc_renderer = ipc_renderer.lock().unwrap();
@@ -338,6 +338,7 @@ impl InlineAbsoluteFragmentInfo {
pub enum CanvasFragmentSource {
WebGL(webrender_api::ImageKey),
Image(Option<Arc<Mutex<IpcSender<CanvasMsg>>>>),
WebGPU(webrender_api::ImageKey),
}

#[derive(Clone)]
@@ -355,6 +356,7 @@ impl CanvasFragmentInfo {
HTMLCanvasDataSource::Image(ipc_sender) => CanvasFragmentSource::Image(
ipc_sender.map(|renderer| Arc::new(Mutex::new(renderer))),
),
HTMLCanvasDataSource::WebGPU(image_key) => CanvasFragmentSource::WebGPU(image_key),
};

CanvasFragmentInfo {
@@ -20,7 +20,9 @@ use crate::media_thread::GLPlayerThread;
use euclid::default::Size2D;
use servo_media::player::context::{GlApi, GlContext, NativeDisplay, PlayerGLContext};
use std::sync::{Arc, Mutex};
use webrender_traits::{WebrenderExternalImageApi, WebrenderExternalImageRegistry};
use webrender_traits::{
WebrenderExternalImageApi, WebrenderExternalImageRegistry, WebrenderImageSource,
};

/// These are the messages that the GLPlayer thread will forward to
/// the video player which lives in htmlmediaelement
@@ -146,7 +148,7 @@ impl GLPlayerExternalImages {
}

impl WebrenderExternalImageApi for GLPlayerExternalImages {
fn lock(&mut self, id: u64) -> (u32, Size2D<i32>) {
fn lock(&mut self, id: u64) -> (WebrenderImageSource, Size2D<i32>) {
// The GLPlayerMsgForward::Lock message inserts a fence in the
// GLPlayer command queue.
self.glplayer_channel
@@ -160,7 +162,7 @@ impl WebrenderExternalImageApi for GLPlayerExternalImages {
// internal OpenGL subsystem.
//self.webrender_gl
// .wait_sync(gl_sync as gl::GLsync, 0, gl::TIMEOUT_IGNORED);
(image_id, size)
(WebrenderImageSource::TextureHandle(image_id), size)
}

fn unlock(&mut self, id: u64) {
@@ -37,6 +37,7 @@ use crate::dom::bindings::root::{Dom, DomRoot};
use crate::dom::bindings::str::{DOMString, USVString};
use crate::dom::bindings::utils::WindowProxyHandler;
use crate::dom::gpubuffer::GPUBufferState;
use crate::dom::gpucanvascontext::WebGPUContextId;
use crate::dom::gpucommandencoder::GPUCommandEncoderState;
use crate::dom::htmlimageelement::SourceSet;
use crate::dom::htmlmediaelement::{HTMLMediaElementFetchContext, MediaFrameRenderer};
@@ -168,7 +169,7 @@ use webgpu::{
WebGPUPipelineLayout, WebGPUQueue, WebGPURenderPipeline, WebGPUSampler, WebGPUShaderModule,
WebGPUTexture, WebGPUTextureView,
};
use webrender_api::{DocumentId, ImageKey};
use webrender_api::{DocumentId, ExternalImageId, ImageKey};
use webxr_api::SwapChainId as WebXRSwapChainId;
use webxr_api::{Finger, Hand, Ray, View};

@@ -541,6 +542,7 @@ unsafe_no_jsmanaged_fields!(PathBuf);
unsafe_no_jsmanaged_fields!(DrawAPaintImageResult);
unsafe_no_jsmanaged_fields!(DocumentId);
unsafe_no_jsmanaged_fields!(ImageKey);
unsafe_no_jsmanaged_fields!(ExternalImageId);
unsafe_no_jsmanaged_fields!(WebGLBufferId);
unsafe_no_jsmanaged_fields!(WebGLChan);
unsafe_no_jsmanaged_fields!(WebGLFramebufferId);
@@ -572,6 +574,7 @@ unsafe_no_jsmanaged_fields!(WebGPUShaderModule);
unsafe_no_jsmanaged_fields!(WebGPUSampler);
unsafe_no_jsmanaged_fields!(WebGPUTexture);
unsafe_no_jsmanaged_fields!(WebGPUTextureView);
unsafe_no_jsmanaged_fields!(WebGPUContextId);
unsafe_no_jsmanaged_fields!(WebGPUCommandBuffer);
unsafe_no_jsmanaged_fields!(WebGPUCommandEncoder);
unsafe_no_jsmanaged_fields!(WebGPUDevice);
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.