mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Implement GPUSwapChain and GPUCanvasContext and interface with Webrender
This commit is contained in:
parent
73760ea594
commit
71401e0855
28 changed files with 882 additions and 91 deletions
|
@ -20,13 +20,12 @@ use crate::dom::canvasrenderingcontext2d::{
|
|||
use crate::dom::document::Document;
|
||||
use crate::dom::element::{AttributeMutation, Element, LayoutElementHelpers};
|
||||
use crate::dom::globalscope::GlobalScope;
|
||||
use crate::dom::gpucanvascontext::GPUCanvasContext;
|
||||
use crate::dom::htmlelement::HTMLElement;
|
||||
use crate::dom::node::{window_from_node, Node};
|
||||
use crate::dom::virtualmethods::VirtualMethods;
|
||||
use crate::dom::webgl2renderingcontext::WebGL2RenderingContext;
|
||||
use crate::dom::webglrenderingcontext::{
|
||||
LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext,
|
||||
};
|
||||
use crate::dom::webglrenderingcontext::WebGLRenderingContext;
|
||||
use crate::script_runtime::JSContext;
|
||||
use base64;
|
||||
use canvas_traits::canvas::{CanvasId, CanvasMsg, FromScriptMsg};
|
||||
|
@ -36,11 +35,12 @@ use euclid::default::{Rect, Size2D};
|
|||
use html5ever::{LocalName, Prefix};
|
||||
use image::png::PNGEncoder;
|
||||
use image::ColorType;
|
||||
use ipc_channel::ipc::IpcSharedMemory;
|
||||
use ipc_channel::ipc::{self as ipcchan, IpcSharedMemory};
|
||||
use js::error::throw_type_error;
|
||||
use js::rust::HandleValue;
|
||||
use profile_traits::ipc;
|
||||
use script_layout_interface::{HTMLCanvasData, HTMLCanvasDataSource};
|
||||
use script_traits::ScriptMsg;
|
||||
use style::attr::{AttrValue, LengthOrPercentageOrAuto};
|
||||
|
||||
const DEFAULT_WIDTH: u32 = 300;
|
||||
|
@ -52,6 +52,7 @@ pub enum CanvasContext {
|
|||
Context2d(Dom<CanvasRenderingContext2D>),
|
||||
WebGL(Dom<WebGLRenderingContext>),
|
||||
WebGL2(Dom<WebGL2RenderingContext>),
|
||||
WebGPU(Dom<GPUCanvasContext>),
|
||||
}
|
||||
|
||||
#[dom_struct]
|
||||
|
@ -95,6 +96,7 @@ impl HTMLCanvasElement {
|
|||
},
|
||||
CanvasContext::WebGL(ref context) => context.recreate(size),
|
||||
CanvasContext::WebGL2(ref context) => context.recreate(size),
|
||||
CanvasContext::WebGPU(_) => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -111,6 +113,11 @@ impl HTMLCanvasElement {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait LayoutCanvasRenderingContextHelpers {
|
||||
#[allow(unsafe_code)]
|
||||
unsafe fn canvas_data_source(self) -> HTMLCanvasDataSource;
|
||||
}
|
||||
|
||||
pub trait LayoutHTMLCanvasElementHelpers {
|
||||
fn data(self) -> HTMLCanvasData;
|
||||
fn get_width(self) -> LengthOrPercentageOrAuto;
|
||||
|
@ -132,6 +139,9 @@ impl LayoutHTMLCanvasElementHelpers for LayoutDom<'_, HTMLCanvasElement> {
|
|||
Some(&CanvasContext::WebGL2(ref context)) => {
|
||||
context.to_layout().canvas_data_source()
|
||||
},
|
||||
Some(&CanvasContext::WebGPU(ref context)) => {
|
||||
context.to_layout().canvas_data_source()
|
||||
},
|
||||
None => HTMLCanvasDataSource::Image(None),
|
||||
}
|
||||
};
|
||||
|
@ -239,6 +249,26 @@ impl HTMLCanvasElement {
|
|||
Some(context)
|
||||
}
|
||||
|
||||
fn get_or_init_webgpu_context(&self) -> Option<DomRoot<GPUCanvasContext>> {
|
||||
if let Some(ctx) = self.context() {
|
||||
return match *ctx {
|
||||
CanvasContext::WebGPU(ref ctx) => Some(DomRoot::from_ref(ctx)),
|
||||
_ => None,
|
||||
};
|
||||
}
|
||||
let (sender, receiver) = ipcchan::channel().unwrap();
|
||||
let _ = self
|
||||
.global()
|
||||
.script_to_constellation_chan()
|
||||
.send(ScriptMsg::GetWebGPUChan(sender));
|
||||
let window = window_from_node(self);
|
||||
let size = self.get_size();
|
||||
let channel = receiver.recv().expect("Failed to get WebGPU channel");
|
||||
let context = GPUCanvasContext::new(window.upcast::<GlobalScope>(), self, size, channel);
|
||||
*self.context.borrow_mut() = Some(CanvasContext::WebGPU(Dom::from_ref(&*context)));
|
||||
Some(context)
|
||||
}
|
||||
|
||||
/// Gets the base WebGLRenderingContext for WebGL or WebGL 2, if exists.
|
||||
pub fn get_base_webgl_context(&self) -> Option<DomRoot<WebGLRenderingContext>> {
|
||||
match *self.context.borrow() {
|
||||
|
@ -296,6 +326,10 @@ impl HTMLCanvasElement {
|
|||
// TODO: add a method in WebGL2RenderingContext to get the pixels.
|
||||
return None;
|
||||
},
|
||||
Some(&CanvasContext::WebGPU(_)) => {
|
||||
// TODO: add a method in GPUCanvasContext to get the pixels.
|
||||
return None;
|
||||
},
|
||||
None => None,
|
||||
};
|
||||
|
||||
|
@ -333,6 +367,9 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
|
|||
"webgl2" | "experimental-webgl2" => self
|
||||
.get_or_init_webgl2_context(cx, options)
|
||||
.map(RenderingContext::WebGL2RenderingContext),
|
||||
"gpupresent" => self
|
||||
.get_or_init_webgpu_context()
|
||||
.map(RenderingContext::GPUCanvasContext),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
@ -371,6 +408,8 @@ impl HTMLCanvasElementMethods for HTMLCanvasElement {
|
|||
None => return Ok(USVString("data:,".into())),
|
||||
}
|
||||
},
|
||||
//TODO: Add method get_image_data to GPUCanvasContext
|
||||
Some(CanvasContext::WebGPU(_)) => return Ok(USVString("data:,".into())),
|
||||
None => {
|
||||
// Each pixel is fully-transparent black.
|
||||
vec![0; (self.Width() * self.Height() * 4) as usize]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue