mirror of
https://github.com/servo/servo.git
synced 2025-06-06 00:25:37 +00:00
Add WebRender integration to Servo.
WebRender is an experimental GPU accelerated rendering backend for Servo. The WebRender backend can be specified by running Servo with the -w option (otherwise the default rendering backend will be used). WebRender has many bugs, and missing features - but it is usable to browse most websites - please report any WebRender specific rendering bugs you encounter!
This commit is contained in:
parent
f7f0eea470
commit
c0531c312f
75 changed files with 2869 additions and 888 deletions
|
@ -33,6 +33,9 @@ git = "https://github.com/ecoal95/rust-offscreen-rendering-context"
|
|||
[dependencies.ipc-channel]
|
||||
git = "https://github.com/servo/ipc-channel"
|
||||
|
||||
[dependencies.webrender_traits]
|
||||
git = "https://github.com/glennw/webrender_traits"
|
||||
|
||||
[dependencies]
|
||||
log = "0.3"
|
||||
num = "0.1.24"
|
||||
|
|
|
@ -24,6 +24,7 @@ use std::sync::mpsc::{Sender, channel};
|
|||
use util::opts;
|
||||
use util::thread::spawn_named;
|
||||
use util::vec::byte_swap;
|
||||
use webrender_traits;
|
||||
|
||||
impl<'a> CanvasPaintThread<'a> {
|
||||
/// It reads image data from the canvas
|
||||
|
@ -63,6 +64,8 @@ pub struct CanvasPaintThread<'a> {
|
|||
path_builder: PathBuilder,
|
||||
state: CanvasPaintState<'a>,
|
||||
saved_states: Vec<CanvasPaintState<'a>>,
|
||||
webrender_api: Option<webrender_traits::RenderApi>,
|
||||
webrender_image_key: Option<webrender_traits::ImageKey>,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -102,27 +105,34 @@ impl<'a> CanvasPaintState<'a> {
|
|||
}
|
||||
|
||||
impl<'a> CanvasPaintThread<'a> {
|
||||
fn new(size: Size2D<i32>) -> CanvasPaintThread<'a> {
|
||||
fn new(size: Size2D<i32>,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> CanvasPaintThread<'a> {
|
||||
let draw_target = CanvasPaintThread::create(size);
|
||||
let path_builder = draw_target.create_path_builder();
|
||||
let webrender_api = webrender_api_sender.map(|wr| wr.create_api());
|
||||
let webrender_image_key = webrender_api.as_ref().map(|wr| wr.alloc_image());
|
||||
CanvasPaintThread {
|
||||
drawtarget: draw_target,
|
||||
path_builder: path_builder,
|
||||
state: CanvasPaintState::new(),
|
||||
saved_states: Vec::new(),
|
||||
webrender_api: webrender_api,
|
||||
webrender_image_key: webrender_image_key,
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new `CanvasPaintThread` and returns the out-of-process sender and the in-process
|
||||
/// sender for it.
|
||||
pub fn start(size: Size2D<i32>) -> (IpcSender<CanvasMsg>, Sender<CanvasMsg>) {
|
||||
pub fn start(size: Size2D<i32>,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
|
||||
-> (IpcSender<CanvasMsg>, Sender<CanvasMsg>) {
|
||||
// TODO(pcwalton): Ask the pipeline to create this for us instead of spawning it directly.
|
||||
// This will be needed for multiprocess Servo.
|
||||
let (out_of_process_chan, out_of_process_port) = ipc::channel::<CanvasMsg>().unwrap();
|
||||
let (in_process_chan, in_process_port) = channel();
|
||||
ROUTER.route_ipc_receiver_to_mpsc_sender(out_of_process_port, in_process_chan.clone());
|
||||
spawn_named("CanvasThread".to_owned(), move || {
|
||||
let mut painter = CanvasPaintThread::new(size);
|
||||
let mut painter = CanvasPaintThread::new(size, webrender_api_sender);
|
||||
loop {
|
||||
let msg = in_process_port.recv();
|
||||
match msg.unwrap() {
|
||||
|
@ -190,8 +200,8 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
},
|
||||
CanvasMsg::FromLayout(message) => {
|
||||
match message {
|
||||
FromLayoutMsg::SendPixelContents(chan) => {
|
||||
painter.send_pixel_contents(chan)
|
||||
FromLayoutMsg::SendData(chan) => {
|
||||
painter.send_data(chan)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -519,9 +529,24 @@ impl<'a> CanvasPaintThread<'a> {
|
|||
self.drawtarget = CanvasPaintThread::create(size);
|
||||
}
|
||||
|
||||
fn send_pixel_contents(&mut self, chan: IpcSender<IpcSharedMemory>) {
|
||||
fn send_data(&mut self, chan: IpcSender<CanvasData>) {
|
||||
self.drawtarget.snapshot().get_data_surface().with_data(|element| {
|
||||
chan.send(IpcSharedMemory::from_bytes(element)).unwrap();
|
||||
if let Some(ref webrender_api) = self.webrender_api {
|
||||
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(),
|
||||
size.width as u32,
|
||||
size.height as u32,
|
||||
webrender_traits::ImageFormat::RGBA8,
|
||||
bytes);
|
||||
}
|
||||
|
||||
let pixel_data = CanvasPixelData {
|
||||
image_data: IpcSharedMemory::from_bytes(element),
|
||||
image_key: self.webrender_image_key,
|
||||
};
|
||||
chan.send(CanvasData::Pixels(pixel_data)).unwrap();
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
* 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/. */
|
||||
|
||||
#![feature(nonzero)]
|
||||
#![feature(plugin)]
|
||||
#![plugin(plugins)]
|
||||
|
||||
|
@ -19,6 +18,7 @@ extern crate log;
|
|||
extern crate num;
|
||||
extern crate offscreen_gl_context;
|
||||
extern crate util;
|
||||
extern crate webrender_traits;
|
||||
|
||||
pub mod canvas_paint_thread;
|
||||
mod premultiplytable;
|
||||
|
|
|
@ -2,9 +2,8 @@
|
|||
* 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_traits::{CanvasCommonMsg, CanvasMsg, CanvasWebGLMsg, FromLayoutMsg, FromPaintMsg};
|
||||
use canvas_traits::{WebGLError, WebGLFramebufferBindingRequest, WebGLParameter, WebGLResult};
|
||||
use core::nonzero::NonZero;
|
||||
use canvas_traits::{CanvasCommonMsg, CanvasMsg, CanvasPixelData, CanvasData, CanvasWebGLMsg};
|
||||
use canvas_traits::{FromLayoutMsg, FromPaintMsg};
|
||||
use euclid::size::Size2D;
|
||||
use gleam::gl;
|
||||
use ipc_channel::ipc::{self, IpcSender, IpcSharedMemory};
|
||||
|
@ -15,186 +14,59 @@ use std::borrow::ToOwned;
|
|||
use std::sync::mpsc::{Sender, channel};
|
||||
use util::thread::spawn_named;
|
||||
use util::vec::byte_swap;
|
||||
use webrender_traits;
|
||||
|
||||
enum WebGLPaintTaskData {
|
||||
WebRender(webrender_traits::RenderApi, webrender_traits::WebGLContextId),
|
||||
Servo(GLContext<NativeGLContext>),
|
||||
}
|
||||
|
||||
pub struct WebGLPaintThread {
|
||||
size: Size2D<i32>,
|
||||
original_context_size: Size2D<i32>,
|
||||
gl_context: GLContext<NativeGLContext>,
|
||||
data: WebGLPaintTaskData,
|
||||
}
|
||||
|
||||
impl WebGLPaintThread {
|
||||
fn new(size: Size2D<i32>, attrs: GLContextAttributes) -> Result<WebGLPaintThread, &'static str> {
|
||||
let context = try!(GLContext::new(size, attrs, ColorAttachmentType::Texture, None));
|
||||
|
||||
// NOTE: As of right now this is always equal to the size parameter,
|
||||
// but this doesn't have to be true. Firefox after failing with
|
||||
// the requested size, tries with the nearest powers of two, for example.
|
||||
let real_size = context.borrow_draw_buffer().unwrap().size();
|
||||
fn new(size: Size2D<i32>,
|
||||
attrs: GLContextAttributes,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Result<WebGLPaintThread, String> {
|
||||
let data = if let Some(sender) = webrender_api_sender {
|
||||
let webrender_api = sender.create_api();
|
||||
let id = try!(webrender_api.request_webgl_context(&size, attrs));
|
||||
WebGLPaintTaskData::WebRender(webrender_api, id)
|
||||
} else {
|
||||
let context = try!(GLContext::<NativeGLContext>::new(size, attrs, ColorAttachmentType::Texture, None));
|
||||
WebGLPaintTaskData::Servo(context)
|
||||
};
|
||||
|
||||
Ok(WebGLPaintThread {
|
||||
size: real_size,
|
||||
original_context_size: real_size,
|
||||
gl_context: context
|
||||
size: size,
|
||||
data: data,
|
||||
})
|
||||
}
|
||||
|
||||
/// In this function the gl commands are called.
|
||||
/// Those messages that just involve a gl call have the call inlined,
|
||||
/// processing of messages that require extra work are moved to functions
|
||||
///
|
||||
/// NB: Not gl-related validations (names, lengths, accepted parameters...) are
|
||||
/// done in the corresponding DOM interfaces
|
||||
pub fn handle_webgl_message(&self, message: CanvasWebGLMsg) {
|
||||
debug!("WebGL message: {:?}", message);
|
||||
|
||||
match message {
|
||||
CanvasWebGLMsg::GetContextAttributes(sender) =>
|
||||
self.context_attributes(sender),
|
||||
CanvasWebGLMsg::ActiveTexture(target) =>
|
||||
gl::active_texture(target),
|
||||
CanvasWebGLMsg::AttachShader(program_id, shader_id) =>
|
||||
gl::attach_shader(program_id, shader_id),
|
||||
CanvasWebGLMsg::BindAttribLocation(program_id, index, name) =>
|
||||
gl::bind_attrib_location(program_id, index, &name),
|
||||
CanvasWebGLMsg::BlendColor(r, g, b, a) =>
|
||||
gl::blend_color(r, g, b, a),
|
||||
CanvasWebGLMsg::BlendEquation(mode) =>
|
||||
gl::blend_equation(mode),
|
||||
CanvasWebGLMsg::BlendEquationSeparate(mode_rgb, mode_alpha) =>
|
||||
gl::blend_equation_separate(mode_rgb, mode_alpha),
|
||||
CanvasWebGLMsg::BlendFunc(src, dest) =>
|
||||
gl::blend_func(src, dest),
|
||||
CanvasWebGLMsg::BlendFuncSeparate(src_rgb, dest_rgb, src_alpha, dest_alpha) =>
|
||||
gl::blend_func_separate(src_rgb, dest_rgb, src_alpha, dest_alpha),
|
||||
CanvasWebGLMsg::BufferData(buffer_type, data, usage) =>
|
||||
gl::buffer_data(buffer_type, &data, usage),
|
||||
CanvasWebGLMsg::BufferSubData(buffer_type, offset, data) =>
|
||||
gl::buffer_sub_data(buffer_type, offset, &data),
|
||||
CanvasWebGLMsg::Clear(mask) =>
|
||||
gl::clear(mask),
|
||||
CanvasWebGLMsg::ClearColor(r, g, b, a) =>
|
||||
gl::clear_color(r, g, b, a),
|
||||
CanvasWebGLMsg::ClearDepth(depth) =>
|
||||
gl::clear_depth(depth),
|
||||
CanvasWebGLMsg::ClearStencil(stencil) =>
|
||||
gl::clear_stencil(stencil),
|
||||
CanvasWebGLMsg::ColorMask(r, g, b, a) =>
|
||||
gl::color_mask(r, g, b, a),
|
||||
CanvasWebGLMsg::CullFace(mode) =>
|
||||
gl::cull_face(mode),
|
||||
CanvasWebGLMsg::DepthFunc(func) =>
|
||||
gl::depth_func(func),
|
||||
CanvasWebGLMsg::DepthMask(flag) =>
|
||||
gl::depth_mask(flag),
|
||||
CanvasWebGLMsg::DepthRange(near, far) =>
|
||||
gl::depth_range(near, far),
|
||||
CanvasWebGLMsg::Disable(cap) =>
|
||||
gl::disable(cap),
|
||||
CanvasWebGLMsg::Enable(cap) =>
|
||||
gl::enable(cap),
|
||||
CanvasWebGLMsg::FrontFace(mode) =>
|
||||
gl::front_face(mode),
|
||||
CanvasWebGLMsg::DrawArrays(mode, first, count) =>
|
||||
gl::draw_arrays(mode, first, count),
|
||||
CanvasWebGLMsg::DrawElements(mode, count, type_, offset) =>
|
||||
gl::draw_elements(mode, count, type_, offset as u32),
|
||||
CanvasWebGLMsg::Hint(name, val) =>
|
||||
gl::hint(name, val),
|
||||
CanvasWebGLMsg::LineWidth(width) =>
|
||||
gl::line_width(width),
|
||||
CanvasWebGLMsg::PixelStorei(name, val) =>
|
||||
gl::pixel_store_i(name, val),
|
||||
CanvasWebGLMsg::PolygonOffset(factor, units) =>
|
||||
gl::polygon_offset(factor, units),
|
||||
CanvasWebGLMsg::Scissor(x, y, width, height) =>
|
||||
gl::scissor(x, y, width, height),
|
||||
CanvasWebGLMsg::EnableVertexAttribArray(attrib_id) =>
|
||||
gl::enable_vertex_attrib_array(attrib_id),
|
||||
CanvasWebGLMsg::GetAttribLocation(program_id, name, chan) =>
|
||||
self.attrib_location(program_id, name, chan),
|
||||
CanvasWebGLMsg::GetBufferParameter(target, param_id, chan) =>
|
||||
self.buffer_parameter(target, param_id, chan),
|
||||
CanvasWebGLMsg::GetParameter(param_id, chan) =>
|
||||
self.parameter(param_id, chan),
|
||||
CanvasWebGLMsg::GetProgramParameter(program_id, param_id, chan) =>
|
||||
self.program_parameter(program_id, param_id, chan),
|
||||
CanvasWebGLMsg::GetShaderParameter(shader_id, param_id, chan) =>
|
||||
self.shader_parameter(shader_id, param_id, chan),
|
||||
CanvasWebGLMsg::GetUniformLocation(program_id, name, chan) =>
|
||||
self.uniform_location(program_id, name, chan),
|
||||
CanvasWebGLMsg::CompileShader(shader_id, source) =>
|
||||
self.compile_shader(shader_id, source),
|
||||
CanvasWebGLMsg::CreateBuffer(chan) =>
|
||||
self.create_buffer(chan),
|
||||
CanvasWebGLMsg::CreateFramebuffer(chan) =>
|
||||
self.create_framebuffer(chan),
|
||||
CanvasWebGLMsg::CreateRenderbuffer(chan) =>
|
||||
self.create_renderbuffer(chan),
|
||||
CanvasWebGLMsg::CreateTexture(chan) =>
|
||||
self.create_texture(chan),
|
||||
CanvasWebGLMsg::CreateProgram(chan) =>
|
||||
self.create_program(chan),
|
||||
CanvasWebGLMsg::CreateShader(shader_type, chan) =>
|
||||
self.create_shader(shader_type, chan),
|
||||
CanvasWebGLMsg::DeleteBuffer(id) =>
|
||||
gl::delete_buffers(&[id]),
|
||||
CanvasWebGLMsg::DeleteFramebuffer(id) =>
|
||||
gl::delete_framebuffers(&[id]),
|
||||
CanvasWebGLMsg::DeleteRenderbuffer(id) =>
|
||||
gl::delete_renderbuffers(&[id]),
|
||||
CanvasWebGLMsg::DeleteTexture(id) =>
|
||||
gl::delete_textures(&[id]),
|
||||
CanvasWebGLMsg::DeleteProgram(id) =>
|
||||
gl::delete_program(id),
|
||||
CanvasWebGLMsg::DeleteShader(id) =>
|
||||
gl::delete_shader(id),
|
||||
CanvasWebGLMsg::BindBuffer(target, id) =>
|
||||
gl::bind_buffer(target, id),
|
||||
CanvasWebGLMsg::BindFramebuffer(target, request) =>
|
||||
self.bind_framebuffer(target, request),
|
||||
CanvasWebGLMsg::BindRenderbuffer(target, id) =>
|
||||
gl::bind_renderbuffer(target, id),
|
||||
CanvasWebGLMsg::BindTexture(target, id) =>
|
||||
gl::bind_texture(target, id),
|
||||
CanvasWebGLMsg::LinkProgram(program_id) =>
|
||||
gl::link_program(program_id),
|
||||
CanvasWebGLMsg::Uniform1f(uniform_id, x) =>
|
||||
gl::uniform_1f(uniform_id, x),
|
||||
CanvasWebGLMsg::Uniform4f(uniform_id, x, y, z, w) =>
|
||||
gl::uniform_4f(uniform_id, x, y, z, w),
|
||||
CanvasWebGLMsg::UseProgram(program_id) =>
|
||||
gl::use_program(program_id),
|
||||
CanvasWebGLMsg::VertexAttrib(attrib_id, x, y, z, w) =>
|
||||
gl::vertex_attrib_4f(attrib_id, x, y, z, w),
|
||||
CanvasWebGLMsg::VertexAttribPointer2f(attrib_id, size, normalized, stride, offset) =>
|
||||
gl::vertex_attrib_pointer_f32(attrib_id, size, normalized, stride, offset as u32),
|
||||
CanvasWebGLMsg::Viewport(x, y, width, height) =>
|
||||
gl::viewport(x, y, width, height),
|
||||
CanvasWebGLMsg::TexImage2D(target, level, internal, width, height, format, data_type, data) =>
|
||||
gl::tex_image_2d(target, level, internal, width, height, /*border*/0, format, data_type, Some(&data)),
|
||||
CanvasWebGLMsg::TexParameteri(target, name, value) =>
|
||||
gl::tex_parameter_i(target, name, value),
|
||||
CanvasWebGLMsg::TexParameterf(target, name, value) =>
|
||||
gl::tex_parameter_f(target, name, value),
|
||||
CanvasWebGLMsg::DrawingBufferWidth(sender) =>
|
||||
self.send_drawing_buffer_width(sender),
|
||||
CanvasWebGLMsg::DrawingBufferHeight(sender) =>
|
||||
self.send_drawing_buffer_height(sender),
|
||||
match self.data {
|
||||
WebGLPaintTaskData::WebRender(ref api, id) => {
|
||||
api.send_webgl_command(id, message);
|
||||
}
|
||||
WebGLPaintTaskData::Servo(ref ctx) => {
|
||||
message.apply(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: Use debug_assertions once tests are run with them
|
||||
let error = gl::get_error();
|
||||
assert!(error == gl::NO_ERROR, "Unexpected WebGL error: 0x{:x} ({})", error, error);
|
||||
}
|
||||
|
||||
/// Creates a new `WebGLPaintThread` and returns the out-of-process sender and the in-process
|
||||
/// sender for it.
|
||||
pub fn start(size: Size2D<i32>, attrs: GLContextAttributes)
|
||||
-> Result<(IpcSender<CanvasMsg>, Sender<CanvasMsg>), &'static str> {
|
||||
pub fn start(size: Size2D<i32>,
|
||||
attrs: GLContextAttributes,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
|
||||
-> Result<(IpcSender<CanvasMsg>, Sender<CanvasMsg>), String> {
|
||||
let (in_process_chan, in_process_port) = channel();
|
||||
let (result_chan, result_port) = channel();
|
||||
spawn_named("WebGLThread".to_owned(), move || {
|
||||
let mut painter = match WebGLPaintThread::new(size, attrs) {
|
||||
let mut painter = match WebGLPaintThread::new(size, attrs, webrender_api_sender) {
|
||||
Ok(thread) => {
|
||||
result_chan.send(Ok(())).unwrap();
|
||||
thread
|
||||
|
@ -217,8 +89,8 @@ impl WebGLPaintThread {
|
|||
},
|
||||
CanvasMsg::FromLayout(message) => {
|
||||
match message {
|
||||
FromLayoutMsg::SendPixelContents(chan) =>
|
||||
painter.send_pixel_contents(chan),
|
||||
FromLayoutMsg::SendData(chan) =>
|
||||
painter.send_data(chan),
|
||||
}
|
||||
}
|
||||
CanvasMsg::FromPaint(message) => {
|
||||
|
@ -239,319 +111,40 @@ impl WebGLPaintThread {
|
|||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn context_attributes(&self, sender: IpcSender<GLContextAttributes>) {
|
||||
sender.send(*self.gl_context.borrow_attributes()).unwrap()
|
||||
}
|
||||
fn send_data(&mut self, chan: IpcSender<CanvasData>) {
|
||||
match self.data {
|
||||
WebGLPaintTaskData::Servo(_) => {
|
||||
let width = self.size.width as usize;
|
||||
let height = self.size.height as usize;
|
||||
|
||||
#[inline]
|
||||
fn send_drawing_buffer_width(&self, sender: IpcSender<i32>) {
|
||||
sender.send(self.size.width).unwrap()
|
||||
}
|
||||
let mut pixels = gl::read_pixels(0, 0,
|
||||
self.size.width as gl::GLsizei,
|
||||
self.size.height as gl::GLsizei,
|
||||
gl::RGBA, gl::UNSIGNED_BYTE);
|
||||
// flip image vertically (texture is upside down)
|
||||
let orig_pixels = pixels.clone();
|
||||
let stride = width * 4;
|
||||
for y in 0..height {
|
||||
let dst_start = y * stride;
|
||||
let src_start = (height - y - 1) * stride;
|
||||
let src_slice = &orig_pixels[src_start .. src_start + stride];
|
||||
(&mut pixels[dst_start .. dst_start + stride]).clone_from_slice(&src_slice[..stride]);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn send_drawing_buffer_height(&self, sender: IpcSender<i32>) {
|
||||
sender.send(self.size.height).unwrap()
|
||||
}
|
||||
// rgba -> bgra
|
||||
byte_swap(&mut pixels);
|
||||
|
||||
fn create_buffer(&self, chan: IpcSender<Option<NonZero<u32>>>) {
|
||||
let buffer = gl::gen_buffers(1)[0];
|
||||
let buffer = if buffer == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { NonZero::new(buffer) })
|
||||
};
|
||||
chan.send(buffer).unwrap();
|
||||
}
|
||||
let pixel_data = CanvasPixelData {
|
||||
image_data: IpcSharedMemory::from_bytes(&pixels[..]),
|
||||
image_key: None,
|
||||
};
|
||||
|
||||
fn create_framebuffer(&self, chan: IpcSender<Option<NonZero<u32>>>) {
|
||||
let framebuffer = gl::gen_framebuffers(1)[0];
|
||||
let framebuffer = if framebuffer == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { NonZero::new(framebuffer) })
|
||||
};
|
||||
chan.send(framebuffer).unwrap();
|
||||
}
|
||||
|
||||
fn create_renderbuffer(&self, chan: IpcSender<Option<NonZero<u32>>>) {
|
||||
let renderbuffer = gl::gen_renderbuffers(1)[0];
|
||||
let renderbuffer = if renderbuffer == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { NonZero::new(renderbuffer) })
|
||||
};
|
||||
chan.send(renderbuffer).unwrap();
|
||||
}
|
||||
|
||||
fn create_texture(&self, chan: IpcSender<Option<NonZero<u32>>>) {
|
||||
let texture = gl::gen_framebuffers(1)[0];
|
||||
let texture = if texture == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { NonZero::new(texture) })
|
||||
};
|
||||
chan.send(texture).unwrap();
|
||||
}
|
||||
|
||||
fn create_program(&self, chan: IpcSender<Option<NonZero<u32>>>) {
|
||||
let program = gl::create_program();
|
||||
let program = if program == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { NonZero::new(program) })
|
||||
};
|
||||
|
||||
chan.send(program).unwrap();
|
||||
}
|
||||
|
||||
fn create_shader(&self, shader_type: u32, chan: IpcSender<Option<NonZero<u32>>>) {
|
||||
let shader = gl::create_shader(shader_type);
|
||||
let shader = if shader == 0 {
|
||||
None
|
||||
} else {
|
||||
Some(unsafe { NonZero::new(shader) })
|
||||
};
|
||||
chan.send(shader).unwrap();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn bind_framebuffer(&self, target: u32, request: WebGLFramebufferBindingRequest) {
|
||||
let id = match request {
|
||||
WebGLFramebufferBindingRequest::Explicit(id) => id,
|
||||
WebGLFramebufferBindingRequest::Default =>
|
||||
self.gl_context.borrow_draw_buffer().unwrap().get_framebuffer(),
|
||||
};
|
||||
|
||||
gl::bind_framebuffer(target, id);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn compile_shader(&self, shader_id: u32, source: String) {
|
||||
gl::shader_source(shader_id, &[source.as_bytes()]);
|
||||
gl::compile_shader(shader_id);
|
||||
}
|
||||
|
||||
fn attrib_location(&self, program_id: u32, name: String, chan: IpcSender<Option<i32>> ) {
|
||||
let attrib_location = gl::get_attrib_location(program_id, &name);
|
||||
|
||||
let attrib_location = if attrib_location == -1 {
|
||||
None
|
||||
} else {
|
||||
Some(attrib_location)
|
||||
};
|
||||
|
||||
chan.send(attrib_location).unwrap();
|
||||
}
|
||||
|
||||
fn parameter(&self,
|
||||
param_id: u32,
|
||||
chan: IpcSender<WebGLResult<WebGLParameter>>) {
|
||||
let result = match param_id {
|
||||
gl::ACTIVE_TEXTURE |
|
||||
//gl::ALPHA_BITS |
|
||||
gl::BLEND_DST_ALPHA |
|
||||
gl::BLEND_DST_RGB |
|
||||
gl::BLEND_EQUATION_ALPHA |
|
||||
gl::BLEND_EQUATION_RGB |
|
||||
gl::BLEND_SRC_ALPHA |
|
||||
gl::BLEND_SRC_RGB |
|
||||
//gl::BLUE_BITS |
|
||||
gl::CULL_FACE_MODE |
|
||||
//gl::DEPTH_BITS |
|
||||
gl::DEPTH_FUNC |
|
||||
gl::FRONT_FACE |
|
||||
//gl::GENERATE_MIPMAP_HINT |
|
||||
//gl::GREEN_BITS |
|
||||
//gl::IMPLEMENTATION_COLOR_READ_FORMAT |
|
||||
//gl::IMPLEMENTATION_COLOR_READ_TYPE |
|
||||
gl::MAX_COMBINED_TEXTURE_IMAGE_UNITS |
|
||||
gl::MAX_CUBE_MAP_TEXTURE_SIZE |
|
||||
//gl::MAX_FRAGMENT_UNIFORM_VECTORS |
|
||||
gl::MAX_RENDERBUFFER_SIZE |
|
||||
gl::MAX_TEXTURE_IMAGE_UNITS |
|
||||
gl::MAX_TEXTURE_SIZE |
|
||||
//gl::MAX_VARYING_VECTORS |
|
||||
gl::MAX_VERTEX_ATTRIBS |
|
||||
gl::MAX_VERTEX_TEXTURE_IMAGE_UNITS |
|
||||
//gl::MAX_VERTEX_UNIFORM_VECTORS |
|
||||
gl::PACK_ALIGNMENT |
|
||||
//gl::RED_BITS |
|
||||
gl::SAMPLE_BUFFERS |
|
||||
gl::SAMPLES |
|
||||
gl::STENCIL_BACK_FAIL |
|
||||
gl::STENCIL_BACK_FUNC |
|
||||
gl::STENCIL_BACK_PASS_DEPTH_FAIL |
|
||||
gl::STENCIL_BACK_PASS_DEPTH_PASS |
|
||||
gl::STENCIL_BACK_REF |
|
||||
gl::STENCIL_BACK_VALUE_MASK |
|
||||
gl::STENCIL_BACK_WRITEMASK |
|
||||
//gl::STENCIL_BITS |
|
||||
gl::STENCIL_CLEAR_VALUE |
|
||||
gl::STENCIL_FAIL |
|
||||
gl::STENCIL_FUNC |
|
||||
gl::STENCIL_PASS_DEPTH_FAIL |
|
||||
gl::STENCIL_PASS_DEPTH_PASS |
|
||||
gl::STENCIL_REF |
|
||||
gl::STENCIL_VALUE_MASK |
|
||||
gl::STENCIL_WRITEMASK |
|
||||
gl::SUBPIXEL_BITS |
|
||||
gl::UNPACK_ALIGNMENT =>
|
||||
//gl::UNPACK_COLORSPACE_CONVERSION_WEBGL =>
|
||||
Ok(WebGLParameter::Int(gl::get_integer_v(param_id))),
|
||||
|
||||
gl::BLEND |
|
||||
gl::CULL_FACE |
|
||||
gl::DEPTH_TEST |
|
||||
gl::DEPTH_WRITEMASK |
|
||||
gl::DITHER |
|
||||
gl::POLYGON_OFFSET_FILL |
|
||||
gl::SAMPLE_COVERAGE_INVERT |
|
||||
gl::STENCIL_TEST =>
|
||||
//gl::UNPACK_FLIP_Y_WEBGL |
|
||||
//gl::UNPACK_PREMULTIPLY_ALPHA_WEBGL =>
|
||||
Ok(WebGLParameter::Bool(gl::get_boolean_v(param_id) != 0)),
|
||||
|
||||
gl::DEPTH_CLEAR_VALUE |
|
||||
gl::LINE_WIDTH |
|
||||
gl::POLYGON_OFFSET_FACTOR |
|
||||
gl::POLYGON_OFFSET_UNITS |
|
||||
gl::SAMPLE_COVERAGE_VALUE =>
|
||||
Ok(WebGLParameter::Float(gl::get_float_v(param_id))),
|
||||
|
||||
gl::VERSION => Ok(WebGLParameter::String("WebGL 1.0".to_owned())),
|
||||
gl::RENDERER |
|
||||
gl::VENDOR => Ok(WebGLParameter::String("Mozilla/Servo".to_owned())),
|
||||
gl::SHADING_LANGUAGE_VERSION => Ok(WebGLParameter::String("WebGL GLSL ES 1.0".to_owned())),
|
||||
|
||||
// TODO(zbarsky, ecoal95): Implement support for the following valid parameters
|
||||
// Float32Array
|
||||
gl::ALIASED_LINE_WIDTH_RANGE |
|
||||
//gl::ALIASED_POINT_SIZE_RANGE |
|
||||
//gl::BLEND_COLOR |
|
||||
gl::COLOR_CLEAR_VALUE |
|
||||
gl::DEPTH_RANGE |
|
||||
|
||||
// WebGLBuffer
|
||||
gl::ARRAY_BUFFER_BINDING |
|
||||
gl::ELEMENT_ARRAY_BUFFER_BINDING |
|
||||
|
||||
// WebGLFrameBuffer
|
||||
gl::FRAMEBUFFER_BINDING |
|
||||
|
||||
// WebGLRenderBuffer
|
||||
gl::RENDERBUFFER_BINDING |
|
||||
|
||||
// WebGLProgram
|
||||
gl::CURRENT_PROGRAM |
|
||||
|
||||
// WebGLTexture
|
||||
gl::TEXTURE_BINDING_2D |
|
||||
gl::TEXTURE_BINDING_CUBE_MAP |
|
||||
|
||||
// sequence<GlBoolean>
|
||||
gl::COLOR_WRITEMASK |
|
||||
|
||||
// Uint32Array
|
||||
gl::COMPRESSED_TEXTURE_FORMATS |
|
||||
|
||||
// Int32Array
|
||||
gl::MAX_VIEWPORT_DIMS |
|
||||
gl::SCISSOR_BOX |
|
||||
gl::VIEWPORT => Err(WebGLError::InvalidEnum),
|
||||
|
||||
// Invalid parameters
|
||||
_ => Err(WebGLError::InvalidEnum)
|
||||
};
|
||||
|
||||
chan.send(result).unwrap();
|
||||
}
|
||||
|
||||
fn buffer_parameter(&self,
|
||||
target: u32,
|
||||
param_id: u32,
|
||||
chan: IpcSender<WebGLResult<WebGLParameter>>) {
|
||||
let result = match param_id {
|
||||
gl::BUFFER_SIZE |
|
||||
gl::BUFFER_USAGE =>
|
||||
Ok(WebGLParameter::Int(gl::get_buffer_parameter_iv(target, param_id))),
|
||||
_ => Err(WebGLError::InvalidEnum),
|
||||
};
|
||||
|
||||
chan.send(result).unwrap();
|
||||
}
|
||||
|
||||
fn program_parameter(&self,
|
||||
program_id: u32,
|
||||
param_id: u32,
|
||||
chan: IpcSender<WebGLResult<WebGLParameter>>) {
|
||||
let result = match param_id {
|
||||
gl::DELETE_STATUS |
|
||||
gl::LINK_STATUS |
|
||||
gl::VALIDATE_STATUS =>
|
||||
Ok(WebGLParameter::Bool(gl::get_program_iv(program_id, param_id) != 0)),
|
||||
gl::ATTACHED_SHADERS |
|
||||
gl::ACTIVE_ATTRIBUTES |
|
||||
gl::ACTIVE_UNIFORMS =>
|
||||
Ok(WebGLParameter::Int(gl::get_program_iv(program_id, param_id))),
|
||||
_ => Err(WebGLError::InvalidEnum),
|
||||
};
|
||||
|
||||
chan.send(result).unwrap();
|
||||
}
|
||||
|
||||
fn shader_parameter(&self,
|
||||
shader_id: u32,
|
||||
param_id: u32,
|
||||
chan: IpcSender<WebGLResult<WebGLParameter>>) {
|
||||
let result = match param_id {
|
||||
gl::SHADER_TYPE =>
|
||||
Ok(WebGLParameter::Int(gl::get_shader_iv(shader_id, param_id))),
|
||||
gl::DELETE_STATUS |
|
||||
gl::COMPILE_STATUS =>
|
||||
Ok(WebGLParameter::Bool(gl::get_shader_iv(shader_id, param_id) != 0)),
|
||||
_ => Err(WebGLError::InvalidEnum),
|
||||
};
|
||||
|
||||
chan.send(result).unwrap();
|
||||
}
|
||||
|
||||
fn uniform_location(&self, program_id: u32, name: String, chan: IpcSender<Option<i32>>) {
|
||||
let location = gl::get_uniform_location(program_id, &name);
|
||||
let location = if location == -1 {
|
||||
None
|
||||
} else {
|
||||
Some(location)
|
||||
};
|
||||
|
||||
chan.send(location).unwrap();
|
||||
}
|
||||
|
||||
fn send_pixel_contents(&mut self, chan: IpcSender<IpcSharedMemory>) {
|
||||
// FIXME(#5652, dmarcos) Instead of a readback strategy we have
|
||||
// to layerize the canvas.
|
||||
// TODO(pcwalton): We'd save a copy if we had an `IpcSharedMemoryBuilder` abstraction that
|
||||
// allowed you to mutate in-place before freezing the object for sending.
|
||||
let width = self.size.width as usize;
|
||||
let height = self.size.height as usize;
|
||||
|
||||
let mut pixels = gl::read_pixels(0, 0,
|
||||
self.size.width as gl::GLsizei,
|
||||
self.size.height as gl::GLsizei,
|
||||
gl::RGBA, gl::UNSIGNED_BYTE);
|
||||
// flip image vertically (texture is upside down)
|
||||
let orig_pixels = pixels.clone();
|
||||
let stride = width * 4;
|
||||
for y in 0..height {
|
||||
let dst_start = y * stride;
|
||||
let src_start = (height - y - 1) * stride;
|
||||
let src_slice = &orig_pixels[src_start .. src_start + stride];
|
||||
(&mut pixels[dst_start .. dst_start + stride]).clone_from_slice(&src_slice[..stride]);
|
||||
chan.send(CanvasData::Pixels(pixel_data)).unwrap();
|
||||
}
|
||||
WebGLPaintTaskData::WebRender(_, id) => {
|
||||
chan.send(CanvasData::WebGL(id)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
// rgba -> bgra
|
||||
byte_swap(&mut pixels);
|
||||
chan.send(IpcSharedMemory::from_bytes(&pixels[..])).unwrap();
|
||||
}
|
||||
|
||||
fn send_native_surface(&self, _: Sender<NativeSurface>) {
|
||||
|
@ -561,18 +154,28 @@ impl WebGLPaintThread {
|
|||
}
|
||||
|
||||
fn recreate(&mut self, size: Size2D<i32>) -> Result<(), &'static str> {
|
||||
if size.width > self.original_context_size.width ||
|
||||
size.height > self.original_context_size.height {
|
||||
try!(self.gl_context.resize(size));
|
||||
self.size = self.gl_context.borrow_draw_buffer().unwrap().size();
|
||||
} else {
|
||||
self.size = size;
|
||||
unsafe { gl::Scissor(0, 0, size.width, size.height); }
|
||||
match self.data {
|
||||
WebGLPaintTaskData::Servo(ref mut context) => {
|
||||
if size.width > self.size.width ||
|
||||
size.height > self.size.height {
|
||||
try!(context.resize(size));
|
||||
self.size = context.borrow_draw_buffer().unwrap().size();
|
||||
} else {
|
||||
self.size = size;
|
||||
unsafe { gl::Scissor(0, 0, size.width, size.height); }
|
||||
}
|
||||
}
|
||||
WebGLPaintTaskData::WebRender(_, _) => {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn init(&mut self) {
|
||||
self.gl_context.make_current().unwrap();
|
||||
if let WebGLPaintTaskData::Servo(ref context) = self.data {
|
||||
context.make_current().unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,9 @@ path = "../plugins"
|
|||
[dependencies.util]
|
||||
path = "../util"
|
||||
|
||||
[dependencies.webrender_traits]
|
||||
git = "https://github.com/glennw/webrender_traits"
|
||||
|
||||
[dependencies]
|
||||
cssparser = {version = "0.5.3", features = ["heap_size", "serde-serialization"]}
|
||||
euclid = {version = "0.6.2", features = ["plugins"]}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
#![crate_name = "canvas_traits"]
|
||||
#![crate_type = "rlib"]
|
||||
#![feature(custom_derive)]
|
||||
#![feature(nonzero)]
|
||||
#![feature(plugin)]
|
||||
#![plugin(heapsize_plugin, plugins, serde_macros)]
|
||||
|
||||
|
@ -20,13 +19,13 @@ extern crate layers;
|
|||
extern crate offscreen_gl_context;
|
||||
extern crate serde;
|
||||
extern crate util;
|
||||
extern crate webrender_traits;
|
||||
|
||||
use azure::azure::{AzColor, AzFloat};
|
||||
use azure::azure_hl::{CapStyle, CompositionOp, JoinStyle};
|
||||
use azure::azure_hl::{ColorPattern, DrawTarget, Pattern};
|
||||
use azure::azure_hl::{ExtendMode, GradientStop, LinearGradientPattern, RadialGradientPattern};
|
||||
use azure::azure_hl::{SurfaceFormat, SurfacePattern};
|
||||
use core::nonzero::NonZero;
|
||||
use cssparser::RGBA;
|
||||
use euclid::matrix2d::Matrix2D;
|
||||
use euclid::point::Point2D;
|
||||
|
@ -35,13 +34,14 @@ use euclid::size::Size2D;
|
|||
use gfx_traits::color;
|
||||
use ipc_channel::ipc::{IpcSender, IpcSharedMemory};
|
||||
use layers::platform::surface::NativeSurface;
|
||||
use offscreen_gl_context::GLContextAttributes;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::default::Default;
|
||||
use std::fmt;
|
||||
use std::str::FromStr;
|
||||
use std::sync::mpsc::Sender;
|
||||
|
||||
pub use webrender_traits::{WebGLFramebufferBindingRequest, WebGLError, WebGLParameter, WebGLResult, WebGLContextId};
|
||||
pub use webrender_traits::WebGLCommand as CanvasWebGLMsg;
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub enum FillRule {
|
||||
Nonzero,
|
||||
|
@ -63,9 +63,21 @@ pub enum CanvasCommonMsg {
|
|||
Recreate(Size2D<i32>),
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub enum CanvasData {
|
||||
Pixels(CanvasPixelData),
|
||||
WebGL(WebGLContextId),
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub struct CanvasPixelData {
|
||||
pub image_data: IpcSharedMemory,
|
||||
pub image_key: Option<webrender_traits::ImageKey>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub enum FromLayoutMsg {
|
||||
SendPixelContents(IpcSender<IpcSharedMemory>),
|
||||
SendData(IpcSender<CanvasData>),
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
@ -124,178 +136,6 @@ pub enum Canvas2dMsg {
|
|||
SetShadowColor(RGBA),
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub enum CanvasWebGLMsg {
|
||||
GetContextAttributes(IpcSender<GLContextAttributes>),
|
||||
ActiveTexture(u32),
|
||||
BlendColor(f32, f32, f32, f32),
|
||||
BlendEquation(u32),
|
||||
BlendEquationSeparate(u32, u32),
|
||||
BlendFunc(u32, u32),
|
||||
BlendFuncSeparate(u32, u32, u32, u32),
|
||||
AttachShader(u32, u32),
|
||||
BindAttribLocation(u32, u32, String),
|
||||
BufferData(u32, Vec<u8>, u32),
|
||||
BufferSubData(u32, isize, Vec<u8>),
|
||||
Clear(u32),
|
||||
ClearColor(f32, f32, f32, f32),
|
||||
ClearDepth(f64),
|
||||
ClearStencil(i32),
|
||||
ColorMask(bool, bool, bool, bool),
|
||||
CullFace(u32),
|
||||
FrontFace(u32),
|
||||
DepthFunc(u32),
|
||||
DepthMask(bool),
|
||||
DepthRange(f64, f64),
|
||||
Enable(u32),
|
||||
Disable(u32),
|
||||
CompileShader(u32, String),
|
||||
CreateBuffer(IpcSender<Option<NonZero<u32>>>),
|
||||
CreateFramebuffer(IpcSender<Option<NonZero<u32>>>),
|
||||
CreateRenderbuffer(IpcSender<Option<NonZero<u32>>>),
|
||||
CreateTexture(IpcSender<Option<NonZero<u32>>>),
|
||||
CreateProgram(IpcSender<Option<NonZero<u32>>>),
|
||||
CreateShader(u32, IpcSender<Option<NonZero<u32>>>),
|
||||
DeleteBuffer(u32),
|
||||
DeleteFramebuffer(u32),
|
||||
DeleteRenderbuffer(u32),
|
||||
DeleteTexture(u32),
|
||||
DeleteProgram(u32),
|
||||
DeleteShader(u32),
|
||||
BindBuffer(u32, u32),
|
||||
BindFramebuffer(u32, WebGLFramebufferBindingRequest),
|
||||
BindRenderbuffer(u32, u32),
|
||||
BindTexture(u32, u32),
|
||||
DrawArrays(u32, i32, i32),
|
||||
DrawElements(u32, i32, u32, i64),
|
||||
EnableVertexAttribArray(u32),
|
||||
GetBufferParameter(u32, u32, IpcSender<WebGLResult<WebGLParameter>>),
|
||||
GetParameter(u32, IpcSender<WebGLResult<WebGLParameter>>),
|
||||
GetProgramParameter(u32, u32, IpcSender<WebGLResult<WebGLParameter>>),
|
||||
GetShaderParameter(u32, u32, IpcSender<WebGLResult<WebGLParameter>>),
|
||||
GetAttribLocation(u32, String, IpcSender<Option<i32>>),
|
||||
GetUniformLocation(u32, String, IpcSender<Option<i32>>),
|
||||
PolygonOffset(f32, f32),
|
||||
Scissor(i32, i32, i32, i32),
|
||||
Hint(u32, u32),
|
||||
LineWidth(f32),
|
||||
PixelStorei(u32, i32),
|
||||
LinkProgram(u32),
|
||||
Uniform1f(i32, f32),
|
||||
Uniform4f(i32, f32, f32, f32, f32),
|
||||
UseProgram(u32),
|
||||
VertexAttrib(u32, f32, f32, f32, f32),
|
||||
VertexAttribPointer2f(u32, i32, bool, i32, u32),
|
||||
Viewport(i32, i32, i32, i32),
|
||||
TexImage2D(u32, i32, i32, i32, i32, u32, u32, Vec<u8>),
|
||||
TexParameteri(u32, u32, i32),
|
||||
TexParameterf(u32, u32, f32),
|
||||
DrawingBufferWidth(IpcSender<i32>),
|
||||
DrawingBufferHeight(IpcSender<i32>),
|
||||
}
|
||||
|
||||
impl fmt::Debug for CanvasWebGLMsg {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
use CanvasWebGLMsg::*;
|
||||
let name = match *self {
|
||||
GetContextAttributes(..) => "GetContextAttributes",
|
||||
ActiveTexture(..) => "ActiveTexture",
|
||||
BlendColor(..) => "BlendColor",
|
||||
BlendEquation(..) => "BlendEquation",
|
||||
BlendEquationSeparate(..) => "BlendEquationSeparate",
|
||||
BlendFunc(..) => "BlendFunc",
|
||||
BlendFuncSeparate(..) => "BlendFuncSeparate",
|
||||
AttachShader(..) => "AttachShader",
|
||||
BindAttribLocation(..) => "BindAttribLocation",
|
||||
BufferData(..) => "BufferData",
|
||||
BufferSubData(..) => "BufferSubData",
|
||||
Clear(..) => "Clear",
|
||||
ClearColor(..) => "ClearColor",
|
||||
ClearDepth(..) => "ClearDepth",
|
||||
ClearStencil(..) => "ClearStencil",
|
||||
ColorMask(..) => "ColorMask",
|
||||
CullFace(..) => "CullFace",
|
||||
FrontFace(..) => "FrontFace",
|
||||
DepthFunc(..) => "DepthFunc",
|
||||
DepthMask(..) => "DepthMask",
|
||||
DepthRange(..) => "DepthRange",
|
||||
Enable(..) => "Enable",
|
||||
Disable(..) => "Disable",
|
||||
CompileShader(..) => "CompileShader",
|
||||
CreateBuffer(..) => "CreateBuffer",
|
||||
CreateFramebuffer(..) => "CreateFramebuffer",
|
||||
CreateRenderbuffer(..) => "CreateRenderbuffer",
|
||||
CreateTexture(..) => "CreateTexture",
|
||||
CreateProgram(..) => "CreateProgram",
|
||||
CreateShader(..) => "CreateShader",
|
||||
DeleteBuffer(..) => "DeleteBuffer",
|
||||
DeleteFramebuffer(..) => "DeleteFramebuffer",
|
||||
DeleteRenderbuffer(..) => "DeleteRenderBuffer",
|
||||
DeleteTexture(..) => "DeleteTexture",
|
||||
DeleteProgram(..) => "DeleteProgram",
|
||||
DeleteShader(..) => "DeleteShader",
|
||||
BindBuffer(..) => "BindBuffer",
|
||||
BindFramebuffer(..) => "BindFramebuffer",
|
||||
BindRenderbuffer(..) => "BindRenderbuffer",
|
||||
BindTexture(..) => "BindTexture",
|
||||
DrawArrays(..) => "DrawArrays",
|
||||
DrawElements(..) => "DrawElements",
|
||||
EnableVertexAttribArray(..) => "EnableVertexAttribArray",
|
||||
GetBufferParameter(..) => "GetBufferParameter",
|
||||
GetParameter(..) => "GetParameter",
|
||||
GetProgramParameter(..) => "GetProgramParameter",
|
||||
GetShaderParameter(..) => "GetShaderParameter",
|
||||
GetAttribLocation(..) => "GetAttribLocation",
|
||||
GetUniformLocation(..) => "GetUniformLocation",
|
||||
PolygonOffset(..) => "PolygonOffset",
|
||||
Scissor(..) => "Scissor",
|
||||
Hint(..) => "Hint",
|
||||
LineWidth(..) => "LineWidth",
|
||||
PixelStorei(..) => "PixelStorei",
|
||||
LinkProgram(..) => "LinkProgram",
|
||||
Uniform4f(..) => "Uniform4f",
|
||||
Uniform1f(..) => "Uniform1f",
|
||||
UseProgram(..) => "UseProgram",
|
||||
VertexAttrib(..) => "VertexAttrib",
|
||||
VertexAttribPointer2f(..) => "VertexAttribPointer2f",
|
||||
Viewport(..) => "Viewport",
|
||||
TexImage2D(..) => "TexImage2D",
|
||||
TexParameteri(..) => "TexParameteri",
|
||||
TexParameterf(..) => "TexParameterf",
|
||||
DrawingBufferWidth(..) => "DrawingBufferWidth",
|
||||
DrawingBufferHeight(..) => "DrawingBufferHeight",
|
||||
};
|
||||
|
||||
write!(f, "CanvasWebGLMsg::{}(..)", name)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Deserialize, Serialize, HeapSizeOf)]
|
||||
pub enum WebGLError {
|
||||
InvalidEnum,
|
||||
InvalidOperation,
|
||||
InvalidValue,
|
||||
OutOfMemory,
|
||||
ContextLost,
|
||||
}
|
||||
|
||||
pub type WebGLResult<T> = Result<T, WebGLError>;
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub enum WebGLFramebufferBindingRequest {
|
||||
Explicit(u32),
|
||||
Default,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize)]
|
||||
pub enum WebGLParameter {
|
||||
Int(i32),
|
||||
Bool(bool),
|
||||
String(String),
|
||||
Float(f32),
|
||||
Invalid,
|
||||
}
|
||||
|
||||
#[derive(Clone, Deserialize, Serialize, HeapSizeOf)]
|
||||
pub struct CanvasGradientStop {
|
||||
pub offset: f64,
|
||||
|
|
|
@ -81,6 +81,12 @@ git = "https://github.com/servo/gaol"
|
|||
[target.aarch64-unknown-linux-gnu.dependencies.gaol]
|
||||
git = "https://github.com/servo/gaol"
|
||||
|
||||
[dependencies.webrender_traits]
|
||||
git = "https://github.com/glennw/webrender_traits"
|
||||
|
||||
[dependencies.webrender]
|
||||
git = "https://github.com/glennw/webrender"
|
||||
|
||||
[dependencies]
|
||||
app_units = {version = "0.2.1", features = ["plugins"]}
|
||||
euclid = {version = "0.6.2", features = ["plugins"]}
|
||||
|
|
|
@ -6,7 +6,7 @@ use CompositorMsg as ConstellationMsg;
|
|||
use app_units::Au;
|
||||
use compositor_layer::{CompositorData, CompositorLayer, RcCompositorLayer, WantsScrollEventsFlag};
|
||||
use compositor_thread::{CompositorEventListener, CompositorProxy};
|
||||
use compositor_thread::{CompositorReceiver, InitialCompositorState, Msg};
|
||||
use compositor_thread::{CompositorReceiver, InitialCompositorState, Msg, RenderListener};
|
||||
use constellation::SendableFrameTree;
|
||||
use euclid::point::TypedPoint2D;
|
||||
use euclid::rect::TypedRect;
|
||||
|
@ -27,15 +27,15 @@ use layers::rendergl;
|
|||
use layers::rendergl::RenderContext;
|
||||
use layers::scene::Scene;
|
||||
use layout_traits::LayoutControlChan;
|
||||
use msg::constellation_msg::{Image, PixelFormat};
|
||||
use msg::constellation_msg::{ConvertPipelineIdFromWebRender, ConvertPipelineIdToWebRender, Image, PixelFormat};
|
||||
use msg::constellation_msg::{Key, KeyModifiers, KeyState, LoadData};
|
||||
use msg::constellation_msg::{NavigationDirection, PipelineId, WindowSizeData};
|
||||
use pipeline::CompositionPipeline;
|
||||
use profile_traits::mem::{self, ReportKind, Reporter, ReporterRequest};
|
||||
use profile_traits::time::{self, ProfilerCategory, profile};
|
||||
use script_traits::CompositorEvent::{MouseMoveEvent, TouchEvent};
|
||||
use script_traits::CompositorEvent::{MouseMoveEvent, MouseButtonEvent, TouchEvent};
|
||||
use script_traits::{AnimationState, ConstellationControlMsg, LayoutControlMsg};
|
||||
use script_traits::{MouseButton, TouchEventType, TouchId};
|
||||
use script_traits::{MouseButton, MouseEventType, TouchEventType, TouchId};
|
||||
use scrolling::ScrollingTimerProxy;
|
||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
@ -51,6 +51,8 @@ use url::Url;
|
|||
use util::geometry::{PagePx, ScreenPx, ViewportPx};
|
||||
use util::opts;
|
||||
use util::print_tree::PrintTree;
|
||||
use webrender;
|
||||
use webrender_traits;
|
||||
use windowing::{self, MouseWindowEvent, WindowEvent, WindowMethods, WindowNavigateMsg};
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
|
@ -192,6 +194,12 @@ pub struct IOCompositor<Window: WindowMethods> {
|
|||
|
||||
/// The id of the pipeline that was last sent a mouse move event, if any.
|
||||
last_mouse_move_recipient: Option<PipelineId>,
|
||||
|
||||
/// The webrender renderer, if enabled.
|
||||
webrender: Option<webrender::Renderer>,
|
||||
|
||||
/// The webrender interface, if enabled.
|
||||
webrender_api: Option<webrender_traits::RenderApi>,
|
||||
}
|
||||
|
||||
pub struct ScrollZoomEvent {
|
||||
|
@ -261,7 +269,23 @@ pub enum CompositeTarget {
|
|||
PngFile
|
||||
}
|
||||
|
||||
fn initialize_png(width: usize, height: usize) -> (Vec<gl::GLuint>, Vec<gl::GLuint>) {
|
||||
struct RenderTargetInfo {
|
||||
framebuffer_ids: Vec<gl::GLuint>,
|
||||
texture_ids: Vec<gl::GLuint>,
|
||||
renderbuffer_ids: Vec<gl::GLuint>,
|
||||
}
|
||||
|
||||
impl RenderTargetInfo {
|
||||
fn empty() -> RenderTargetInfo {
|
||||
RenderTargetInfo {
|
||||
framebuffer_ids: Vec::new(),
|
||||
texture_ids: Vec::new(),
|
||||
renderbuffer_ids: Vec::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_png(width: usize, height: usize) -> RenderTargetInfo {
|
||||
let framebuffer_ids = gl::gen_framebuffers(1);
|
||||
gl::bind_framebuffer(gl::FRAMEBUFFER, framebuffer_ids[0]);
|
||||
|
||||
|
@ -278,13 +302,64 @@ fn initialize_png(width: usize, height: usize) -> (Vec<gl::GLuint>, Vec<gl::GLui
|
|||
|
||||
gl::bind_texture(gl::TEXTURE_2D, 0);
|
||||
|
||||
(framebuffer_ids, texture_ids)
|
||||
let renderbuffer_ids = if opts::get().use_webrender {
|
||||
let renderbuffer_ids = gl::gen_renderbuffers(1);
|
||||
gl::bind_renderbuffer(gl::RENDERBUFFER, renderbuffer_ids[0]);
|
||||
gl::renderbuffer_storage(gl::RENDERBUFFER,
|
||||
gl::STENCIL_INDEX8,
|
||||
width as GLsizei,
|
||||
height as GLsizei);
|
||||
gl::framebuffer_renderbuffer(gl::FRAMEBUFFER,
|
||||
gl::STENCIL_ATTACHMENT,
|
||||
gl::RENDERBUFFER,
|
||||
renderbuffer_ids[0]);
|
||||
renderbuffer_ids
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
|
||||
RenderTargetInfo {
|
||||
framebuffer_ids: framebuffer_ids,
|
||||
texture_ids: texture_ids,
|
||||
renderbuffer_ids: renderbuffer_ids
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reporter_name() -> String {
|
||||
"compositor-reporter".to_owned()
|
||||
}
|
||||
|
||||
struct RenderNotifier {
|
||||
compositor_proxy: Box<CompositorProxy>,
|
||||
constellation_chan: Sender<ConstellationMsg>,
|
||||
}
|
||||
|
||||
impl RenderNotifier {
|
||||
fn new(compositor_proxy: Box<CompositorProxy>,
|
||||
constellation_chan: Sender<ConstellationMsg>) -> RenderNotifier {
|
||||
RenderNotifier {
|
||||
compositor_proxy: compositor_proxy,
|
||||
constellation_chan: constellation_chan,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl webrender_traits::RenderNotifier for RenderNotifier {
|
||||
fn new_frame_ready(&mut self) {
|
||||
self.compositor_proxy.recomposite();
|
||||
}
|
||||
|
||||
fn pipeline_size_changed(&mut self,
|
||||
pipeline_id: webrender_traits::PipelineId,
|
||||
size: Option<Size2D<f32>>) {
|
||||
let pipeline_id = pipeline_id.from_webrender();
|
||||
let size = size.unwrap_or(Size2D::zero());
|
||||
|
||||
self.constellation_chan.send(ConstellationMsg::FrameSize(pipeline_id,
|
||||
size)).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
impl<Window: WindowMethods> IOCompositor<Window> {
|
||||
fn new(window: Rc<Window>, state: InitialCompositorState)
|
||||
-> IOCompositor<Window> {
|
||||
|
@ -306,6 +381,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
Some(_) => CompositeTarget::PngFile,
|
||||
None => CompositeTarget::Window
|
||||
};
|
||||
|
||||
let webrender_api = state.webrender_api_sender.map(|sender| {
|
||||
sender.create_api()
|
||||
});
|
||||
|
||||
let native_display = window.native_display();
|
||||
IOCompositor {
|
||||
window: window,
|
||||
|
@ -345,6 +425,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
surface_map: SurfaceMap::new(BUFFER_MAP_SIZE),
|
||||
pending_subpages: HashSet::new(),
|
||||
last_mouse_move_recipient: None,
|
||||
webrender: state.webrender,
|
||||
webrender_api: webrender_api,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -352,6 +434,14 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
-> IOCompositor<Window> {
|
||||
let mut compositor = IOCompositor::new(window, state);
|
||||
|
||||
if let Some(ref mut webrender) = compositor.webrender {
|
||||
let compositor_proxy_for_webrender = compositor.channel_to_self
|
||||
.clone_compositor_proxy();
|
||||
let render_notifier = RenderNotifier::new(compositor_proxy_for_webrender,
|
||||
compositor.constellation_chan.clone());
|
||||
webrender.set_render_notifier(Box::new(render_notifier));
|
||||
}
|
||||
|
||||
// Set the size of the root layer.
|
||||
compositor.update_zoom_transform();
|
||||
|
||||
|
@ -674,6 +764,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
|
||||
self.root_pipeline = Some(frame_tree.pipeline.clone());
|
||||
|
||||
if let Some(ref webrender_api) = self.webrender_api {
|
||||
let pipeline_id = frame_tree.pipeline.id.to_webrender();
|
||||
webrender_api.set_root_pipeline(pipeline_id);
|
||||
}
|
||||
|
||||
// If we have an old root layer, release all old tiles before replacing it.
|
||||
let old_root_layer = self.scene.root.take();
|
||||
if let Some(ref old_root_layer) = old_root_layer {
|
||||
|
@ -1172,6 +1267,36 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
MouseWindowEvent::MouseDown(_, p) => p,
|
||||
MouseWindowEvent::MouseUp(_, p) => p,
|
||||
};
|
||||
|
||||
if let Some(ref webrender_api) = self.webrender_api {
|
||||
let root_pipeline_id = match self.get_root_pipeline_id() {
|
||||
Some(root_pipeline_id) => root_pipeline_id,
|
||||
None => return,
|
||||
};
|
||||
let root_pipeline = match self.pipeline(root_pipeline_id) {
|
||||
Some(root_pipeline) => root_pipeline,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let translated_point =
|
||||
webrender_api.translate_point_to_layer_space(&point.to_untyped());
|
||||
let event_to_send = match mouse_window_event {
|
||||
MouseWindowEvent::Click(button, _) => {
|
||||
MouseButtonEvent(MouseEventType::Click, button, translated_point)
|
||||
}
|
||||
MouseWindowEvent::MouseDown(button, _) => {
|
||||
MouseButtonEvent(MouseEventType::MouseDown, button, translated_point)
|
||||
}
|
||||
MouseWindowEvent::MouseUp(button, _) => {
|
||||
MouseButtonEvent(MouseEventType::MouseUp, button, translated_point)
|
||||
}
|
||||
};
|
||||
root_pipeline.script_chan
|
||||
.send(ConstellationControlMsg::SendEvent(root_pipeline_id,
|
||||
event_to_send))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
match self.find_topmost_layer_at_point(point / self.scene.scale) {
|
||||
Some(result) => result.layer.send_mouse_event(self, mouse_window_event, result.point),
|
||||
None => {},
|
||||
|
@ -1184,6 +1309,25 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
return
|
||||
}
|
||||
|
||||
if let Some(ref webrender_api) = self.webrender_api {
|
||||
let root_pipeline_id = match self.get_root_pipeline_id() {
|
||||
Some(root_pipeline_id) => root_pipeline_id,
|
||||
None => return,
|
||||
};
|
||||
let root_pipeline = match self.pipeline(root_pipeline_id) {
|
||||
Some(root_pipeline) => root_pipeline,
|
||||
None => return,
|
||||
};
|
||||
|
||||
let translated_point =
|
||||
webrender_api.translate_point_to_layer_space(&cursor.to_untyped());
|
||||
let event_to_send = MouseMoveEvent(Some(translated_point));
|
||||
root_pipeline.script_chan
|
||||
.send(ConstellationControlMsg::SendEvent(root_pipeline_id,
|
||||
event_to_send))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
match self.find_topmost_layer_at_point(cursor / self.scene.scale) {
|
||||
Some(result) => {
|
||||
// In the case that the mouse was previously over a different layer,
|
||||
|
@ -1285,30 +1429,52 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
|
||||
fn process_pending_scroll_events(&mut self) {
|
||||
let had_events = self.pending_scroll_zoom_events.len() > 0;
|
||||
for event in std_mem::replace(&mut self.pending_scroll_zoom_events,
|
||||
Vec::new()) {
|
||||
let delta = event.delta / self.scene.scale;
|
||||
let cursor = event.cursor.as_f32() / self.scene.scale;
|
||||
|
||||
if let Some(ref mut layer) = self.scene.root {
|
||||
layer.handle_scroll_event(delta, cursor);
|
||||
match self.webrender_api {
|
||||
Some(ref webrender_api) => {
|
||||
// Batch up all scroll events into one, or else we'll do way too much painting.
|
||||
let mut total_delta = None;
|
||||
let mut last_cursor = Point2D::zero();
|
||||
for scroll_event in self.pending_scroll_zoom_events.drain(..) {
|
||||
let this_delta = scroll_event.delta / self.scene.scale;
|
||||
last_cursor = scroll_event.cursor.as_f32() / self.scene.scale;
|
||||
match total_delta {
|
||||
None => total_delta = Some(this_delta),
|
||||
Some(ref mut total_delta) => *total_delta = *total_delta + this_delta,
|
||||
}
|
||||
}
|
||||
// TODO(gw): Support zoom (WR issue #28).
|
||||
if let Some(total_delta) = total_delta {
|
||||
webrender_api.scroll(total_delta.to_untyped(), last_cursor.to_untyped());
|
||||
}
|
||||
}
|
||||
None => {
|
||||
for event in std_mem::replace(&mut self.pending_scroll_zoom_events,
|
||||
Vec::new()) {
|
||||
let delta = event.delta / self.scene.scale;
|
||||
let cursor = event.cursor.as_f32() / self.scene.scale;
|
||||
|
||||
if event.magnification != 1.0 {
|
||||
self.zoom_action = true;
|
||||
self.zoom_time = precise_time_s();
|
||||
self.viewport_zoom = ScaleFactor::new(
|
||||
(self.viewport_zoom.get() * event.magnification)
|
||||
.min(self.max_viewport_zoom.as_ref().map_or(MAX_ZOOM, ScaleFactor::get))
|
||||
.max(self.min_viewport_zoom.as_ref().map_or(MIN_ZOOM, ScaleFactor::get)));
|
||||
self.update_zoom_transform();
|
||||
if let Some(ref mut layer) = self.scene.root {
|
||||
layer.handle_scroll_event(delta, cursor);
|
||||
}
|
||||
|
||||
if event.magnification != 1.0 {
|
||||
self.zoom_action = true;
|
||||
self.zoom_time = precise_time_s();
|
||||
self.viewport_zoom = ScaleFactor::new(
|
||||
(self.viewport_zoom.get() * event.magnification)
|
||||
.min(self.max_viewport_zoom.as_ref().map_or(MAX_ZOOM, ScaleFactor::get))
|
||||
.max(self.min_viewport_zoom.as_ref().map_or(MIN_ZOOM, ScaleFactor::get)));
|
||||
self.update_zoom_transform();
|
||||
}
|
||||
|
||||
self.perform_updates_after_scroll();
|
||||
}
|
||||
|
||||
if had_events {
|
||||
self.send_viewport_rects_for_all_layers();
|
||||
}
|
||||
}
|
||||
|
||||
self.perform_updates_after_scroll();
|
||||
}
|
||||
|
||||
if had_events {
|
||||
self.send_viewport_rects_for_all_layers();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1542,6 +1708,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
|
||||
/// Returns true if any buffer requests were sent or false otherwise.
|
||||
fn send_buffer_requests_for_all_layers(&mut self) -> bool {
|
||||
if self.webrender.is_some() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if let Some(ref root_layer) = self.scene.root {
|
||||
root_layer.update_transform_state(&Matrix4::identity(),
|
||||
&Matrix4::identity(),
|
||||
|
@ -1656,7 +1826,15 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
// frame tree.
|
||||
let mut pipeline_epochs = HashMap::new();
|
||||
for (id, details) in &self.pipeline_details {
|
||||
pipeline_epochs.insert(*id, details.current_epoch);
|
||||
if let Some(ref webrender) = self.webrender {
|
||||
let webrender_pipeline_id = id.to_webrender();
|
||||
if let Some(webrender_traits::Epoch(epoch)) = webrender.current_epoch(webrender_pipeline_id) {
|
||||
let epoch = Epoch(epoch);
|
||||
pipeline_epochs.insert(*id, epoch);
|
||||
}
|
||||
} else {
|
||||
pipeline_epochs.insert(*id, details.current_epoch);
|
||||
}
|
||||
}
|
||||
|
||||
// Pass the pipeline/epoch states to the constellation and check
|
||||
|
@ -1707,7 +1885,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
/// is WindowAndPng Ok(Some(png::Image)) is returned.
|
||||
pub fn composite_specific_target(&mut self, target: CompositeTarget) -> Result<Option<Image>, UnableToComposite> {
|
||||
|
||||
if !self.context.is_some() {
|
||||
if self.context.is_none() && self.webrender.is_none() {
|
||||
return Err(UnableToComposite::NoContext)
|
||||
}
|
||||
let (width, height) =
|
||||
|
@ -1716,6 +1894,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
return Err(UnableToComposite::WindowUnprepared)
|
||||
}
|
||||
|
||||
if let Some(ref mut webrender) = self.webrender {
|
||||
assert!(self.context.is_none());
|
||||
webrender.update();
|
||||
}
|
||||
|
||||
let wait_for_stable_image = match target {
|
||||
CompositeTarget::WindowAndPng | CompositeTarget::PngFile => true,
|
||||
CompositeTarget::Window => opts::get().exit_after_load,
|
||||
|
@ -1738,8 +1921,8 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
}
|
||||
}
|
||||
|
||||
let (framebuffer_ids, texture_ids) = match target {
|
||||
CompositeTarget::Window => (vec!(), vec!()),
|
||||
let render_target_info = match target {
|
||||
CompositeTarget::Window => RenderTargetInfo::empty(),
|
||||
_ => initialize_png(width, height)
|
||||
};
|
||||
|
||||
|
@ -1760,7 +1943,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
};
|
||||
|
||||
// Paint the scene.
|
||||
if let Some(ref layer) = self.scene.root {
|
||||
if let Some(ref mut webrender) = self.webrender {
|
||||
assert!(self.context.is_none());
|
||||
webrender.render(self.window_size.to_untyped());
|
||||
} else if let Some(ref layer) = self.scene.root {
|
||||
match self.context {
|
||||
Some(context) => {
|
||||
if let Some((point, size)) = self.viewport {
|
||||
|
@ -1790,16 +1976,21 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
let rv = match target {
|
||||
CompositeTarget::Window => None,
|
||||
CompositeTarget::WindowAndPng => {
|
||||
let img = self.draw_img(framebuffer_ids, texture_ids, width, height);
|
||||
let img = self.draw_img(render_target_info,
|
||||
width,
|
||||
height);
|
||||
Some(Image {
|
||||
width: img.width(),
|
||||
height: img.height(),
|
||||
format: PixelFormat::RGB8,
|
||||
bytes: IpcSharedMemory::from_bytes(&*img),
|
||||
id: None,
|
||||
})
|
||||
}
|
||||
CompositeTarget::PngFile => {
|
||||
let img = self.draw_img(framebuffer_ids, texture_ids, width, height);
|
||||
let img = self.draw_img(render_target_info,
|
||||
width,
|
||||
height);
|
||||
let path = opts::get().output_file.as_ref().unwrap();
|
||||
let mut file = File::create(path).unwrap();
|
||||
DynamicImage::ImageRgb8(img).save(&mut file, ImageFormat::PNG).unwrap();
|
||||
|
@ -1820,8 +2011,7 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
}
|
||||
|
||||
fn draw_img(&self,
|
||||
framebuffer_ids: Vec<gl::GLuint>,
|
||||
texture_ids: Vec<gl::GLuint>,
|
||||
render_target_info: RenderTargetInfo,
|
||||
width: usize,
|
||||
height: usize)
|
||||
-> RgbImage {
|
||||
|
@ -1832,8 +2022,11 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
|
||||
gl::bind_framebuffer(gl::FRAMEBUFFER, 0);
|
||||
|
||||
gl::delete_buffers(&texture_ids);
|
||||
gl::delete_frame_buffers(&framebuffer_ids);
|
||||
gl::delete_buffers(&render_target_info.texture_ids);
|
||||
gl::delete_frame_buffers(&render_target_info.framebuffer_ids);
|
||||
if opts::get().use_webrender {
|
||||
gl::delete_renderbuffers(&render_target_info.renderbuffer_ids);
|
||||
}
|
||||
|
||||
// flip image vertically (texture is upside down)
|
||||
let orig_pixels = pixels.clone();
|
||||
|
@ -1859,10 +2052,12 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
}
|
||||
|
||||
fn initialize_compositing(&mut self) {
|
||||
let show_debug_borders = opts::get().show_debug_borders;
|
||||
self.context = Some(rendergl::RenderContext::new(self.native_display.clone(),
|
||||
show_debug_borders,
|
||||
opts::get().output_file.is_some()))
|
||||
if self.webrender.is_none() {
|
||||
let show_debug_borders = opts::get().show_debug_borders;
|
||||
self.context = Some(rendergl::RenderContext::new(self.native_display.clone(),
|
||||
show_debug_borders,
|
||||
opts::get().output_file.is_some()))
|
||||
}
|
||||
}
|
||||
|
||||
fn find_topmost_layer_at_point_for_layer(&self,
|
||||
|
@ -1951,6 +2146,10 @@ impl<Window: WindowMethods> IOCompositor<Window> {
|
|||
self.surface_map.insert_surfaces(&self.native_display, surfaces);
|
||||
}
|
||||
|
||||
fn get_root_pipeline_id(&self) -> Option<PipelineId> {
|
||||
self.scene.root.as_ref().map(|root_layer| root_layer.extra_data.borrow().pipeline_id)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn dump_layer_tree(&self) {
|
||||
if !opts::get().dump_layer_tree {
|
||||
|
@ -2076,19 +2275,37 @@ impl<Window> CompositorEventListener for IOCompositor<Window> where Window: Wind
|
|||
///
|
||||
/// This is used when resizing the window.
|
||||
fn repaint_synchronously(&mut self) {
|
||||
while self.shutdown_state != ShutdownState::ShuttingDown {
|
||||
let msg = self.port.recv_compositor_msg();
|
||||
let received_new_buffers = match msg {
|
||||
Msg::AssignPaintedBuffers(..) => true,
|
||||
_ => false,
|
||||
};
|
||||
let keep_going = self.handle_browser_message(msg);
|
||||
if received_new_buffers {
|
||||
self.composite();
|
||||
break
|
||||
if self.webrender.is_none() {
|
||||
while self.shutdown_state != ShutdownState::ShuttingDown {
|
||||
let msg = self.port.recv_compositor_msg();
|
||||
let received_new_buffers = match msg {
|
||||
Msg::AssignPaintedBuffers(..) => true,
|
||||
_ => false,
|
||||
};
|
||||
let keep_going = self.handle_browser_message(msg);
|
||||
if received_new_buffers {
|
||||
self.composite();
|
||||
break
|
||||
}
|
||||
if !keep_going {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !keep_going {
|
||||
break
|
||||
} else {
|
||||
while self.shutdown_state != ShutdownState::ShuttingDown {
|
||||
let msg = self.port.recv_compositor_msg();
|
||||
let need_recomposite = match msg {
|
||||
Msg::RecompositeAfterScroll => true,
|
||||
_ => false,
|
||||
};
|
||||
let keep_going = self.handle_browser_message(msg);
|
||||
if need_recomposite {
|
||||
self.composite();
|
||||
break
|
||||
}
|
||||
if !keep_going {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,8 @@ use url::Url;
|
|||
use windowing::{WindowEvent, WindowMethods};
|
||||
pub use constellation::SendableFrameTree;
|
||||
pub use windowing;
|
||||
use webrender;
|
||||
use webrender_traits;
|
||||
|
||||
/// Sends messages to the compositor. This is a trait supplied by the port because the method used
|
||||
/// to communicate with the compositor may have to kick OS event loops awake, communicate cross-
|
||||
|
@ -100,6 +102,16 @@ pub fn run_script_listener_thread(compositor_proxy: Box<CompositorProxy + 'stati
|
|||
}
|
||||
}
|
||||
|
||||
pub trait RenderListener {
|
||||
fn recomposite(&mut self);
|
||||
}
|
||||
|
||||
impl RenderListener for Box<CompositorProxy + 'static> {
|
||||
fn recomposite(&mut self) {
|
||||
self.send(Msg::RecompositeAfterScroll);
|
||||
}
|
||||
}
|
||||
|
||||
/// Implementation of the abstract `PaintListener` interface.
|
||||
impl PaintListener for Box<CompositorProxy + 'static + Send> {
|
||||
fn native_display(&mut self) -> Option<NativeDisplay> {
|
||||
|
@ -301,4 +313,7 @@ pub struct InitialCompositorState {
|
|||
pub time_profiler_chan: time::ProfilerChan,
|
||||
/// A channel to the memory profiler thread.
|
||||
pub mem_profiler_chan: mem::ProfilerChan,
|
||||
/// Instance of webrender API if enabled
|
||||
pub webrender: Option<webrender::Renderer>,
|
||||
pub webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ use url::Url;
|
|||
use util::geometry::PagePx;
|
||||
use util::thread::spawn_named;
|
||||
use util::{opts, prefs};
|
||||
use webrender_traits;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
enum ReadyToSave {
|
||||
|
@ -181,6 +182,9 @@ pub struct Constellation<LTF, STF> {
|
|||
|
||||
/// Document states for loaded pipelines (used only when writing screenshots).
|
||||
document_states: HashMap<PipelineId, DocumentState>,
|
||||
|
||||
// Webrender interface, if enabled.
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
}
|
||||
|
||||
/// State needed to construct a constellation.
|
||||
|
@ -203,6 +207,8 @@ pub struct InitialConstellationState {
|
|||
pub mem_profiler_chan: mem::ProfilerChan,
|
||||
/// Whether the constellation supports the clipboard.
|
||||
pub supports_clipboard: bool,
|
||||
/// Optional webrender API reference (if enabled).
|
||||
pub webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
}
|
||||
|
||||
/// Stores the navigation context for a single frame in the frame tree.
|
||||
|
@ -347,6 +353,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
scheduler_chan: TimerScheduler::start(),
|
||||
child_processes: Vec::new(),
|
||||
document_states: HashMap::new(),
|
||||
webrender_api_sender: state.webrender_api_sender,
|
||||
};
|
||||
let namespace_id = constellation.next_pipeline_namespace_id();
|
||||
PipelineNamespace::install(namespace_id);
|
||||
|
@ -399,6 +406,7 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
load_data: load_data,
|
||||
device_pixel_ratio: self.window_size.device_pixel_ratio,
|
||||
pipeline_namespace_id: self.next_pipeline_namespace_id(),
|
||||
webrender_api_sender: self.webrender_api_sender.clone(),
|
||||
});
|
||||
|
||||
if spawning_paint_only {
|
||||
|
@ -1196,7 +1204,9 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
size: &Size2D<i32>,
|
||||
response_sender: IpcSender<(IpcSender<CanvasMsg>, usize)>) {
|
||||
let id = self.canvas_paint_threads.len();
|
||||
let (out_of_process_sender, in_process_sender) = CanvasPaintThread::start(*size);
|
||||
let webrender_api = self.webrender_api_sender.clone();
|
||||
let (out_of_process_sender, in_process_sender) = CanvasPaintThread::start(*size,
|
||||
webrender_api);
|
||||
self.canvas_paint_threads.push(in_process_sender);
|
||||
response_sender.send((out_of_process_sender, id)).unwrap()
|
||||
}
|
||||
|
@ -1206,13 +1216,14 @@ impl<LTF: LayoutThreadFactory, STF: ScriptThreadFactory> Constellation<LTF, STF>
|
|||
size: &Size2D<i32>,
|
||||
attributes: GLContextAttributes,
|
||||
response_sender: IpcSender<Result<(IpcSender<CanvasMsg>, usize), String>>) {
|
||||
let response = match WebGLPaintThread::start(*size, attributes) {
|
||||
let webrender_api = self.webrender_api_sender.clone();
|
||||
let response = match WebGLPaintThread::start(*size, attributes, webrender_api) {
|
||||
Ok((out_of_process_sender, in_process_sender)) => {
|
||||
let id = self.webgl_paint_threads.len();
|
||||
self.webgl_paint_threads.push(in_process_sender);
|
||||
Ok((out_of_process_sender, id))
|
||||
},
|
||||
Err(msg) => Err(msg.to_owned()),
|
||||
Err(msg) => Err(msg),
|
||||
};
|
||||
|
||||
response_sender.send(response).unwrap()
|
||||
|
|
|
@ -48,6 +48,8 @@ extern crate time;
|
|||
extern crate url;
|
||||
#[macro_use]
|
||||
extern crate util;
|
||||
extern crate webrender;
|
||||
extern crate webrender_traits;
|
||||
|
||||
pub use compositor_thread::{CompositorEventListener, CompositorProxy, CompositorThread};
|
||||
pub use constellation::Constellation;
|
||||
|
|
|
@ -35,6 +35,7 @@ use util::geometry::{PagePx, ViewportPx};
|
|||
use util::ipc::OptionalIpcSender;
|
||||
use util::opts::{self, Opts};
|
||||
use util::prefs;
|
||||
use webrender_traits;
|
||||
|
||||
/// A uniquely-identifiable pipeline of script thread, layout thread, and paint thread.
|
||||
pub struct Pipeline {
|
||||
|
@ -113,6 +114,8 @@ pub struct InitialPipelineState {
|
|||
pub load_data: LoadData,
|
||||
/// The ID of the pipeline namespace for this script thread.
|
||||
pub pipeline_namespace_id: PipelineNamespaceId,
|
||||
/// Optional webrender api (if enabled).
|
||||
pub webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
}
|
||||
|
||||
impl Pipeline {
|
||||
|
@ -225,6 +228,7 @@ impl Pipeline {
|
|||
layout_content_process_shutdown_port: layout_content_process_shutdown_port,
|
||||
script_content_process_shutdown_chan: script_content_process_shutdown_chan,
|
||||
script_content_process_shutdown_port: script_content_process_shutdown_port,
|
||||
webrender_api_sender: state.webrender_api_sender,
|
||||
};
|
||||
|
||||
let privileged_pipeline_content = PrivilegedPipelineContent {
|
||||
|
@ -376,6 +380,7 @@ pub struct UnprivilegedPipelineContent {
|
|||
layout_content_process_shutdown_port: IpcReceiver<()>,
|
||||
script_content_process_shutdown_chan: IpcSender<()>,
|
||||
script_content_process_shutdown_port: IpcReceiver<()>,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>,
|
||||
}
|
||||
|
||||
impl UnprivilegedPipelineContent {
|
||||
|
@ -419,7 +424,8 @@ impl UnprivilegedPipelineContent {
|
|||
self.time_profiler_chan,
|
||||
self.mem_profiler_chan,
|
||||
self.layout_shutdown_chan,
|
||||
self.layout_content_process_shutdown_chan.clone());
|
||||
self.layout_content_process_shutdown_chan.clone(),
|
||||
self.webrender_api_sender);
|
||||
|
||||
if wait_for_completion {
|
||||
self.script_content_process_shutdown_port.recv().unwrap();
|
||||
|
|
|
@ -69,6 +69,9 @@ features = ["plugins"]
|
|||
[dependencies.ipc-channel]
|
||||
git = "https://github.com/servo/ipc-channel"
|
||||
|
||||
[dependencies.webrender_traits]
|
||||
git = "https://github.com/glennw/webrender_traits"
|
||||
|
||||
[target.x86_64-apple-darwin.dependencies]
|
||||
core-foundation = "0.2"
|
||||
core-graphics = "0.2"
|
||||
|
|
|
@ -45,6 +45,7 @@ use util::linked_list::prepend_from;
|
|||
use util::opts;
|
||||
use util::print_tree::PrintTree;
|
||||
use util::range::Range;
|
||||
use webrender_traits::WebGLContextId;
|
||||
|
||||
pub use style::dom::OpaqueNode;
|
||||
|
||||
|
@ -641,7 +642,10 @@ impl StackingContext {
|
|||
layer_info: layer_info,
|
||||
last_child_layer_info: None,
|
||||
};
|
||||
StackingContextLayerCreator::add_layers_to_preserve_drawing_order(&mut stacking_context);
|
||||
// webrender doesn't care about layers in the display list - it's handled internally.
|
||||
if !opts::get().use_webrender {
|
||||
StackingContextLayerCreator::add_layers_to_preserve_drawing_order(&mut stacking_context);
|
||||
}
|
||||
stacking_context
|
||||
}
|
||||
|
||||
|
@ -681,7 +685,8 @@ impl StackingContext {
|
|||
// TODO(gw): This is a hack to avoid running the DL optimizer
|
||||
// on 3d transformed tiles. We should have a better solution
|
||||
// than just disabling the opts here.
|
||||
if paint_context.layer_kind == LayerKind::HasTransform {
|
||||
if paint_context.layer_kind == LayerKind::HasTransform ||
|
||||
opts::get().use_webrender { // webrender takes care of all culling via aabb tree!
|
||||
self.draw_into_context(&self.display_list,
|
||||
paint_context,
|
||||
&transform,
|
||||
|
@ -775,6 +780,9 @@ struct StackingContextLayerCreator {
|
|||
|
||||
impl StackingContextLayerCreator {
|
||||
fn new() -> StackingContextLayerCreator {
|
||||
// webrender doesn't care about layers in the display list - it's handled internally.
|
||||
debug_assert!(!opts::get().use_webrender);
|
||||
|
||||
StackingContextLayerCreator {
|
||||
display_list_for_next_layer: None,
|
||||
next_layer_info: None,
|
||||
|
@ -969,6 +977,7 @@ pub enum DisplayItem {
|
|||
SolidColorClass(Box<SolidColorDisplayItem>),
|
||||
TextClass(Box<TextDisplayItem>),
|
||||
ImageClass(Box<ImageDisplayItem>),
|
||||
WebGLClass(Box<WebGLDisplayItem>),
|
||||
BorderClass(Box<BorderDisplayItem>),
|
||||
GradientClass(Box<GradientDisplayItem>),
|
||||
LineClass(Box<LineDisplayItem>),
|
||||
|
@ -976,6 +985,7 @@ pub enum DisplayItem {
|
|||
StackingContextClass(Arc<StackingContext>),
|
||||
LayeredItemClass(Box<LayeredItem>),
|
||||
NoopClass(Box<BaseDisplayItem>),
|
||||
IframeClass(Box<IframeDisplayItem>),
|
||||
}
|
||||
|
||||
/// Information common to all display items.
|
||||
|
@ -1236,6 +1246,20 @@ pub struct ImageDisplayItem {
|
|||
pub image_rendering: image_rendering::T,
|
||||
}
|
||||
|
||||
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
|
||||
pub struct WebGLDisplayItem {
|
||||
pub base: BaseDisplayItem,
|
||||
#[ignore_heap_size_of = "Defined in webrender_traits"]
|
||||
pub context_id: WebGLContextId,
|
||||
}
|
||||
|
||||
|
||||
/// Paints an iframe.
|
||||
#[derive(Clone, HeapSizeOf, Deserialize, Serialize)]
|
||||
pub struct IframeDisplayItem {
|
||||
pub base: BaseDisplayItem,
|
||||
pub iframe: PipelineId,
|
||||
}
|
||||
|
||||
/// Paints a gradient.
|
||||
#[derive(Clone, Deserialize, HeapSizeOf, Serialize)]
|
||||
|
@ -1450,6 +1474,10 @@ impl DisplayItem {
|
|||
image_item.image_rendering.clone());
|
||||
}
|
||||
|
||||
DisplayItem::WebGLClass(_) => {
|
||||
panic!("Shouldn't be here, WebGL display items are created just with webrender");
|
||||
}
|
||||
|
||||
DisplayItem::BorderClass(ref border) => {
|
||||
paint_context.draw_border(&border.base.bounds,
|
||||
&border.border_widths,
|
||||
|
@ -1499,6 +1527,7 @@ impl DisplayItem {
|
|||
DisplayItem::LayeredItemClass(_) => panic!("Found layered item during drawing."),
|
||||
|
||||
DisplayItem::NoopClass(_) => { }
|
||||
DisplayItem::IframeClass(..) => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1507,6 +1536,7 @@ impl DisplayItem {
|
|||
DisplayItem::SolidColorClass(ref solid_color) => Some(&solid_color.base),
|
||||
DisplayItem::TextClass(ref text) => Some(&text.base),
|
||||
DisplayItem::ImageClass(ref image_item) => Some(&image_item.base),
|
||||
DisplayItem::WebGLClass(ref webgl_item) => Some(&webgl_item.base),
|
||||
DisplayItem::BorderClass(ref border) => Some(&border.base),
|
||||
DisplayItem::GradientClass(ref gradient) => Some(&gradient.base),
|
||||
DisplayItem::LineClass(ref line) => Some(&line.base),
|
||||
|
@ -1514,6 +1544,7 @@ impl DisplayItem {
|
|||
DisplayItem::LayeredItemClass(ref layered_item) => layered_item.item.base(),
|
||||
DisplayItem::NoopClass(ref base_item) => Some(base_item),
|
||||
DisplayItem::StackingContextClass(_) => None,
|
||||
DisplayItem::IframeClass(ref iframe) => Some(&iframe.base),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1563,6 +1594,7 @@ impl fmt::Debug for DisplayItem {
|
|||
solid_color.color.a),
|
||||
DisplayItem::TextClass(_) => "Text".to_owned(),
|
||||
DisplayItem::ImageClass(_) => "Image".to_owned(),
|
||||
DisplayItem::WebGLClass(_) => "WebGL".to_owned(),
|
||||
DisplayItem::BorderClass(_) => "Border".to_owned(),
|
||||
DisplayItem::GradientClass(_) => "Gradient".to_owned(),
|
||||
DisplayItem::LineClass(_) => "Line".to_owned(),
|
||||
|
@ -1571,6 +1603,7 @@ impl fmt::Debug for DisplayItem {
|
|||
DisplayItem::LayeredItemClass(ref layered_item) =>
|
||||
format!("LayeredItem({:?})", layered_item.item),
|
||||
DisplayItem::NoopClass(_) => "Noop".to_owned(),
|
||||
DisplayItem::IframeClass(_) => "Iframe".to_owned(),
|
||||
},
|
||||
self.bounds(),
|
||||
)
|
||||
|
|
|
@ -23,6 +23,7 @@ use text::shaping::ShaperMethods;
|
|||
use time;
|
||||
use unicode_script::Script;
|
||||
use util::cache::HashCache;
|
||||
use webrender_traits;
|
||||
|
||||
static TEXT_SHAPING_PERFORMANCE_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
|
||||
|
||||
|
@ -100,6 +101,7 @@ pub struct Font {
|
|||
pub shaper: Option<Shaper>,
|
||||
pub shape_cache: HashCache<ShapeCacheEntry, Arc<GlyphStore>>,
|
||||
pub glyph_advance_cache: HashCache<u32, FractionalPixel>,
|
||||
pub font_key: Option<webrender_traits::FontKey>,
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
|
|
@ -24,12 +24,19 @@ use url::Url;
|
|||
use util::prefs;
|
||||
use util::str::LowercaseString;
|
||||
use util::thread::spawn_named;
|
||||
use webrender_traits;
|
||||
|
||||
/// A list of font templates that make up a given font family.
|
||||
struct FontTemplates {
|
||||
templates: Vec<FontTemplate>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
pub struct FontTemplateInfo {
|
||||
pub font_template: Arc<FontTemplateData>,
|
||||
pub font_key: Option<webrender_traits::FontKey>,
|
||||
}
|
||||
|
||||
impl FontTemplates {
|
||||
fn new() -> FontTemplates {
|
||||
FontTemplates {
|
||||
|
@ -73,7 +80,8 @@ impl FontTemplates {
|
|||
}
|
||||
}
|
||||
|
||||
let template = FontTemplate::new(identifier, maybe_data);
|
||||
let template = FontTemplate::new(identifier,
|
||||
maybe_data);
|
||||
self.templates.push(template);
|
||||
}
|
||||
}
|
||||
|
@ -91,7 +99,7 @@ pub enum Command {
|
|||
/// Reply messages sent from the font cache thread to the FontContext caller.
|
||||
#[derive(Deserialize, Serialize, Debug)]
|
||||
pub enum Reply {
|
||||
GetFontTemplateReply(Option<Arc<FontTemplateData>>),
|
||||
GetFontTemplateReply(Option<FontTemplateInfo>),
|
||||
}
|
||||
|
||||
/// The font cache thread itself. It maintains a list of reference counted
|
||||
|
@ -104,6 +112,8 @@ struct FontCache {
|
|||
web_families: HashMap<LowercaseString, FontTemplates>,
|
||||
font_context: FontContextHandle,
|
||||
resource_thread: ResourceThread,
|
||||
webrender_api: Option<webrender_traits::RenderApi>,
|
||||
webrender_fonts: HashMap<Atom, webrender_traits::FontKey>,
|
||||
}
|
||||
|
||||
fn populate_generic_fonts() -> HashMap<FontFamily, LowercaseString> {
|
||||
|
@ -285,24 +295,46 @@ impl FontCache {
|
|||
}
|
||||
}
|
||||
|
||||
fn get_font_template_info(&mut self, template: Arc<FontTemplateData>) -> FontTemplateInfo {
|
||||
let webrender_fonts = &mut self.webrender_fonts;
|
||||
let font_key = self.webrender_api.as_ref().map(|webrender_api| {
|
||||
*webrender_fonts.entry(template.identifier.clone()).or_insert_with(|| {
|
||||
match (template.bytes_if_in_memory(), template.native_font()) {
|
||||
(Some(bytes), _) => webrender_api.add_raw_font(bytes),
|
||||
(None, Some(native_font)) => webrender_api.add_native_font(native_font),
|
||||
(None, None) => webrender_api.add_raw_font(template.bytes().clone()),
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
FontTemplateInfo {
|
||||
font_template: template,
|
||||
font_key: font_key,
|
||||
}
|
||||
}
|
||||
|
||||
fn find_font_template(&mut self, family: &FontFamily, desc: &FontTemplateDescriptor)
|
||||
-> Option<Arc<FontTemplateData>> {
|
||||
self.find_font_in_web_family(family, desc)
|
||||
-> Option<FontTemplateInfo> {
|
||||
let template = self.find_font_in_web_family(family, desc)
|
||||
.or_else(|| {
|
||||
let transformed_family = self.transform_family(family);
|
||||
self.find_font_in_local_family(&transformed_family, desc)
|
||||
})
|
||||
});
|
||||
|
||||
template.map(|template| {
|
||||
self.get_font_template_info(template)
|
||||
})
|
||||
}
|
||||
|
||||
fn last_resort_font_template(&mut self, desc: &FontTemplateDescriptor)
|
||||
-> Arc<FontTemplateData> {
|
||||
-> FontTemplateInfo {
|
||||
let last_resort = last_resort_font_families();
|
||||
|
||||
for family in &last_resort {
|
||||
let family = LowercaseString::new(family);
|
||||
let maybe_font_in_family = self.find_font_in_local_family(&family, desc);
|
||||
if let Some(family) = maybe_font_in_family {
|
||||
return family;
|
||||
return self.get_font_template_info(family)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -318,7 +350,8 @@ pub struct FontCacheThread {
|
|||
}
|
||||
|
||||
impl FontCacheThread {
|
||||
pub fn new(resource_thread: ResourceThread) -> FontCacheThread {
|
||||
pub fn new(resource_thread: ResourceThread,
|
||||
webrender_api: Option<webrender_traits::RenderApi>) -> FontCacheThread {
|
||||
let (chan, port) = ipc::channel().unwrap();
|
||||
|
||||
let channel_to_self = chan.clone();
|
||||
|
@ -334,6 +367,8 @@ impl FontCacheThread {
|
|||
web_families: HashMap::new(),
|
||||
font_context: FontContextHandle::new(),
|
||||
resource_thread: resource_thread,
|
||||
webrender_api: webrender_api,
|
||||
webrender_fonts: HashMap::new(),
|
||||
};
|
||||
|
||||
cache.refresh_local_families();
|
||||
|
@ -346,7 +381,7 @@ impl FontCacheThread {
|
|||
}
|
||||
|
||||
pub fn find_font_template(&self, family: FontFamily, desc: FontTemplateDescriptor)
|
||||
-> Option<Arc<FontTemplateData>> {
|
||||
-> Option<FontTemplateInfo> {
|
||||
|
||||
let (response_chan, response_port) = ipc::channel().unwrap();
|
||||
self.chan.send(Command::GetFontTemplate(family, desc, response_chan)).unwrap();
|
||||
|
@ -361,7 +396,7 @@ impl FontCacheThread {
|
|||
}
|
||||
|
||||
pub fn last_resort_font_template(&self, desc: FontTemplateDescriptor)
|
||||
-> Arc<FontTemplateData> {
|
||||
-> FontTemplateInfo {
|
||||
|
||||
let (response_chan, response_port) = ipc::channel().unwrap();
|
||||
self.chan.send(Command::GetLastResortFontTemplate(desc, response_chan)).unwrap();
|
||||
|
|
|
@ -28,6 +28,7 @@ use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
|
|||
use string_cache::Atom;
|
||||
use style::computed_values::{font_style, font_variant};
|
||||
use util::cache::HashCache;
|
||||
use webrender_traits;
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android", target_os = "windows"))]
|
||||
fn create_scaled_font(template: &Arc<FontTemplateData>, pt_size: Au) -> ScaledFont {
|
||||
|
@ -105,9 +106,12 @@ impl FontContext {
|
|||
}
|
||||
|
||||
/// Create a font for use in layout calculations.
|
||||
fn create_layout_font(&self, template: Arc<FontTemplateData>,
|
||||
descriptor: FontTemplateDescriptor, pt_size: Au,
|
||||
variant: font_variant::T) -> Result<Font, ()> {
|
||||
fn create_layout_font(&self,
|
||||
template: Arc<FontTemplateData>,
|
||||
descriptor: FontTemplateDescriptor,
|
||||
pt_size: Au,
|
||||
variant: font_variant::T,
|
||||
font_key: Option<webrender_traits::FontKey>) -> Result<Font, ()> {
|
||||
// TODO: (Bug #3463): Currently we only support fake small-caps
|
||||
// painting. We should also support true small-caps (where the
|
||||
// font supports it) in the future.
|
||||
|
@ -133,6 +137,7 @@ impl FontContext {
|
|||
metrics: metrics,
|
||||
shape_cache: HashCache::new(),
|
||||
glyph_advance_cache: HashCache::new(),
|
||||
font_key: font_key,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -201,14 +206,15 @@ impl FontContext {
|
|||
}
|
||||
|
||||
if !cache_hit {
|
||||
let font_template = self.font_cache_thread.find_font_template(family.clone(),
|
||||
desc.clone());
|
||||
match font_template {
|
||||
Some(font_template) => {
|
||||
let layout_font = self.create_layout_font(font_template,
|
||||
let template_info = self.font_cache_thread.find_font_template(family.clone(),
|
||||
desc.clone());
|
||||
match template_info {
|
||||
Some(template_info) => {
|
||||
let layout_font = self.create_layout_font(template_info.font_template,
|
||||
desc.clone(),
|
||||
style.font_size,
|
||||
style.font_variant);
|
||||
style.font_variant,
|
||||
template_info.font_key);
|
||||
let font = match layout_font {
|
||||
Ok(layout_font) => {
|
||||
let layout_font = Rc::new(RefCell::new(layout_font));
|
||||
|
@ -250,11 +256,12 @@ impl FontContext {
|
|||
}
|
||||
|
||||
if !cache_hit {
|
||||
let font_template = self.font_cache_thread.last_resort_font_template(desc.clone());
|
||||
let layout_font = self.create_layout_font(font_template,
|
||||
let template_info = self.font_cache_thread.last_resort_font_template(desc.clone());
|
||||
let layout_font = self.create_layout_font(template_info.font_template,
|
||||
desc.clone(),
|
||||
style.font_size,
|
||||
style.font_variant);
|
||||
style.font_variant,
|
||||
template_info.font_key);
|
||||
match layout_font {
|
||||
Ok(layout_font) => {
|
||||
let layout_font = Rc::new(RefCell::new(layout_font));
|
||||
|
|
|
@ -75,6 +75,7 @@ extern crate unicode_script;
|
|||
extern crate url;
|
||||
#[macro_use]
|
||||
extern crate util;
|
||||
extern crate webrender_traits;
|
||||
|
||||
pub use paint_context::PaintContext;
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use string_cache::Atom;
|
||||
use webrender_traits::NativeFontHandle;
|
||||
|
||||
/// Platform specific font representation for Linux.
|
||||
/// The identifier is an absolute path, and the bytes
|
||||
|
@ -36,4 +37,22 @@ impl FontTemplateData {
|
|||
identifier: identifier,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a clone of the data in this font. This may be a hugely expensive
|
||||
/// operation (depending on the platform) which performs synchronous disk I/O
|
||||
/// and should never be done lightly.
|
||||
pub fn bytes(&self) -> Vec<u8> {
|
||||
self.bytes.clone()
|
||||
}
|
||||
|
||||
/// Returns a clone of the bytes in this font if they are in memory. This function never
|
||||
/// performs disk I/O.
|
||||
pub fn bytes_if_in_memory(&self) -> Option<Vec<u8>> {
|
||||
Some(self.bytes())
|
||||
}
|
||||
|
||||
/// Returns the native font that underlies this font template, if applicable.
|
||||
pub fn native_font(&self) -> Option<NativeFontHandle> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,12 @@ use core_text::font::CTFont;
|
|||
use serde::de::{Error, Visitor};
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::borrow::ToOwned;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Mutex;
|
||||
use string_cache::Atom;
|
||||
use url::Url;
|
||||
|
||||
/// Platform specific font representation for mac.
|
||||
/// The identifier is a PostScript font name. The
|
||||
|
@ -62,6 +65,39 @@ impl FontTemplateData {
|
|||
}
|
||||
ctfont.as_ref().map(|ctfont| (*ctfont).clone())
|
||||
}
|
||||
|
||||
/// Returns a clone of the data in this font. This may be a hugely expensive
|
||||
/// operation (depending on the platform) which performs synchronous disk I/O
|
||||
/// and should never be done lightly.
|
||||
pub fn bytes(&self) -> Vec<u8> {
|
||||
match self.bytes_if_in_memory() {
|
||||
Some(font_data) => return font_data,
|
||||
None => {}
|
||||
}
|
||||
|
||||
let path = Url::parse(&*self.ctfont()
|
||||
.expect("No Core Text font available!")
|
||||
.url()
|
||||
.expect("No URL for Core Text font!")
|
||||
.get_string()
|
||||
.to_string()).expect("Couldn't parse Core Text font URL!")
|
||||
.to_file_path()
|
||||
.expect("Core Text font didn't name a path!");
|
||||
let mut bytes = Vec::new();
|
||||
File::open(path).expect("Couldn't open font file!").read_to_end(&mut bytes).unwrap();
|
||||
bytes
|
||||
}
|
||||
|
||||
/// Returns a clone of the bytes in this font if they are in memory. This function never
|
||||
/// performs disk I/O.
|
||||
pub fn bytes_if_in_memory(&self) -> Option<Vec<u8>> {
|
||||
self.font_data.clone()
|
||||
}
|
||||
|
||||
/// Returns the native font that underlies this font template, if applicable.
|
||||
pub fn native_font(&self) -> Option<CGFont> {
|
||||
self.ctfont().map(|ctfont| ctfont.copy_to_CGFont())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
|
@ -13,6 +13,7 @@ use std::sync::Arc;
|
|||
use text::glyph::{CharIndex, GlyphStore};
|
||||
use util::range::Range;
|
||||
use util::vec::{Comparator, FullBinarySearchMethods};
|
||||
use webrender_traits;
|
||||
|
||||
thread_local! {
|
||||
static INDEX_OF_FIRST_GLYPH_RUN_CACHE: Cell<Option<(*const TextRun, CharIndex, usize)>> =
|
||||
|
@ -27,6 +28,7 @@ pub struct TextRun {
|
|||
pub font_template: Arc<FontTemplateData>,
|
||||
pub actual_pt_size: Au,
|
||||
pub font_metrics: FontMetrics,
|
||||
pub font_key: Option<webrender_traits::FontKey>,
|
||||
/// The glyph runs that make up this text run.
|
||||
pub glyphs: Arc<Vec<GlyphRun>>,
|
||||
pub bidi_level: u8,
|
||||
|
@ -177,6 +179,7 @@ impl<'a> TextRun {
|
|||
text: Arc::new(text),
|
||||
font_metrics: font.metrics.clone(),
|
||||
font_template: font.handle.template(),
|
||||
font_key: font.font_key,
|
||||
actual_pt_size: font.actual_pt_size,
|
||||
glyphs: Arc::new(glyphs),
|
||||
bidi_level: bidi_level,
|
||||
|
|
|
@ -56,6 +56,9 @@ path = "../util"
|
|||
[dependencies.ipc-channel]
|
||||
git = "https://github.com/servo/ipc-channel"
|
||||
|
||||
[dependencies.webrender_traits]
|
||||
git = "https://github.com/glennw/webrender_traits"
|
||||
|
||||
[dependencies]
|
||||
app_units = {version = "0.2.1", features = ["plugins"]}
|
||||
bitflags = "0.3"
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
use app_units::{Au, AU_PER_PX};
|
||||
use azure::azure_hl::Color;
|
||||
use block::BlockFlow;
|
||||
use canvas_traits::{CanvasMsg, FromLayoutMsg};
|
||||
use canvas_traits::{CanvasMsg, CanvasPixelData, CanvasData, FromLayoutMsg};
|
||||
use context::LayoutContext;
|
||||
use euclid::num::Zero;
|
||||
use euclid::{Matrix4, Point2D, Point3D, Rect, SideOffsets2D, Size2D};
|
||||
|
@ -26,7 +26,7 @@ use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayIte
|
|||
use gfx::display_list::{BorderRadii, BoxShadowClipMode, BoxShadowDisplayItem, ClippingRegion};
|
||||
use gfx::display_list::{DisplayItem, DisplayItemMetadata, DisplayList, DisplayListSection};
|
||||
use gfx::display_list::{GradientDisplayItem};
|
||||
use gfx::display_list::{GradientStop, ImageDisplayItem, LayeredItem, LayerInfo};
|
||||
use gfx::display_list::{GradientStop, IframeDisplayItem, ImageDisplayItem, WebGLDisplayItem, LayeredItem, LayerInfo};
|
||||
use gfx::display_list::{LineDisplayItem, OpaqueNode, SolidColorDisplayItem};
|
||||
use gfx::display_list::{StackingContext, TextDisplayItem, TextOrientation};
|
||||
use gfx::paint_thread::THREAD_TINT_COLORS;
|
||||
|
@ -50,8 +50,7 @@ use style::properties::style_structs::Border;
|
|||
use style::properties::{self, ComputedValues};
|
||||
use style::values::RGBA;
|
||||
use style::values::computed;
|
||||
use style::values::computed::LinearGradient;
|
||||
use style::values::computed::{LengthOrNone, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||
use style::values::computed::{LengthOrNone, LengthOrPercentage, LengthOrPercentageOrAuto, LinearGradient};
|
||||
use style::values::specified::{AngleOrCorner, HorizontalDirection, VerticalDirection};
|
||||
use style_traits::cursor::Cursor;
|
||||
use table_cell::CollapsedBordersForCell;
|
||||
|
@ -948,9 +947,12 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
stacking_relative_flow_origin,
|
||||
self);
|
||||
|
||||
if !stacking_relative_border_box.intersects(stacking_relative_display_port) {
|
||||
debug!("Fragment::build_display_list: outside display port");
|
||||
return
|
||||
// webrender deals with all culling via aabb
|
||||
if !opts::get().use_webrender {
|
||||
if !stacking_relative_border_box.intersects(stacking_relative_display_port) {
|
||||
debug!("Fragment::build_display_list: outside display port");
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the clip rect. If there's nothing to render at all, don't even construct
|
||||
|
@ -1112,20 +1114,31 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}
|
||||
SpecificFragmentInfo::Iframe(ref fragment_info) => {
|
||||
if !stacking_relative_content_box.is_empty() {
|
||||
let layer_id = self.layer_id();
|
||||
display_list.content.push_back(DisplayItem::LayeredItemClass(box LayeredItem {
|
||||
item: DisplayItem::NoopClass(
|
||||
box BaseDisplayItem::new(&stacking_relative_content_box,
|
||||
DisplayItemMetadata::new(self.node,
|
||||
&*self.style,
|
||||
Cursor::DefaultCursor),
|
||||
clip)),
|
||||
layer_id: layer_id
|
||||
}));
|
||||
if opts::get().use_webrender {
|
||||
display_list.content.push_back(DisplayItem::IframeClass(box IframeDisplayItem {
|
||||
base: BaseDisplayItem::new(&stacking_relative_content_box,
|
||||
DisplayItemMetadata::new(self.node,
|
||||
&*self.style,
|
||||
Cursor::DefaultCursor),
|
||||
clip),
|
||||
iframe: fragment_info.pipeline_id,
|
||||
}));
|
||||
} else {
|
||||
let layer_id = self.layer_id();
|
||||
display_list.content.push_back(DisplayItem::LayeredItemClass(box LayeredItem {
|
||||
item: DisplayItem::NoopClass(
|
||||
box BaseDisplayItem::new(&stacking_relative_content_box,
|
||||
DisplayItemMetadata::new(self.node,
|
||||
&*self.style,
|
||||
Cursor::DefaultCursor),
|
||||
clip)),
|
||||
layer_id: layer_id
|
||||
}));
|
||||
|
||||
display_list.layer_info.push_back(LayerInfo::new(layer_id,
|
||||
ScrollPolicy::Scrollable,
|
||||
Some(fragment_info.pipeline_id)));
|
||||
display_list.layer_info.push_back(LayerInfo::new(layer_id,
|
||||
ScrollPolicy::Scrollable,
|
||||
Some(fragment_info.pipeline_id)));
|
||||
}
|
||||
}
|
||||
}
|
||||
SpecificFragmentInfo::Image(ref mut image_fragment) => {
|
||||
|
@ -1144,7 +1157,6 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
}
|
||||
}
|
||||
SpecificFragmentInfo::Canvas(ref canvas_fragment_info) => {
|
||||
// TODO(ecoal95): make the canvas with a renderer use the custom layer
|
||||
let width = canvas_fragment_info.replaced_image_fragment_info
|
||||
.computed_inline_size.map_or(0, |w| w.to_px() as usize);
|
||||
let height = canvas_fragment_info.replaced_image_fragment_info
|
||||
|
@ -1156,7 +1168,7 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
let ipc_renderer = ipc_renderer.lock().unwrap();
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
ipc_renderer.send(CanvasMsg::FromLayout(
|
||||
FromLayoutMsg::SendPixelContents(sender))).unwrap();
|
||||
FromLayoutMsg::SendData(sender))).unwrap();
|
||||
let data = receiver.recv().unwrap();
|
||||
|
||||
// Propagate the layer and the renderer to the paint thread.
|
||||
|
@ -1165,31 +1177,54 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
|
||||
data
|
||||
},
|
||||
None => IpcSharedMemory::from_byte(0xFFu8, width * height * 4),
|
||||
};
|
||||
let display_item = DisplayItem::ImageClass(box ImageDisplayItem {
|
||||
base: BaseDisplayItem::new(&stacking_relative_content_box,
|
||||
DisplayItemMetadata::new(self.node,
|
||||
&*self.style,
|
||||
Cursor::DefaultCursor),
|
||||
clip),
|
||||
image: Arc::new(Image {
|
||||
width: width as u32,
|
||||
height: height as u32,
|
||||
format: PixelFormat::RGBA8,
|
||||
bytes: canvas_data,
|
||||
None => CanvasData::Pixels(CanvasPixelData {
|
||||
image_data: IpcSharedMemory::from_byte(0xFFu8, width * height * 4),
|
||||
image_key: None,
|
||||
}),
|
||||
stretch_size: stacking_relative_content_box.size,
|
||||
image_rendering: image_rendering::T::Auto,
|
||||
});
|
||||
};
|
||||
|
||||
display_list.content.push_back(DisplayItem::LayeredItemClass(box LayeredItem {
|
||||
item: display_item,
|
||||
layer_id: layer_id
|
||||
}));
|
||||
let display_item = match canvas_data {
|
||||
CanvasData::Pixels(canvas_data) => {
|
||||
DisplayItem::ImageClass(box ImageDisplayItem {
|
||||
base: BaseDisplayItem::new(&stacking_relative_content_box,
|
||||
DisplayItemMetadata::new(self.node,
|
||||
&*self.style,
|
||||
Cursor::DefaultCursor),
|
||||
clip),
|
||||
image: Arc::new(Image {
|
||||
width: width as u32,
|
||||
height: height as u32,
|
||||
format: PixelFormat::RGBA8,
|
||||
bytes: canvas_data.image_data,
|
||||
id: canvas_data.image_key,
|
||||
}),
|
||||
stretch_size: stacking_relative_content_box.size,
|
||||
image_rendering: image_rendering::T::Auto,
|
||||
})
|
||||
}
|
||||
CanvasData::WebGL(context_id) => {
|
||||
DisplayItem::WebGLClass(box WebGLDisplayItem {
|
||||
base: BaseDisplayItem::new(&stacking_relative_content_box,
|
||||
DisplayItemMetadata::new(self.node,
|
||||
&*self.style,
|
||||
Cursor::DefaultCursor),
|
||||
clip),
|
||||
context_id: context_id,
|
||||
})
|
||||
}
|
||||
};
|
||||
|
||||
display_list.layer_info.push_back(
|
||||
LayerInfo::new(layer_id, ScrollPolicy::Scrollable, None));
|
||||
if opts::get().use_webrender {
|
||||
display_list.content.push_back(display_item);
|
||||
} else {
|
||||
display_list.content.push_back(DisplayItem::LayeredItemClass(box LayeredItem {
|
||||
item: display_item,
|
||||
layer_id: layer_id
|
||||
}));
|
||||
|
||||
display_list.layer_info.push_back(
|
||||
LayerInfo::new(layer_id, ScrollPolicy::Scrollable, None));
|
||||
}
|
||||
}
|
||||
}
|
||||
SpecificFragmentInfo::UnscannedText(_) => {
|
||||
|
@ -1993,4 +2028,3 @@ pub enum StackingContextCreationMode {
|
|||
OuterScrollWrapper,
|
||||
InnerScrollWrapper,
|
||||
}
|
||||
|
||||
|
|
|
@ -1928,9 +1928,14 @@ impl InlineMetrics {
|
|||
#[inline]
|
||||
pub fn from_font_metrics(font_metrics: &FontMetrics, line_height: Au) -> InlineMetrics {
|
||||
let leading = line_height - (font_metrics.ascent + font_metrics.descent);
|
||||
// Calculating the half leading here and then using leading - half_leading
|
||||
// below ensure that we don't introduce any rounding accuracy issues here.
|
||||
// The invariant is that the resulting total line height must exactly
|
||||
// equal the requested line_height.
|
||||
let half_leading = leading.scale_by(0.5);
|
||||
InlineMetrics {
|
||||
block_size_above_baseline: font_metrics.ascent + leading.scale_by(0.5),
|
||||
depth_below_baseline: font_metrics.descent + leading.scale_by(0.5),
|
||||
block_size_above_baseline: font_metrics.ascent + half_leading,
|
||||
depth_below_baseline: font_metrics.descent + leading - half_leading,
|
||||
ascent: font_metrics.ascent,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ use ipc_channel::router::ROUTER;
|
|||
use layout_debug;
|
||||
use layout_traits::LayoutThreadFactory;
|
||||
use log;
|
||||
use msg::constellation_msg::{ConstellationChan, Failure, PipelineId};
|
||||
use msg::constellation_msg::{ConstellationChan, ConvertPipelineIdToWebRender, Failure, PipelineId};
|
||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheResult, ImageCacheThread};
|
||||
use parallel;
|
||||
use profile_traits::mem::{self, Report, ReportKind, ReportsChan};
|
||||
|
@ -80,6 +80,8 @@ use util::opts;
|
|||
use util::thread;
|
||||
use util::thread_state;
|
||||
use util::workqueue::WorkQueue;
|
||||
use webrender_helpers::WebRenderStackingContextConverter;
|
||||
use webrender_traits;
|
||||
use wrapper::{LayoutNode, NonOpaqueStyleAndLayoutData, ServoLayoutNode, ThreadSafeLayoutNode};
|
||||
|
||||
/// The number of screens of data we're allowed to generate display lists for in each direction.
|
||||
|
@ -221,6 +223,8 @@ pub struct LayoutThread {
|
|||
/// The CSS error reporter for all CSS loaded in this layout thread
|
||||
error_reporter: CSSErrorReporter,
|
||||
|
||||
// Webrender interface, if enabled.
|
||||
webrender_api: Option<webrender_traits::RenderApi>,
|
||||
}
|
||||
|
||||
impl LayoutThreadFactory for LayoutThread {
|
||||
|
@ -240,7 +244,8 @@ impl LayoutThreadFactory for LayoutThread {
|
|||
time_profiler_chan: time::ProfilerChan,
|
||||
mem_profiler_chan: mem::ProfilerChan,
|
||||
shutdown_chan: IpcSender<()>,
|
||||
content_process_shutdown_chan: IpcSender<()>) {
|
||||
content_process_shutdown_chan: IpcSender<()>,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>) {
|
||||
let ConstellationChan(con_chan) = constellation_chan.clone();
|
||||
thread::spawn_named_with_send_on_failure(format!("LayoutThread {:?}", id),
|
||||
thread_state::LAYOUT,
|
||||
|
@ -258,7 +263,8 @@ impl LayoutThreadFactory for LayoutThread {
|
|||
image_cache_thread,
|
||||
font_cache_thread,
|
||||
time_profiler_chan,
|
||||
mem_profiler_chan.clone());
|
||||
mem_profiler_chan.clone(),
|
||||
webrender_api_sender);
|
||||
|
||||
let reporter_name = format!("layout-reporter-{}", id);
|
||||
mem_profiler_chan.run_with_memory_reporting(|| {
|
||||
|
@ -367,7 +373,8 @@ impl LayoutThread {
|
|||
image_cache_thread: ImageCacheThread,
|
||||
font_cache_thread: FontCacheThread,
|
||||
time_profiler_chan: time::ProfilerChan,
|
||||
mem_profiler_chan: mem::ProfilerChan)
|
||||
mem_profiler_chan: mem::ProfilerChan,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>)
|
||||
-> LayoutThread {
|
||||
let device = Device::new(
|
||||
MediaType::Screen,
|
||||
|
@ -437,6 +444,7 @@ impl LayoutThread {
|
|||
expired_animations: Arc::new(RwLock::new(HashMap::new())),
|
||||
epoch: Epoch(0),
|
||||
viewport_size: Size2D::new(Au(0), Au(0)),
|
||||
webrender_api: webrender_api_sender.map(|wr| wr.create_api()),
|
||||
rw_data: Arc::new(Mutex::new(
|
||||
LayoutThreadData {
|
||||
constellation_chan: constellation_chan,
|
||||
|
@ -705,7 +713,8 @@ impl LayoutThread {
|
|||
self.time_profiler_chan.clone(),
|
||||
self.mem_profiler_chan.clone(),
|
||||
info.layout_shutdown_chan,
|
||||
info.content_process_shutdown_chan);
|
||||
info.content_process_shutdown_chan,
|
||||
self.webrender_api.as_ref().map(|wr| wr.clone_sender()));
|
||||
}
|
||||
|
||||
/// Enters a quiescent state in which no new messages will be processed until an `ExitNow` is
|
||||
|
@ -908,9 +917,40 @@ impl LayoutThread {
|
|||
debug!("Layout done!");
|
||||
|
||||
self.epoch.next();
|
||||
self.paint_chan
|
||||
.send(LayoutToPaintMsg::PaintInit(self.epoch, paint_layer))
|
||||
.unwrap();
|
||||
|
||||
if opts::get().use_webrender {
|
||||
let api = self.webrender_api.as_ref().unwrap();
|
||||
// TODO: Avoid the temporary conversion and build webrender sc/dl directly!
|
||||
let Epoch(epoch_number) = self.epoch;
|
||||
let epoch = webrender_traits::Epoch(epoch_number);
|
||||
let pipeline_id = self.id.to_webrender();
|
||||
|
||||
// TODO(gw) For now only create a root scrolling layer!
|
||||
let root_scroll_layer_id = webrender_traits::ScrollLayerId::new(pipeline_id, 0);
|
||||
let sc_id = rw_data.stacking_context.as_ref()
|
||||
.unwrap()
|
||||
.convert_to_webrender(&self.webrender_api.as_ref().unwrap(),
|
||||
pipeline_id,
|
||||
epoch,
|
||||
Some(root_scroll_layer_id));
|
||||
let root_background_color = webrender_traits::ColorF::new(root_background_color.r,
|
||||
root_background_color.g,
|
||||
root_background_color.b,
|
||||
root_background_color.a);
|
||||
|
||||
let viewport_size = Size2D::new(self.viewport_size.width.to_f32_px(),
|
||||
self.viewport_size.height.to_f32_px());
|
||||
|
||||
api.set_root_stacking_context(sc_id,
|
||||
root_background_color,
|
||||
epoch,
|
||||
pipeline_id,
|
||||
viewport_size);
|
||||
} else {
|
||||
self.paint_chan
|
||||
.send(LayoutToPaintMsg::PaintInit(self.epoch, paint_layer))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ extern crate unicode_script;
|
|||
extern crate url;
|
||||
#[macro_use]
|
||||
extern crate util;
|
||||
extern crate webrender_traits;
|
||||
|
||||
#[macro_use]
|
||||
mod layout_debug;
|
||||
|
@ -95,4 +96,5 @@ mod table_rowgroup;
|
|||
mod table_wrapper;
|
||||
mod text;
|
||||
mod traversal;
|
||||
mod webrender_helpers;
|
||||
mod wrapper;
|
||||
|
|
481
components/layout/webrender_helpers.rs
Normal file
481
components/layout/webrender_helpers.rs
Normal file
|
@ -0,0 +1,481 @@
|
|||
/* 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/. */
|
||||
|
||||
// TODO(gw): This contains helper traits and implementations for converting Servo display lists
|
||||
// into WebRender display lists. In the future, this step should be completely removed.
|
||||
// This might be achieved by sharing types between WR and Servo display lists, or
|
||||
// completely converting layout to directly generate WebRender display lists, for example.
|
||||
|
||||
use app_units::Au;
|
||||
use azure::azure_hl::Color;
|
||||
use euclid::num::Zero;
|
||||
use euclid::{Point2D, Rect, Size2D};
|
||||
use gfx::display_list::{BorderRadii, BoxShadowClipMode, ClippingRegion};
|
||||
use gfx::display_list::{DisplayItem, DisplayList};
|
||||
use gfx::display_list::{GradientStop, StackingContext};
|
||||
use gfx_traits::ScrollPolicy;
|
||||
use msg::constellation_msg::ConvertPipelineIdToWebRender;
|
||||
use style::computed_values::filter::{self, Filter};
|
||||
use style::computed_values::{image_rendering, mix_blend_mode};
|
||||
use style::values::computed::BorderStyle;
|
||||
use webrender_traits;
|
||||
|
||||
pub trait WebRenderStackingContextConverter {
|
||||
fn convert_to_webrender(&self,
|
||||
api: &webrender_traits::RenderApi,
|
||||
pipeline_id: webrender_traits::PipelineId,
|
||||
epoch: webrender_traits::Epoch,
|
||||
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
|
||||
-> webrender_traits::StackingContextId;
|
||||
}
|
||||
|
||||
trait WebRenderDisplayListConverter {
|
||||
fn convert_to_webrender(&self,
|
||||
api: &webrender_traits::RenderApi,
|
||||
pipeline_id: webrender_traits::PipelineId,
|
||||
epoch: webrender_traits::Epoch) -> webrender_traits::DisplayListBuilder;
|
||||
}
|
||||
|
||||
trait WebRenderDisplayItemConverter {
|
||||
fn convert_to_webrender(&self,
|
||||
api: &webrender_traits::RenderApi,
|
||||
pipeline_id: webrender_traits::PipelineId,
|
||||
epoch: webrender_traits::Epoch,
|
||||
level: webrender_traits::StackingLevel,
|
||||
builder: &mut webrender_traits::DisplayListBuilder);
|
||||
}
|
||||
|
||||
trait ToBorderStyle {
|
||||
fn to_border_style(&self) -> webrender_traits::BorderStyle;
|
||||
}
|
||||
|
||||
impl ToBorderStyle for BorderStyle {
|
||||
fn to_border_style(&self) -> webrender_traits::BorderStyle {
|
||||
match *self {
|
||||
BorderStyle::none => webrender_traits::BorderStyle::None,
|
||||
BorderStyle::solid => webrender_traits::BorderStyle::Solid,
|
||||
BorderStyle::double => webrender_traits::BorderStyle::Double,
|
||||
BorderStyle::dotted => webrender_traits::BorderStyle::Dotted,
|
||||
BorderStyle::dashed => webrender_traits::BorderStyle::Dashed,
|
||||
BorderStyle::hidden => webrender_traits::BorderStyle::Hidden,
|
||||
BorderStyle::groove => webrender_traits::BorderStyle::Groove,
|
||||
BorderStyle::ridge => webrender_traits::BorderStyle::Ridge,
|
||||
BorderStyle::inset => webrender_traits::BorderStyle::Inset,
|
||||
BorderStyle::outset => webrender_traits::BorderStyle::Outset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait ToBoxShadowClipMode {
|
||||
fn to_clip_mode(&self) -> webrender_traits::BoxShadowClipMode;
|
||||
}
|
||||
|
||||
impl ToBoxShadowClipMode for BoxShadowClipMode {
|
||||
fn to_clip_mode(&self) -> webrender_traits::BoxShadowClipMode {
|
||||
match *self {
|
||||
BoxShadowClipMode::None => webrender_traits::BoxShadowClipMode::None,
|
||||
BoxShadowClipMode::Inset => webrender_traits::BoxShadowClipMode::Inset,
|
||||
BoxShadowClipMode::Outset => webrender_traits::BoxShadowClipMode::Outset,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait ToSizeF {
|
||||
fn to_sizef(&self) -> Size2D<f32>;
|
||||
}
|
||||
|
||||
trait ToPointF {
|
||||
fn to_pointf(&self) -> Point2D<f32>;
|
||||
}
|
||||
|
||||
impl ToPointF for Point2D<Au> {
|
||||
fn to_pointf(&self) -> Point2D<f32> {
|
||||
Point2D::new(self.x.to_f32_px(), self.y.to_f32_px())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToSizeF for Size2D<Au> {
|
||||
fn to_sizef(&self) -> Size2D<f32> {
|
||||
Size2D::new(self.width.to_f32_px(), self.height.to_f32_px())
|
||||
}
|
||||
}
|
||||
|
||||
trait ToRectF {
|
||||
fn to_rectf(&self) -> Rect<f32>;
|
||||
}
|
||||
|
||||
impl ToRectF for Rect<Au> {
|
||||
fn to_rectf(&self) -> Rect<f32> {
|
||||
let x = self.origin.x.to_f32_px();
|
||||
let y = self.origin.y.to_f32_px();
|
||||
let w = self.size.width.to_f32_px();
|
||||
let h = self.size.height.to_f32_px();
|
||||
Rect::new(Point2D::new(x, y), Size2D::new(w, h))
|
||||
}
|
||||
}
|
||||
|
||||
trait ToColorF {
|
||||
fn to_colorf(&self) -> webrender_traits::ColorF;
|
||||
}
|
||||
|
||||
impl ToColorF for Color {
|
||||
fn to_colorf(&self) -> webrender_traits::ColorF {
|
||||
webrender_traits::ColorF::new(self.r, self.g, self.b, self.a)
|
||||
}
|
||||
}
|
||||
|
||||
trait ToGradientStop {
|
||||
fn to_gradient_stop(&self) -> webrender_traits::GradientStop;
|
||||
}
|
||||
|
||||
impl ToGradientStop for GradientStop {
|
||||
fn to_gradient_stop(&self) -> webrender_traits::GradientStop {
|
||||
webrender_traits::GradientStop {
|
||||
offset: self.offset,
|
||||
color: self.color.to_colorf(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait ToClipRegion {
|
||||
fn to_clip_region(&self) -> webrender_traits::ClipRegion;
|
||||
}
|
||||
|
||||
impl ToClipRegion for ClippingRegion {
|
||||
fn to_clip_region(&self) -> webrender_traits::ClipRegion {
|
||||
webrender_traits::ClipRegion::new(self.main.to_rectf(),
|
||||
self.complex.iter().map(|complex_clipping_region| {
|
||||
webrender_traits::ComplexClipRegion::new(
|
||||
complex_clipping_region.rect.to_rectf(),
|
||||
complex_clipping_region.radii.to_border_radius(),
|
||||
)
|
||||
}).collect())
|
||||
}
|
||||
}
|
||||
|
||||
trait ToBorderRadius {
|
||||
fn to_border_radius(&self) -> webrender_traits::BorderRadius;
|
||||
}
|
||||
|
||||
impl ToBorderRadius for BorderRadii<Au> {
|
||||
fn to_border_radius(&self) -> webrender_traits::BorderRadius {
|
||||
webrender_traits::BorderRadius {
|
||||
top_left: self.top_left.to_sizef(),
|
||||
top_right: self.top_right.to_sizef(),
|
||||
bottom_left: self.bottom_left.to_sizef(),
|
||||
bottom_right: self.bottom_right.to_sizef(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait ToBlendMode {
|
||||
fn to_blend_mode(&self) -> webrender_traits::MixBlendMode;
|
||||
}
|
||||
|
||||
impl ToBlendMode for mix_blend_mode::T {
|
||||
fn to_blend_mode(&self) -> webrender_traits::MixBlendMode {
|
||||
match *self {
|
||||
mix_blend_mode::T::normal => webrender_traits::MixBlendMode::Normal,
|
||||
mix_blend_mode::T::multiply => webrender_traits::MixBlendMode::Multiply,
|
||||
mix_blend_mode::T::screen => webrender_traits::MixBlendMode::Screen,
|
||||
mix_blend_mode::T::overlay => webrender_traits::MixBlendMode::Overlay,
|
||||
mix_blend_mode::T::darken => webrender_traits::MixBlendMode::Darken,
|
||||
mix_blend_mode::T::lighten => webrender_traits::MixBlendMode::Lighten,
|
||||
mix_blend_mode::T::color_dodge => webrender_traits::MixBlendMode::ColorDodge,
|
||||
mix_blend_mode::T::color_burn => webrender_traits::MixBlendMode::ColorBurn,
|
||||
mix_blend_mode::T::hard_light => webrender_traits::MixBlendMode::HardLight,
|
||||
mix_blend_mode::T::soft_light => webrender_traits::MixBlendMode::SoftLight,
|
||||
mix_blend_mode::T::difference => webrender_traits::MixBlendMode::Difference,
|
||||
mix_blend_mode::T::exclusion => webrender_traits::MixBlendMode::Exclusion,
|
||||
mix_blend_mode::T::hue => webrender_traits::MixBlendMode::Hue,
|
||||
mix_blend_mode::T::saturation => webrender_traits::MixBlendMode::Saturation,
|
||||
mix_blend_mode::T::color => webrender_traits::MixBlendMode::Color,
|
||||
mix_blend_mode::T::luminosity => webrender_traits::MixBlendMode::Luminosity,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait ToImageRendering {
|
||||
fn to_image_rendering(&self) -> webrender_traits::ImageRendering;
|
||||
}
|
||||
|
||||
impl ToImageRendering for image_rendering::T {
|
||||
fn to_image_rendering(&self) -> webrender_traits::ImageRendering {
|
||||
match *self {
|
||||
image_rendering::T::CrispEdges => webrender_traits::ImageRendering::CrispEdges,
|
||||
image_rendering::T::Auto => webrender_traits::ImageRendering::Auto,
|
||||
image_rendering::T::Pixelated => webrender_traits::ImageRendering::Pixelated,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait ToFilterOps {
|
||||
fn to_filter_ops(&self) -> Vec<webrender_traits::FilterOp>;
|
||||
}
|
||||
|
||||
impl ToFilterOps for filter::T {
|
||||
fn to_filter_ops(&self) -> Vec<webrender_traits::FilterOp> {
|
||||
let mut result = Vec::with_capacity(self.filters.len());
|
||||
for filter in self.filters.iter() {
|
||||
match *filter {
|
||||
Filter::Blur(radius) => result.push(webrender_traits::FilterOp::Blur(radius)),
|
||||
Filter::Brightness(amount) => result.push(webrender_traits::FilterOp::Brightness(amount)),
|
||||
Filter::Contrast(amount) => result.push(webrender_traits::FilterOp::Contrast(amount)),
|
||||
Filter::Grayscale(amount) => result.push(webrender_traits::FilterOp::Grayscale(amount)),
|
||||
Filter::HueRotate(angle) => result.push(webrender_traits::FilterOp::HueRotate(angle.0)),
|
||||
Filter::Invert(amount) => result.push(webrender_traits::FilterOp::Invert(amount)),
|
||||
Filter::Opacity(amount) => result.push(webrender_traits::FilterOp::Opacity(amount)),
|
||||
Filter::Saturate(amount) => result.push(webrender_traits::FilterOp::Saturate(amount)),
|
||||
Filter::Sepia(amount) => result.push(webrender_traits::FilterOp::Sepia(amount)),
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
}
|
||||
|
||||
impl WebRenderStackingContextConverter for StackingContext {
|
||||
fn convert_to_webrender(&self,
|
||||
api: &webrender_traits::RenderApi,
|
||||
pipeline_id: webrender_traits::PipelineId,
|
||||
epoch: webrender_traits::Epoch,
|
||||
scroll_layer_id: Option<webrender_traits::ScrollLayerId>)
|
||||
-> webrender_traits::StackingContextId {
|
||||
let scroll_policy = self.layer_info
|
||||
.map_or(webrender_traits::ScrollPolicy::Scrollable, |info| {
|
||||
match info.scroll_policy {
|
||||
ScrollPolicy::Scrollable => webrender_traits::ScrollPolicy::Scrollable,
|
||||
ScrollPolicy::FixedPosition => webrender_traits::ScrollPolicy::Fixed,
|
||||
}
|
||||
});
|
||||
|
||||
let mut sc = webrender_traits::StackingContext::new(scroll_layer_id,
|
||||
scroll_policy,
|
||||
self.bounds.to_rectf(),
|
||||
self.overflow.to_rectf(),
|
||||
self.z_index,
|
||||
&self.transform,
|
||||
&self.perspective,
|
||||
self.establishes_3d_context,
|
||||
self.blend_mode.to_blend_mode(),
|
||||
self.filters.to_filter_ops());
|
||||
|
||||
let dl_builder = self.display_list.convert_to_webrender(api,
|
||||
pipeline_id,
|
||||
epoch);
|
||||
api.add_display_list(dl_builder, &mut sc, pipeline_id, epoch);
|
||||
|
||||
api.add_stacking_context(sc, pipeline_id, epoch)
|
||||
}
|
||||
}
|
||||
|
||||
impl WebRenderDisplayListConverter for Box<DisplayList> {
|
||||
fn convert_to_webrender(&self,
|
||||
api: &webrender_traits::RenderApi,
|
||||
pipeline_id: webrender_traits::PipelineId,
|
||||
epoch: webrender_traits::Epoch) -> webrender_traits::DisplayListBuilder {
|
||||
let mut builder = webrender_traits::DisplayListBuilder::new();
|
||||
|
||||
for item in &self.background_and_borders {
|
||||
item.convert_to_webrender(api,
|
||||
pipeline_id,
|
||||
epoch,
|
||||
webrender_traits::StackingLevel::BackgroundAndBorders,
|
||||
&mut builder);
|
||||
}
|
||||
|
||||
for item in &self.block_backgrounds_and_borders {
|
||||
item.convert_to_webrender(api,
|
||||
pipeline_id,
|
||||
epoch,
|
||||
webrender_traits::StackingLevel::BlockBackgroundAndBorders,
|
||||
&mut builder);
|
||||
}
|
||||
|
||||
for item in &self.floats {
|
||||
item.convert_to_webrender(api,
|
||||
pipeline_id,
|
||||
epoch,
|
||||
webrender_traits::StackingLevel::Floats,
|
||||
&mut builder);
|
||||
}
|
||||
|
||||
for item in &self.content {
|
||||
item.convert_to_webrender(api,
|
||||
pipeline_id,
|
||||
epoch,
|
||||
webrender_traits::StackingLevel::Content,
|
||||
&mut builder);
|
||||
}
|
||||
|
||||
for item in &self.positioned_content {
|
||||
item.convert_to_webrender(api,
|
||||
pipeline_id,
|
||||
epoch,
|
||||
webrender_traits::StackingLevel::PositionedContent,
|
||||
&mut builder);
|
||||
}
|
||||
|
||||
for item in &self.outlines {
|
||||
item.convert_to_webrender(api,
|
||||
pipeline_id,
|
||||
epoch,
|
||||
webrender_traits::StackingLevel::Outlines,
|
||||
&mut builder);
|
||||
}
|
||||
|
||||
builder
|
||||
}
|
||||
}
|
||||
|
||||
impl WebRenderDisplayItemConverter for DisplayItem {
|
||||
fn convert_to_webrender(&self,
|
||||
api: &webrender_traits::RenderApi,
|
||||
pipeline_id: webrender_traits::PipelineId,
|
||||
epoch: webrender_traits::Epoch,
|
||||
level: webrender_traits::StackingLevel,
|
||||
builder: &mut webrender_traits::DisplayListBuilder) {
|
||||
match *self {
|
||||
DisplayItem::SolidColorClass(ref item) => {
|
||||
let color = item.color.to_colorf();
|
||||
if color.a > 0.0 {
|
||||
builder.push_rect(level,
|
||||
item.base.bounds.to_rectf(),
|
||||
item.base.clip.to_clip_region(),
|
||||
color);
|
||||
}
|
||||
}
|
||||
DisplayItem::TextClass(ref item) => {
|
||||
let mut origin = item.baseline_origin.clone();
|
||||
let mut glyphs = vec!();
|
||||
|
||||
for slice in item.text_run.natural_word_slices_in_visual_order(&item.range) {
|
||||
for glyph in slice.glyphs.iter_glyphs_for_char_range(&slice.range) {
|
||||
let glyph_advance = glyph.advance();
|
||||
let glyph_offset = glyph.offset().unwrap_or(Point2D::zero());
|
||||
let glyph = webrender_traits::GlyphInstance {
|
||||
index: glyph.id(),
|
||||
x: (origin.x + glyph_offset.x).to_f32_px(),
|
||||
y: (origin.y + glyph_offset.y).to_f32_px(),
|
||||
};
|
||||
origin = Point2D::new(origin.x + glyph_advance, origin.y);
|
||||
glyphs.push(glyph);
|
||||
};
|
||||
}
|
||||
|
||||
if glyphs.len() > 0 {
|
||||
builder.push_text(level,
|
||||
item.base.bounds.to_rectf(),
|
||||
item.base.clip.to_clip_region(),
|
||||
glyphs,
|
||||
item.text_run.font_key.expect("Font not added to webrender!"),
|
||||
item.text_color.to_colorf(),
|
||||
item.text_run.actual_pt_size,
|
||||
item.blur_radius);
|
||||
}
|
||||
}
|
||||
DisplayItem::ImageClass(ref item) => {
|
||||
if let Some(id) = item.image.id {
|
||||
if item.stretch_size.width > Au(0) &&
|
||||
item.stretch_size.height > Au(0) {
|
||||
builder.push_image(level,
|
||||
item.base.bounds.to_rectf(),
|
||||
item.base.clip.to_clip_region(),
|
||||
item.stretch_size.to_sizef(),
|
||||
item.image_rendering.to_image_rendering(),
|
||||
id);
|
||||
}
|
||||
}
|
||||
}
|
||||
DisplayItem::WebGLClass(ref item) => {
|
||||
builder.push_webgl_canvas(level,
|
||||
item.base.bounds.to_rectf(),
|
||||
item.base.clip.to_clip_region(),
|
||||
item.context_id);
|
||||
}
|
||||
DisplayItem::BorderClass(ref item) => {
|
||||
let rect = item.base.bounds.to_rectf();
|
||||
let left = webrender_traits::BorderSide {
|
||||
width: item.border_widths.left.to_f32_px(),
|
||||
color: item.color.left.to_colorf(),
|
||||
style: item.style.left.to_border_style(),
|
||||
};
|
||||
let top = webrender_traits::BorderSide {
|
||||
width: item.border_widths.top.to_f32_px(),
|
||||
color: item.color.top.to_colorf(),
|
||||
style: item.style.top.to_border_style(),
|
||||
};
|
||||
let right = webrender_traits::BorderSide {
|
||||
width: item.border_widths.right.to_f32_px(),
|
||||
color: item.color.right.to_colorf(),
|
||||
style: item.style.right.to_border_style(),
|
||||
};
|
||||
let bottom = webrender_traits::BorderSide {
|
||||
width: item.border_widths.bottom.to_f32_px(),
|
||||
color: item.color.bottom.to_colorf(),
|
||||
style: item.style.bottom.to_border_style(),
|
||||
};
|
||||
let radius = item.radius.to_border_radius();
|
||||
builder.push_border(level,
|
||||
rect,
|
||||
item.base.clip.to_clip_region(),
|
||||
left,
|
||||
top,
|
||||
right,
|
||||
bottom,
|
||||
radius);
|
||||
}
|
||||
DisplayItem::GradientClass(ref item) => {
|
||||
let rect = item.base.bounds.to_rectf();
|
||||
let start_point = item.start_point.to_pointf();
|
||||
let end_point = item.end_point.to_pointf();
|
||||
let mut stops = Vec::new();
|
||||
for stop in &item.stops {
|
||||
stops.push(stop.to_gradient_stop());
|
||||
}
|
||||
builder.push_gradient(level,
|
||||
rect,
|
||||
item.base.clip.to_clip_region(),
|
||||
start_point,
|
||||
end_point,
|
||||
stops);
|
||||
}
|
||||
DisplayItem::LineClass(..) => {
|
||||
println!("TODO DisplayItem::LineClass");
|
||||
}
|
||||
DisplayItem::LayeredItemClass(..) |
|
||||
DisplayItem::NoopClass(..) => {
|
||||
panic!("Unexpected in webrender!");
|
||||
}
|
||||
DisplayItem::BoxShadowClass(ref item) => {
|
||||
let rect = item.base.bounds.to_rectf();
|
||||
let box_bounds = item.box_bounds.to_rectf();
|
||||
builder.push_box_shadow(level,
|
||||
rect,
|
||||
item.base.clip.to_clip_region(),
|
||||
box_bounds,
|
||||
item.offset.to_pointf(),
|
||||
item.color.to_colorf(),
|
||||
item.blur_radius.to_f32_px(),
|
||||
item.spread_radius.to_f32_px(),
|
||||
item.border_radius.to_f32_px(),
|
||||
item.clip_mode.to_clip_mode());
|
||||
}
|
||||
DisplayItem::IframeClass(ref item) => {
|
||||
let rect = item.base.bounds.to_rectf();
|
||||
let pipeline_id = item.iframe.to_webrender();
|
||||
builder.push_iframe(level,
|
||||
rect,
|
||||
item.base.clip.to_clip_region(),
|
||||
pipeline_id);
|
||||
}
|
||||
DisplayItem::StackingContextClass(ref item) => {
|
||||
let stacking_context_id = item.convert_to_webrender(api,
|
||||
pipeline_id,
|
||||
epoch,
|
||||
None);
|
||||
builder.push_stacking_context(level, stacking_context_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,6 +28,9 @@ path = "../util"
|
|||
[dependencies.ipc-channel]
|
||||
git = "https://github.com/servo/ipc-channel"
|
||||
|
||||
[dependencies.webrender_traits]
|
||||
git = "https://github.com/glennw/webrender_traits"
|
||||
|
||||
[dependencies]
|
||||
serde = "0.6"
|
||||
serde_macros = "0.6"
|
||||
|
|
|
@ -14,6 +14,7 @@ extern crate script_traits;
|
|||
extern crate serde;
|
||||
extern crate url;
|
||||
extern crate util;
|
||||
extern crate webrender_traits;
|
||||
|
||||
// This module contains traits in layout used generically
|
||||
// in the rest of Servo.
|
||||
|
@ -54,5 +55,6 @@ pub trait LayoutThreadFactory {
|
|||
time_profiler_chan: time::ProfilerChan,
|
||||
mem_profiler_chan: mem::ProfilerChan,
|
||||
shutdown_chan: IpcSender<()>,
|
||||
content_process_shutdown_chan: IpcSender<()>);
|
||||
content_process_shutdown_chan: IpcSender<()>,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,9 @@ git = "https://github.com/servo/ipc-channel"
|
|||
[dependencies.plugins]
|
||||
path = "../plugins"
|
||||
|
||||
[dependencies.webrender_traits]
|
||||
git = "https://github.com/glennw/webrender_traits"
|
||||
|
||||
[dependencies]
|
||||
bitflags = "0.3"
|
||||
cssparser = {version = "0.5.3", features = ["heap_size", "serde-serialization"]}
|
||||
|
|
|
@ -17,6 +17,7 @@ use std::fmt;
|
|||
use url::Url;
|
||||
use util::geometry::{PagePx, ViewportPx};
|
||||
use webdriver_msg::{LoadStatus, WebDriverScriptCommand};
|
||||
use webrender_traits;
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
pub struct ConstellationChan<T: Deserialize + Serialize>(pub IpcSender<T>);
|
||||
|
@ -207,7 +208,7 @@ pub enum WebDriverCommandMsg {
|
|||
TakeScreenshot(PipelineId, IpcSender<Option<Image>>),
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Eq, PartialEq, Serialize, HeapSizeOf)]
|
||||
#[derive(Clone, Copy, Deserialize, Eq, PartialEq, Serialize, HeapSizeOf)]
|
||||
pub enum PixelFormat {
|
||||
K8, // Luminance channel only
|
||||
KA8, // Luminance + alpha
|
||||
|
@ -228,6 +229,8 @@ pub struct Image {
|
|||
pub format: PixelFormat,
|
||||
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
||||
pub bytes: IpcSharedMemory,
|
||||
#[ignore_heap_size_of = "Defined in webrender_traits"]
|
||||
pub id: Option<webrender_traits::ImageKey>,
|
||||
}
|
||||
|
||||
/// Similar to net::resource_thread::LoadData
|
||||
|
@ -353,3 +356,28 @@ impl fmt::Display for PipelineId {
|
|||
|
||||
#[derive(Clone, PartialEq, Eq, Copy, Hash, Debug, Deserialize, Serialize, HeapSizeOf)]
|
||||
pub struct SubpageId(pub u32);
|
||||
|
||||
pub trait ConvertPipelineIdToWebRender {
|
||||
fn to_webrender(&self) -> webrender_traits::PipelineId;
|
||||
}
|
||||
|
||||
pub trait ConvertPipelineIdFromWebRender {
|
||||
fn from_webrender(&self) -> PipelineId;
|
||||
}
|
||||
|
||||
impl ConvertPipelineIdToWebRender for PipelineId {
|
||||
fn to_webrender(&self) -> webrender_traits::PipelineId {
|
||||
let PipelineNamespaceId(namespace_id) = self.namespace_id;
|
||||
let PipelineIndex(index) = self.index;
|
||||
webrender_traits::PipelineId(namespace_id, index)
|
||||
}
|
||||
}
|
||||
|
||||
impl ConvertPipelineIdFromWebRender for webrender_traits::PipelineId {
|
||||
fn from_webrender(&self) -> PipelineId {
|
||||
PipelineId {
|
||||
namespace_id: PipelineNamespaceId(self.0),
|
||||
index: PipelineIndex(self.1),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ extern crate rustc_serialize;
|
|||
extern crate serde;
|
||||
extern crate url;
|
||||
extern crate util;
|
||||
extern crate webrender_traits;
|
||||
|
||||
pub mod constellation_msg;
|
||||
pub mod webdriver_msg;
|
||||
|
|
|
@ -28,6 +28,9 @@ path = "../msg"
|
|||
[dependencies.ipc-channel]
|
||||
git = "https://github.com/servo/ipc-channel"
|
||||
|
||||
[dependencies.webrender_traits]
|
||||
git = "https://github.com/glennw/webrender_traits"
|
||||
|
||||
[dependencies]
|
||||
hyper = { version = "0.7", features = [ "serde-serialization" ] }
|
||||
log = "0.3"
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
use immeta::load_from_buf;
|
||||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use ipc_channel::router::ROUTER;
|
||||
use net_traits::image::base::{Image, ImageMetadata, load_from_memory};
|
||||
use net_traits::image::base::{Image, ImageMetadata, load_from_memory, PixelFormat};
|
||||
use net_traits::image_cache_thread::ImageResponder;
|
||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheCommand, ImageCacheThread, ImageState};
|
||||
use net_traits::image_cache_thread::{ImageCacheResult, ImageOrMetadataAvailable, ImageResponse, UsePlaceholder};
|
||||
|
@ -23,6 +23,7 @@ use url::Url;
|
|||
use util::resource_files::resources_dir_path;
|
||||
use util::thread::spawn_named;
|
||||
use util::threadpool::ThreadPool;
|
||||
use webrender_traits;
|
||||
|
||||
///
|
||||
/// TODO(gw): Remaining work on image cache:
|
||||
|
@ -51,6 +52,12 @@ struct PendingLoad {
|
|||
url: Arc<Url>
|
||||
}
|
||||
|
||||
enum LoadResult {
|
||||
Loaded(Image),
|
||||
PlaceholderLoaded(Arc<Image>),
|
||||
None
|
||||
}
|
||||
|
||||
impl PendingLoad {
|
||||
fn new(url: Arc<Url>) -> PendingLoad {
|
||||
PendingLoad {
|
||||
|
@ -250,6 +257,9 @@ struct ImageCache {
|
|||
|
||||
// The placeholder image used when an image fails to load
|
||||
placeholder_image: Option<Arc<Image>>,
|
||||
|
||||
// Webrender API instance, if enabled.
|
||||
webrender_api: Option<webrender_traits::RenderApi>,
|
||||
}
|
||||
|
||||
/// Message that the decoder worker threads send to main image cache thread.
|
||||
|
@ -265,6 +275,16 @@ enum SelectResult {
|
|||
Decoder(DecoderMsg),
|
||||
}
|
||||
|
||||
fn convert_format(format: PixelFormat) -> webrender_traits::ImageFormat {
|
||||
match format {
|
||||
PixelFormat::K8 | PixelFormat::KA8 => {
|
||||
panic!("Not support by webrender yet");
|
||||
}
|
||||
PixelFormat::RGB8 => webrender_traits::ImageFormat::RGB8,
|
||||
PixelFormat::RGBA8 => webrender_traits::ImageFormat::RGBA8,
|
||||
}
|
||||
}
|
||||
|
||||
impl ImageCache {
|
||||
fn run(&mut self) {
|
||||
let mut exit_sender: Option<IpcSender<()>> = None;
|
||||
|
@ -381,10 +401,10 @@ impl ImageCache {
|
|||
Err(_) => {
|
||||
match self.placeholder_image.clone() {
|
||||
Some(placeholder_image) => {
|
||||
self.complete_load(msg.key, ImageResponse::PlaceholderLoaded(
|
||||
self.complete_load(msg.key, LoadResult::PlaceholderLoaded(
|
||||
placeholder_image))
|
||||
}
|
||||
None => self.complete_load(msg.key, ImageResponse::None),
|
||||
None => self.complete_load(msg.key, LoadResult::None),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -395,16 +415,34 @@ impl ImageCache {
|
|||
// Handle a message from one of the decoder worker threads
|
||||
fn handle_decoder(&mut self, msg: DecoderMsg) {
|
||||
let image = match msg.image {
|
||||
None => ImageResponse::None,
|
||||
Some(image) => ImageResponse::Loaded(Arc::new(image)),
|
||||
None => LoadResult::None,
|
||||
Some(image) => LoadResult::Loaded(image),
|
||||
};
|
||||
self.complete_load(msg.key, image);
|
||||
}
|
||||
|
||||
// Change state of a url from pending -> loaded.
|
||||
fn complete_load(&mut self, key: LoadKey, image_response: ImageResponse) {
|
||||
fn complete_load(&mut self, key: LoadKey, mut load_result: LoadResult) {
|
||||
let pending_load = self.pending_loads.remove(&key).unwrap();
|
||||
|
||||
if let Some(ref webrender_api) = self.webrender_api {
|
||||
match load_result {
|
||||
LoadResult::Loaded(ref mut image) => {
|
||||
let format = convert_format(image.format);
|
||||
let mut bytes = Vec::new();
|
||||
bytes.extend_from_slice(&*image.bytes);
|
||||
image.id = Some(webrender_api.add_image(image.width, image.height, format, bytes));
|
||||
}
|
||||
LoadResult::PlaceholderLoaded(..) | LoadResult::None => {}
|
||||
}
|
||||
}
|
||||
|
||||
let image_response = match load_result {
|
||||
LoadResult::Loaded(image) => ImageResponse::Loaded(Arc::new(image)),
|
||||
LoadResult::PlaceholderLoaded(image) => ImageResponse::PlaceholderLoaded(image),
|
||||
LoadResult::None => ImageResponse::None,
|
||||
};
|
||||
|
||||
let completed_load = CompletedLoad::new(image_response.clone());
|
||||
self.completed_loads.insert(pending_load.url, completed_load);
|
||||
|
||||
|
@ -510,7 +548,8 @@ impl ImageCache {
|
|||
}
|
||||
|
||||
/// Create a new image cache.
|
||||
pub fn new_image_cache_thread(resource_thread: ResourceThread) -> ImageCacheThread {
|
||||
pub fn new_image_cache_thread(resource_thread: ResourceThread,
|
||||
webrender_api: Option<webrender_traits::RenderApi>) -> ImageCacheThread {
|
||||
let (ipc_command_sender, ipc_command_receiver) = ipc::channel().unwrap();
|
||||
let (progress_sender, progress_receiver) = channel();
|
||||
let (decoder_sender, decoder_receiver) = channel();
|
||||
|
@ -526,7 +565,14 @@ pub fn new_image_cache_thread(resource_thread: ResourceThread) -> ImageCacheThre
|
|||
file.read_to_end(&mut image_data)
|
||||
});
|
||||
let placeholder_image = result.ok().map(|_| {
|
||||
Arc::new(load_from_memory(&image_data).unwrap())
|
||||
let mut image = load_from_memory(&image_data).unwrap();
|
||||
if let Some(ref webrender_api) = webrender_api {
|
||||
let format = convert_format(image.format);
|
||||
let mut bytes = Vec::new();
|
||||
bytes.extend_from_slice(&*image.bytes);
|
||||
image.id = Some(webrender_api.add_image(image.width, image.height, format, bytes));
|
||||
}
|
||||
Arc::new(image)
|
||||
});
|
||||
|
||||
// Ask the router to proxy messages received over IPC to us.
|
||||
|
@ -543,6 +589,7 @@ pub fn new_image_cache_thread(resource_thread: ResourceThread) -> ImageCacheThre
|
|||
completed_loads: HashMap::new(),
|
||||
resource_thread: resource_thread,
|
||||
placeholder_image: placeholder_image,
|
||||
webrender_api: webrender_api,
|
||||
};
|
||||
|
||||
cache.run();
|
||||
|
|
|
@ -27,6 +27,7 @@ extern crate time;
|
|||
extern crate url;
|
||||
extern crate util;
|
||||
extern crate uuid;
|
||||
extern crate webrender_traits;
|
||||
extern crate websocket;
|
||||
|
||||
pub mod about_loader;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
use ipc_channel::ipc::IpcSharedMemory;
|
||||
use piston_image::{self, DynamicImage, GenericImage, ImageFormat};
|
||||
use stb_image::image as stb_image2;
|
||||
use util::opts;
|
||||
use util::vec::byte_swap;
|
||||
|
||||
pub use msg::constellation_msg::{Image, ImageMetadata, PixelFormat};
|
||||
|
@ -15,14 +16,25 @@ pub use msg::constellation_msg::{Image, ImageMetadata, PixelFormat};
|
|||
// TODO(pcwalton): Speed up with SIMD, or better yet, find some way to not do this.
|
||||
fn byte_swap_and_premultiply(data: &mut [u8]) {
|
||||
let length = data.len();
|
||||
|
||||
// No need to pre-multiply alpha when using direct GPU rendering.
|
||||
let premultiply_alpha = !opts::get().use_webrender;
|
||||
|
||||
for i in (0..length).step_by(4) {
|
||||
let r = data[i + 2];
|
||||
let g = data[i + 1];
|
||||
let b = data[i + 0];
|
||||
let a = data[i + 3];
|
||||
data[i + 0] = ((r as u32) * (a as u32) / 255) as u8;
|
||||
data[i + 1] = ((g as u32) * (a as u32) / 255) as u8;
|
||||
data[i + 2] = ((b as u32) * (a as u32) / 255) as u8;
|
||||
|
||||
if premultiply_alpha {
|
||||
data[i + 0] = ((r as u32) * (a as u32) / 255) as u8;
|
||||
data[i + 1] = ((g as u32) * (a as u32) / 255) as u8;
|
||||
data[i + 2] = ((b as u32) * (a as u32) / 255) as u8;
|
||||
} else {
|
||||
data[i + 0] = r;
|
||||
data[i + 1] = g;
|
||||
data[i + 2] = b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -58,6 +70,7 @@ pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
|
|||
height: image.height as u32,
|
||||
format: PixelFormat::RGBA8,
|
||||
bytes: IpcSharedMemory::from_bytes(&image.data[..]),
|
||||
id: None,
|
||||
})
|
||||
}
|
||||
stb_image2::LoadResult::ImageF32(_image) => {
|
||||
|
@ -83,6 +96,7 @@ pub fn load_from_memory(buffer: &[u8]) -> Option<Image> {
|
|||
height: rgba.height(),
|
||||
format: PixelFormat::RGBA8,
|
||||
bytes: IpcSharedMemory::from_bytes(&*rgba),
|
||||
id: None,
|
||||
})
|
||||
}
|
||||
Err(e) => {
|
||||
|
|
|
@ -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_traits::{CanvasMsg, FromLayoutMsg};
|
||||
use canvas_traits::{CanvasMsg, FromLayoutMsg, CanvasData};
|
||||
use dom::attr::Attr;
|
||||
use dom::attr::AttrValue;
|
||||
use dom::bindings::cell::DOMRefCell;
|
||||
|
@ -202,10 +202,17 @@ impl HTMLCanvasElement {
|
|||
|
||||
let data = if let Some(renderer) = self.ipc_renderer() {
|
||||
let (sender, receiver) = ipc::channel().unwrap();
|
||||
let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender));
|
||||
let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendData(sender));
|
||||
renderer.send(msg).unwrap();
|
||||
|
||||
receiver.recv().unwrap().to_vec()
|
||||
match receiver.recv().unwrap() {
|
||||
CanvasData::Pixels(pixel_data)
|
||||
=> pixel_data.image_data.to_vec(),
|
||||
CanvasData::WebGL(_)
|
||||
// TODO(ecoal95): Not sure if WebGL canvas is required for 2d spec,
|
||||
// but I think it's not.
|
||||
=> return None,
|
||||
}
|
||||
} else {
|
||||
repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect()
|
||||
};
|
||||
|
|
|
@ -72,6 +72,7 @@ pub struct WebGLRenderingContext {
|
|||
#[ignore_heap_size_of = "Defined in ipc-channel"]
|
||||
ipc_renderer: IpcSender<CanvasMsg>,
|
||||
canvas: JS<HTMLCanvasElement>,
|
||||
#[ignore_heap_size_of = "Defined in webrender_traits"]
|
||||
last_error: Cell<Option<WebGLError>>,
|
||||
texture_unpacking_settings: Cell<TextureUnpacking>,
|
||||
bound_texture_2d: MutNullableHeap<JS<WebGLTexture>>,
|
||||
|
@ -462,6 +463,7 @@ impl WebGLRenderingContextMethods for WebGLRenderingContext {
|
|||
Some(data) => data,
|
||||
None => return self.webgl_error(InvalidValue),
|
||||
};
|
||||
|
||||
if offset < 0 {
|
||||
return self.webgl_error(InvalidValue);
|
||||
}
|
||||
|
|
88
components/servo/Cargo.lock
generated
88
components/servo/Cargo.lock
generated
|
@ -15,7 +15,7 @@ dependencies = [
|
|||
"gaol 0.0.1 (git+https://github.com/servo/gaol)",
|
||||
"gfx 0.0.1",
|
||||
"gfx_tests 0.0.1",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin_app 0.0.1",
|
||||
"image 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
|
@ -42,6 +42,8 @@ dependencies = [
|
|||
"util 0.0.1",
|
||||
"util_tests 0.0.1",
|
||||
"webdriver_server 0.0.1",
|
||||
"webrender 0.1.0 (git+https://github.com/glennw/webrender)",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -152,7 +154,7 @@ dependencies = [
|
|||
"canvas_traits 0.0.1",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx_traits 0.0.1",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"layers 0.2.2 (git+https://github.com/servo/rust-layers)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -160,6 +162,7 @@ dependencies = [
|
|||
"offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)",
|
||||
"plugins 0.0.1",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -179,6 +182,7 @@ dependencies = [
|
|||
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -200,7 +204,7 @@ name = "cgl"
|
|||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -273,7 +277,7 @@ dependencies = [
|
|||
"gaol 0.0.1 (git+https://github.com/servo/gaol)",
|
||||
"gfx 0.0.1",
|
||||
"gfx_traits 0.0.1",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"layers 0.2.2 (git+https://github.com/servo/rust-layers)",
|
||||
|
@ -292,6 +296,8 @@ dependencies = [
|
|||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender 0.1.0 (git+https://github.com/glennw/webrender)",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -680,6 +686,7 @@ dependencies = [
|
|||
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -728,7 +735,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gleam"
|
||||
version = "0.2.3"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gl_generator 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -748,7 +755,7 @@ dependencies = [
|
|||
"cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"compositing 0.0.1",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.2.2 (git+https://github.com/servo/rust-layers)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
|
@ -904,7 +911,7 @@ dependencies = [
|
|||
"cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -965,7 +972,7 @@ dependencies = [
|
|||
"cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_plugin 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1018,6 +1025,7 @@ dependencies = [
|
|||
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1034,6 +1042,7 @@ dependencies = [
|
|||
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1194,6 +1203,7 @@ dependencies = [
|
|||
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1218,6 +1228,7 @@ dependencies = [
|
|||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
"websocket 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -1334,7 +1345,7 @@ dependencies = [
|
|||
"core-foundation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gl_generator 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1559,6 +1570,22 @@ name = "rustc-serialize"
|
|||
version = "0.3.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped_threadpool"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc_version 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "script"
|
||||
version = "0.0.1"
|
||||
|
@ -1659,6 +1686,11 @@ dependencies = [
|
|||
"string_cache 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "0.6.6"
|
||||
|
@ -1766,7 +1798,7 @@ dependencies = [
|
|||
"cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"expat-sys 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"io-surface 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2174,6 +2206,42 @@ dependencies = [
|
|||
"webdriver 0.4.0 (git+https://github.com/jgraham/webdriver-rust.git)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webrender"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/glennw/webrender#90cd6afdd64cdb48f606dbe0ce5d1ac352329004"
|
||||
dependencies = [
|
||||
"app_units 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-text 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)",
|
||||
"scoped_threadpool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webrender_traits"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/glennw/webrender_traits#8ccc1608590d219d1df54e49f2f1e887995b4d60"
|
||||
dependencies = [
|
||||
"app_units 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)",
|
||||
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "websocket"
|
||||
version = "0.14.0"
|
||||
|
|
|
@ -52,6 +52,12 @@ name = "reftest"
|
|||
path = "../../tests/reftest.rs"
|
||||
harness = false
|
||||
|
||||
[dependencies.webrender_traits]
|
||||
git = "https://github.com/glennw/webrender_traits"
|
||||
|
||||
[dependencies.webrender]
|
||||
git = "https://github.com/glennw/webrender"
|
||||
|
||||
[features]
|
||||
default = ["glutin_app", "window", "webdriver"]
|
||||
window = ["glutin_app/window"]
|
||||
|
|
|
@ -48,6 +48,9 @@ mod export {
|
|||
#[cfg(feature = "webdriver")]
|
||||
extern crate webdriver_server;
|
||||
|
||||
extern crate webrender;
|
||||
extern crate webrender_traits;
|
||||
|
||||
#[cfg(feature = "webdriver")]
|
||||
fn webdriver(port: u16, constellation: Sender<ConstellationMsg>) {
|
||||
webdriver_server::start_server(port, constellation);
|
||||
|
@ -82,6 +85,7 @@ use std::borrow::Borrow;
|
|||
use std::rc::Rc;
|
||||
use std::sync::mpsc::Sender;
|
||||
use util::opts;
|
||||
use util::resource_files::resources_dir_path;
|
||||
|
||||
pub use _util as util;
|
||||
pub use export::canvas;
|
||||
|
@ -147,6 +151,35 @@ impl Browser {
|
|||
devtools::start_server(port)
|
||||
});
|
||||
|
||||
let (webrender, webrender_api_sender) = if opts::get().use_webrender {
|
||||
let mut resource_path = resources_dir_path();
|
||||
resource_path.push("shaders");
|
||||
|
||||
// TODO(gw): Duplicates device_pixels_per_screen_px from compositor. Tidy up!
|
||||
let hidpi_factor = window.as_ref()
|
||||
.map(|window| window.hidpi_factor().get())
|
||||
.unwrap_or(1.0);
|
||||
let device_pixel_ratio = match opts.device_pixels_per_px {
|
||||
Some(device_pixels_per_px) => device_pixels_per_px,
|
||||
None => match opts.output_file {
|
||||
Some(_) => 1.0,
|
||||
None => hidpi_factor,
|
||||
}
|
||||
};
|
||||
|
||||
let (webrender, webrender_sender) =
|
||||
webrender::Renderer::new(webrender::RendererOptions {
|
||||
device_pixel_ratio: device_pixel_ratio,
|
||||
resource_path: resource_path,
|
||||
enable_aa: opts.enable_text_antialiasing,
|
||||
enable_msaa: opts.use_msaa,
|
||||
enable_profiler: opts.webrender_stats,
|
||||
});
|
||||
(Some(webrender), Some(webrender_sender))
|
||||
} else {
|
||||
(None, None)
|
||||
};
|
||||
|
||||
// Create the constellation, which maintains the engine
|
||||
// pipelines, including the script and layout threads, as well
|
||||
// as the navigation context.
|
||||
|
@ -155,7 +188,8 @@ impl Browser {
|
|||
time_profiler_chan.clone(),
|
||||
mem_profiler_chan.clone(),
|
||||
devtools_chan,
|
||||
supports_clipboard);
|
||||
supports_clipboard,
|
||||
webrender_api_sender.clone());
|
||||
|
||||
if cfg!(feature = "webdriver") {
|
||||
if let Some(port) = opts.webdriver_port {
|
||||
|
@ -171,6 +205,8 @@ impl Browser {
|
|||
constellation_chan: constellation_chan,
|
||||
time_profiler_chan: time_profiler_chan,
|
||||
mem_profiler_chan: mem_profiler_chan,
|
||||
webrender: webrender,
|
||||
webrender_api_sender: webrender_api_sender,
|
||||
});
|
||||
|
||||
Browser {
|
||||
|
@ -200,11 +236,13 @@ fn create_constellation(opts: opts::Opts,
|
|||
time_profiler_chan: time::ProfilerChan,
|
||||
mem_profiler_chan: mem::ProfilerChan,
|
||||
devtools_chan: Option<Sender<devtools_traits::DevtoolsControlMsg>>,
|
||||
supports_clipboard: bool) -> Sender<ConstellationMsg> {
|
||||
supports_clipboard: bool,
|
||||
webrender_api_sender: Option<webrender_traits::RenderApiSender>) -> Sender<ConstellationMsg> {
|
||||
let resource_thread = new_resource_thread(opts.user_agent.clone(), devtools_chan.clone());
|
||||
|
||||
let image_cache_thread = new_image_cache_thread(resource_thread.clone());
|
||||
let font_cache_thread = FontCacheThread::new(resource_thread.clone());
|
||||
let image_cache_thread = new_image_cache_thread(resource_thread.clone(),
|
||||
webrender_api_sender.as_ref().map(|wr| wr.create_api()));
|
||||
let font_cache_thread = FontCacheThread::new(resource_thread.clone(),
|
||||
webrender_api_sender.as_ref().map(|wr| wr.create_api()));
|
||||
let storage_thread: StorageThread = StorageThreadFactory::new();
|
||||
|
||||
let initial_state = InitialConstellationState {
|
||||
|
@ -217,6 +255,7 @@ fn create_constellation(opts: opts::Opts,
|
|||
time_profiler_chan: time_profiler_chan,
|
||||
mem_profiler_chan: mem_profiler_chan,
|
||||
supports_clipboard: supports_clipboard,
|
||||
webrender_api_sender: webrender_api_sender,
|
||||
};
|
||||
let constellation_chan =
|
||||
Constellation::<layout::layout_thread::LayoutThread,
|
||||
|
|
|
@ -183,6 +183,15 @@ pub struct Opts {
|
|||
|
||||
/// Enable vsync in the compositor
|
||||
pub enable_vsync: bool,
|
||||
|
||||
/// True to enable the webrender painting/compositing backend.
|
||||
pub use_webrender: bool,
|
||||
|
||||
/// True to show webrender profiling stats on screen.
|
||||
pub webrender_stats: bool,
|
||||
|
||||
/// True if WebRender should use multisample antialiasing.
|
||||
pub use_msaa: bool,
|
||||
}
|
||||
|
||||
fn print_usage(app: &str, opts: &Options) {
|
||||
|
@ -272,6 +281,12 @@ pub struct DebugOptions {
|
|||
|
||||
/// Disable vsync in the compositor
|
||||
pub disable_vsync: bool,
|
||||
|
||||
/// Show webrender profiling stats on screen.
|
||||
pub webrender_stats: bool,
|
||||
|
||||
/// Use multisample antialiasing in WebRender.
|
||||
pub use_msaa: bool,
|
||||
}
|
||||
|
||||
|
||||
|
@ -307,6 +322,8 @@ impl DebugOptions {
|
|||
"gc-profile" => debug_options.gc_profile = true,
|
||||
"load-webfonts-synchronously" => debug_options.load_webfonts_synchronously = true,
|
||||
"disable-vsync" => debug_options.disable_vsync = true,
|
||||
"wr-stats" => debug_options.webrender_stats = true,
|
||||
"msaa" => debug_options.use_msaa = true,
|
||||
"" => {},
|
||||
_ => return Err(option)
|
||||
};
|
||||
|
@ -354,6 +371,8 @@ pub fn print_debug_usage(app: &str) -> ! {
|
|||
"Load web fonts synchronously to avoid non-deterministic network-driven reflows");
|
||||
print_option("disable-vsync",
|
||||
"Disable vsync mode in the compositor to allow profiling at more than monitor refresh rate");
|
||||
print_option("wr-stats", "Show WebRender profiler on screen.");
|
||||
print_option("msaa", "Use multisample antialiasing in WebRender.");
|
||||
|
||||
println!("");
|
||||
|
||||
|
@ -483,6 +502,9 @@ pub fn default_opts() -> Opts {
|
|||
exit_after_load: false,
|
||||
no_native_titlebar: false,
|
||||
enable_vsync: true,
|
||||
use_webrender: false,
|
||||
webrender_stats: false,
|
||||
use_msaa: false,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -526,6 +548,7 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
opts.optmulti("", "pref",
|
||||
"A preference to set to enable", "dom.mozbrowser.enabled");
|
||||
opts.optflag("b", "no-native-titlebar", "Do not use native titlebar");
|
||||
opts.optflag("w", "webrender", "Use webrender backend");
|
||||
|
||||
let opt_match = match opts.parse(args) {
|
||||
Ok(m) => m,
|
||||
|
@ -668,6 +691,8 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
(contents, url)
|
||||
}).collect();
|
||||
|
||||
let use_webrender = opt_match.opt_present("w") && !opt_match.opt_present("z");
|
||||
|
||||
let opts = Opts {
|
||||
is_running_problem_test: is_running_problem_test,
|
||||
url: Some(url),
|
||||
|
@ -717,6 +742,9 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
|
|||
exit_after_load: opt_match.opt_present("x"),
|
||||
no_native_titlebar: opt_match.opt_present("b"),
|
||||
enable_vsync: !debug_options.disable_vsync,
|
||||
use_webrender: use_webrender,
|
||||
webrender_stats: debug_options.webrender_stats,
|
||||
use_msaa: debug_options.use_msaa,
|
||||
};
|
||||
|
||||
set_defaults(opts);
|
||||
|
|
90
ports/cef/Cargo.lock
generated
90
ports/cef/Cargo.lock
generated
|
@ -12,7 +12,7 @@ dependencies = [
|
|||
"devtools 0.0.1",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx 0.0.1",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin_app 0.0.1",
|
||||
"js 0.1.2 (git+https://github.com/servo/rust-mozjs)",
|
||||
"layers 0.2.2 (git+https://github.com/servo/rust-layers)",
|
||||
|
@ -141,7 +141,7 @@ dependencies = [
|
|||
"canvas_traits 0.0.1",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx_traits 0.0.1",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"layers 0.2.2 (git+https://github.com/servo/rust-layers)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -149,6 +149,7 @@ dependencies = [
|
|||
"offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)",
|
||||
"plugins 0.0.1",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -168,6 +169,7 @@ dependencies = [
|
|||
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -189,7 +191,7 @@ name = "cgl"
|
|||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -247,7 +249,7 @@ dependencies = [
|
|||
"gaol 0.0.1 (git+https://github.com/servo/gaol)",
|
||||
"gfx 0.0.1",
|
||||
"gfx_traits 0.0.1",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"layers 0.2.2 (git+https://github.com/servo/rust-layers)",
|
||||
|
@ -266,6 +268,8 @@ dependencies = [
|
|||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender 0.1.0 (git+https://github.com/glennw/webrender)",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -621,6 +625,7 @@ dependencies = [
|
|||
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -660,7 +665,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gleam"
|
||||
version = "0.2.3"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gl_generator 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -680,7 +685,7 @@ dependencies = [
|
|||
"cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"compositing 0.0.1",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.2.2 (git+https://github.com/servo/rust-layers)",
|
||||
"msg 0.0.1",
|
||||
"net_traits 0.0.1",
|
||||
|
@ -836,7 +841,7 @@ dependencies = [
|
|||
"cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -897,7 +902,7 @@ dependencies = [
|
|||
"cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_plugin 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -950,6 +955,7 @@ dependencies = [
|
|||
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -966,6 +972,7 @@ dependencies = [
|
|||
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1126,6 +1133,7 @@ dependencies = [
|
|||
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1150,6 +1158,7 @@ dependencies = [
|
|||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
"websocket 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -1240,7 +1249,7 @@ dependencies = [
|
|||
"core-foundation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gl_generator 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1447,6 +1456,22 @@ name = "rustc-serialize"
|
|||
version = "0.3.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped_threadpool"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc_version 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "script"
|
||||
version = "0.0.1"
|
||||
|
@ -1538,6 +1563,11 @@ dependencies = [
|
|||
"string_cache 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "0.6.6"
|
||||
|
@ -1587,7 +1617,7 @@ dependencies = [
|
|||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gaol 0.0.1 (git+https://github.com/servo/gaol)",
|
||||
"gfx 0.0.1",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glutin_app 0.0.1",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"layers 0.2.2 (git+https://github.com/servo/rust-layers)",
|
||||
|
@ -1606,6 +1636,8 @@ dependencies = [
|
|||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webdriver_server 0.0.1",
|
||||
"webrender 0.1.0 (git+https://github.com/glennw/webrender)",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1680,7 +1712,7 @@ dependencies = [
|
|||
"cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"expat-sys 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"io-surface 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2060,6 +2092,42 @@ dependencies = [
|
|||
"webdriver 0.4.0 (git+https://github.com/jgraham/webdriver-rust.git)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webrender"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/glennw/webrender#90cd6afdd64cdb48f606dbe0ce5d1ac352329004"
|
||||
dependencies = [
|
||||
"app_units 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-text 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)",
|
||||
"scoped_threadpool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webrender_traits"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/glennw/webrender_traits#8ccc1608590d219d1df54e49f2f1e887995b4d60"
|
||||
dependencies = [
|
||||
"app_units 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)",
|
||||
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "websocket"
|
||||
version = "0.14.0"
|
||||
|
|
|
@ -68,6 +68,8 @@ const CMD_OR_ALT: constellation_msg::KeyModifiers = ALT;
|
|||
#[cfg(feature = "window")]
|
||||
const LINE_HEIGHT: f32 = 38.0;
|
||||
|
||||
const MULTISAMPLES: u16 = 16;
|
||||
|
||||
/// The type of a window.
|
||||
#[cfg(feature = "window")]
|
||||
pub struct Window {
|
||||
|
@ -88,18 +90,27 @@ impl Window {
|
|||
parent: Option<glutin::WindowID>) -> Rc<Window> {
|
||||
let width = window_size.to_untyped().width;
|
||||
let height = window_size.to_untyped().height;
|
||||
let mut builder = glutin::WindowBuilder::new().with_title("Servo".to_string())
|
||||
.with_decorations(!opts::get().no_native_titlebar)
|
||||
.with_dimensions(width, height)
|
||||
.with_gl(Window::gl_version())
|
||||
.with_visibility(is_foreground)
|
||||
.with_parent(parent)
|
||||
.with_multitouch();
|
||||
let mut builder =
|
||||
glutin::WindowBuilder::new().with_title("Servo".to_string())
|
||||
.with_decorations(!opts::get().no_native_titlebar)
|
||||
.with_dimensions(width, height)
|
||||
.with_gl(Window::gl_version())
|
||||
.with_visibility(is_foreground)
|
||||
.with_parent(parent)
|
||||
.with_multitouch();
|
||||
|
||||
if opts::get().enable_vsync {
|
||||
builder = builder.with_vsync();
|
||||
}
|
||||
|
||||
if opts::get().use_webrender {
|
||||
builder = builder.with_stencil_buffer(8);
|
||||
}
|
||||
|
||||
if opts::get().use_msaa {
|
||||
builder = builder.with_multisampling(MULTISAMPLES)
|
||||
}
|
||||
|
||||
let mut glutin_window = builder.build().unwrap();
|
||||
|
||||
unsafe { glutin_window.make_current().expect("Failed to make context current!") }
|
||||
|
@ -144,7 +155,11 @@ impl Window {
|
|||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn gl_version() -> GlRequest {
|
||||
GlRequest::Specific(Api::OpenGl, (2, 1))
|
||||
if opts::get().use_webrender {
|
||||
GlRequest::Specific(Api::OpenGl, (3, 2))
|
||||
} else {
|
||||
GlRequest::Specific(Api::OpenGl, (2, 1))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
|
@ -305,32 +320,49 @@ impl Window {
|
|||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
// TODO(gw): This is an awful hack to work around the
|
||||
// broken way we currently call X11 from multiple threads.
|
||||
//
|
||||
// On some (most?) X11 implementations, blocking here
|
||||
// with XPeekEvent results in the paint thread getting stuck
|
||||
// in XGetGeometry randomly. When this happens the result
|
||||
// is that until you trigger the XPeekEvent to return
|
||||
// (by moving the mouse over the window) the paint thread
|
||||
// never completes and you don't see the most recent
|
||||
// results.
|
||||
//
|
||||
// For now, poll events and sleep for ~1 frame if there
|
||||
// are no events. This means we don't spin the CPU at
|
||||
// 100% usage, but is far from ideal!
|
||||
//
|
||||
// See https://github.com/servo/servo/issues/5780
|
||||
//
|
||||
let first_event = self.window.poll_events().next();
|
||||
|
||||
match first_event {
|
||||
Some(event) => {
|
||||
self.handle_window_event(event)
|
||||
// WebRender can use the normal blocking event check and proper vsync,
|
||||
// because it doesn't call X11 functions from another thread, so doesn't
|
||||
// hit the same issues explained below.
|
||||
if opts::get().use_webrender {
|
||||
let event = self.window.wait_events().next().unwrap();
|
||||
let mut close = self.handle_window_event(event);
|
||||
if !close {
|
||||
while let Some(event) = self.window.poll_events().next() {
|
||||
if self.handle_window_event(event) {
|
||||
close = true;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
thread::sleep(Duration::from_millis(16));
|
||||
false
|
||||
close
|
||||
} else {
|
||||
// TODO(gw): This is an awful hack to work around the
|
||||
// broken way we currently call X11 from multiple threads.
|
||||
//
|
||||
// On some (most?) X11 implementations, blocking here
|
||||
// with XPeekEvent results in the paint thread getting stuck
|
||||
// in XGetGeometry randomly. When this happens the result
|
||||
// is that until you trigger the XPeekEvent to return
|
||||
// (by moving the mouse over the window) the paint thread
|
||||
// never completes and you don't see the most recent
|
||||
// results.
|
||||
//
|
||||
// For now, poll events and sleep for ~1 frame if there
|
||||
// are no events. This means we don't spin the CPU at
|
||||
// 100% usage, but is far from ideal!
|
||||
//
|
||||
// See https://github.com/servo/servo/issues/5780
|
||||
//
|
||||
let first_event = self.window.poll_events().next();
|
||||
|
||||
match first_event {
|
||||
Some(event) => {
|
||||
self.handle_window_event(event)
|
||||
}
|
||||
None => {
|
||||
thread::sleep(Duration::from_millis(16));
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
88
ports/gonk/Cargo.lock
generated
88
ports/gonk/Cargo.lock
generated
|
@ -8,7 +8,7 @@ dependencies = [
|
|||
"errno 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx 0.0.1",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"layers 0.2.2 (git+https://github.com/servo/rust-layers)",
|
||||
"layout 0.0.1",
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -133,7 +133,7 @@ dependencies = [
|
|||
"canvas_traits 0.0.1",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gfx_traits 0.0.1",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"layers 0.2.2 (git+https://github.com/servo/rust-layers)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -141,6 +141,7 @@ dependencies = [
|
|||
"offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)",
|
||||
"plugins 0.0.1",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -160,6 +161,7 @@ dependencies = [
|
|||
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -181,7 +183,7 @@ name = "cgl"
|
|||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -239,7 +241,7 @@ dependencies = [
|
|||
"gaol 0.0.1 (git+https://github.com/servo/gaol)",
|
||||
"gfx 0.0.1",
|
||||
"gfx_traits 0.0.1",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"image 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"layers 0.2.2 (git+https://github.com/servo/rust-layers)",
|
||||
|
@ -258,6 +260,8 @@ dependencies = [
|
|||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender 0.1.0 (git+https://github.com/glennw/webrender)",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -623,6 +627,7 @@ dependencies = [
|
|||
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -662,7 +667,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gleam"
|
||||
version = "0.2.3"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"gl_generator 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -817,7 +822,7 @@ dependencies = [
|
|||
"cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"leaky-cow 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
@ -878,7 +883,7 @@ dependencies = [
|
|||
"cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-foundation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"heapsize_plugin 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -931,6 +936,7 @@ dependencies = [
|
|||
"unicode-script 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -947,6 +953,7 @@ dependencies = [
|
|||
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1107,6 +1114,7 @@ dependencies = [
|
|||
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1131,6 +1139,7 @@ dependencies = [
|
|||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
"websocket 0.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
|
@ -1221,7 +1230,7 @@ dependencies = [
|
|||
"core-foundation 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gl_generator 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"khronos_api 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -1428,6 +1437,22 @@ name = "rustc-serialize"
|
|||
version = "0.3.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped_threadpool"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc_version 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "script"
|
||||
version = "0.0.1"
|
||||
|
@ -1519,6 +1544,11 @@ dependencies = [
|
|||
"string_cache 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "0.6.6"
|
||||
|
@ -1568,7 +1598,7 @@ dependencies = [
|
|||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gaol 0.0.1 (git+https://github.com/servo/gaol)",
|
||||
"gfx 0.0.1",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"layers 0.2.2 (git+https://github.com/servo/rust-layers)",
|
||||
"layout 0.0.1",
|
||||
|
@ -1585,6 +1615,8 @@ dependencies = [
|
|||
"style 0.0.1",
|
||||
"url 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"util 0.0.1",
|
||||
"webrender 0.1.0 (git+https://github.com/glennw/webrender)",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1659,7 +1691,7 @@ dependencies = [
|
|||
"cgl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"expat-sys 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"glx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"io-surface 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2008,6 +2040,42 @@ dependencies = [
|
|||
"wayland-client 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webrender"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/glennw/webrender#90cd6afdd64cdb48f606dbe0ce5d1ac352329004"
|
||||
dependencies = [
|
||||
"app_units 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-text 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"fnv 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"freetype 0.1.0 (git+https://github.com/servo/rust-freetype)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"lazy_static 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"num 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)",
|
||||
"scoped_threadpool 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"time 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"webrender_traits 0.1.0 (git+https://github.com/glennw/webrender_traits)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webrender_traits"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/glennw/webrender_traits#8ccc1608590d219d1df54e49f2f1e887995b4d60"
|
||||
dependencies = [
|
||||
"app_units 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core-graphics 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"gleam 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ipc-channel 0.2.0 (git+https://github.com/servo/ipc-channel)",
|
||||
"offscreen_gl_context 0.1.0 (git+https://github.com/ecoal95/rust-offscreen-rendering-context)",
|
||||
"serde 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_macros 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "websocket"
|
||||
version = "0.14.0"
|
||||
|
|
193
resources/shaders/blend.fs.glsl
Normal file
193
resources/shaders/blend.fs.glsl
Normal file
|
@ -0,0 +1,193 @@
|
|||
/* 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/. */
|
||||
|
||||
vec3 Multiply(vec3 Cb, vec3 Cs) {
|
||||
return Cb * Cs;
|
||||
}
|
||||
|
||||
vec3 Screen(vec3 Cb, vec3 Cs) {
|
||||
return Cb + Cs - (Cb * Cs);
|
||||
}
|
||||
|
||||
vec3 HardLight(vec3 Cb, vec3 Cs) {
|
||||
vec3 m = Multiply(Cb, 2.0 * Cs);
|
||||
vec3 s = Screen(Cb, 2.0 * Cs - 1.0);
|
||||
vec3 edge = vec3(0.5, 0.5, 0.5);
|
||||
return mix(m, s, step(edge, Cs));
|
||||
}
|
||||
|
||||
// TODO: Worth doing with mix/step? Check GLSL output.
|
||||
float ColorDodge(float Cb, float Cs) {
|
||||
if (Cb == 0.0)
|
||||
return 0.0;
|
||||
else if (Cs == 1.0)
|
||||
return 1.0;
|
||||
else
|
||||
return min(1.0, Cb / (1.0 - Cs));
|
||||
}
|
||||
|
||||
// TODO: Worth doing with mix/step? Check GLSL output.
|
||||
float ColorBurn(float Cb, float Cs) {
|
||||
if (Cb == 1.0)
|
||||
return 1.0;
|
||||
else if (Cs == 0.0)
|
||||
return 0.0;
|
||||
else
|
||||
return 1.0 - min(1.0, (1.0 - Cb) / Cs);
|
||||
}
|
||||
|
||||
float SoftLight(float Cb, float Cs) {
|
||||
if (Cs <= 0.5) {
|
||||
return Cb - (1.0 - 2.0 * Cs) * Cb * (1.0 - Cb);
|
||||
} else {
|
||||
float D;
|
||||
|
||||
if (Cb <= 0.25)
|
||||
D = ((16.0 * Cb - 12.0) * Cb + 4.0) * Cb;
|
||||
else
|
||||
D = sqrt(Cb);
|
||||
|
||||
return Cb + (2.0 * Cs - 1.0) * (D - Cb);
|
||||
}
|
||||
}
|
||||
|
||||
vec3 Difference(vec3 Cb, vec3 Cs) {
|
||||
return abs(Cb - Cs);
|
||||
}
|
||||
|
||||
vec3 Exclusion(vec3 Cb, vec3 Cs) {
|
||||
return Cb + Cs - 2.0 * Cb * Cs;
|
||||
}
|
||||
|
||||
// These functions below are taken from the spec.
|
||||
// There's probably a much quicker way to implement
|
||||
// them in GLSL...
|
||||
float Sat(vec3 c) {
|
||||
return max(c.r, max(c.g, c.b)) - min(c.r, min(c.g, c.b));
|
||||
}
|
||||
|
||||
float Lum(vec3 c) {
|
||||
vec3 f = vec3(0.3, 0.59, 0.11);
|
||||
return dot(c, f);
|
||||
}
|
||||
|
||||
vec3 ClipColor(vec3 C) {
|
||||
float L = Lum(C);
|
||||
float n = min(C.r, min(C.g, C.b));
|
||||
float x = max(C.r, max(C.g, C.b));
|
||||
|
||||
if (n < 0.0)
|
||||
C = L + (((C - L) * L) / (L - n));
|
||||
|
||||
if (x > 1.0)
|
||||
C = L + (((C - L) * (1.0 - L)) / (x - L));
|
||||
|
||||
return C;
|
||||
}
|
||||
|
||||
vec3 SetLum(vec3 C, float l) {
|
||||
float d = l - Lum(C);
|
||||
return ClipColor(C + d);
|
||||
}
|
||||
|
||||
void SetSatInner(inout float Cmin, inout float Cmid, inout float Cmax, float s) {
|
||||
if (Cmax > Cmin) {
|
||||
Cmid = (((Cmid - Cmin) * s) / (Cmax - Cmin));
|
||||
Cmax = s;
|
||||
} else {
|
||||
Cmid = 0.0;
|
||||
Cmax = 0.0;
|
||||
}
|
||||
Cmin = 0.0;
|
||||
}
|
||||
|
||||
vec3 SetSat(vec3 C, float s) {
|
||||
if (C.r <= C.g) {
|
||||
if (C.g <= C.b) {
|
||||
SetSatInner(C.r, C.g, C.b, s);
|
||||
} else {
|
||||
if (C.r <= C.b) {
|
||||
SetSatInner(C.r, C.b, C.g, s);
|
||||
} else {
|
||||
SetSatInner(C.b, C.r, C.g, s);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (C.r <= C.b) {
|
||||
SetSatInner(C.g, C.r, C.b, s);
|
||||
} else {
|
||||
if (C.g <= C.b) {
|
||||
SetSatInner(C.g, C.b, C.r, s);
|
||||
} else {
|
||||
SetSatInner(C.b, C.g, C.r, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
return C;
|
||||
}
|
||||
|
||||
vec3 Hue(vec3 Cb, vec3 Cs) {
|
||||
return SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb));
|
||||
}
|
||||
|
||||
vec3 Saturation(vec3 Cb, vec3 Cs) {
|
||||
return SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb));
|
||||
}
|
||||
|
||||
vec3 Color(vec3 Cb, vec3 Cs) {
|
||||
return SetLum(Cs, Lum(Cb));
|
||||
}
|
||||
|
||||
vec3 Luminosity(vec3 Cb, vec3 Cs) {
|
||||
return SetLum(Cb, Lum(Cs));
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec3 Cs = Texture(sDiffuse, vColorTexCoord).xyz;
|
||||
vec3 Cb = Texture(sMask, vMaskTexCoord).xyz;
|
||||
|
||||
// TODO: Relies on the ordering of MixBlendMode enum!
|
||||
// TODO: May be best to have separate shaders (esp. on Tegra)
|
||||
int blend_mode = int(uBlendParams.x);
|
||||
|
||||
// Return yellow if none of the branches match (shouldn't happen).
|
||||
vec3 result = vec3(1.0, 1.0, 0.0);
|
||||
|
||||
if (blend_mode == 2) {
|
||||
result = Screen(Cb, Cs);
|
||||
} else if (blend_mode == 3) {
|
||||
result = HardLight(Cs, Cb); // Overlay is inverse of Hardlight
|
||||
} else if (blend_mode == 6) {
|
||||
result.r = ColorDodge(Cb.r, Cs.r);
|
||||
result.g = ColorDodge(Cb.g, Cs.g);
|
||||
result.b = ColorDodge(Cb.b, Cs.b);
|
||||
} else if (blend_mode == 7) {
|
||||
result.r = ColorBurn(Cb.r, Cs.r);
|
||||
result.g = ColorBurn(Cb.g, Cs.g);
|
||||
result.b = ColorBurn(Cb.b, Cs.b);
|
||||
} else if (blend_mode == 8) {
|
||||
result = HardLight(Cb, Cs);
|
||||
} else if (blend_mode == 9) {
|
||||
result.r = SoftLight(Cb.r, Cs.r);
|
||||
result.g = SoftLight(Cb.g, Cs.g);
|
||||
result.b = SoftLight(Cb.b, Cs.b);
|
||||
} else if (blend_mode == 10) {
|
||||
result = Difference(Cb, Cs);
|
||||
} else if (blend_mode == 11) {
|
||||
result = Exclusion(Cb, Cs);
|
||||
} else if (blend_mode == 12) {
|
||||
result = Hue(Cb, Cs);
|
||||
} else if (blend_mode == 13) {
|
||||
result = Saturation(Cb, Cs);
|
||||
} else if (blend_mode == 14) {
|
||||
result = Color(Cb, Cs);
|
||||
} else if (blend_mode == 15) {
|
||||
result = Luminosity(Cb, Cs);
|
||||
}
|
||||
|
||||
// TODO: Handle output alpha correctly.
|
||||
SetFragColor(vec4(result, 1.0));
|
||||
}
|
||||
|
10
resources/shaders/blend.vs.glsl
Normal file
10
resources/shaders/blend.vs.glsl
Normal file
|
@ -0,0 +1,10 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vColorTexCoord = aColorTexCoordRectTop.xy;
|
||||
vMaskTexCoord = aMaskTexCoordRectTop.xy / 65535.0;
|
||||
gl_Position = uTransform * vec4(aPosition, 1.0);
|
||||
}
|
9
resources/shaders/blit.fs.glsl
Normal file
9
resources/shaders/blit.fs.glsl
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec4 diffuse = Texture(sDiffuse, vColorTexCoord);
|
||||
SetFragColor(diffuse * vColor);
|
||||
}
|
12
resources/shaders/blit.vs.glsl
Normal file
12
resources/shaders/blit.vs.glsl
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vColor = aColorRectTL / 255.0;
|
||||
vColorTexCoord = aColorTexCoordRectTop.xy;
|
||||
vec4 pos = vec4(aPosition, 1.0);
|
||||
pos.xy = SnapToPixels(pos.xy);
|
||||
gl_Position = uTransform * pos;
|
||||
}
|
44
resources/shaders/blur.fs.glsl
Normal file
44
resources/shaders/blur.fs.glsl
Normal file
|
@ -0,0 +1,44 @@
|
|||
/* 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/. */
|
||||
|
||||
// `vBorderPosition` is the position of the source texture in the atlas.
|
||||
|
||||
float gauss(float x, float sigma) {
|
||||
return (1.0 / sqrt(6.283185307179586 * sigma * sigma)) * exp(-(x * x) / (2.0 * sigma * sigma));
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
#ifdef SERVO_ES2
|
||||
// TODO(gw): for loops have to be unrollable on es2.
|
||||
SetFragColor(vec4(1.0, 0.0, 0.0, 1.0));
|
||||
#else
|
||||
vec2 sideOffsets = (vDestTextureSize - vSourceTextureSize) / 2.0;
|
||||
int range = int(vBlurRadius) * 3;
|
||||
float sigma = vBlurRadius / 2.0;
|
||||
vec4 value = vec4(0.0);
|
||||
vec2 sourceTextureUvOrigin = vBorderPosition.xy;
|
||||
vec2 sourceTextureUvSize = vBorderPosition.zw - sourceTextureUvOrigin;
|
||||
for (int offset = -range; offset <= range; offset++) {
|
||||
float offsetF = float(offset);
|
||||
vec2 lColorTexCoord = (vColorTexCoord.xy * vDestTextureSize - sideOffsets) /
|
||||
vSourceTextureSize;
|
||||
lColorTexCoord += vec2(offsetF) / vSourceTextureSize * uDirection;
|
||||
vec4 x = lColorTexCoord.x >= 0.0 &&
|
||||
lColorTexCoord.x <= 1.0 &&
|
||||
lColorTexCoord.y >= 0.0 &&
|
||||
lColorTexCoord.y <= 1.0 ?
|
||||
Texture(sDiffuse, lColorTexCoord * sourceTextureUvSize + sourceTextureUvOrigin) :
|
||||
vec4(0.0);
|
||||
|
||||
// Alpha must be premultiplied in order to properly blur the alpha channel.
|
||||
value += vec4(x.rgb * x.a, x.a) * gauss(offsetF, sigma);
|
||||
}
|
||||
|
||||
// Unpremultiply the alpha.
|
||||
value = vec4(value.rgb / value.a, value.a);
|
||||
|
||||
SetFragColor(value);
|
||||
#endif
|
||||
}
|
||||
|
14
resources/shaders/blur.vs.glsl
Normal file
14
resources/shaders/blur.vs.glsl
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vColorTexCoord = aColorTexCoordRectTop.xy;
|
||||
vBorderPosition = aBorderPosition;
|
||||
vBlurRadius = aBlurRadius;
|
||||
vDestTextureSize = aDestTextureSize;
|
||||
vSourceTextureSize = aSourceTextureSize;
|
||||
gl_Position = uTransform * vec4(aPosition, 1.0);
|
||||
}
|
||||
|
41
resources/shaders/border.fs.glsl
Normal file
41
resources/shaders/border.fs.glsl
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* 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/. */
|
||||
|
||||
/*
|
||||
Ellipse equation:
|
||||
|
||||
(x-h)^2 (y-k)^2
|
||||
------- + ------- <= 1
|
||||
rx^2 ry^2
|
||||
|
||||
*/
|
||||
|
||||
float Value(vec2 position) {
|
||||
float outer_rx = vBorderRadii.x;
|
||||
float outer_ry = vBorderRadii.y;
|
||||
float outer_dx = position.x * position.x / (outer_rx * outer_rx);
|
||||
float outer_dy = position.y * position.y / (outer_ry * outer_ry);
|
||||
if (outer_dx + outer_dy > 1.0)
|
||||
return 0.0;
|
||||
|
||||
float inner_rx = vBorderRadii.z;
|
||||
float inner_ry = vBorderRadii.w;
|
||||
if (inner_rx == 0.0 || inner_ry == 0.0)
|
||||
return 1.0;
|
||||
|
||||
float inner_dx = position.x * position.x / (inner_rx * inner_rx);
|
||||
float inner_dy = position.y * position.y / (inner_ry * inner_ry);
|
||||
return inner_dx + inner_dy >= 1.0 ? 1.0 : 0.0;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec2 position = vPosition - vBorderPosition.xy;
|
||||
vec4 pixelBounds = vec4(floor(position.x), floor(position.y),
|
||||
ceil(position.x), ceil(position.y));
|
||||
float value = (Value(pixelBounds.xy) + Value(pixelBounds.zy) +
|
||||
Value(pixelBounds.xw) + Value(pixelBounds.zw)) / 4.0;
|
||||
SetFragColor(vec4(vColor.rgb, mix(1.0 - vColor.a, vColor.a, value)));
|
||||
}
|
||||
|
12
resources/shaders/border.vs.glsl
Normal file
12
resources/shaders/border.vs.glsl
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vColor = aColorRectTL;
|
||||
vPosition = aPosition.xy;
|
||||
vBorderPosition = aBorderPosition;
|
||||
vBorderRadii = aBorderRadii;
|
||||
gl_Position = uTransform * vec4(aPosition, 1.0);
|
||||
}
|
146
resources/shaders/box_shadow.fs.glsl
Normal file
146
resources/shaders/box_shadow.fs.glsl
Normal file
|
@ -0,0 +1,146 @@
|
|||
/* 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/. */
|
||||
|
||||
// See http://asciimath.org to render the equations here.
|
||||
|
||||
// The Gaussian function used for blurring:
|
||||
//
|
||||
// G_sigma(x) = 1/sqrt(2 pi sigma^2) e^(-x^2/(2 sigma^2))
|
||||
float gauss(float x, float sigma) {
|
||||
float sigmaPow2 = sigma * sigma;
|
||||
return 1.0 / sqrt(6.283185307179586 * sigmaPow2) * exp(-(x * x) / (2.0 * sigmaPow2));
|
||||
}
|
||||
|
||||
// An approximation of the error function, which is related to the integral of the Gaussian
|
||||
// function:
|
||||
//
|
||||
// "erf"(x) = 2/sqrt(pi) int_0^x e^(-t^2) dt
|
||||
// ~~ 1 - 1 / (1 + a_1 x + a_2 x^2 + a_3 x^3 + a_4 x^4)^4
|
||||
//
|
||||
// where:
|
||||
//
|
||||
// a_1 = 0.278393, a_2 = 0.230389, a_3 = 0.000972, a_4 = 0.078108
|
||||
//
|
||||
// This approximation is accurate to `5 xx 10^-4`, more than accurate enough for our purposes.
|
||||
//
|
||||
// See: https://en.wikipedia.org/wiki/Error_function#Approximation_with_elementary_functions
|
||||
float erf(float x) {
|
||||
bool negative = x < 0.0;
|
||||
if (negative)
|
||||
x = -x;
|
||||
float x2 = x * x;
|
||||
float x3 = x2 * x;
|
||||
float x4 = x2 * x2;
|
||||
float denom = 1.0 + 0.278393 * x + 0.230389 * x2 + 0.000972 * x3 + 0.078108 * x4;
|
||||
float result = 1.0 - 1.0 / (denom * denom * denom * denom);
|
||||
return negative ? -result : result;
|
||||
}
|
||||
|
||||
// A useful helper for calculating integrals of the Gaussian function via the error function:
|
||||
//
|
||||
// "erf"_sigma(x) = 2 int 1/sqrt(2 pi sigma^2) e^(-x^2/(2 sigma^2)) dx
|
||||
// = "erf"(x/(sigma sqrt(2)))
|
||||
float erfSigma(float x, float sigma) {
|
||||
return erf(x / (sigma * 1.4142135623730951));
|
||||
}
|
||||
|
||||
// Returns the blurred color value from the box itself (not counting any rounded corners). `p_0` is
|
||||
// the vector distance to the top left corner of the box; `p_1` is the vector distance to its
|
||||
// bottom right corner.
|
||||
//
|
||||
// "colorFromRect"_sigma(p_0, p_1)
|
||||
// = int_{p_{0_y}}^{p_{1_y}} int_{p_{1_x}}^{p_{0_x}} G_sigma(y) G_sigma(x) dx dy
|
||||
// = 1/4 ("erf"_sigma(p_{1_x}) - "erf"_sigma(p_{0_x}))
|
||||
// ("erf"_sigma(p_{1_y}) - "erf"_sigma(p_{0_y}))
|
||||
float colorFromRect(vec2 p0, vec2 p1, float sigma) {
|
||||
return (erfSigma(p1.x, sigma) - erfSigma(p0.x, sigma)) *
|
||||
(erfSigma(p1.y, sigma) - erfSigma(p0.y, sigma)) / 4.0;
|
||||
}
|
||||
|
||||
// Returns the `x` coordinate on the ellipse with the given radii for the given `y` coordinate:
|
||||
//
|
||||
// "ellipsePoint"(y, y_0, a, b) = a sqrt(1 - ((y - y_0) / b)^2)
|
||||
float ellipsePoint(float y, float y0, vec2 radii) {
|
||||
float bStep = (y - y0) / radii.y;
|
||||
return radii.x * sqrt(1.0 - bStep * bStep);
|
||||
}
|
||||
|
||||
// A helper function to compute the value that needs to be subtracted to accommodate the border
|
||||
// corners.
|
||||
//
|
||||
// "colorCutout"_sigma(x_{0_l}, x_{0_r}, y_0, y_{min}, y_{max}, a, b)
|
||||
// = int_{y_{min}}^{y_{max}}
|
||||
// int_{x_{0_r} + "ellipsePoint"(y, y_0, a, b)}^{x_{0_r} + a} G_sigma(y) G_sigma(x) dx
|
||||
// + int_{x_{0_l} - a}^{x_{0_l} - "ellipsePoint"(y, y_0, a, b)} G_sigma(y) G_sigma(x)
|
||||
// dx dy
|
||||
// = int_{y_{min}}^{y_{max}} 1/2 G_sigma(y)
|
||||
// ("erf"_sigma(x_{0_r} + a) - "erf"_sigma(x_{0_r} + "ellipsePoint"(y, y_0, a, b)) +
|
||||
// "erf"_sigma(x_{0_l} - "ellipsePoint"(y, y_0, a, b)) - "erf"_sigma(x_{0_l} - a))
|
||||
//
|
||||
// with the outer integral evaluated numerically.
|
||||
float colorCutoutGeneral(float x0l,
|
||||
float x0r,
|
||||
float y0,
|
||||
float yMin,
|
||||
float yMax,
|
||||
vec2 radii,
|
||||
float sigma) {
|
||||
float sum = 0.0;
|
||||
for (float y = yMin; y <= yMax; y += 1.0) {
|
||||
float xEllipsePoint = ellipsePoint(y, y0, radii);
|
||||
sum += gauss(y, sigma) *
|
||||
(erfSigma(x0r + radii.x, sigma) - erfSigma(x0r + xEllipsePoint, sigma) +
|
||||
erfSigma(x0l - xEllipsePoint, sigma) - erfSigma(x0l - radii.x, sigma));
|
||||
}
|
||||
return sum / 2.0;
|
||||
}
|
||||
|
||||
// The value that needs to be subtracted to accommodate the top border corners.
|
||||
float colorCutoutTop(float x0l, float x0r, float y0, vec2 radii, float sigma) {
|
||||
return colorCutoutGeneral(x0l, x0r, y0, y0, y0 + radii.y, radii, sigma);
|
||||
}
|
||||
|
||||
// The value that needs to be subtracted to accommodate the bottom border corners.
|
||||
float colorCutoutBottom(float x0l, float x0r, float y0, vec2 radii, float sigma) {
|
||||
return colorCutoutGeneral(x0l, x0r, y0, y0 - radii.y, y0, radii, sigma);
|
||||
}
|
||||
|
||||
// The blurred color value for the point at `pos` with the top left corner of the box at
|
||||
// `p_{0_"rect"}` and the bottom right corner of the box at `p_{1_"rect"}`.
|
||||
float color(vec2 pos, vec2 p0Rect, vec2 p1Rect, vec2 radii, float sigma) {
|
||||
// Compute the vector distances `p_0` and `p_1`.
|
||||
vec2 p0 = p0Rect - pos, p1 = p1Rect - pos;
|
||||
|
||||
// Compute the basic color `"colorFromRect"_sigma(p_0, p_1)`. This is all we have to do if
|
||||
// the box is unrounded.
|
||||
float cRect = colorFromRect(p0, p1, sigma);
|
||||
if (radii.x == 0.0 || radii.y == 0.0)
|
||||
return cRect;
|
||||
|
||||
// Compute the inner corners of the box, taking border radii into account: `x_{0_l}`,
|
||||
// `y_{0_t}`, `x_{0_r}`, and `y_{0_b}`.
|
||||
float x0l = p0.x + radii.x;
|
||||
float y0t = p1.y - radii.y;
|
||||
float x0r = p1.x - radii.x;
|
||||
float y0b = p0.y + radii.y;
|
||||
|
||||
// Compute the final color:
|
||||
//
|
||||
// "colorFromRect"_sigma(p_0, p_1) -
|
||||
// ("colorCutoutTop"_sigma(x_{0_l}, x_{0_r}, y_{0_t}, a, b) +
|
||||
// "colorCutoutBottom"_sigma(x_{0_l}, x_{0_r}, y_{0_b}, a, b))
|
||||
float cCutoutTop = colorCutoutTop(x0l, x0r, y0t, radii, sigma);
|
||||
float cCutoutBottom = colorCutoutBottom(x0l, x0r, y0b, radii, sigma);
|
||||
return cRect - (cCutoutTop + cCutoutBottom);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
vec2 pos = vPosition.xy;
|
||||
vec2 p0Rect = vBorderPosition.xy, p1Rect = vBorderPosition.zw;
|
||||
vec2 radii = vBorderRadii.xy;
|
||||
float sigma = vBlurRadius / 2.0;
|
||||
float value = color(pos, p0Rect, p1Rect, radii, sigma);
|
||||
SetFragColor(vec4(vColor.rgb, max(value, 0.0)));
|
||||
}
|
||||
|
14
resources/shaders/box_shadow.vs.glsl
Normal file
14
resources/shaders/box_shadow.vs.glsl
Normal file
|
@ -0,0 +1,14 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vPosition = aPosition.xy;
|
||||
vColor = aColorRectTL;
|
||||
vBorderPosition = aBorderPosition;
|
||||
vBorderRadii = aBorderRadii;
|
||||
vBlurRadius = aBlurRadius;
|
||||
gl_Position = uTransform * vec4(aPosition, 1.0);
|
||||
}
|
||||
|
8
resources/shaders/clear.fs.glsl
Normal file
8
resources/shaders/clear.fs.glsl
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
SetFragColor(vColor);
|
||||
}
|
9
resources/shaders/clear.vs.glsl
Normal file
9
resources/shaders/clear.vs.glsl
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vColor = aColorRectTL / 255.0;
|
||||
gl_Position = uTransform * vec4(aPosition, 1.0);
|
||||
}
|
8
resources/shaders/debug_color.fs.glsl
Normal file
8
resources/shaders/debug_color.fs.glsl
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
SetFragColor(vColor);
|
||||
}
|
11
resources/shaders/debug_color.vs.glsl
Normal file
11
resources/shaders/debug_color.vs.glsl
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vColor = aColorRectTL;
|
||||
vec4 pos = vec4(aPosition, 1.0);
|
||||
pos.xy = floor(pos.xy * uDevicePixelRatio + 0.5) / uDevicePixelRatio;
|
||||
gl_Position = uTransform * pos;
|
||||
}
|
13
resources/shaders/debug_font.fs.glsl
Normal file
13
resources/shaders/debug_font.fs.glsl
Normal file
|
@ -0,0 +1,13 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
#ifdef SERVO_ES2
|
||||
float alpha = Texture(sDiffuse, vColorTexCoord.xy).a;
|
||||
#else
|
||||
float alpha = Texture(sDiffuse, vColorTexCoord.xy).r;
|
||||
#endif
|
||||
SetFragColor(vec4(vColor.xyz, vColor.w * alpha));
|
||||
}
|
12
resources/shaders/debug_font.vs.glsl
Normal file
12
resources/shaders/debug_font.vs.glsl
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vColor = aColorRectTL;
|
||||
vColorTexCoord = aColorTexCoordRectTop.xy;
|
||||
vec4 pos = vec4(aPosition, 1.0);
|
||||
pos.xy = floor(pos.xy * uDevicePixelRatio + 0.5) / uDevicePixelRatio;
|
||||
gl_Position = uTransform * pos;
|
||||
}
|
42
resources/shaders/es2_common.fs.glsl
Normal file
42
resources/shaders/es2_common.fs.glsl
Normal file
|
@ -0,0 +1,42 @@
|
|||
/* 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/. */
|
||||
|
||||
#version 110
|
||||
|
||||
#define SERVO_ES2
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform sampler2D sDiffuse;
|
||||
uniform sampler2D sMask;
|
||||
uniform vec4 uBlendParams;
|
||||
uniform vec4 uAtlasParams;
|
||||
uniform vec2 uDirection;
|
||||
uniform vec4 uFilterParams;
|
||||
|
||||
varying vec2 vPosition;
|
||||
varying vec4 vColor;
|
||||
varying vec2 vColorTexCoord;
|
||||
varying vec2 vMaskTexCoord;
|
||||
varying vec4 vBorderPosition;
|
||||
varying vec4 vBorderRadii;
|
||||
varying vec2 vDestTextureSize;
|
||||
varying vec2 vSourceTextureSize;
|
||||
varying float vBlurRadius;
|
||||
varying vec4 vTileParams;
|
||||
varying vec4 vClipInRect;
|
||||
varying vec4 vClipOutRect;
|
||||
|
||||
vec4 Texture(sampler2D sampler, vec2 texCoord) {
|
||||
return texture2D(sampler, texCoord);
|
||||
}
|
||||
|
||||
float GetAlphaFromMask(vec4 mask) {
|
||||
return mask.a;
|
||||
}
|
||||
|
||||
void SetFragColor(vec4 color) {
|
||||
gl_FragColor = color;
|
||||
}
|
||||
|
70
resources/shaders/es2_common.vs.glsl
Normal file
70
resources/shaders/es2_common.vs.glsl
Normal file
|
@ -0,0 +1,70 @@
|
|||
/* 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/. */
|
||||
|
||||
#version 110
|
||||
|
||||
#define SERVO_ES2
|
||||
|
||||
uniform mat4 uTransform;
|
||||
uniform vec4 uOffsets[32];
|
||||
uniform vec4 uClipRects[64];
|
||||
uniform mat4 uMatrixPalette[32];
|
||||
uniform vec2 uDirection;
|
||||
uniform vec4 uBlendParams;
|
||||
uniform vec4 uFilterParams;
|
||||
uniform float uDevicePixelRatio;
|
||||
uniform vec4 uTileParams[64];
|
||||
|
||||
attribute vec3 aPosition;
|
||||
attribute vec4 aPositionRect; // Width can be negative to flip horizontally (for border corners).
|
||||
attribute vec4 aColorRectTL;
|
||||
attribute vec4 aColorRectTR;
|
||||
attribute vec4 aColorRectBR;
|
||||
attribute vec4 aColorRectBL;
|
||||
attribute vec4 aColorTexCoordRectTop;
|
||||
attribute vec4 aColorTexCoordRectBottom;
|
||||
attribute vec4 aMaskTexCoordRectTop;
|
||||
attribute vec4 aMaskTexCoordRectBottom;
|
||||
attribute vec4 aBorderPosition;
|
||||
attribute vec4 aBorderRadii;
|
||||
attribute vec2 aSourceTextureSize;
|
||||
attribute vec2 aDestTextureSize;
|
||||
attribute float aBlurRadius;
|
||||
// x = matrix index; y = clip-in rect; z = clip-out rect; w = tile params index.
|
||||
//
|
||||
// A negative w value activates border corner mode. In this mode, the TR and BL colors are ignored,
|
||||
// the color of the top left corner applies to all vertices of the top left triangle, and the color
|
||||
// of the bottom right corner applies to all vertices of the bottom right triangle.
|
||||
attribute vec4 aMisc;
|
||||
|
||||
varying vec2 vPosition;
|
||||
varying vec4 vColor;
|
||||
varying vec2 vColorTexCoord;
|
||||
varying vec2 vMaskTexCoord;
|
||||
varying vec4 vBorderPosition;
|
||||
varying vec4 vBorderRadii;
|
||||
varying vec2 vDestTextureSize;
|
||||
varying vec2 vSourceTextureSize;
|
||||
varying float vBlurRadius;
|
||||
varying vec4 vTileParams;
|
||||
varying vec4 vClipInRect;
|
||||
varying vec4 vClipOutRect;
|
||||
|
||||
int Bottom7Bits(int value) {
|
||||
return value % 0x80;
|
||||
}
|
||||
|
||||
bool IsBottomTriangle() {
|
||||
// FIXME(pcwalton): No gl_VertexID in OpenGL ES 2. We'll need some extra data.
|
||||
return false;
|
||||
}
|
||||
|
||||
vec2 SnapToPixels(vec2 pos)
|
||||
{
|
||||
// Snap the vertex to pixel position to guarantee correct texture
|
||||
// sampling when using bilinear filtering.
|
||||
|
||||
// TODO(gw): ES2 doesn't have round(). Do we ever get negative coords here?
|
||||
return floor(0.5 + pos * uDevicePixelRatio) / uDevicePixelRatio;
|
||||
}
|
148
resources/shaders/filter.fs.glsl
Normal file
148
resources/shaders/filter.fs.glsl
Normal file
|
@ -0,0 +1,148 @@
|
|||
/* 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/. */
|
||||
|
||||
vec3 rgbToHsv(vec3 c) {
|
||||
float value = max(max(c.r, c.g), c.b);
|
||||
|
||||
float chroma = value - min(min(c.r, c.g), c.b);
|
||||
if (chroma == 0.0) {
|
||||
return vec3(0.0);
|
||||
}
|
||||
float saturation = chroma / value;
|
||||
|
||||
float hue;
|
||||
if (c.r == value)
|
||||
hue = (c.g - c.b) / chroma;
|
||||
else if (c.g == value)
|
||||
hue = 2.0 + (c.b - c.r) / chroma;
|
||||
else // if (c.b == value)
|
||||
hue = 4.0 + (c.r - c.g) / chroma;
|
||||
|
||||
hue *= 1.0/6.0;
|
||||
if (hue < 0.0)
|
||||
hue += 1.0;
|
||||
return vec3(hue, saturation, value);
|
||||
}
|
||||
|
||||
vec3 hsvToRgb(vec3 c) {
|
||||
if (c.s == 0.0) {
|
||||
return vec3(c.z);
|
||||
}
|
||||
|
||||
float hue = c.x * 6.0;
|
||||
int sector = int(hue);
|
||||
float residualHue = hue - float(sector);
|
||||
|
||||
vec3 pqt = c.z * vec3(1.0 - c.y, 1.0 - c.y * residualHue, 1.0 - c.y * (1.0 - residualHue));
|
||||
if (sector == 0)
|
||||
return vec3(c.z, pqt.z, pqt.x);
|
||||
if (sector == 1)
|
||||
return vec3(pqt.y, c.z, pqt.x);
|
||||
if (sector == 2)
|
||||
return vec3(pqt.x, c.z, pqt.z);
|
||||
if (sector == 3)
|
||||
return vec3(pqt.x, pqt.y, c.z);
|
||||
if (sector == 4)
|
||||
return vec3(pqt.z, pqt.x, c.z);
|
||||
return vec3(c.z, pqt.x, pqt.y);
|
||||
}
|
||||
|
||||
float gauss(float x, float sigma) {
|
||||
if (sigma == 0.0)
|
||||
return 1.0;
|
||||
return (1.0 / sqrt(6.283185307179586 * sigma * sigma)) * exp(-(x * x) / (2.0 * sigma * sigma));
|
||||
}
|
||||
|
||||
vec4 Blur(float radius, vec2 direction) {
|
||||
#ifdef SERVO_ES2
|
||||
// TODO(gw): for loops have to be unrollable on es2.
|
||||
return vec4(1.0, 0.0, 0.0, 1.0);
|
||||
#else
|
||||
int range = int(radius) * 3;
|
||||
float sigma = radius / 2.0;
|
||||
vec4 color = vec4(0.0);
|
||||
for (int offset = -range; offset <= range; offset++) {
|
||||
float offsetF = float(offset);
|
||||
|
||||
// Here, we use the vMaskTexCoord.xy (i.e. the muv) to store the texture size.
|
||||
vec2 texCoord = vColorTexCoord.xy + vec2(offsetF) / vMaskTexCoord.xy * direction;
|
||||
vec4 x = texCoord.x >= 0.0 &&
|
||||
texCoord.x <= 1.0 &&
|
||||
texCoord.y >= 0.0 &&
|
||||
texCoord.y <= 1.0 ?
|
||||
Texture(sDiffuse, texCoord) :
|
||||
vec4(0.0);
|
||||
color += x * gauss(offsetF, sigma);
|
||||
}
|
||||
return color;
|
||||
#endif
|
||||
}
|
||||
|
||||
vec4 Contrast(vec4 Cs, float amount) {
|
||||
return vec4(Cs.rgb * amount - 0.5 * amount + 0.5, 1.0);
|
||||
}
|
||||
|
||||
vec4 Grayscale(vec4 Cs, float amount) {
|
||||
float ia = 1.0 - amount;
|
||||
return mat4(vec4(0.2126 + 0.7874 * ia, 0.2126 - 0.2126 * ia, 0.2126 - 0.2126 * ia, 0.0),
|
||||
vec4(0.7152 - 0.7152 * ia, 0.7152 + 0.2848 * ia, 0.7152 - 0.7152 * ia, 0.0),
|
||||
vec4(0.0722 - 0.0722 * ia, 0.0722 - 0.0722 * ia, 0.0722 + 0.9278 * ia, 0.0),
|
||||
vec4(0.0, 0.0, 0.0, 1.0)) * Cs;
|
||||
}
|
||||
|
||||
vec4 HueRotate(vec4 Cs, float amount) {
|
||||
vec3 CsHsv = rgbToHsv(Cs.rgb);
|
||||
CsHsv.x = mod(CsHsv.x + amount / 6.283185307179586, 1.0);
|
||||
return vec4(hsvToRgb(CsHsv), Cs.a);
|
||||
}
|
||||
|
||||
vec4 Invert(vec4 Cs, float amount) {
|
||||
return mix(Cs, vec4(1.0, 1.0, 1.0, Cs.a) - vec4(Cs.rgb, 0.0), amount);
|
||||
}
|
||||
|
||||
vec4 Saturate(vec4 Cs, float amount) {
|
||||
return vec4(hsvToRgb(min(vec3(1.0, amount, 1.0) * rgbToHsv(Cs.rgb), vec3(1.0))), Cs.a);
|
||||
}
|
||||
|
||||
vec4 Sepia(vec4 Cs, float amount) {
|
||||
float ia = 1.0 - amount;
|
||||
return mat4(vec4(0.393 + 0.607 * ia, 0.349 - 0.349 * ia, 0.272 - 0.272 * ia, 0.0),
|
||||
vec4(0.769 - 0.769 * ia, 0.686 + 0.314 * ia, 0.534 - 0.534 * ia, 0.0),
|
||||
vec4(0.189 - 0.189 * ia, 0.168 - 0.168 * ia, 0.131 + 0.869 * ia, 0.0),
|
||||
vec4(0.0, 0.0, 0.0, 1.0)) * Cs;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
// TODO: May be best to have separate shaders (esp. on Tegra)
|
||||
int filterOp = int(uFilterParams.x);
|
||||
float amount = uFilterParams.y;
|
||||
|
||||
// Return yellow if none of the branches match (shouldn't happen).
|
||||
vec4 result = vec4(1.0, 1.0, 0.0, 1.0);
|
||||
|
||||
if (filterOp == 0) {
|
||||
// Gaussian blur is specially handled:
|
||||
result = Blur(amount, uFilterParams.zw);
|
||||
} else {
|
||||
vec4 Cs = Texture(sDiffuse, vColorTexCoord);
|
||||
|
||||
if (filterOp == 1) {
|
||||
result = Contrast(Cs, amount);
|
||||
} else if (filterOp == 2) {
|
||||
result = Grayscale(Cs, amount);
|
||||
} else if (filterOp == 3) {
|
||||
result = HueRotate(Cs, amount);
|
||||
} else if (filterOp == 4) {
|
||||
result = Invert(Cs, amount);
|
||||
} else if (filterOp == 5) {
|
||||
result = Saturate(Cs, amount);
|
||||
} else if (filterOp == 6) {
|
||||
result = Sepia(Cs, amount);
|
||||
}
|
||||
}
|
||||
|
||||
SetFragColor(result);
|
||||
}
|
||||
|
12
resources/shaders/filter.vs.glsl
Normal file
12
resources/shaders/filter.vs.glsl
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vColorTexCoord = aColorTexCoordRectTop.xy;
|
||||
vMaskTexCoord = aMaskTexCoordRectTop.xy;
|
||||
vec4 pos = vec4(aPosition, 1.0);
|
||||
pos.xy = SnapToPixels(pos.xy);
|
||||
gl_Position = uTransform * pos;
|
||||
}
|
41
resources/shaders/gl3_common.fs.glsl
Normal file
41
resources/shaders/gl3_common.fs.glsl
Normal file
|
@ -0,0 +1,41 @@
|
|||
/* 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/. */
|
||||
|
||||
#version 150
|
||||
|
||||
#define SERVO_GL3
|
||||
|
||||
uniform sampler2D sDiffuse;
|
||||
uniform sampler2D sMask;
|
||||
uniform vec4 uBlendParams;
|
||||
uniform vec2 uDirection;
|
||||
uniform vec4 uFilterParams;
|
||||
|
||||
in vec2 vPosition;
|
||||
in vec4 vColor;
|
||||
in vec2 vColorTexCoord;
|
||||
in vec2 vMaskTexCoord;
|
||||
in vec4 vBorderPosition;
|
||||
in vec4 vBorderRadii;
|
||||
in vec2 vDestTextureSize;
|
||||
in vec2 vSourceTextureSize;
|
||||
in float vBlurRadius;
|
||||
in vec4 vTileParams;
|
||||
in vec4 vClipInRect;
|
||||
in vec4 vClipOutRect;
|
||||
|
||||
out vec4 oFragColor;
|
||||
|
||||
vec4 Texture(sampler2D sampler, vec2 texCoord) {
|
||||
return texture(sampler, texCoord);
|
||||
}
|
||||
|
||||
float GetAlphaFromMask(vec4 mask) {
|
||||
return mask.r;
|
||||
}
|
||||
|
||||
void SetFragColor(vec4 color) {
|
||||
oFragColor = color;
|
||||
}
|
||||
|
68
resources/shaders/gl3_common.vs.glsl
Normal file
68
resources/shaders/gl3_common.vs.glsl
Normal file
|
@ -0,0 +1,68 @@
|
|||
/* 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/. */
|
||||
|
||||
#version 150
|
||||
|
||||
#define SERVO_GL3
|
||||
|
||||
uniform mat4 uTransform;
|
||||
uniform vec4 uOffsets[32];
|
||||
uniform vec4 uClipRects[64];
|
||||
uniform mat4 uMatrixPalette[32];
|
||||
uniform vec2 uDirection;
|
||||
uniform vec4 uBlendParams;
|
||||
uniform vec4 uFilterParams;
|
||||
uniform float uDevicePixelRatio;
|
||||
uniform vec4 uTileParams[64];
|
||||
uniform vec4 uAtlasParams;
|
||||
|
||||
in vec3 aPosition;
|
||||
in vec4 aPositionRect; // Width can be negative to flip horizontally (for border corners).
|
||||
in vec4 aColorRectTL;
|
||||
in vec4 aColorRectTR;
|
||||
in vec4 aColorRectBR;
|
||||
in vec4 aColorRectBL;
|
||||
in vec4 aColorTexCoordRectTop;
|
||||
in vec4 aColorTexCoordRectBottom;
|
||||
in vec4 aMaskTexCoordRectTop;
|
||||
in vec4 aMaskTexCoordRectBottom;
|
||||
in vec4 aBorderPosition;
|
||||
in vec4 aBorderRadii;
|
||||
in vec2 aSourceTextureSize;
|
||||
in vec2 aDestTextureSize;
|
||||
in float aBlurRadius;
|
||||
// x = matrix index; y = clip-in rect; z = clip-out rect; w = tile params index.
|
||||
//
|
||||
// A negative w value activates border corner mode. In this mode, the TR and BL colors are ignored,
|
||||
// the color of the top left corner applies to all vertices of the top left triangle, and the color
|
||||
// of the bottom right corner applies to all vertices of the bottom right triangle.
|
||||
in vec4 aMisc;
|
||||
|
||||
out vec2 vPosition;
|
||||
out vec4 vColor;
|
||||
out vec2 vColorTexCoord;
|
||||
out vec2 vMaskTexCoord;
|
||||
out vec4 vBorderPosition;
|
||||
out vec4 vBorderRadii;
|
||||
out vec2 vDestTextureSize;
|
||||
out vec2 vSourceTextureSize;
|
||||
out float vBlurRadius;
|
||||
out vec4 vTileParams;
|
||||
out vec4 vClipInRect;
|
||||
out vec4 vClipOutRect;
|
||||
|
||||
int Bottom7Bits(int value) {
|
||||
return value & 0x7f;
|
||||
}
|
||||
|
||||
bool IsBottomTriangle() {
|
||||
return gl_VertexID > 2;
|
||||
}
|
||||
|
||||
vec2 SnapToPixels(vec2 pos)
|
||||
{
|
||||
// Snap the vertex to pixel position to guarantee correct texture
|
||||
// sampling when using bilinear filtering.
|
||||
return round(pos * uDevicePixelRatio) / uDevicePixelRatio;
|
||||
}
|
8
resources/shaders/mask.fs.glsl
Normal file
8
resources/shaders/mask.fs.glsl
Normal file
|
@ -0,0 +1,8 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
SetFragColor(vColor);
|
||||
}
|
9
resources/shaders/mask.vs.glsl
Normal file
9
resources/shaders/mask.vs.glsl
Normal file
|
@ -0,0 +1,9 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vColor = aColorRectTL / 255.0;
|
||||
gl_Position = uTransform * vec4(aPosition, 1.0);
|
||||
}
|
38
resources/shaders/quad.fs.glsl
Normal file
38
resources/shaders/quad.fs.glsl
Normal file
|
@ -0,0 +1,38 @@
|
|||
/* 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/. */
|
||||
|
||||
// GLSL point in rect test.
|
||||
// See: https://stackoverflow.com/questions/12751080/glsl-point-inside-box-test
|
||||
bool PointInRect(vec2 p, vec2 p0, vec2 p1)
|
||||
{
|
||||
vec2 s = step(p0, p) - step(p1, p);
|
||||
return s.x * s.y != 0.0;
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
// Clip out.
|
||||
if (PointInRect(vPosition, vClipOutRect.xy, vClipOutRect.zw)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Clip in.
|
||||
if (!PointInRect(vPosition, vClipInRect.xy, vClipInRect.zw)) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// Apply image tiling parameters (offset and scale) to color UVs.
|
||||
vec2 colorTexCoord = vTileParams.xy + fract(vColorTexCoord.xy) * vTileParams.zw;
|
||||
vec2 maskTexCoord = vMaskTexCoord.xy;
|
||||
|
||||
// Fetch the diffuse and mask texels.
|
||||
vec4 diffuse = Texture(sDiffuse, colorTexCoord);
|
||||
vec4 mask = Texture(sMask, maskTexCoord);
|
||||
|
||||
// Extract alpha from the mask (component depends on platform)
|
||||
float alpha = GetAlphaFromMask(mask);
|
||||
|
||||
// Write the final fragment color.
|
||||
SetFragColor(diffuse * vec4(vColor.rgb, vColor.a * alpha));
|
||||
}
|
112
resources/shaders/quad.vs.glsl
Normal file
112
resources/shaders/quad.vs.glsl
Normal file
|
@ -0,0 +1,112 @@
|
|||
/* 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/. */
|
||||
|
||||
vec2 Bilerp2(vec2 tl, vec2 tr, vec2 br, vec2 bl, vec2 st) {
|
||||
return mix(mix(tl, bl, st.y), mix(tr, br, st.y), st.x);
|
||||
}
|
||||
|
||||
vec4 Bilerp4(vec4 tl, vec4 tr, vec4 br, vec4 bl, vec2 st) {
|
||||
return mix(mix(tl, bl, st.y), mix(tr, br, st.y), st.x);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
// Extract the image tiling parameters.
|
||||
// These are passed to the fragment shader, since
|
||||
// the uv interpolation must be done per-fragment.
|
||||
vTileParams = uTileParams[Bottom7Bits(int(aMisc.w))];
|
||||
|
||||
// Determine clip rects.
|
||||
vClipOutRect = uClipRects[int(aMisc.z)];
|
||||
vec4 clipInRect = uClipRects[int(aMisc.y)];
|
||||
|
||||
// Extract the complete (stacking context + css transform) transform
|
||||
// for this vertex. Transform the position by it.
|
||||
vec2 offsetParams = uOffsets[Bottom7Bits(int(aMisc.x))].xy;
|
||||
mat4 matrix = uMatrixPalette[Bottom7Bits(int(aMisc.x))];
|
||||
|
||||
vec2 p0 = aPositionRect.xy + offsetParams;
|
||||
vec2 p1 = p0 + aPositionRect.zw;
|
||||
|
||||
vec2 rect_origin = SnapToPixels(p0);
|
||||
vec2 rect_size = SnapToPixels(p1) - rect_origin;
|
||||
|
||||
// Determine the position, color, and mask texture coordinates of this vertex.
|
||||
vec4 localPos = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
bool isBorderCorner = int(aMisc.w) >= 0x80;
|
||||
bool isBottomTriangle = IsBottomTriangle();
|
||||
if (aPosition.y == 0.0) {
|
||||
localPos.y = rect_origin.y;
|
||||
if (aPosition.x == 0.0) {
|
||||
localPos.x = rect_origin.x;
|
||||
if (isBorderCorner) {
|
||||
vColor = isBottomTriangle ? aColorRectBL : aColorRectTR;
|
||||
}
|
||||
} else {
|
||||
localPos.x = rect_origin.x + rect_size.x;
|
||||
if (isBorderCorner) {
|
||||
vColor = aColorRectTR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
localPos.y = rect_origin.y + rect_size.y;
|
||||
if (aPosition.x == 0.0) {
|
||||
localPos.x = rect_origin.x;
|
||||
if (isBorderCorner) {
|
||||
vColor = aColorRectBL;
|
||||
}
|
||||
} else {
|
||||
localPos.x = rect_origin.x + rect_size.x;
|
||||
if (isBorderCorner) {
|
||||
vColor = isBottomTriangle ? aColorRectBL : aColorRectTR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rotate or clip as necessary. If there is no rotation, we can clip here in the vertex shader
|
||||
// and save a whole bunch of fragment shader invocations. If there is a rotation, we fall back
|
||||
// to FS clipping.
|
||||
//
|
||||
// The rotation angle is encoded as a negative bottom left u coordinate. (uv coordinates should
|
||||
// always be nonnegative normally, and gradients don't use color textures, so this is fine.)
|
||||
vec4 colorTexCoordRectBottom = aColorTexCoordRectBottom;
|
||||
vec2 localST;
|
||||
if (colorTexCoordRectBottom.z < 0.0) {
|
||||
float angle = -colorTexCoordRectBottom.z;
|
||||
vec2 center = rect_origin + rect_size / 2.0;
|
||||
vec2 translatedPos = localPos.xy - center;
|
||||
localST = (localPos.xy - rect_origin) / rect_size;
|
||||
localPos.xy = vec2(translatedPos.x * cos(angle) - translatedPos.y * sin(angle),
|
||||
translatedPos.x * sin(angle) + translatedPos.y * cos(angle)) + center;
|
||||
colorTexCoordRectBottom.z = aColorTexCoordRectTop.x;
|
||||
vClipInRect = clipInRect;
|
||||
} else {
|
||||
localPos.x = clamp(localPos.x, clipInRect.x, clipInRect.z);
|
||||
localPos.y = clamp(localPos.y, clipInRect.y, clipInRect.w);
|
||||
localST = (localPos.xy - rect_origin) / rect_size;
|
||||
vClipInRect = vec4(-1e37, -1e37, 1e38, 1e38);
|
||||
}
|
||||
|
||||
vColorTexCoord = Bilerp2(aColorTexCoordRectTop.xy, aColorTexCoordRectTop.zw,
|
||||
colorTexCoordRectBottom.xy, colorTexCoordRectBottom.zw,
|
||||
localST);
|
||||
vMaskTexCoord = Bilerp2(aMaskTexCoordRectTop.xy, aMaskTexCoordRectTop.zw,
|
||||
aMaskTexCoordRectBottom.xy, aMaskTexCoordRectBottom.zw,
|
||||
localST);
|
||||
if (!isBorderCorner) {
|
||||
vColor = Bilerp4(aColorRectTL, aColorRectTR, aColorRectBR, aColorRectBL, localST);
|
||||
}
|
||||
|
||||
// Normalize the vertex color and mask texture coordinates.
|
||||
vColor /= 255.0;
|
||||
vMaskTexCoord /= uAtlasParams.zw;
|
||||
|
||||
vPosition = localPos.xy;
|
||||
|
||||
vec4 worldPos = matrix * localPos;
|
||||
|
||||
// Transform by the orthographic projection into clip space.
|
||||
gl_Position = uTransform * worldPos;
|
||||
}
|
||||
|
11
resources/shaders/tile.fs.glsl
Normal file
11
resources/shaders/tile.fs.glsl
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void) {
|
||||
vec2 textureSize = vBorderPosition.zw - vBorderPosition.xy;
|
||||
vec2 colorTexCoord = vBorderPosition.xy + mod(vColorTexCoord.xy, 1.0) * textureSize;
|
||||
vec4 diffuse = Texture(sDiffuse, colorTexCoord);
|
||||
SetFragColor(diffuse);
|
||||
}
|
||||
|
11
resources/shaders/tile.vs.glsl
Normal file
11
resources/shaders/tile.vs.glsl
Normal file
|
@ -0,0 +1,11 @@
|
|||
/* 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/. */
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vColorTexCoord = aBorderRadii.xy;
|
||||
vBorderPosition = aBorderPosition;
|
||||
gl_Position = uTransform * vec4(aPosition, 1.0);
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ use style::font_face::Source;
|
|||
fn test_local_web_font() {
|
||||
let (inp_chan, _) = ipc::channel().unwrap();
|
||||
let (out_chan, out_receiver) = ipc::channel().unwrap();
|
||||
let font_cache_thread = FontCacheThread::new(inp_chan);
|
||||
let font_cache_thread = FontCacheThread::new(inp_chan, None);
|
||||
let family_name = FontFamily::FamilyName(From::from("test family"));
|
||||
let variant_name = FontFamily::FamilyName(From::from("test font face"));
|
||||
|
||||
|
|
|
@ -58,7 +58,7 @@ def update_properties():
|
|||
|
||||
|
||||
def render_arg(render_backend):
|
||||
return {"cpu": "--cpu", "webrender": "--webrender"}[render_backend]
|
||||
return {"cpu": "--cpu", "webrender": "-w"}[render_backend]
|
||||
|
||||
|
||||
class ServoBrowser(NullBrowser):
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue