Layerize canvas

Note that this keeps using readback right now, `NativeSurface` painting
will be implemented soon.

Also see https://github.com/servo/servo/issues/6142
This commit is contained in:
ecoal95 2015-05-20 10:29:08 +02:00
parent 6481058309
commit 3350522306
35 changed files with 769 additions and 500 deletions

View file

@ -13,17 +13,24 @@ git = "https://github.com/servo/rust-azure"
[dependencies.geom]
git = "https://github.com/servo/rust-geom"
[dependencies.layers]
git = "https://github.com/servo/rust-layers"
[dependencies.gleam]
git = "https://github.com/servo/gleam"
[dependencies.canvas_traits]
path = "../canvas_traits"
[dependencies.util]
path = "../util"
[dependencies.gfx]
path = "../gfx"
[dependencies.gfx_traits]
path = "../gfx_traits"
[dependencies.offscreen_gl_context]
git = "https://github.com/ecoal95/rust-offscreen-rendering-context"
features = ["texture_surface"]
[dependencies]
cssparser = "0.3.1"

View file

@ -1,83 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use canvas_paint_task::{FillOrStrokeStyle, LineCapStyle, LineJoinStyle, CompositionOrBlending};
use geom::matrix2d::Matrix2D;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use std::sync::mpsc::{Sender};
#[derive(Clone)]
pub enum CanvasMsg {
Canvas2d(Canvas2dMsg),
Common(CanvasCommonMsg),
WebGL(CanvasWebGLMsg),
}
#[derive(Clone)]
pub enum Canvas2dMsg {
Arc(Point2D<f32>, f32, f32, f32, bool),
ArcTo(Point2D<f32>, Point2D<f32>, f32),
DrawImage(Vec<u8>, Size2D<f64>, Rect<f64>, Rect<f64>, bool),
DrawImageSelf(Size2D<f64>, Rect<f64>, Rect<f64>, bool),
BeginPath,
BezierCurveTo(Point2D<f32>, Point2D<f32>, Point2D<f32>),
ClearRect(Rect<f32>),
Clip,
ClosePath,
Fill,
FillRect(Rect<f32>),
GetImageData(Rect<f64>, Size2D<f64>, Sender<Vec<u8>>),
LineTo(Point2D<f32>),
MoveTo(Point2D<f32>),
PutImageData(Vec<u8>, Rect<f64>, Option<Rect<f64>>),
QuadraticCurveTo(Point2D<f32>, Point2D<f32>),
Rect(Rect<f32>),
RestoreContext,
SaveContext,
StrokeRect(Rect<f32>),
Stroke,
SetFillStyle(FillOrStrokeStyle),
SetStrokeStyle(FillOrStrokeStyle),
SetLineWidth(f32),
SetLineCap(LineCapStyle),
SetLineJoin(LineJoinStyle),
SetMiterLimit(f32),
SetGlobalAlpha(f32),
SetGlobalComposition(CompositionOrBlending),
SetTransform(Matrix2D<f32>),
}
#[derive(Clone)]
pub enum CanvasWebGLMsg {
AttachShader(u32, u32),
BindBuffer(u32, u32),
BufferData(u32, Vec<f32>, u32),
Clear(u32),
ClearColor(f32, f32, f32, f32),
CompileShader(u32),
CreateBuffer(Sender<u32>),
CreateProgram(Sender<u32>),
CreateShader(u32, Sender<u32>),
DrawArrays(u32, i32, i32),
EnableVertexAttribArray(u32),
GetAttribLocation(u32, String, Sender<i32>),
GetShaderInfoLog(u32, Sender<String>),
GetShaderParameter(u32, u32, Sender<i32>),
GetUniformLocation(u32, String, Sender<u32>),
LinkProgram(u32),
ShaderSource(u32, Vec<String>),
Uniform4fv(u32, Vec<f32>),
UseProgram(u32),
VertexAttribPointer2f(u32, i32, bool, i32, i64),
Viewport(i32, i32, i32, i32),
}
#[derive(Clone)]
pub enum CanvasCommonMsg {
Close,
Recreate(Size2D<i32>),
SendPixelContents(Sender<Vec<u8>>),
}

View file

@ -5,19 +5,18 @@
use azure::azure::AzFloat;
use azure::azure_hl::{DrawTarget, SurfaceFormat, BackendType, StrokeOptions, DrawOptions, Pattern};
use azure::azure_hl::{ColorPattern, PathBuilder, DrawSurfaceOptions, Filter};
use azure::azure_hl::{GradientStop, LinearGradientPattern, RadialGradientPattern, ExtendMode};
use azure::azure_hl::{JoinStyle, CapStyle, CompositionOp};
use canvas_msg::{CanvasMsg, Canvas2dMsg, CanvasCommonMsg};
use azure::azure_hl::{JoinStyle, CapStyle};
use canvas_traits::*;
use geom::matrix2d::Matrix2D;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use gfx::color;
use layers::platform::surface::NativeSurface;
use gfx_traits::color;
use num::ToPrimitive;
use util::task::spawn_named;
use util::vec::byte_swap;
use cssparser::RGBA;
use std::borrow::ToOwned;
use std::mem;
use std::sync::mpsc::{channel, Sender};
@ -257,6 +256,8 @@ impl<'a> CanvasPaintTask<'a> {
CanvasCommonMsg::Recreate(size) => painter.recreate(size),
CanvasCommonMsg::SendPixelContents(chan) =>
painter.send_pixel_contents(chan),
CanvasCommonMsg::SendNativeSurface(chan) =>
painter.send_native_surface(chan),
}
},
CanvasMsg::WebGL(_) => panic!("Wrong message sent to Canvas2D task"),
@ -497,6 +498,14 @@ impl<'a> CanvasPaintTask<'a> {
})
}
fn send_native_surface(&self, chan: Sender<NativeSurface>) {
let mut native_surface: NativeSurface =
NativeSurface::from_draw_target_backing(self.drawtarget.backing.clone());
native_surface.mark_wont_leak();
chan.send(native_surface).unwrap();
}
fn get_image_data(&self, mut dest_rect: Rect<f64>, canvas_size: Size2D<f64>, chan: Sender<Vec<u8>>) {
if dest_rect.size.width < 0.0 {
dest_rect.size.width = -dest_rect.size.width;
@ -566,340 +575,6 @@ impl<'a> CanvasPaintTask<'a> {
}
}
#[derive(Clone)]
pub struct CanvasGradientStop {
pub offset: f64,
pub color: RGBA,
}
#[derive(Clone)]
pub struct LinearGradientStyle {
pub x0: f64,
pub y0: f64,
pub x1: f64,
pub y1: f64,
pub stops: Vec<CanvasGradientStop>
}
impl LinearGradientStyle {
pub fn new(x0: f64, y0: f64, x1: f64, y1: f64, stops: Vec<CanvasGradientStop>)
-> LinearGradientStyle {
LinearGradientStyle {
x0: x0,
y0: y0,
x1: x1,
y1: y1,
stops: stops,
}
}
}
#[derive(Clone)]
pub struct RadialGradientStyle {
pub x0: f64,
pub y0: f64,
pub r0: f64,
pub x1: f64,
pub y1: f64,
pub r1: f64,
pub stops: Vec<CanvasGradientStop>
}
impl RadialGradientStyle {
pub fn new(x0: f64, y0: f64, r0: f64, x1: f64, y1: f64, r1: f64, stops: Vec<CanvasGradientStop>)
-> RadialGradientStyle {
RadialGradientStyle {
x0: x0,
y0: y0,
r0: r0,
x1: x1,
y1: y1,
r1: r1,
stops: stops,
}
}
}
#[derive(Clone)]
pub enum FillOrStrokeStyle {
Color(RGBA),
LinearGradient(LinearGradientStyle),
RadialGradient(RadialGradientStyle),
}
impl FillOrStrokeStyle {
fn to_azure_pattern(&self, drawtarget: &DrawTarget) -> Pattern {
match *self {
FillOrStrokeStyle::Color(ref color) => {
Pattern::Color(ColorPattern::new(color::new(color.red,
color.green,
color.blue,
color.alpha)))
},
FillOrStrokeStyle::LinearGradient(ref linear_gradient_style) => {
let gradient_stops: Vec<GradientStop> = linear_gradient_style.stops.iter().map(|s| {
GradientStop {
offset: s.offset as AzFloat,
color: color::new(s.color.red, s.color.green, s.color.blue, s.color.alpha)
}
}).collect();
Pattern::LinearGradient(LinearGradientPattern::new(
&Point2D(linear_gradient_style.x0 as AzFloat, linear_gradient_style.y0 as AzFloat),
&Point2D(linear_gradient_style.x1 as AzFloat, linear_gradient_style.y1 as AzFloat),
drawtarget.create_gradient_stops(&gradient_stops, ExtendMode::Clamp),
&Matrix2D::identity()))
},
FillOrStrokeStyle::RadialGradient(ref radial_gradient_style) => {
let gradient_stops: Vec<GradientStop> = radial_gradient_style.stops.iter().map(|s| {
GradientStop {
offset: s.offset as AzFloat,
color: color::new(s.color.red, s.color.green, s.color.blue, s.color.alpha)
}
}).collect();
Pattern::RadialGradient(RadialGradientPattern::new(
&Point2D(radial_gradient_style.x0 as AzFloat, radial_gradient_style.y0 as AzFloat),
&Point2D(radial_gradient_style.x1 as AzFloat, radial_gradient_style.y1 as AzFloat),
radial_gradient_style.r0 as AzFloat, radial_gradient_style.r1 as AzFloat,
drawtarget.create_gradient_stops(&gradient_stops, ExtendMode::Clamp),
&Matrix2D::identity()))
}
}
}
}
#[derive(Copy, Clone, PartialEq)]
pub enum LineCapStyle {
Butt = 0,
Round = 1,
Square = 2,
}
impl LineCapStyle {
fn to_azure_style(&self) -> CapStyle {
match *self {
LineCapStyle::Butt => CapStyle::Butt,
LineCapStyle::Round => CapStyle::Round,
LineCapStyle::Square => CapStyle::Square,
}
}
pub fn from_str(string: &str) -> Option<LineCapStyle> {
match string {
"butt" => Some(LineCapStyle::Butt),
"round" => Some(LineCapStyle::Round),
"square" => Some(LineCapStyle::Square),
_ => None
}
}
}
#[derive(Copy, Clone, PartialEq)]
pub enum LineJoinStyle {
Round = 0,
Bevel = 1,
Miter = 2,
}
impl LineJoinStyle {
fn to_azure_style(&self) -> JoinStyle {
match *self {
LineJoinStyle::Round => JoinStyle::Round,
LineJoinStyle::Bevel => JoinStyle::Bevel,
LineJoinStyle::Miter => JoinStyle::Miter,
}
}
pub fn from_str(string: &str) -> Option<LineJoinStyle> {
match string {
"round" => Some(LineJoinStyle::Round),
"bevel" => Some(LineJoinStyle::Bevel),
"miter" => Some(LineJoinStyle::Miter),
_ => None
}
}
}
#[derive(Copy, Clone, PartialEq)]
pub enum CompositionStyle {
SrcIn,
SrcOut,
SrcOver,
SrcAtop,
DestIn,
DestOut,
DestOver,
DestAtop,
Copy,
Lighter,
Xor,
}
impl CompositionStyle {
fn to_azure_style(&self) -> CompositionOp {
match *self {
CompositionStyle::SrcIn => CompositionOp::In,
CompositionStyle::SrcOut => CompositionOp::Out,
CompositionStyle::SrcOver => CompositionOp::Over,
CompositionStyle::SrcAtop => CompositionOp::Atop,
CompositionStyle::DestIn => CompositionOp::DestIn,
CompositionStyle::DestOut => CompositionOp::DestOut,
CompositionStyle::DestOver => CompositionOp::DestOver,
CompositionStyle::DestAtop => CompositionOp::DestAtop,
CompositionStyle::Copy => CompositionOp::Source,
CompositionStyle::Lighter => CompositionOp::Add,
CompositionStyle::Xor => CompositionOp::Xor,
}
}
pub fn from_str(string: &str) -> Option<CompositionStyle> {
match string {
"source-in" => Some(CompositionStyle::SrcIn),
"source-out" => Some(CompositionStyle::SrcOut),
"source-over" => Some(CompositionStyle::SrcOver),
"source-atop" => Some(CompositionStyle::SrcAtop),
"destination-in" => Some(CompositionStyle::DestIn),
"destination-out" => Some(CompositionStyle::DestOut),
"destination-over" => Some(CompositionStyle::DestOver),
"destination-atop" => Some(CompositionStyle::DestAtop),
"copy" => Some(CompositionStyle::Copy),
"lighter" => Some(CompositionStyle::Lighter),
"xor" => Some(CompositionStyle::Xor),
_ => None
}
}
pub fn to_str(&self) -> &str {
match *self {
CompositionStyle::SrcIn => "source-in",
CompositionStyle::SrcOut => "source-out",
CompositionStyle::SrcOver => "source-over",
CompositionStyle::SrcAtop => "source-atop",
CompositionStyle::DestIn => "destination-in",
CompositionStyle::DestOut => "destination-out",
CompositionStyle::DestOver => "destination-over",
CompositionStyle::DestAtop => "destination-atop",
CompositionStyle::Copy => "copy",
CompositionStyle::Lighter => "lighter",
CompositionStyle::Xor => "xor",
}
}
}
#[derive(Copy, Clone, PartialEq)]
pub enum BlendingStyle {
Multiply,
Screen,
Overlay,
Darken,
Lighten,
ColorDodge,
ColorBurn,
HardLight,
SoftLight,
Difference,
Exclusion,
Hue,
Saturation,
Color,
Luminosity,
}
impl BlendingStyle {
fn to_azure_style(&self) -> CompositionOp {
match *self {
BlendingStyle::Multiply => CompositionOp::Multiply,
BlendingStyle::Screen => CompositionOp::Screen,
BlendingStyle::Overlay => CompositionOp::Overlay,
BlendingStyle::Darken => CompositionOp::Darken,
BlendingStyle::Lighten => CompositionOp::Lighten,
BlendingStyle::ColorDodge => CompositionOp::ColorDodge,
BlendingStyle::ColorBurn => CompositionOp::ColorBurn,
BlendingStyle::HardLight => CompositionOp::HardLight,
BlendingStyle::SoftLight => CompositionOp::SoftLight,
BlendingStyle::Difference => CompositionOp::Difference,
BlendingStyle::Exclusion => CompositionOp::Exclusion,
BlendingStyle::Hue => CompositionOp::Hue,
BlendingStyle::Saturation => CompositionOp::Saturation,
BlendingStyle::Color => CompositionOp::Color,
BlendingStyle::Luminosity => CompositionOp::Luminosity,
}
}
pub fn from_str(string: &str) -> Option<BlendingStyle> {
match string {
"multiply" => Some(BlendingStyle::Multiply),
"screen" => Some(BlendingStyle::Screen),
"overlay" => Some(BlendingStyle::Overlay),
"darken" => Some(BlendingStyle::Darken),
"lighten" => Some(BlendingStyle::Lighten),
"color-dodge" => Some(BlendingStyle::ColorDodge),
"color-burn" => Some(BlendingStyle::ColorBurn),
"hard-light" => Some(BlendingStyle::HardLight),
"soft-light" => Some(BlendingStyle::SoftLight),
"difference" => Some(BlendingStyle::Difference),
"exclusion" => Some(BlendingStyle::Exclusion),
"hue" => Some(BlendingStyle::Hue),
"saturation" => Some(BlendingStyle::Saturation),
"color" => Some(BlendingStyle::Color),
"luminosity" => Some(BlendingStyle::Luminosity),
_ => None
}
}
pub fn to_str(&self) -> &str {
match *self {
BlendingStyle::Multiply => "multiply",
BlendingStyle::Screen => "screen",
BlendingStyle::Overlay => "overlay",
BlendingStyle::Darken => "darken",
BlendingStyle::Lighten => "lighten",
BlendingStyle::ColorDodge => "color-dodge",
BlendingStyle::ColorBurn => "color-burn",
BlendingStyle::HardLight => "hard-light",
BlendingStyle::SoftLight => "soft-light",
BlendingStyle::Difference => "difference",
BlendingStyle::Exclusion => "exclusion",
BlendingStyle::Hue => "hue",
BlendingStyle::Saturation => "saturation",
BlendingStyle::Color => "color",
BlendingStyle::Luminosity => "luminosity",
}
}
}
#[derive(Copy, Clone, PartialEq)]
pub enum CompositionOrBlending {
Composition(CompositionStyle),
Blending(BlendingStyle),
}
impl CompositionOrBlending {
fn to_azure_style(&self) -> CompositionOp {
match *self {
CompositionOrBlending::Composition(op) => op.to_azure_style(),
CompositionOrBlending::Blending(op) => op.to_azure_style(),
}
}
pub fn default() -> CompositionOrBlending {
CompositionOrBlending::Composition(CompositionStyle::SrcOver)
}
pub fn from_str(string: &str) -> Option<CompositionOrBlending> {
if let Some(op) = CompositionStyle::from_str(string) {
return Some(CompositionOrBlending::Composition(op));
}
if let Some(op) = BlendingStyle::from_str(string) {
return Some(CompositionOrBlending::Blending(op));
}
None
}
}
/// Used by drawImage to get rid of the extra pixels of the image data that
/// won't be copied to the canvas
/// image_data: Color pixel data of the image

View file

@ -6,13 +6,15 @@
#![feature(collections)]
#![feature(rustc_private)]
extern crate canvas_traits;
extern crate azure;
extern crate cssparser;
extern crate geom;
extern crate gfx;
extern crate gfx_traits;
extern crate util;
extern crate gleam;
extern crate num;
extern crate layers;
extern crate offscreen_gl_context;
#[macro_use]
@ -20,4 +22,3 @@ extern crate log;
pub mod canvas_paint_task;
pub mod webgl_paint_task;
pub mod canvas_msg;

View file

@ -2,7 +2,7 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use canvas_msg::{CanvasMsg, CanvasWebGLMsg, CanvasCommonMsg};
use canvas_traits::{CanvasMsg, CanvasWebGLMsg, CanvasCommonMsg};
use geom::size::Size2D;
use gleam::gl;
@ -14,7 +14,8 @@ use std::borrow::ToOwned;
use std::slice::bytes::copy_memory;
use std::sync::mpsc::{channel, Sender};
use util::vec::byte_swap;
use offscreen_gl_context::{GLContext, GLContextAttributes};
use layers::platform::surface::NativeSurface;
use offscreen_gl_context::{GLContext, GLContextAttributes, ColorAttachmentType};
pub struct WebGLPaintTask {
size: Size2D<i32>,
@ -29,7 +30,9 @@ unsafe impl Send for WebGLPaintTask {}
impl WebGLPaintTask {
fn new(size: Size2D<i32>) -> Result<WebGLPaintTask, &'static str> {
// TODO(ecoal95): Get the GLContextAttributes from the `GetContext` call
let context = try!(GLContext::create_offscreen(size, GLContextAttributes::default()));
let context = try!(GLContext::create_offscreen_with_color_attachment(size,
GLContextAttributes::default(),
ColorAttachmentType::TextureWithSurface));
Ok(WebGLPaintTask {
size: size,
original_context_size: size,
@ -76,7 +79,10 @@ impl WebGLPaintTask {
CanvasMsg::Common(message) => {
match message {
CanvasCommonMsg::Close => break,
CanvasCommonMsg::SendPixelContents(chan) => painter.send_pixel_contents(chan),
CanvasCommonMsg::SendPixelContents(chan) =>
painter.send_pixel_contents(chan),
CanvasCommonMsg::SendNativeSurface(chan) =>
painter.send_native_surface(chan),
// TODO(ecoal95): handle error nicely
CanvasCommonMsg::Recreate(size) => painter.recreate(size).unwrap(),
}
@ -184,6 +190,12 @@ impl WebGLPaintTask {
chan.send(pixels).unwrap();
}
fn send_native_surface(&self, _: Sender<NativeSurface>) {
// FIXME(ecoal95): We need to make a clone of the surface in order to
// implement this
unimplemented!()
}
fn shader_source(&self, shader_id: u32, source_lines: Vec<String>) {
let mut lines: Vec<&[u8]> = source_lines.iter().map(|line| line.as_bytes()).collect();
gl::shader_source(shader_id, &mut lines);