aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <metajack+bors@gmail.com>2014-12-11 17:09:54 -0700
committerbors-servo <metajack+bors@gmail.com>2014-12-11 17:09:54 -0700
commit15187cb4512baa57902ac07fe902df14b3c99500 (patch)
tree55fed5688389d26e6b6eafd6b2e256523056894b
parentd31237f3439e5e5d4055b3a9e53eaeee4f3cdf2c (diff)
parent9d192de63dfff70dacd9372f6523d0852f865c49 (diff)
downloadservo-15187cb4512baa57902ac07fe902df14b3c99500.tar.gz
servo-15187cb4512baa57902ac07fe902df14b3c99500.zip
auto merge of #4327 : glennw/servo/glutin-android, r=larsbergstrom,larsbergstrom
-rw-r--r--.gitmodules3
-rw-r--r--components/servo/.cargo/config2
-rw-r--r--components/servo/Cargo.lock4
-rw-r--r--components/servo/main.rs172
-rw-r--r--ports/glutin/window.rs113
-rw-r--r--python/servo/build_commands.py26
-rw-r--r--python/servo/command_base.py12
m---------support/android-rs-glue0
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