Write out PNG file after compositing based on -o option.

This commit is contained in:
Jack Moffitt 2013-07-16 09:54:16 -06:00
parent 12eb1e55a6
commit 31f7c4ba14
4 changed files with 42 additions and 8 deletions

View file

@ -24,6 +24,8 @@ use std::comm;
use std::comm::{Chan, SharedChan, Port}; use std::comm::{Chan, SharedChan, Port};
use std::num::Orderable; use std::num::Orderable;
use std::task; use std::task;
use std::uint;
use std::vec;
use extra::uv_global_loop; use extra::uv_global_loop;
use extra::timer; use extra::timer;
use geom::matrix::identity; use geom::matrix::identity;
@ -35,6 +37,8 @@ use layers::layers::{ImageData, WithDataFn};
use layers::layers::{TextureLayerKind, TextureLayer, TextureManager}; use layers::layers::{TextureLayerKind, TextureLayer, TextureManager};
use layers::rendergl; use layers::rendergl;
use layers::scene::Scene; use layers::scene::Scene;
use opengles::gl2;
use png;
use servo_util::{time, url}; use servo_util::{time, url};
use servo_util::time::profile; use servo_util::time::profile;
use servo_util::time::ProfilerChan; use servo_util::time::ProfilerChan;
@ -464,6 +468,8 @@ impl CompositorTask {
}; };
let profiler_chan = self.profiler_chan.clone(); let profiler_chan = self.profiler_chan.clone();
let write_png = self.opts.output_file.is_some();
let exit = self.opts.exit_after_load;
let composite = || { let composite = || {
do profile(time::CompositingCategory, profiler_chan.clone()) { do profile(time::CompositingCategory, profiler_chan.clone()) {
debug!("compositor: compositing"); debug!("compositor: compositing");
@ -474,7 +480,40 @@ impl CompositorTask {
rendergl::render_scene(context, scene); rendergl::render_scene(context, scene);
} }
// Render to PNG. We must read from the back buffer (ie, before
// window.present()) as OpenGL ES 2 does not have glReadBuffer().
if write_png {
let (width, height) = (window_size.width as uint, window_size.height as uint);
let path = Path(*self.opts.output_file.get_ref());
let mut pixels = gl2::read_pixels(0, 0,
width as gl2::GLsizei,
height as gl2::GLsizei,
gl2::RGB, gl2::UNSIGNED_BYTE);
// flip image vertically (texture is upside down)
let orig_pixels = pixels.clone();
let stride = width * 3;
for uint::range(0, height) |y| {
let dst_start = y * stride;
let src_start = (height - y - 1) * stride;
vec::bytes::copy_memory(pixels.mut_slice(dst_start, dst_start + stride),
orig_pixels.slice(src_start, src_start + stride),
stride);
}
let img = png::Image {
width: width as u32,
height: height as u32,
color_type: png::RGB8,
pixels: pixels,
};
let res = png::store_png(&img, &path);
assert!(res.is_ok());
*done = true;
}
window.present(); window.present();
if exit { *done = true; }
}; };
// When the user scrolls, move the layer around. // When the user scrolls, move the layer around.
@ -548,12 +587,6 @@ impl CompositorTask {
*recomposite = true; *recomposite = true;
} }
if self.opts.exit_after_load {
do window.set_finished_callback || {
*done = true;
}
}
// Enter the main event loop. // Enter the main event loop.
while !*done { while !*done {
// Check for new messages coming from the rendering task. // Check for new messages coming from the rendering task.

View file

@ -21,6 +21,7 @@ extern mod js;
extern mod layers; extern mod layers;
extern mod newcss (name = "css"); extern mod newcss (name = "css");
extern mod opengles; extern mod opengles;
extern mod png;
extern mod script; extern mod script;
extern mod servo_net (name = "net"); extern mod servo_net (name = "net");
extern mod servo_msg (name = "msg"); extern mod servo_msg (name = "msg");

@ -1 +1 @@
Subproject commit 17bd4bbc04942e7de9eae76c0f8a76dfcb3dc9fc Subproject commit b5cb5593f4938a578eebda56c905bbaff33efe66

@ -1 +1 @@
Subproject commit e2b6deb09da651aa188f154394d63f45188de653 Subproject commit 8cf4744b6c17a1df5f4f056313d32fb6e5af959e