mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Improve gl.putImageData
This commit should allow us to send smaller blobs to the canvas thread, I made it into its own commit just to try=wpt.
This commit is contained in:
parent
3d910feb3a
commit
82c7d71811
2 changed files with 31 additions and 8 deletions
|
@ -454,14 +454,13 @@ impl<'a> CanvasData<'a> {
|
||||||
imagedata: Vec<u8>,
|
imagedata: Vec<u8>,
|
||||||
offset: Vector2D<i32>,
|
offset: Vector2D<i32>,
|
||||||
image_data_size: Size2D<i32>,
|
image_data_size: Size2D<i32>,
|
||||||
dirty_rect: Rect<i32>,
|
dest_rect: Rect<i32>,
|
||||||
) {
|
) {
|
||||||
assert_eq!(image_data_size.width * image_data_size.height * 4, imagedata.len() as i32);
|
assert_eq!(image_data_size.width * image_data_size.height * 4, imagedata.len() as i32);
|
||||||
|
|
||||||
let dest_rect = dirty_rect.translate(&offset);
|
|
||||||
let image_size = image_data_size;
|
let image_size = image_data_size;
|
||||||
|
|
||||||
let first_pixel = dest_rect.origin - offset;
|
let first_pixel = dest_rect.origin;
|
||||||
let mut src_line = (first_pixel.y * (image_size.width * 4) + first_pixel.x * 4) as usize;
|
let mut src_line = (first_pixel.y * (image_size.width * 4) + first_pixel.x * 4) as usize;
|
||||||
|
|
||||||
let mut dest =
|
let mut dest =
|
||||||
|
@ -487,9 +486,7 @@ impl<'a> CanvasData<'a> {
|
||||||
dest_rect.size,
|
dest_rect.size,
|
||||||
dest_rect.size.width * 4,
|
dest_rect.size.width * 4,
|
||||||
SurfaceFormat::B8G8R8A8) {
|
SurfaceFormat::B8G8R8A8) {
|
||||||
self.drawtarget.copy_surface(source_surface,
|
self.drawtarget.copy_surface(source_surface, Rect::from_size(dest_rect.size), offset.to_point());
|
||||||
Rect::new(Point2D::new(0, 0), dest_rect.size),
|
|
||||||
dest_rect.origin);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ use dom::htmlcanvaselement::{CanvasContext, HTMLCanvasElement};
|
||||||
use dom::imagedata::ImageData;
|
use dom::imagedata::ImageData;
|
||||||
use dom::node::{Node, NodeDamage, window_from_node};
|
use dom::node::{Node, NodeDamage, window_from_node};
|
||||||
use dom_struct::dom_struct;
|
use dom_struct::dom_struct;
|
||||||
use euclid::{Transform2D, Point2D, Vector2D, Rect, Size2D, vec2};
|
use euclid::{Transform2D, Point2D, Rect, Size2D, vec2};
|
||||||
use ipc_channel::ipc::{self, IpcSender};
|
use ipc_channel::ipc::{self, IpcSender};
|
||||||
use net_traits::image::base::PixelFormat;
|
use net_traits::image::base::PixelFormat;
|
||||||
use net_traits::image_cache::CanRequestImages;
|
use net_traits::image_cache::CanRequestImages;
|
||||||
|
@ -1206,6 +1206,9 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
mut dirty_width: i32,
|
mut dirty_width: i32,
|
||||||
mut dirty_height: i32,
|
mut dirty_height: i32,
|
||||||
) {
|
) {
|
||||||
|
// FIXME(nox): There are many arithmetic operations here that can
|
||||||
|
// overflow or underflow, this should probably be audited.
|
||||||
|
|
||||||
let imagedata_size = Size2D::new(imagedata.Width() as i32, imagedata.Height() as i32);
|
let imagedata_size = Size2D::new(imagedata.Width() as i32, imagedata.Height() as i32);
|
||||||
if imagedata_size.width <= 0 || imagedata_size.height <= 0 {
|
if imagedata_size.width <= 0 || imagedata_size.height <= 0 {
|
||||||
return;
|
return;
|
||||||
|
@ -1227,6 +1230,21 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
dirty_height = -dirty_height;
|
dirty_height = -dirty_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Ignore any pixel that would be drawn before the beginning of the
|
||||||
|
// canvas surface.
|
||||||
|
let mut dest_x = dx + dirty_x;
|
||||||
|
let mut dest_y = dy + dirty_y;
|
||||||
|
if dest_x < 0 {
|
||||||
|
dirty_x -= dest_x;
|
||||||
|
dirty_width += dest_x;
|
||||||
|
dest_x = 0;
|
||||||
|
}
|
||||||
|
if dest_y < 0 {
|
||||||
|
dirty_y -= dest_y;
|
||||||
|
dirty_height += dest_y;
|
||||||
|
dest_y = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Step 4.
|
// Step 4.
|
||||||
if dirty_x < 0 {
|
if dirty_x < 0 {
|
||||||
dirty_width += dirty_x;
|
dirty_width += dirty_x;
|
||||||
|
@ -1245,6 +1263,14 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
dirty_height = imagedata_size.height - dirty_y;
|
dirty_height = imagedata_size.height - dirty_y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We take care of ignoring any pixel that would be drawn after the end
|
||||||
|
// of the canvas surface.
|
||||||
|
let canvas_size = self.canvas.as_ref().map_or(Size2D::zero(), |c| c.get_size()).to_i32();
|
||||||
|
let origin = Point2D::new(dest_x, dest_y);
|
||||||
|
let drawable_size = (origin - canvas_size.to_vector().to_point()).to_size().abs();
|
||||||
|
dirty_width = dirty_width.min(drawable_size.width);
|
||||||
|
dirty_height = dirty_height.min(drawable_size.height);
|
||||||
|
|
||||||
// Step 6.
|
// Step 6.
|
||||||
if dirty_width <= 0 || dirty_height <= 0 {
|
if dirty_width <= 0 || dirty_height <= 0 {
|
||||||
return;
|
return;
|
||||||
|
@ -1257,7 +1283,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
|
||||||
// Step 7.
|
// Step 7.
|
||||||
self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(
|
self.send_canvas_2d_msg(Canvas2dMsg::PutImageData(
|
||||||
buffer.into(),
|
buffer.into(),
|
||||||
Vector2D::new(dx, dy),
|
origin.to_vector(),
|
||||||
imagedata_size,
|
imagedata_size,
|
||||||
Rect::new(
|
Rect::new(
|
||||||
Point2D::new(dirty_x, dirty_y),
|
Point2D::new(dirty_x, dirty_y),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue