diff options
author | bors-servo <metajack+bors@gmail.com> | 2014-12-11 17:09:54 -0700 |
---|---|---|
committer | bors-servo <metajack+bors@gmail.com> | 2014-12-11 17:09:54 -0700 |
commit | 15187cb4512baa57902ac07fe902df14b3c99500 (patch) | |
tree | 55fed5688389d26e6b6eafd6b2e256523056894b | |
parent | d31237f3439e5e5d4055b3a9e53eaeee4f3cdf2c (diff) | |
parent | 9d192de63dfff70dacd9372f6523d0852f865c49 (diff) | |
download | servo-15187cb4512baa57902ac07fe902df14b3c99500.tar.gz servo-15187cb4512baa57902ac07fe902df14b3c99500.zip |
auto merge of #4327 : glennw/servo/glutin-android, r=larsbergstrom,larsbergstrom
-rw-r--r-- | .gitmodules | 3 | ||||
-rw-r--r-- | components/servo/.cargo/config | 2 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 4 | ||||
-rw-r--r-- | components/servo/main.rs | 172 | ||||
-rw-r--r-- | ports/glutin/window.rs | 113 | ||||
-rw-r--r-- | python/servo/build_commands.py | 26 | ||||
-rw-r--r-- | python/servo/command_base.py | 12 | ||||
m--------- | support/android-rs-glue | 0 |
8 files changed, 254 insertions, 78 deletions
diff --git a/.gitmodules b/.gitmodules index 0b77f02726e..cbc43176bd7 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "tests/wpt/web-platform-tests"] path = tests/wpt/web-platform-tests url = https://github.com/servo/web-platform-tests.git +[submodule "support/android-rs-glue"] + path = support/android-rs-glue + url = https://github.com/servo/android-rs-glue diff --git a/components/servo/.cargo/config b/components/servo/.cargo/config new file mode 100644 index 00000000000..5ad542ef4e2 --- /dev/null +++ b/components/servo/.cargo/config @@ -0,0 +1,2 @@ +[target.arm-linux-androideabi] +linker = "../../support/android-rs-glue/apk-builder/target/apk-builder" diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index 6abc4ad6e76..bb04bd528af 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -17,7 +17,7 @@ dependencies = [ [[package]] name = "android_glue" version = "0.0.1" -source = "git+https://github.com/tomaka/android-rs-glue#fe9acb5bd465da1df4561e2bd4ebcc6d305134a4" +source = "git+https://github.com/tomaka/android-rs-glue#cac0adb90bc576758f1ebf3b5e567961b1605c1f" dependencies = [ "compile_msg 0.1.1 (git+https://github.com/huonw/compile_msg)", ] @@ -299,7 +299,7 @@ dependencies = [ [[package]] name = "glutin" version = "0.0.2" -source = "git+https://github.com/tomaka/glutin#c95b778e2c077c0b410f366ad3c85a93c40c6095" +source = "git+https://github.com/tomaka/glutin#749c47d8c20af078b06e8506b68a54e3799c1a8b" dependencies = [ "android_glue 0.0.1 (git+https://github.com/tomaka/android-rs-glue)", "cocoa 0.1.1 (git+https://github.com/servo/rust-cocoa)", diff --git a/components/servo/main.rs b/components/servo/main.rs index a6d7f28db73..2176461bb46 100644 --- a/components/servo/main.rs +++ b/components/servo/main.rs @@ -5,103 +5,169 @@ #![comment = "The Servo Parallel Browser Project"] #![license = "MPL"] +#![feature(phase)] + #![deny(unused_imports)] #![deny(unused_variables)] +#[cfg(target_os="android")] +extern crate libc; + extern crate servo; extern crate native; extern crate time; extern crate "util" as servo_util; -#[cfg(all(feature = "glutin",not(any(test,target_os="android"))))] +#[cfg(all(feature = "glutin",not(test)))] extern crate "glutin_app" as app; -#[cfg(all(feature = "glfw_app",not(any(test,target_os="android"))))] +#[cfg(all(feature = "glfw_app",not(test)))] extern crate "glfw_app" as app; -#[cfg(not(any(test,target_os="android")))] +#[cfg(not(test))] extern crate compositing; -#[cfg(not(any(test,target_os="android")))] +#[cfg(target_os="android")] +#[phase(plugin, link)] +extern crate android_glue; + +#[cfg(target_os="android")] +use libc::c_int; + +#[cfg(not(test))] use servo_util::opts; -#[cfg(not(any(test,target_os="android")))] +#[cfg(not(test))] use servo_util::rtinstrument; -#[cfg(not(any(test,target_os="android")))] +#[cfg(not(test))] use servo::Browser; -#[cfg(not(any(test,target_os="android")))] +#[cfg(not(test))] use compositing::windowing::{IdleWindowEvent, InitializeCompositingWindowEvent, ResizeWindowEvent}; -#[cfg(not(any(test,target_os="android")))] +#[cfg(not(test))] use compositing::windowing::{WindowEvent}; #[cfg(not(any(test,target_os="android")))] use std::os; -#[cfg(not(any(test,target_os="android")))] +#[cfg(not(test))] struct BrowserWrapper { browser: Browser<app::window::Window>, } -#[cfg(not(any(test,target_os="android")))] -#[start] -#[allow(dead_code)] -fn start(argc: int, argv: *const *const u8) -> int { - native::start(argc, argv, proc() { - if opts::from_cmdline_args(os::args().as_slice()) { - let window = if opts::get().headless { - None - } else { - Some(app::create_window()) - }; +#[cfg(target_os="android")] +android_start!(main) - let mut browser = BrowserWrapper { - browser: Browser::new(window.clone()), - }; +#[cfg(target_os="android")] +fn get_args() -> Vec<String> { + vec![ + "servo".to_string(), + "http://en.wikipedia.org/wiki/Rust".to_string() + ] +} - match window { - None => {} - Some(ref window) => { - unsafe { - window.set_nested_event_loop_listener(&mut browser); - } +#[cfg(not(target_os="android"))] +fn get_args() -> Vec<String> { + os::args() +} + +#[cfg(target_os="android")] +fn redirect_output(file_no: c_int) { + use libc::funcs::posix88::unistd::{pipe, dup2}; + use libc::funcs::posix88::stdio::fdopen; + use libc::c_char; + use libc::funcs::c95::stdio::fgets; + use std::mem; + use std::c_str::CString; + + unsafe { + let mut pipes: [c_int, ..2] = [ 0, 0 ]; + pipe(pipes.as_mut_ptr()); + dup2(pipes[1], file_no); + let input_file = "r".with_c_str(|mode| { + fdopen(pipes[0], mode) + }); + spawn(proc() { + loop { + let mut read_buffer: [c_char, ..1024] = mem::zeroed(); + fgets(read_buffer.as_mut_ptr(), read_buffer.len() as i32, input_file); + let cs = CString::new(read_buffer.as_ptr(), false); + match cs.as_str() { + Some(s) => android_glue::write_log(s), + None => {}, } } + }); + } +} - browser.browser.handle_event(InitializeCompositingWindowEvent); +#[cfg(target_os="android")] +fn setup_logging() { + use libc::consts::os::posix88::{STDERR_FILENO, STDOUT_FILENO}; + //os::setenv("RUST_LOG", "servo,gfx,msg,util,layers,js,glut,std,rt,extra"); + redirect_output(STDERR_FILENO); + redirect_output(STDOUT_FILENO); +} - loop { - let should_continue = match window { - None => browser.browser.handle_event(IdleWindowEvent), - Some(ref window) => { - let event = window.wait_events(); - browser.browser.handle_event(event) - } - }; - if !should_continue { - break +#[cfg(not(target_os="android"))] +fn setup_logging() { +} + +fn main() { + if opts::from_cmdline_args(get_args().as_slice()) { + setup_logging(); + + let window = if opts::get().headless { + None + } else { + Some(app::create_window()) + }; + + let mut browser = BrowserWrapper { + browser: Browser::new(window.clone()), + }; + + match window { + None => {} + Some(ref window) => { + unsafe { + window.set_nested_event_loop_listener(&mut browser); } } + } - match window { - None => {} + browser.browser.handle_event(InitializeCompositingWindowEvent); + + loop { + let should_continue = match window { + None => browser.browser.handle_event(IdleWindowEvent), Some(ref window) => { - unsafe { - window.remove_nested_event_loop_listener(); - } + let event = window.wait_events(); + browser.browser.handle_event(event) } + }; + if !should_continue { + break } + }; - let BrowserWrapper { - browser - } = browser; - browser.shutdown(); - - rtinstrument::teardown(); + match window { + None => {} + Some(ref window) => { + unsafe { + window.remove_nested_event_loop_listener(); + } + } } - }) + + let BrowserWrapper { + browser + } = browser; + browser.shutdown(); + + rtinstrument::teardown(); + } } -#[cfg(not(any(test,target_os="android")))] impl app::NestedEventLoopListener for BrowserWrapper { fn handle_event_from_nested_event_loop(&mut self, event: WindowEvent) -> bool { let is_resize = match event { diff --git a/ports/glutin/window.rs b/ports/glutin/window.rs index f9d4dfdfa5d..a7e1eebc24c 100644 --- a/ports/glutin/window.rs +++ b/ports/glutin/window.rs @@ -15,11 +15,11 @@ use compositing::windowing::{Forward, Back}; use geom::point::{Point2D, TypedPoint2D}; use geom::scale_factor::ScaleFactor; use geom::size::TypedSize2D; -use gleam::gl; use layers::geometry::DevicePixel; use layers::platform::surface::NativeGraphicsMetadata; use msg::compositor_msg::{IdlePaintState, PaintState, PaintingPaintState}; use msg::compositor_msg::{FinishedLoading, Blank, Loading, PerformingLayout, ReadyState}; +use msg::constellation_msg::LoadData; use std::cell::{Cell, RefCell}; use std::rc::Rc; use time::{mod, Timespec}; @@ -28,14 +28,14 @@ use util::opts::{RenderApi, Mesa, OpenGL}; use glutin; use NestedEventLoopListener; +#[cfg(not(target_os="android"))] +use gleam::gl; + #[cfg(target_os="linux")] use std::ptr; struct HeadlessContext { - // Although currently unused, this context needs to be stored. - // Otherwise, its drop() is called, deleting the mesa context - // before it can be used. - _context: glutin::HeadlessContext, + context: glutin::HeadlessContext, size: TypedSize2D<DevicePixel, uint>, } @@ -72,6 +72,28 @@ pub struct Window { last_title_set_time: Cell<Timespec>, } +#[cfg(not(target_os="android"))] +fn load_gl_functions(glutin: &WindowHandle) { + match glutin { + &Windowed(ref window) => gl::load_with(|s| window.get_proc_address(s)), + &Headless(ref headless) => gl::load_with(|s| headless.context.get_proc_address(s)), + } +} + +#[cfg(target_os="android")] +fn load_gl_functions(_glutin: &WindowHandle) { +} + +#[cfg(not(target_os="android"))] +fn gl_version() -> (uint, uint) { + (3, 0) +} + +#[cfg(target_os="android")] +fn gl_version() -> (uint, uint) { + (2, 0) +} + impl Window { /// Creates a new window. pub fn new(is_foreground: bool, size: TypedSize2D<DevicePixel, uint>, render_api: RenderApi) @@ -85,14 +107,12 @@ impl Window { let glutin_window = glutin::WindowBuilder::new() .with_title("Servo [glutin]".to_string()) .with_dimensions(window_size.width, window_size.height) - .with_gl_version((3, 0)) + .with_gl_version(gl_version()) .with_visibility(is_foreground) .build() .unwrap(); unsafe { glutin_window.make_current() }; - gl::load_with(|s| glutin_window.get_proc_address(s)); - Windowed(glutin_window) } Mesa => { @@ -101,15 +121,15 @@ impl Window { let headless_context = headless_builder.build().unwrap(); unsafe { headless_context.make_current() }; - gl::load_with(|s| headless_context.get_proc_address(s)); - Headless(HeadlessContext { - _context: headless_context, + context: headless_context, size: size, }) } }; + load_gl_functions(&glutin); + let window = Window { glutin: glutin, event_queue: RefCell::new(vec!()), @@ -184,6 +204,22 @@ impl WindowMethods for Window { ScaleFactor(1.0) } + fn set_page_title(&self, _: Option<String>) { + // TODO(gw) + } + + fn set_page_load_data(&self, _: LoadData) { + // TODO(gw) + } + + fn load_end(&self) { + // TODO(gw) + } + + fn prepare_for_composite(&self) -> bool { + true + } + #[cfg(target_os="linux")] fn native_metadata(&self) -> NativeGraphicsMetadata { match self.glutin { @@ -209,6 +245,14 @@ impl WindowMethods for Window { } } } + + #[cfg(target_os="android")] + fn native_metadata(&self) -> NativeGraphicsMetadata { + use egl::egl::GetCurrentDisplay; + NativeGraphicsMetadata { + display: GetCurrentDisplay(), + } + } } impl Window { @@ -416,7 +460,7 @@ impl Window { match self.glutin { Windowed(ref window) => { let mut close_event = false; - for event in window.poll_events() { + for event in window.wait_events() { close_event = self.handle_window_event(event); if close_event { break; @@ -453,3 +497,48 @@ impl CompositorProxy for GlutinCompositorProxy { } as Box<CompositorProxy+Send> } } + +// These functions aren't actually called. They are here as a link +// hack because Skia references them. + +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn glBindVertexArrayOES(_array: uint) +{ + unimplemented!() +} + +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn glDeleteVertexArraysOES(_n: int, _arrays: *const ()) +{ + unimplemented!() +} + +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn glGenVertexArraysOES(_n: int, _arrays: *const ()) +{ + unimplemented!() +} + +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn glRenderbufferStorageMultisampleIMG(_: int, _: int, _: int, _: int, _: int) +{ + unimplemented!() +} + +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn glFramebufferTexture2DMultisampleIMG(_: int, _: int, _: int, _: int, _: int, _: int) +{ + unimplemented!() +} + +#[allow(non_snake_case)] +#[no_mangle] +pub extern "C" fn glDiscardFramebufferEXT(_: int, _: int, _: *const ()) +{ + unimplemented!() +} diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py index cade77fbbd7..a283b0d6c91 100644 --- a/python/servo/build_commands.py +++ b/python/servo/build_commands.py @@ -46,6 +46,8 @@ class MachCommands(CommandBase): android = self.config["build"]["android"] opts = [] + features = [] + if release: opts += ["--release"] if target: @@ -54,8 +56,17 @@ class MachCommands(CommandBase): opts += ["-j", jobs] if verbose: opts += ["-v"] + if android: + # Ensure the APK builder submodule has been built first + apk_builder_dir = "support/android-rs-glue" + with cd(path.join(apk_builder_dir, "apk-builder")): + subprocess.call(["cargo", "build"], env=self.build_env()) + + # FIXME: This can be simplified when glutin becomes the default + # and glfw has been removed. + opts += ["--target", "arm-linux-androideabi", "--no-default-features"] + features += ["glutin"] - features = [] if debug_mozjs or self.config["build"]["debug-mozjs"]: features += ["script/debugmozjs"] @@ -72,16 +83,9 @@ class MachCommands(CommandBase): env=self.build_env()) env['OPENSSL_PATH'] = path.join(self.android_support_dir(), "openssl-1.0.1j") - make_opts = [] - if opts: - make_opts += ["CARGO_OPTS=" + " ".join(opts)] - status = subprocess.call( - ["make", "-C", "ports/android"] + make_opts, - env=env) - else: - status = subprocess.call( - ["cargo", "build"] + opts, - env=env, cwd=self.servo_crate()) + status = subprocess.call( + ["cargo", "build"] + opts, + env=env, cwd=self.servo_crate()) elapsed = time() - build_start print("Build completed in %0.2fs" % elapsed) diff --git a/python/servo/command_base.py b/python/servo/command_base.py index 2af5fcd63c1..32c6b2538c9 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -140,6 +140,18 @@ class CommandBase(object): if self.config["android"]["toolchain"]: env["ANDROID_TOOLCHAIN"] = self.config["android"]["toolchain"] + # FIXME: These are set because they are the variable names that + # android-rs-glue expects. However, other submodules have makefiles that + # reference the env var names above. Once glutin is enabled and set as + # the default, we could modify the subproject makefiles to use the names + # below and remove the vars above, to avoid duplication. + if "ANDROID_SDK" in env: + env["ANDROID_HOME"] = env["ANDROID_SDK"] + if "ANDROID_NDK" in env: + env["NDK_HOME"] = env["ANDROID_NDK"] + if "ANDROID_TOOLCHAIN" in env: + env["NDK_STANDALONE"] = env["ANDROID_TOOLCHAIN"] + return env def servo_crate(self): diff --git a/support/android-rs-glue b/support/android-rs-glue new file mode 160000 +Subproject e59b03e0d74e78852f8658aa038e1ae54758ba6 |