mirror of
https://github.com/servo/servo.git
synced 2025-08-07 06:25:32 +01:00
auto merge of #4969 : servo/servo/parallel-paint-demo, r=glennw
You can enable this with `-Z show-parallel-paint`. The output looks like this: 
This commit is contained in:
commit
49ff6b2ccc
3 changed files with 54 additions and 25 deletions
|
@ -355,7 +355,8 @@ impl<C> PaintTask<C> where C: PaintListener + Send {
|
||||||
for (i, tile) in tiles.into_iter().enumerate() {
|
for (i, tile) in tiles.into_iter().enumerate() {
|
||||||
let thread_id = i % self.worker_threads.len();
|
let thread_id = i % self.worker_threads.len();
|
||||||
let layer_buffer = self.find_or_create_layer_buffer_for_tile(&tile, scale);
|
let layer_buffer = self.find_or_create_layer_buffer_for_tile(&tile, scale);
|
||||||
self.worker_threads[thread_id].paint_tile(tile,
|
self.worker_threads[thread_id].paint_tile(thread_id,
|
||||||
|
tile,
|
||||||
layer_buffer,
|
layer_buffer,
|
||||||
stacking_context.clone(),
|
stacking_context.clone(),
|
||||||
scale);
|
scale);
|
||||||
|
@ -423,7 +424,7 @@ impl WorkerThreadProxy {
|
||||||
let thread_count = if opts::get().gpu_painting {
|
let thread_count = if opts::get().gpu_painting {
|
||||||
1
|
1
|
||||||
} else {
|
} else {
|
||||||
opts::get().layout_threads
|
opts::get().paint_threads
|
||||||
};
|
};
|
||||||
(0..thread_count).map(|_| {
|
(0..thread_count).map(|_| {
|
||||||
let (from_worker_sender, from_worker_receiver) = channel();
|
let (from_worker_sender, from_worker_receiver) = channel();
|
||||||
|
@ -447,11 +448,12 @@ impl WorkerThreadProxy {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn paint_tile(&mut self,
|
fn paint_tile(&mut self,
|
||||||
|
thread_id: usize,
|
||||||
tile: BufferRequest,
|
tile: BufferRequest,
|
||||||
layer_buffer: Option<Box<LayerBuffer>>,
|
layer_buffer: Option<Box<LayerBuffer>>,
|
||||||
stacking_context: Arc<StackingContext>,
|
stacking_context: Arc<StackingContext>,
|
||||||
scale: f32) {
|
scale: f32) {
|
||||||
self.sender.send(MsgToWorkerThread::PaintTile(tile, layer_buffer, stacking_context, scale)).unwrap()
|
self.sender.send(MsgToWorkerThread::PaintTile(thread_id, tile, layer_buffer, stacking_context, scale)).unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_painted_tile_buffer(&mut self) -> Box<LayerBuffer> {
|
fn get_painted_tile_buffer(&mut self) -> Box<LayerBuffer> {
|
||||||
|
@ -495,8 +497,8 @@ impl WorkerThread {
|
||||||
loop {
|
loop {
|
||||||
match self.receiver.recv().unwrap() {
|
match self.receiver.recv().unwrap() {
|
||||||
MsgToWorkerThread::Exit => break,
|
MsgToWorkerThread::Exit => break,
|
||||||
MsgToWorkerThread::PaintTile(tile, layer_buffer, stacking_context, scale) => {
|
MsgToWorkerThread::PaintTile(thread_id, tile, layer_buffer, stacking_context, scale) => {
|
||||||
let draw_target = self.optimize_and_paint_tile(&tile, stacking_context, scale);
|
let draw_target = self.optimize_and_paint_tile(thread_id, &tile, stacking_context, scale);
|
||||||
let buffer = self.create_layer_buffer_for_painted_tile(&tile,
|
let buffer = self.create_layer_buffer_for_painted_tile(&tile,
|
||||||
layer_buffer,
|
layer_buffer,
|
||||||
draw_target,
|
draw_target,
|
||||||
|
@ -508,6 +510,7 @@ impl WorkerThread {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn optimize_and_paint_tile(&mut self,
|
fn optimize_and_paint_tile(&mut self,
|
||||||
|
thread_id: usize,
|
||||||
tile: &BufferRequest,
|
tile: &BufferRequest,
|
||||||
stacking_context: Arc<StackingContext>,
|
stacking_context: Arc<StackingContext>,
|
||||||
scale: f32)
|
scale: f32)
|
||||||
|
@ -563,7 +566,24 @@ impl WorkerThread {
|
||||||
&matrix,
|
&matrix,
|
||||||
None);
|
None);
|
||||||
paint_context.draw_target.flush();
|
paint_context.draw_target.flush();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if opts::get().show_debug_parallel_paint {
|
||||||
|
// Overlay a transparent solid color to identify the thread that
|
||||||
|
// painted this tile.
|
||||||
|
let colors = [Color { r: 6.0/255.0, g: 153.0/255.0, b: 198.0/255.0, a: 0.7 },
|
||||||
|
Color { r: 255.0/255.0, g: 212.0/255.0, b: 83.0/255.0, a: 0.7 },
|
||||||
|
Color { r: 116.0/255.0, g: 29.0/255.0, b: 109.0/255.0, a: 0.7 },
|
||||||
|
Color { r: 204.0/255.0, g: 158.0/255.0, b: 199.0/255.0, a: 0.7 },
|
||||||
|
Color { r: 242.0/255.0, g: 46.0/255.0, b: 121.0/255.0, a: 0.7 },
|
||||||
|
Color { r: 116.0/255.0, g: 203.0/255.0, b: 196.0/255.0, a: 0.7 },
|
||||||
|
Color { r: 255.0/255.0, g: 249.0/255.0, b: 201.0/255.0, a: 0.7 },
|
||||||
|
Color { r: 137.0/255.0, g: 196.0/255.0, b: 78.0/255.0, a: 0.7 }];
|
||||||
|
paint_context.draw_solid_color(&Rect(Point2D(Au(0), Au(0)),
|
||||||
|
Size2D(Au::from_px(size.width as isize),
|
||||||
|
Au::from_px(size.height as isize))),
|
||||||
|
colors[thread_id % colors.len()]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_target
|
draw_target
|
||||||
|
@ -613,7 +633,7 @@ impl WorkerThread {
|
||||||
|
|
||||||
enum MsgToWorkerThread {
|
enum MsgToWorkerThread {
|
||||||
Exit,
|
Exit,
|
||||||
PaintTile(BufferRequest, Option<Box<LayerBuffer>>, Arc<StackingContext>, f32),
|
PaintTile(usize, BufferRequest, Option<Box<LayerBuffer>>, Arc<StackingContext>, f32),
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MsgFromWorkerThread {
|
enum MsgFromWorkerThread {
|
||||||
|
|
|
@ -27,8 +27,8 @@ pub struct Opts {
|
||||||
|
|
||||||
/// How many threads to use for CPU painting (`-t`).
|
/// How many threads to use for CPU painting (`-t`).
|
||||||
///
|
///
|
||||||
/// FIXME(pcwalton): This is not currently used. All painting is sequential.
|
/// Note that painting is sequentialized when using GPU painting.
|
||||||
pub n_paint_threads: uint,
|
pub paint_threads: uint,
|
||||||
|
|
||||||
/// True to use GPU painting via Skia-GL, false to use CPU painting via Skia (`-g`). Note that
|
/// True to use GPU painting via Skia-GL, false to use CPU painting via Skia (`-g`). Note that
|
||||||
/// compositing is always done on the GPU.
|
/// compositing is always done on the GPU.
|
||||||
|
@ -75,6 +75,9 @@ pub struct Opts {
|
||||||
/// True if we should show borders on all fragments for debugging purposes (`--show-debug-fragment-borders`).
|
/// True if we should show borders on all fragments for debugging purposes (`--show-debug-fragment-borders`).
|
||||||
pub show_debug_fragment_borders: bool,
|
pub show_debug_fragment_borders: bool,
|
||||||
|
|
||||||
|
/// True if we should paint tiles with overlays based on which thread painted them.
|
||||||
|
pub show_debug_parallel_paint: bool,
|
||||||
|
|
||||||
/// If set with --disable-text-aa, disable antialiasing on fonts. This is primarily useful for reftests
|
/// If set with --disable-text-aa, disable antialiasing on fonts. This is primarily useful for reftests
|
||||||
/// where pixel perfect results are required when using fonts such as the Ahem
|
/// where pixel perfect results are required when using fonts such as the Ahem
|
||||||
/// font for layout tests.
|
/// font for layout tests.
|
||||||
|
@ -128,6 +131,7 @@ pub fn print_debug_usage(app: &str) {
|
||||||
print_option("profile-tasks", "Instrument each task, writing the output to a file.");
|
print_option("profile-tasks", "Instrument each task, writing the output to a file.");
|
||||||
print_option("show-compositor-borders", "Paint borders along layer and tile boundaries.");
|
print_option("show-compositor-borders", "Paint borders along layer and tile boundaries.");
|
||||||
print_option("show-fragment-borders", "Paint borders along fragment boundaries.");
|
print_option("show-fragment-borders", "Paint borders along fragment boundaries.");
|
||||||
|
print_option("show-parallel-paint", "Overlay tiles with colors showing which thread painted them.");
|
||||||
print_option("trace-layout", "Write layout trace to an external file for debugging.");
|
print_option("trace-layout", "Write layout trace to an external file for debugging.");
|
||||||
print_option("validate-display-list-geometry",
|
print_option("validate-display-list-geometry",
|
||||||
"Display an error when display list geometry escapes overflow region.");
|
"Display an error when display list geometry escapes overflow region.");
|
||||||
|
@ -151,7 +155,7 @@ static FORCE_CPU_PAINTING: bool = false;
|
||||||
pub fn default_opts() -> Opts {
|
pub fn default_opts() -> Opts {
|
||||||
Opts {
|
Opts {
|
||||||
urls: vec!(),
|
urls: vec!(),
|
||||||
n_paint_threads: 1,
|
paint_threads: 1,
|
||||||
gpu_painting: false,
|
gpu_painting: false,
|
||||||
tile_size: 512,
|
tile_size: 512,
|
||||||
device_pixels_per_px: None,
|
device_pixels_per_px: None,
|
||||||
|
@ -166,6 +170,7 @@ pub fn default_opts() -> Opts {
|
||||||
bubble_inline_sizes_separately: false,
|
bubble_inline_sizes_separately: false,
|
||||||
show_debug_borders: false,
|
show_debug_borders: false,
|
||||||
show_debug_fragment_borders: false,
|
show_debug_fragment_borders: false,
|
||||||
|
show_debug_parallel_paint: false,
|
||||||
enable_text_antialiasing: false,
|
enable_text_antialiasing: false,
|
||||||
trace_layout: false,
|
trace_layout: false,
|
||||||
devtools_port: None,
|
devtools_port: None,
|
||||||
|
@ -249,9 +254,9 @@ pub fn from_cmdline_args(args: &[String]) -> bool {
|
||||||
ScaleFactor(dppx_str.parse().unwrap())
|
ScaleFactor(dppx_str.parse().unwrap())
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut n_paint_threads: uint = match opt_match.opt_str("t") {
|
let mut paint_threads: uint = match opt_match.opt_str("t") {
|
||||||
Some(n_paint_threads_str) => n_paint_threads_str.parse().unwrap(),
|
Some(paint_threads_str) => paint_threads_str.parse().unwrap(),
|
||||||
None => 1, // FIXME: Number of cores.
|
None => cmp::max(rt::default_sched_threads() * 3 / 4, 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
// If only the flag is present, default to a 5 second period for both profilers.
|
// If only the flag is present, default to a 5 second period for both profilers.
|
||||||
|
@ -274,7 +279,7 @@ pub fn from_cmdline_args(args: &[String]) -> bool {
|
||||||
let mut bubble_inline_sizes_separately = debug_options.contains(&"bubble-widths");
|
let mut bubble_inline_sizes_separately = debug_options.contains(&"bubble-widths");
|
||||||
let trace_layout = debug_options.contains(&"trace-layout");
|
let trace_layout = debug_options.contains(&"trace-layout");
|
||||||
if trace_layout {
|
if trace_layout {
|
||||||
n_paint_threads = 1;
|
paint_threads = 1;
|
||||||
layout_threads = 1;
|
layout_threads = 1;
|
||||||
bubble_inline_sizes_separately = true;
|
bubble_inline_sizes_separately = true;
|
||||||
}
|
}
|
||||||
|
@ -295,7 +300,7 @@ pub fn from_cmdline_args(args: &[String]) -> bool {
|
||||||
|
|
||||||
let opts = Opts {
|
let opts = Opts {
|
||||||
urls: urls,
|
urls: urls,
|
||||||
n_paint_threads: n_paint_threads,
|
paint_threads: paint_threads,
|
||||||
gpu_painting: gpu_painting,
|
gpu_painting: gpu_painting,
|
||||||
tile_size: tile_size,
|
tile_size: tile_size,
|
||||||
device_pixels_per_px: device_pixels_per_px,
|
device_pixels_per_px: device_pixels_per_px,
|
||||||
|
@ -315,6 +320,7 @@ pub fn from_cmdline_args(args: &[String]) -> bool {
|
||||||
user_agent: opt_match.opt_str("u"),
|
user_agent: opt_match.opt_str("u"),
|
||||||
show_debug_borders: debug_options.contains(&"show-compositor-borders"),
|
show_debug_borders: debug_options.contains(&"show-compositor-borders"),
|
||||||
show_debug_fragment_borders: debug_options.contains(&"show-fragment-borders"),
|
show_debug_fragment_borders: debug_options.contains(&"show-fragment-borders"),
|
||||||
|
show_debug_parallel_paint: debug_options.contains(&"show-parallel-paint"),
|
||||||
enable_text_antialiasing: !debug_options.contains(&"disable-text-aa"),
|
enable_text_antialiasing: !debug_options.contains(&"disable-text-aa"),
|
||||||
dump_flow_tree: debug_options.contains(&"dump-flow-tree"),
|
dump_flow_tree: debug_options.contains(&"dump-flow-tree"),
|
||||||
validate_display_list_geometry: debug_options.contains(&"validate-display-list-geometry"),
|
validate_display_list_geometry: debug_options.contains(&"validate-display-list-geometry"),
|
||||||
|
|
|
@ -60,10 +60,20 @@ pub extern "C" fn cef_initialize(args: *const cef_main_args_t,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let rendering_threads = unsafe {
|
||||||
|
if ((*settings).rendering_threads as uint) < 1 {
|
||||||
|
1
|
||||||
|
} else if (*settings).rendering_threads as uint > MAX_RENDERING_THREADS {
|
||||||
|
MAX_RENDERING_THREADS
|
||||||
|
} else {
|
||||||
|
(*settings).rendering_threads as uint
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
let urls = vec![HOME_URL.to_owned()];
|
let urls = vec![HOME_URL.to_owned()];
|
||||||
opts::set_opts(opts::Opts {
|
opts::set_opts(opts::Opts {
|
||||||
urls: urls,
|
urls: urls,
|
||||||
n_paint_threads: 1,
|
paint_threads: rendering_threads,
|
||||||
gpu_painting: false,
|
gpu_painting: false,
|
||||||
tile_size: 512,
|
tile_size: 512,
|
||||||
device_pixels_per_px: None,
|
device_pixels_per_px: None,
|
||||||
|
@ -71,21 +81,14 @@ pub extern "C" fn cef_initialize(args: *const cef_main_args_t,
|
||||||
memory_profiler_period: None,
|
memory_profiler_period: None,
|
||||||
enable_experimental: false,
|
enable_experimental: false,
|
||||||
nonincremental_layout: false,
|
nonincremental_layout: false,
|
||||||
layout_threads: unsafe {
|
layout_threads: rendering_threads,
|
||||||
if ((*settings).rendering_threads as uint) < 1 {
|
|
||||||
1
|
|
||||||
} else if (*settings).rendering_threads as uint > MAX_RENDERING_THREADS {
|
|
||||||
MAX_RENDERING_THREADS
|
|
||||||
} else {
|
|
||||||
(*settings).rendering_threads as uint
|
|
||||||
}
|
|
||||||
},
|
|
||||||
output_file: None,
|
output_file: None,
|
||||||
headless: false,
|
headless: false,
|
||||||
hard_fail: false,
|
hard_fail: false,
|
||||||
bubble_inline_sizes_separately: false,
|
bubble_inline_sizes_separately: false,
|
||||||
show_debug_borders: false,
|
show_debug_borders: false,
|
||||||
show_debug_fragment_borders: false,
|
show_debug_fragment_borders: false,
|
||||||
|
show_debug_parallel_paint: false,
|
||||||
enable_text_antialiasing: true,
|
enable_text_antialiasing: true,
|
||||||
trace_layout: false,
|
trace_layout: false,
|
||||||
devtools_port: None,
|
devtools_port: None,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue