mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Auto merge of #11744 - emilio:wr-default, r=glennw
webgl: Unlock WebRender by default by adding a readback based fallback to WebGL context creation. <!-- Please describe your changes on the following line: --> --- <!-- 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 <!-- Either: --> - [x] These changes do not require tests because refactoring. <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> This should give us the chance to use WebRender by default in OSX. r? @pcwalton cc @glennw @larsbergstrom <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11744) <!-- Reviewable:end -->
This commit is contained in:
commit
68aca87e30
2 changed files with 55 additions and 27 deletions
|
@ -30,7 +30,7 @@ impl<'a> CanvasPaintThread<'a> {
|
||||||
let canvas_rect = Rect::new(Point2D::new(0i32, 0i32), canvas_size);
|
let canvas_rect = Rect::new(Point2D::new(0i32, 0i32), canvas_size);
|
||||||
let src_read_rect = canvas_rect.intersection(&read_rect).unwrap_or(Rect::zero());
|
let src_read_rect = canvas_rect.intersection(&read_rect).unwrap_or(Rect::zero());
|
||||||
|
|
||||||
let mut image_data = Vec::new();
|
let mut image_data = vec![];
|
||||||
if src_read_rect.is_empty() || canvas_size.width <= 0 && canvas_size.height <= 0 {
|
if src_read_rect.is_empty() || canvas_size.width <= 0 && canvas_size.height <= 0 {
|
||||||
return image_data;
|
return image_data;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ impl<'a> CanvasPaintThread<'a> {
|
||||||
drawtarget: draw_target,
|
drawtarget: draw_target,
|
||||||
path_builder: path_builder,
|
path_builder: path_builder,
|
||||||
state: CanvasPaintState::new(),
|
state: CanvasPaintState::new(),
|
||||||
saved_states: Vec::new(),
|
saved_states: vec![],
|
||||||
webrender_api: webrender_api,
|
webrender_api: webrender_api,
|
||||||
webrender_image_key: webrender_image_key,
|
webrender_image_key: webrender_image_key,
|
||||||
}
|
}
|
||||||
|
@ -543,13 +543,11 @@ impl<'a> CanvasPaintThread<'a> {
|
||||||
self.drawtarget.snapshot().get_data_surface().with_data(|element| {
|
self.drawtarget.snapshot().get_data_surface().with_data(|element| {
|
||||||
if let Some(ref webrender_api) = self.webrender_api {
|
if let Some(ref webrender_api) = self.webrender_api {
|
||||||
let size = self.drawtarget.get_size();
|
let size = self.drawtarget.get_size();
|
||||||
let mut bytes = Vec::new();
|
|
||||||
bytes.extend_from_slice(element);
|
|
||||||
webrender_api.update_image(self.webrender_image_key.unwrap(),
|
webrender_api.update_image(self.webrender_image_key.unwrap(),
|
||||||
size.width as u32,
|
size.width as u32,
|
||||||
size.height as u32,
|
size.height as u32,
|
||||||
webrender_traits::ImageFormat::RGBA8,
|
webrender_traits::ImageFormat::RGBA8,
|
||||||
bytes);
|
element.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let pixel_data = CanvasPixelData {
|
let pixel_data = CanvasPixelData {
|
||||||
|
|
|
@ -15,7 +15,7 @@ use webrender_traits;
|
||||||
|
|
||||||
enum WebGLPaintTaskData {
|
enum WebGLPaintTaskData {
|
||||||
WebRender(webrender_traits::RenderApi, webrender_traits::WebGLContextId),
|
WebRender(webrender_traits::RenderApi, webrender_traits::WebGLContextId),
|
||||||
Servo(GLContext<NativeGLContext>),
|
Readback(GLContext<NativeGLContext>, (Option<(webrender_traits::RenderApi, webrender_traits::ImageKey)>)),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WebGLPaintThread {
|
pub struct WebGLPaintThread {
|
||||||
|
@ -23,36 +23,56 @@ pub struct WebGLPaintThread {
|
||||||
data: WebGLPaintTaskData,
|
data: WebGLPaintTaskData,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_readback_painter(size: Size2D<i32>,
|
||||||
|
attrs: GLContextAttributes,
|
||||||
|
webrender_api: Option<webrender_traits::RenderApi>)
|
||||||
|
-> Result<(WebGLPaintThread, GLLimits), String> {
|
||||||
|
let context = try!(GLContext::<NativeGLContext>::new(size, attrs, ColorAttachmentType::Texture, None));
|
||||||
|
let limits = context.borrow_limits().clone();
|
||||||
|
let webrender_api_and_image_key = webrender_api.map(|wr| {
|
||||||
|
let key = wr.alloc_image();
|
||||||
|
(wr, key)
|
||||||
|
});
|
||||||
|
let painter = WebGLPaintThread {
|
||||||
|
size: size,
|
||||||
|
data: WebGLPaintTaskData::Readback(context, webrender_api_and_image_key)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((painter, limits))
|
||||||
|
}
|
||||||
|
|
||||||
impl WebGLPaintThread {
|
impl WebGLPaintThread {
|
||||||
fn new(size: Size2D<i32>,
|
fn new(size: Size2D<i32>,
|
||||||
attrs: GLContextAttributes,
|
attrs: GLContextAttributes,
|
||||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
|
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
|
||||||
-> Result<(WebGLPaintThread, GLLimits), String> {
|
-> Result<(WebGLPaintThread, GLLimits), String> {
|
||||||
let (data, limits) = if let Some(sender) = webrender_api_sender {
|
if let Some(sender) = webrender_api_sender {
|
||||||
let webrender_api = sender.create_api();
|
let wr_api = sender.create_api();
|
||||||
let (id, limits) = try!(webrender_api.request_webgl_context(&size, attrs));
|
match wr_api.request_webgl_context(&size, attrs) {
|
||||||
(WebGLPaintTaskData::WebRender(webrender_api, id), limits)
|
Ok((id, limits)) => {
|
||||||
|
let painter = WebGLPaintThread {
|
||||||
|
data: WebGLPaintTaskData::WebRender(wr_api, id),
|
||||||
|
size: size
|
||||||
|
};
|
||||||
|
Ok((painter, limits))
|
||||||
|
},
|
||||||
|
Err(msg) => {
|
||||||
|
warn!("Initial context creation failed, falling back to readback: {}", msg);
|
||||||
|
create_readback_painter(size, attrs, Some(wr_api))
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let context = try!(GLContext::<NativeGLContext>::new(size, attrs, ColorAttachmentType::Texture, None));
|
create_readback_painter(size, attrs, None)
|
||||||
let limits = context.borrow_limits().clone();
|
}
|
||||||
(WebGLPaintTaskData::Servo(context), limits)
|
|
||||||
};
|
|
||||||
|
|
||||||
let painter_object = WebGLPaintThread {
|
|
||||||
size: size,
|
|
||||||
data: data,
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok((painter_object, limits))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_webgl_message(&self, message: webrender_traits::WebGLCommand) {
|
fn handle_webgl_message(&self, message: webrender_traits::WebGLCommand) {
|
||||||
debug!("WebGL message: {:?}", message);
|
debug!("WebGL message: {:?}", message);
|
||||||
match self.data {
|
match self.data {
|
||||||
WebGLPaintTaskData::WebRender(ref api, id) => {
|
WebGLPaintTaskData::WebRender(ref api, id) => {
|
||||||
api.send_webgl_command(id, message);
|
api.send_webgl_command(id, message);
|
||||||
}
|
}
|
||||||
WebGLPaintTaskData::Servo(ref ctx) => {
|
WebGLPaintTaskData::Readback(ref ctx, _) => {
|
||||||
message.apply(ctx);
|
message.apply(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,7 +124,7 @@ impl WebGLPaintThread {
|
||||||
|
|
||||||
fn send_data(&mut self, chan: IpcSender<CanvasData>) {
|
fn send_data(&mut self, chan: IpcSender<CanvasData>) {
|
||||||
match self.data {
|
match self.data {
|
||||||
WebGLPaintTaskData::Servo(_) => {
|
WebGLPaintTaskData::Readback(_, ref webrender_api_and_image_key) => {
|
||||||
let width = self.size.width as usize;
|
let width = self.size.width as usize;
|
||||||
let height = self.size.height as usize;
|
let height = self.size.height as usize;
|
||||||
|
|
||||||
|
@ -125,9 +145,19 @@ impl WebGLPaintThread {
|
||||||
// rgba -> bgra
|
// rgba -> bgra
|
||||||
byte_swap(&mut pixels);
|
byte_swap(&mut pixels);
|
||||||
|
|
||||||
|
if let Some((ref wr, wr_image_key)) = *webrender_api_and_image_key {
|
||||||
|
// TODO: This shouldn't be a common path, but try to avoid
|
||||||
|
// the spurious clone().
|
||||||
|
wr.update_image(wr_image_key,
|
||||||
|
width as u32,
|
||||||
|
height as u32,
|
||||||
|
webrender_traits::ImageFormat::RGBA8,
|
||||||
|
pixels.clone());
|
||||||
|
}
|
||||||
|
|
||||||
let pixel_data = CanvasPixelData {
|
let pixel_data = CanvasPixelData {
|
||||||
image_data: IpcSharedMemory::from_bytes(&pixels[..]),
|
image_data: IpcSharedMemory::from_bytes(&pixels[..]),
|
||||||
image_key: None,
|
image_key: webrender_api_and_image_key.as_ref().map(|&(_, key)| key),
|
||||||
};
|
};
|
||||||
|
|
||||||
chan.send(CanvasData::Pixels(pixel_data)).unwrap();
|
chan.send(CanvasData::Pixels(pixel_data)).unwrap();
|
||||||
|
@ -141,7 +171,7 @@ impl WebGLPaintThread {
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn recreate(&mut self, size: Size2D<i32>) -> Result<(), &'static str> {
|
fn recreate(&mut self, size: Size2D<i32>) -> Result<(), &'static str> {
|
||||||
match self.data {
|
match self.data {
|
||||||
WebGLPaintTaskData::Servo(ref mut context) => {
|
WebGLPaintTaskData::Readback(ref mut context, _) => {
|
||||||
if size.width > self.size.width ||
|
if size.width > self.size.width ||
|
||||||
size.height > self.size.height {
|
size.height > self.size.height {
|
||||||
try!(context.resize(size));
|
try!(context.resize(size));
|
||||||
|
@ -160,7 +190,7 @@ impl WebGLPaintThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(&mut self) {
|
fn init(&mut self) {
|
||||||
if let WebGLPaintTaskData::Servo(ref context) = self.data {
|
if let WebGLPaintTaskData::Readback(ref context, _) = self.data {
|
||||||
context.make_current().unwrap();
|
context.make_current().unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue