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

Make offscreen canvas rendering context use offscreen canvas' size; Consolidate size helpers #24524

Merged
merged 1 commit into from Nov 11, 2019
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Addresses issues raised in #24465; removes redundancy in set_bitmap_d…

…imensions

Removed passing test .ini files and moved euclid extensions to euclidext.rs to factor out redundant code
  • Loading branch information
bblanke committed Nov 10, 2019
commit ec2961920b74fbe0345f72e6007c6d42ae852019

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

@@ -13,7 +13,7 @@ use std::marker::PhantomData;
use std::mem;
use std::sync::Arc;
use webrender::api::DirtyRect;
use webrender_api::units::RectExt;
use webrender_api::units::RectExt as RectExt_;

/// The canvas data stores a state machine for the current status of
/// the path data and any relevant transformations that are
@@ -449,7 +449,7 @@ impl<'a> CanvasData<'a> {
let source_rect = source_rect.ceil();
// It discards the extra pixels (if any) that won't be painted
let image_data = if Rect::from_size(image_size).contains_rect(&source_rect) {
pixels::rgba8_get_rect(&image_data, image_size.to_u32(), source_rect.to_u32()).into()
pixels::rgba8_get_rect(&image_data, image_size.to_u64(), source_rect.to_u64()).into()
} else {
image_data.into()
};
@@ -927,10 +927,10 @@ impl<'a> CanvasData<'a> {
self.backend.set_global_composition(op, &mut self.state);
}

pub fn recreate(&mut self, size: Size2D<u32>) {
pub fn recreate(&mut self, size: Size2D<u64>) {
self.drawtarget = self
.backend
.create_drawtarget(Size2D::new(size.width as u64, size.height as u64));
.create_drawtarget(Size2D::new(size.width, size.height));
self.state = self.backend.recreate_paint_state(&self.state);
self.saved_states.clear();
// Webrender doesn't let images change size, so we clear the webrender image key.
@@ -997,7 +997,7 @@ impl<'a> CanvasData<'a> {
}

// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
pub fn put_image_data(&mut self, mut imagedata: Vec<u8>, rect: Rect<u32>) {
pub fn put_image_data(&mut self, mut imagedata: Vec<u8>, rect: Rect<u64>) {
assert_eq!(imagedata.len() % 4, 0);
assert_eq!(rect.size.area() as usize, imagedata.len() / 4);
pixels::rgba8_byte_swap_and_premultiply_inplace(&mut imagedata);
@@ -1082,7 +1082,7 @@ impl<'a> CanvasData<'a> {
/// canvas_size: The size of the canvas we're reading from
/// read_rect: The area of the canvas we want to read from
#[allow(unsafe_code)]
pub fn read_pixels(&self, read_rect: Rect<u32>, canvas_size: Size2D<u32>) -> Vec<u8> {
pub fn read_pixels(&self, read_rect: Rect<u64>, canvas_size: Size2D<u64>) -> Vec<u8> {
let canvas_rect = Rect::from_size(canvas_size);
if canvas_rect
.intersection(&read_rect)
@@ -1092,7 +1092,7 @@ impl<'a> CanvasData<'a> {
}

self.drawtarget.snapshot_data(&|bytes| {
pixels::rgba8_get_rect(bytes, canvas_size.to_u32(), read_rect.to_u32()).into_owned()
pixels::rgba8_get_rect(bytes, canvas_size, read_rect).into_owned()
})
}
}
@@ -1189,3 +1189,35 @@ impl RectToi32 for Rect<f64> {
)
}
}

pub trait Size2DExt {
fn to_u64(&self) -> Size2D<u64>;
}

impl Size2DExt for Size2D<f64> {
fn to_u64(&self) -> Size2D<u64> {
self.cast()
}
}

impl Size2DExt for Size2D<u32> {
fn to_u64(&self) -> Size2D<u64> {
self.cast()
}
}

pub trait RectExt {
fn to_u64(&self) -> Rect<u64>;
}

impl RectExt for Rect<f64> {
fn to_u64(&self) -> Rect<u64> {
self.cast()
}
}

impl RectExt for Rect<u32> {
fn to_u64(&self) -> Rect<u64> {
self.cast()
}
}
@@ -144,7 +144,7 @@ impl<'a> CanvasPaintThread<'a> {
) => {
let image_data = self
.canvas(canvas_id)
.read_pixels(source_rect.to_u32(), image_size.to_u32());
.read_pixels(source_rect.to_u64(), image_size.to_u64());
self.canvas(other_canvas_id).draw_image(
image_data.into(),
source_rect.size,
@@ -29,7 +29,7 @@ pub enum CanvasMsg {
),
FromLayout(FromLayoutMsg, CanvasId),
FromScript(FromScriptMsg, CanvasId),
Recreate(Size2D<u32>, CanvasId),
Recreate(Size2D<u64>, CanvasId),
Close(CanvasId),
Exit,
}
@@ -54,11 +54,11 @@ pub enum Canvas2dMsg {
Fill,
FillText(String, f64, f64, Option<f64>),
FillRect(Rect<f32>),
GetImageData(Rect<u32>, Size2D<u32>, IpcBytesSender),
GetImageData(Rect<u64>, Size2D<u64>, IpcBytesSender),
IsPointInPath(f64, f64, FillRule, IpcSender<bool>),
LineTo(Point2D<f32>),
MoveTo(Point2D<f32>),
PutImageData(Rect<u32>, IpcBytesReceiver),
PutImageData(Rect<u64>, IpcBytesReceiver),
QuadraticCurveTo(Point2D<f32>, Point2D<f32>),
Rect(Rect<f32>),
RestoreContext,
@@ -23,7 +23,7 @@ pub enum PixelFormat {
BGRA8,
}

pub fn rgba8_get_rect(pixels: &[u8], size: Size2D<u32>, rect: Rect<u32>) -> Cow<[u8]> {
pub fn rgba8_get_rect(pixels: &[u8], size: Size2D<u64>, rect: Rect<u64>) -> Cow<[u8]> {
assert!(!rect.is_empty());
assert!(Rect::from_size(size).contains_rect(&rect));
assert_eq!(pixels.len() % 4, 0);
@@ -85,18 +85,19 @@ pub fn multiply_u8_color(a: u8, b: u8) -> u8 {

pub fn clip(
mut origin: Point2D<i32>,
mut size: Size2D<u32>,
surface: Size2D<u32>,
) -> Option<Rect<u32>> {
mut size: Size2D<u64>,
surface: Size2D<u64>,
) -> Option<Rect<u64>> {
if origin.x < 0 {
size.width = size.width.saturating_sub(-origin.x as u32);
size.width = size.width.saturating_sub(-origin.x as u64);
origin.x = 0;
}
if origin.y < 0 {
size.height = size.height.saturating_sub(-origin.y as u32);
size.height = size.height.saturating_sub(-origin.y as u64);
origin.y = 0;
}
Rect::new(origin.to_u32(), size)
let origin = Point2D::new(origin.x as u64, origin.y as u64);
Rect::new(origin, size)
.intersection(&Rect::from_size(surface))
.filter(|rect| !rect.is_empty())
}
@@ -24,6 +24,7 @@ use crate::dom::imagedata::ImageData;
use crate::dom::node::{Node, NodeDamage};
use crate::dom::paintworkletglobalscope::PaintWorkletGlobalScope;
use crate::dom::textmetrics::TextMetrics;
use crate::euclidext::Size2DExt;
use crate::unpremultiplytable::UNPREMULTIPLY_TABLE;
use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg};
use canvas_traits::canvas::{CompositionOrBlending, FillOrStrokeStyle, FillRule};
@@ -180,6 +181,19 @@ impl CanvasState {
.unwrap()
}

// https://html.spec.whatwg.org/multipage/#concept-canvas-set-bitmap-dimensions
pub fn set_bitmap_dimensions(&self, size: Size2D<u64>) {
self.reset_to_initial_state();
self.ipc_renderer
.send(CanvasMsg::Recreate(size, self.get_canvas_id()))
.unwrap();
}

pub fn reset_to_initial_state(&self) {
self.saved_states.borrow_mut().clear();
*self.state.borrow_mut() = CanvasContextState::new();
}

fn create_drawable_rect(&self, x: f64, y: f64, w: f64, h: f64) -> Option<Rect<f32>> {
if !([x, y, w, h].iter().all(|val| val.is_finite())) {
return None;
@@ -300,7 +314,7 @@ impl CanvasState {
}
}

pub fn get_rect(&self, canvas_size: Size2D<u32>, rect: Rect<u32>) -> Vec<u8> {
pub fn get_rect(&self, canvas_size: Size2D<u64>, rect: Rect<u64>) -> Vec<u8> {
assert!(self.origin_is_clean());

assert!(Rect::from_size(canvas_size).contains_rect(&rect));
@@ -1019,7 +1033,7 @@ impl CanvasState {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-getimagedata
pub fn get_image_data(
&self,
canvas_size: Size2D<u32>,
canvas_size: Size2D<u64>,
global: &GlobalScope,
sx: i32,
sy: i32,
@@ -1038,7 +1052,7 @@ impl CanvasState {
}

let (origin, size) = adjust_size_sign(Point2D::new(sx, sy), Size2D::new(sw, sh));
let read_rect = match pixels::clip(origin, size, canvas_size) {
let read_rect = match pixels::clip(origin, size.to_u64(), canvas_size) {
Some(rect) => rect,
None => {
// All the pixels are outside the canvas surface.
@@ -1057,7 +1071,7 @@ impl CanvasState {
// https://html.spec.whatwg.org/multipage/#dom-context-2d-putimagedata
pub fn put_image_data(
&self,
canvas_size: Size2D<u32>,
canvas_size: Size2D<u64>,
imagedata: &ImageData,
dx: i32,
dy: i32,
@@ -1078,7 +1092,7 @@ impl CanvasState {
#[allow(unsafe_code)]
pub fn put_image_data_(
&self,
canvas_size: Size2D<u32>,
canvas_size: Size2D<u64>,
imagedata: &ImageData,
dx: i32,
dy: i32,
@@ -1106,7 +1120,7 @@ impl CanvasState {
Point2D::new(dirty_x, dirty_y),
Size2D::new(dirty_width, dirty_height),
);
let src_rect = match pixels::clip(src_origin, src_size, imagedata_size) {
let src_rect = match pixels::clip(src_origin, src_size.to_u64(), imagedata_size.to_u64()) {
Some(rect) => rect,
None => return,
};
@@ -22,9 +22,10 @@ use crate::dom::globalscope::GlobalScope;
use crate::dom::htmlcanvaselement::HTMLCanvasElement;
use crate::dom::imagedata::ImageData;
use crate::dom::textmetrics::TextMetrics;
use crate::euclidext::Size2DExt;
use canvas_traits::canvas::{Canvas2dMsg, CanvasId, CanvasMsg};
use dom_struct::dom_struct;
use euclid::default::{Rect, Size2D};
use euclid::default::{Point2D, Rect, Size2D};
use ipc_channel::ipc::IpcSender;
use servo_url::ServoUrl;
use std::mem;
@@ -75,12 +76,13 @@ impl CanvasRenderingContext2D {
.borrow()
.get_ipc_renderer()
.send(CanvasMsg::Recreate(
size,
size.to_u64(),
self.canvas_state.borrow().get_canvas_id(),
))
.unwrap();
}

// TODO: This duplicates functionality in canvas state
// https://html.spec.whatwg.org/multipage/#reset-the-rendering-context-to-its-default-state
fn reset_to_initial_state(&self) {
self.canvas_state
@@ -90,6 +92,15 @@ impl CanvasRenderingContext2D {
.clear();
*self.canvas_state.borrow().get_state().borrow_mut() = CanvasContextState::new();
}
/*
pub fn get_canvas_state(&self) -> Ref<CanvasState> {
self.canvas_state.borrow()
}
*/

pub fn set_canvas_bitmap_dimensions(&self, size: Size2D<u64>) {
self.canvas_state.borrow().set_bitmap_dimensions(size);
}

pub fn mark_as_dirty(&self) {
self.canvas_state
@@ -116,6 +127,7 @@ impl CanvasRenderingContext2D {
self.canvas_state.borrow().send_canvas_2d_msg(msg)
}

// TODO: Remove this
pub fn get_ipc_renderer(&self) -> IpcSender<CanvasMsg> {
self.canvas_state.borrow().get_ipc_renderer().clone()
}
@@ -125,10 +137,14 @@ impl CanvasRenderingContext2D {
}

pub fn get_rect(&self, rect: Rect<u32>) -> Vec<u8> {
let rect = Rect::new(
This conversation was marked as resolved by jdm

This comment has been minimized.

@jdm

jdm Oct 24, 2019

Member

Is this the same as rect.to_u64() if we import the helper trait?

Point2D::new(rect.origin.x as u64, rect.origin.y as u64),
Size2D::new(rect.size.width as u64, rect.size.height as u64),
);
self.canvas_state.borrow().get_rect(
self.canvas
.as_ref()
.map_or(Size2D::zero(), |c| c.get_size()),
.map_or(Size2D::zero(), |c| c.get_size().to_u64()),
rect,
)
}
@@ -469,7 +485,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
self.canvas_state.borrow().get_image_data(
self.canvas
.as_ref()
.map_or(Size2D::zero(), |c| c.get_size()),
.map_or(Size2D::zero(), |c| c.get_size().to_u64()),
&self.global(),
sx,
sy,
@@ -483,7 +499,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
self.canvas_state.borrow().put_image_data(
self.canvas
.as_ref()
.map_or(Size2D::zero(), |c| c.get_size()),
.map_or(Size2D::zero(), |c| c.get_size().to_u64()),
imagedata,
dx,
dy,
@@ -505,7 +521,7 @@ impl CanvasRenderingContext2DMethods for CanvasRenderingContext2D {
self.canvas_state.borrow().put_image_data_(
self.canvas
.as_ref()
.map_or(Size2D::zero(), |c| c.get_size()),
.map_or(Size2D::zero(), |c| c.get_size().to_u64()),
imagedata,
dx,
dy,
@@ -28,6 +28,7 @@ use crate::dom::webgl2renderingcontext::WebGL2RenderingContext;
use crate::dom::webglrenderingcontext::{
LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext,
};
use crate::euclidext::Size2DExt;
use crate::script_runtime::JSContext;
use base64;
use canvas_traits::canvas::{CanvasId, CanvasMsg, FromScriptMsg};
@@ -94,7 +95,9 @@ impl HTMLCanvasElement {
let size = self.get_size();
if let Some(ref context) = *self.context.borrow() {
match *context {
CanvasContext::Context2d(ref context) => context.set_bitmap_dimensions(size),
CanvasContext::Context2d(ref context) => {
context.set_canvas_bitmap_dimensions(size.to_u64())
},
CanvasContext::WebGL(ref context) => context.recreate(size),
CanvasContext::WebGL2(ref context) => context.recreate(size),
}
@@ -169,8 +169,8 @@ impl ImageData {
}

#[allow(unsafe_code)]
pub unsafe fn get_rect(&self, rect: Rect<u32>) -> Cow<[u8]> {
pixels::rgba8_get_rect(self.as_slice(), self.get_size(), rect)
pub unsafe fn get_rect(&self, rect: Rect<u64>) -> Cow<[u8]> {
pixels::rgba8_get_rect(self.as_slice(), self.get_size().to_u64(), rect)
}

pub fn get_size(&self) -> Size2D<u32> {
@@ -194,3 +194,13 @@ impl ImageDataMethods for ImageData {
NonNull::new(self.data.get()).expect("got a null pointer")
}
}

pub trait Size2DExt {
This conversation was marked as resolved by jdm

This comment has been minimized.

@jdm

jdm Oct 24, 2019

Member

This can be imported from crate::euclidext::Size2DExt instead.

fn to_u64(&self) -> Size2D<u64>;
}

impl Size2DExt for Size2D<u32> {
fn to_u64(&self) -> Size2D<u64> {
return Size2D::new(self.width as u64, self.height as u64);
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.