Remove the gonk port

This commit is contained in:
Lars Bergstrom 2016-05-27 13:51:09 -05:00
parent 3ec20d9cf5
commit 02c7e06d54
19 changed files with 5 additions and 4050 deletions

View file

@ -4,7 +4,7 @@
Servo is a prototype web browser engine written in the Servo is a prototype web browser engine written in the
[Rust](https://github.com/rust-lang/rust) language. It is currently developed on [Rust](https://github.com/rust-lang/rust) language. It is currently developed on
64bit OS X, 64bit Linux, Android, and Gonk (Firefox OS). 64bit OS X, 64bit Linux, and Android.
Servo welcomes contribution from everyone. See Servo welcomes contribution from everyone. See
[`CONTRIBUTING.md`](CONTRIBUTING.md) and [`HACKING_QUICKSTART.md`](docs/HACKING_QUICKSTART.md) [`CONTRIBUTING.md`](CONTRIBUTING.md) and [`HACKING_QUICKSTART.md`](docs/HACKING_QUICKSTART.md)

View file

@ -414,7 +414,6 @@ pub fn multiprocess() -> bool {
enum UserAgent { enum UserAgent {
Desktop, Desktop,
Android, Android,
Gonk,
} }
#[derive(Clone, Debug, Eq, Deserialize, PartialEq, Serialize)] #[derive(Clone, Debug, Eq, Deserialize, PartialEq, Serialize)]
@ -453,21 +452,13 @@ fn default_user_agent_string(agent: UserAgent) -> String {
UserAgent::Android => { UserAgent::Android => {
"Mozilla/5.0 (Android; Mobile; rv:37.0) Servo/1.0 Firefox/37.0" "Mozilla/5.0 (Android; Mobile; rv:37.0) Servo/1.0 Firefox/37.0"
} }
UserAgent::Gonk => {
"Mozilla/5.0 (Mobile; rv:37.0) Servo/1.0 Firefox/37.0"
}
}.to_owned() }.to_owned()
} }
#[cfg(target_os = "android")] #[cfg(target_os = "android")]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::Android; const DEFAULT_USER_AGENT: UserAgent = UserAgent::Android;
// FIXME: This requires https://github.com/servo/servo/issues/7138 to provide the #[cfg(not(target_os = "android"))]
// correct string in Gonk builds (i.e., it will never be chosen today).
#[cfg(target_os = "gonk")]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::Gonk;
#[cfg(not(any(target_os = "android", target_os = "gonk")))]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::Desktop; const DEFAULT_USER_AGENT: UserAgent = UserAgent::Desktop;
pub fn default_opts() -> Opts { pub fn default_opts() -> Opts {
@ -561,7 +552,7 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
opts.optopt("", "resolution", "Set window resolution.", "800x600"); opts.optopt("", "resolution", "Set window resolution.", "800x600");
opts.optopt("u", opts.optopt("u",
"user-agent", "user-agent",
"Set custom user agent string (or android / gonk / desktop for platform default)", "Set custom user agent string (or android / desktop for platform default)",
"NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)"); "NCSA Mosaic/1.0 (X11;SunOS 4.1.4 sun4m)");
opts.optflag("M", "multiprocess", "Run in multiprocess mode"); opts.optflag("M", "multiprocess", "Run in multiprocess mode");
opts.optflag("S", "sandbox", "Run in a sandbox if multiprocess"); opts.optflag("S", "sandbox", "Run in a sandbox if multiprocess");
@ -743,7 +734,6 @@ pub fn from_cmdline_args(args: &[String]) -> ArgumentParsingResult {
let user_agent = match opt_match.opt_str("u") { let user_agent = match opt_match.opt_str("u") {
Some(ref ua) if ua == "android" => default_user_agent_string(UserAgent::Android), Some(ref ua) if ua == "android" => default_user_agent_string(UserAgent::Android),
Some(ref ua) if ua == "gonk" => default_user_agent_string(UserAgent::Gonk),
Some(ref ua) if ua == "desktop" => default_user_agent_string(UserAgent::Desktop), Some(ref ua) if ua == "desktop" => default_user_agent_string(UserAgent::Desktop),
Some(ua) => ua, Some(ua) => ua,
None => default_user_agent_string(DEFAULT_USER_AGENT), None => default_user_agent_string(DEFAULT_USER_AGENT),

View file

@ -55,8 +55,6 @@
* Embedding implementation for the Chrome Embedding Framework (CEF) API. * Embedding implementation for the Chrome Embedding Framework (CEF) API.
* glutin * glutin
* Embedding implementation for the `glutin` windowing library. * Embedding implementation for the `glutin` windowing library.
* gonk
* Embedding implementation for the Firefox OS devices.
* python * python
* servo * servo
* Implementations of servo-specific mach commands. * Implementations of servo-specific mach commands.

View file

@ -1,3 +0,0 @@
[target.arm-linux-androideabi]
ar = "arm-linux-androideabi-ar"
linker = "./fake-ld.sh"

2456
ports/gonk/Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,29 +0,0 @@
[package]
name = "b2s"
version = "0.0.1"
authors = ["The Servo Project Developers"]
build = "build.rs"
[dependencies]
compositing = {path = "../../components/compositing"}
layers = {git = "https://github.com/servo/rust-layers", features = ["plugins"]}
msg = {path = "../../components/msg"}
script = {path = "../../components/script"}
script_traits = {path = "../../components/script_traits"}
style_traits = {path = "../../components/style_traits"}
net_traits = {path = "../../components/net_traits"}
gfx = {path = "../../components/gfx"}
layout = {path = "../../components/layout"}
devtools = {path = "../../components/devtools"}
servo = {path = "../../components/servo", default-features = false}
profile = {path = "../../components/profile"}
util = {path = "../../components/util"}
env_logger = "0.3"
url = {version = "1.0.0", features = ["heap_size"]}
time = "0.1.17"
errno = "0.1"
libc = "0.2"
euclid = {version = "0.6.4", features = ["plugins"]}
gleam = "0.2.8"
servo-egl = "0.2"

View file

@ -1,89 +0,0 @@
# Instructions for building the Gonk port
## Set up an android toolchain and NDK
Follow the steps [here](https://github.com/servo/servo/wiki/Building-for-Android) for setting up the Android NDK
and toolchain.
## Bootstrap B2G
We have a bootstrap of the require B2G prebuilt binaries, assuming that you are targeting a Flame device.
```
curl https://servo-rust.s3.amazonaws.com/B2G/B2G.tgz
tar zxvf B2G.tgz
```
## Build B2G
If you are not using a Flame or just would like to have a local build of the binaries, you can also build B2G locally. Note: this will take a long time and will take around 20GB of space
Disable the screen timeout on the device, and connect to wifi. Also connect it to your computer
with remote debugging enabled.
```
git clone https://github.com/mozilla-b2g/B2G
./config.sh flame-kk
```
If behind a firewall, put the following in your gitconfig:
```
[url "https://github"]
insteadOf = git://github
[url "https://git.mozilla.org/external/caf"]
insteadOf = git://codeaurora.org
```
Then run
```
./build.sh libssl libsuspend libz libGLESv2 toolbox libhardware
```
## Build B2S
Either set the corresponding `b2g` key in `.servobuild` to the path to the B2G bootstrap or clone (along with), or set the `$GONKDIR` environment variable.
Do the same for the `ndk` and `toolchain` keys (`$ANDROID_NDK` and `$ANDROID_TOOLCHAIN` respectively)
Run `./mach build-gonk` from the root directory
## Copy the files to the Flame
To reduce the size of libmozjs.so (`target/arm-linux-androideabi/build/mozjs-sys-*/out/libmozjs.so`),
you can run `strip` on it. Use the one in your toolchain (`$ANDROID_TOOLCHAIN/bin/arm-linux-androideabi-strip libmozjs.so`).
Make sure the device is on, connected to wifi, with high or no screen timeout.
```
# Switch to a read-write system
adb remount
# Copy mozjs
adb push /path/to/stripped/mozjs.so system/lib
# Copy b2s
adb push target/arm-linux-androideabi system/bin
# Copy resources
adb shell mkdir sdcard/servo
adb push resources sdcard/servo
```
## Run B2S
Make sure you're still connected to wifi
```
adb shell stop b2g
adb shell "echo 127 > /sys/class/leds/lcd-backlight/brightness”
adb shell start b2g
```
Now run `adb shell`, `cd` to `system/bin`, and run `./b2s <url>`
If the screen keeps alternating between B2G and B2S, run `adb shell stop b2g` (you can restart it later).

View file

@ -1,16 +0,0 @@
/* 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/. */
use std::env;
use std::process::Command;
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let result = Command::new("make")
.args(&["-f", "makefile.cargo"])
.status()
.unwrap();
assert!(result.success());
println!("cargo:rustc-flags=-L native={}", out_dir);
}

View file

@ -1,8 +0,0 @@
#!/bin/bash
# Add the position-independent executable flag if not building a shared lib.
if echo $@ | grep -qv " -shared"
then
PIE_FLAG="-pie"
fi
arm-linux-androideabi-g++ $@ $LDFLAGS $PIE_FLAG -lGLESv2 -L$GONKDIR/backup-flame/system/lib/

View file

@ -1,25 +0,0 @@
ifeq (androideabi,$(findstring androideabi,$(TARGET)))
CXX := $(TARGET)-g++
AR := $(TARGET)-ar
CFLAGS := -fPIC -O2
else
CXX ?= g++
AR ?= ar
endif
CSRC := src/native_window_glue.cpp
OBJS := $(CSRC:%.cpp=$(OUT_DIR)/%.o)
.PHONY: all
all: $(OUT_DIR)/libnative_window_glue.a
$(OUT_DIR)/%.o: %.cpp
mkdir -p `dirname $@` && $(CXX) $< -o $@ -c $(CXXFLAGS) $(CPPFLAGS)
$(OUT_DIR)/libnative_window_glue.a: $(OBJS)
$(AR) rcs $@ $<

View file

@ -1,251 +0,0 @@
/* 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/. */
use compositing::windowing::{WindowEvent, MouseWindowEvent};
use errno::errno;
use euclid::point::Point2D;
use libc::{c_int, c_long, time_t};
use script_traits::{MouseButton, TouchEventType};
use std::fs::File;
use std::io::Read;
use std::mem::{size_of, transmute, zeroed};
use std::os::unix::io::AsRawFd;
use std::path::Path;
use std::sync::mpsc::Sender;
use std::thread;
extern {
// XXX: no variadic form in std libs?
fn ioctl(fd: c_int, req: c_int, ...) -> c_int;
}
#[repr(C)]
struct linux_input_event {
sec: time_t,
msec: c_long,
evt_type: u16,
code: u16,
value: i32,
}
#[repr(C)]
struct linux_input_absinfo {
value: i32,
minimum: i32,
maximum: i32,
fuzz: i32,
flat: i32,
resolution: i32,
}
const IOC_NONE: c_int = 0;
const IOC_WRITE: c_int = 1;
const IOC_READ: c_int = 2;
fn ioc(dir: c_int, ioctype: c_int, nr: c_int, size: c_int) -> c_int {
dir << 30 | size << 16 | ioctype << 8 | nr
}
fn ev_ioc_g_abs(abs: u16) -> c_int {
ioc(IOC_READ, 'E' as c_int, (0x40 + abs) as i32, size_of::<linux_input_absinfo>() as i32)
}
const EV_SYN: u16 = 0;
const EV_ABS: u16 = 3;
const EV_REPORT: u16 = 0;
const ABS_MT_SLOT: u16 = 0x2F;
const ABS_MT_TOUCH_MAJOR: u16 = 0x30;
const ABS_MT_TOUCH_MINOR: u16 = 0x31;
const ABS_MT_WIDTH_MAJOR: u16 = 0x32;
const ABS_MT_WIDTH_MINOR: u16 = 0x33;
const ABS_MT_ORIENTATION: u16 = 0x34;
const ABS_MT_POSITION_X: u16 = 0x35;
const ABS_MT_POSITION_Y: u16 = 0x36;
const ABS_MT_TRACKING_ID: u16 = 0x39;
struct InputSlot {
tracking_id: i32,
x: i32,
y: i32,
}
fn dist(x1: i32, x2: i32, y1: i32, y2: i32) -> f32 {
let deltaX = (x2 - x1) as f32;
let deltaY = (y2 - y1) as f32;
(deltaX * deltaX + deltaY * deltaY).sqrt()
}
fn read_input_device(device_path: &Path,
sender: &Sender<WindowEvent>) {
let mut device = match File::open(device_path) {
Ok(dev) => dev,
Err(e) => {
println!("Couldn't open device! {}", e);
return;
},
};
let fd = device.as_raw_fd();
let mut x_info: linux_input_absinfo = unsafe { zeroed() };
let mut y_info: linux_input_absinfo = unsafe { zeroed() };
unsafe {
let ret = ioctl(fd, ev_ioc_g_abs(ABS_MT_POSITION_X), &mut x_info);
if ret < 0 {
println!("Couldn't get ABS_MT_POSITION_X info {} {}", ret, errno());
}
}
unsafe {
let ret = ioctl(fd, ev_ioc_g_abs(ABS_MT_POSITION_Y), &mut y_info);
if ret < 0 {
println!("Couldn't get ABS_MT_POSITION_Y info {} {}", ret, errno());
}
}
let touchWidth = x_info.maximum - x_info.minimum;
let touchHeight = y_info.maximum - y_info.minimum;
println!("xMin: {}, yMin: {}, touchWidth: {}, touchHeight: {}",
x_info.minimum, y_info.minimum, touchWidth, touchHeight);
// XXX: Why isn't size_of treated as constant?
// let buf: [u8; (16 * size_of::<linux_input_event>())];
let mut buf: [u8; (16 * 16)] = unsafe { zeroed() };
let mut slots: [InputSlot; 10] = unsafe { zeroed() };
for slot in slots.iter_mut() {
slot.tracking_id = -1;
}
let mut last_x = 0;
let mut last_y = 0;
let mut first_x = 0;
let mut first_y = 0;
let mut last_dist: f32 = 0f32;
let mut touch_count: i32 = 0;
let mut current_slot: usize = 0;
// XXX: Need to use the real dimensions of the screen
let screen_dist = dist(0, 480, 854, 0);
loop {
let read = match device.read(&mut buf) {
Ok(count) => {
assert!(count % size_of::<linux_input_event>() == 0,
"Unexpected input device read length!");
count
},
Err(e) => {
println!("Couldn't read device! {}", e);
return;
}
};
let count = read / size_of::<linux_input_event>();
let events: *mut linux_input_event = unsafe { transmute(buf.as_mut_ptr()) };
let mut tracking_updated = false;
for idx in 0..(count as isize) {
let event: &linux_input_event = unsafe { transmute(events.offset(idx)) };
match (event.evt_type, event.code) {
(EV_SYN, EV_REPORT) => {
let slotA = &slots[0];
if tracking_updated {
tracking_updated = false;
if slotA.tracking_id == -1 {
println!("Touch up");
let delta_x = slotA.x - first_x;
let delta_y = slotA.y - first_y;
let dist = delta_x * delta_x + delta_y * delta_y;
if dist < 16 {
let click_pt = Point2D::typed(slotA.x as f32, slotA.y as f32);
println!("Dispatching click!");
sender.send(
WindowEvent::MouseWindowEventClass(
MouseWindowEvent::MouseDown(MouseButton::Left, click_pt))).ok().unwrap();
sender.send(
WindowEvent::MouseWindowEventClass(
MouseWindowEvent::MouseUp(MouseButton::Left, click_pt))).ok().unwrap();
sender.send(
WindowEvent::MouseWindowEventClass(
MouseWindowEvent::Click(MouseButton::Left, click_pt))).ok().unwrap();
}
} else {
println!("Touch down");
last_x = slotA.x;
last_y = slotA.y;
first_x = slotA.x;
first_y = slotA.y;
if touch_count >= 2 {
let slotB = &slots[1];
last_dist = dist(slotA.x, slotB.x, slotA.y, slotB.y);
}
}
} else {
println!("Touch move x: {}, y: {}", slotA.x, slotA.y);
sender.send(
WindowEvent::Scroll(Point2D::typed((slotA.x - last_x) as f32, (slotA.y - last_y) as f32),
Point2D::typed(slotA.x, slotA.y),
TouchEventType::Move)).ok().unwrap();
last_x = slotA.x;
last_y = slotA.y;
if touch_count >= 2 {
let slotB = &slots[1];
let cur_dist = dist(slotA.x, slotB.x, slotA.y, slotB.y);
println!("Zooming {} {} {} {}",
cur_dist, last_dist, screen_dist,
((screen_dist + (cur_dist - last_dist)) / screen_dist));
sender.send(
WindowEvent::Zoom((screen_dist + (cur_dist - last_dist)) /
screen_dist)).ok().unwrap();
last_dist = cur_dist;
}
}
},
(EV_SYN, _) => println!("Unknown SYN code {}", event.code),
(EV_ABS, ABS_MT_SLOT) => {
if (event.value as usize) < slots.len() {
current_slot = event.value as usize;
} else {
println!("Invalid slot! {}", event.value);
}
},
(EV_ABS, ABS_MT_TOUCH_MAJOR) => (),
(EV_ABS, ABS_MT_TOUCH_MINOR) => (),
(EV_ABS, ABS_MT_WIDTH_MAJOR) => (),
(EV_ABS, ABS_MT_WIDTH_MINOR) => (),
(EV_ABS, ABS_MT_ORIENTATION) => (),
(EV_ABS, ABS_MT_POSITION_X) => {
slots[current_slot].x = event.value - x_info.minimum;
},
(EV_ABS, ABS_MT_POSITION_Y) => {
slots[current_slot].y = event.value - y_info.minimum;
},
(EV_ABS, ABS_MT_TRACKING_ID) => {
let current_id = slots[current_slot].tracking_id;
if current_id != event.value &&
(current_id == -1 || event.value == -1) {
tracking_updated = true;
if event.value == -1 {
touch_count -= 1;
} else {
touch_count += 1;
}
}
slots[current_slot].tracking_id = event.value;
},
(EV_ABS, _) => println!("Unknown ABS code {}", event.code),
(_, _) => println!("Unknown event type {}", event.evt_type),
}
}
}
}
pub fn run_input_loop(event_sender: &Sender<WindowEvent>) {
let sender = event_sender.clone();
thread::spawn(move || {
// XXX need to scan all devices and read every one.
let touchinputdev = Path::new("/dev/input/event0");
read_input_device(&touchinputdev, &sender);
});
}

View file

@ -1,88 +0,0 @@
/* 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/. */
#![deny(unused_imports)]
#![deny(unused_variables)]
#![feature(box_syntax)]
#![feature(convert)]
// For FFI
#![allow(non_snake_case, dead_code)]
//! The `servo` test application.
//!
//! Creates a `Browser` instance with a simple implementation of
//! the compositor's `WindowMethods` to create a working web browser.
//!
//! This browser's implementation of `WindowMethods` is built on top
//! of [glutin], the cross-platform OpenGL utility and windowing
//! library.
//!
//! For the engine itself look next door in lib.rs.
//!
//! [glutin]: https://github.com/tomaka/glutin
extern crate compositing;
extern crate egl;
extern crate env_logger;
extern crate errno;
extern crate euclid;
extern crate gleam;
extern crate layers;
extern crate libc;
extern crate msg;
extern crate net_traits;
extern crate script_traits;
extern crate servo;
extern crate style_traits;
extern crate time;
extern crate url;
extern crate util;
#[link(name = "stlport")]
extern {}
use compositing::windowing::WindowEvent;
use servo::Browser;
use std::env;
use util::opts;
use util::panicking;
mod input;
mod window;
struct BrowserWrapper {
browser: Browser,
}
fn main() {
env_logger::init().unwrap();
// Parse the command line options and store them globally
opts::from_cmdline_args(env::args().collect::<Vec<_>>().as_slice());
panicking::initiate_panic_hook();
let window = window::Window::new();
// Our wrapper around `Browser` that also implements some
// callbacks required by the glutin window implementation.
let mut browser = BrowserWrapper {
browser: Browser::new(window.clone()),
};
input::run_input_loop(&window.event_send);
browser.browser.handle_events(vec![WindowEvent::InitializeCompositing]);
// Feed events from the window to the browser until the browser
// says to stop.
loop {
let events = window.wait_events();
let should_continue = browser.browser.handle_events(events);
if !should_continue {
break
}
}
}

View file

@ -1,74 +0,0 @@
/* 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/. */
#include <stdarg.h>
#include <stdio.h>
#include "system/window.h"
struct GonkNativeWindow {
ANativeWindow window;
int (*set_usage)(struct ANativeWindow* window, int usage);
int (*set_format)(struct ANativeWindow* window, int format);
int (*set_transform)(struct ANativeWindow* window, int transform);
int (*set_dimensions)(struct ANativeWindow* window, int w, int h);
int (*api_connect)(struct ANativeWindow* window, int api);
int (*api_disconnect)(struct ANativeWindow* window, int api);
};
// Rust doesn't support implementing variadic functions, so handle that here
extern "C" int
gnw_perform(struct ANativeWindow* window, int op, ...) {
GonkNativeWindow *gnw = (GonkNativeWindow *)window;
va_list ap;
switch (op) {
case NATIVE_WINDOW_SET_USAGE: {
int usage;
va_start(ap, op);
usage = va_arg(ap, int);
va_end(ap);
return gnw->set_usage(window, usage);
}
case NATIVE_WINDOW_SET_BUFFERS_FORMAT: {
int format;
va_start(ap, op);
format = va_arg(ap, int);
va_end(ap);
return gnw->set_format(window, format);
}
case NATIVE_WINDOW_SET_BUFFERS_TRANSFORM: {
int transform;
va_start(ap, op);
transform = va_arg(ap, int);
va_end(ap);
return gnw->set_transform(window, transform);
}
case NATIVE_WINDOW_SET_BUFFERS_DIMENSIONS: {
int w, h;
va_start(ap, op);
w = va_arg(ap, int);
h = va_arg(ap, int);
va_end(ap);
return gnw->set_dimensions(window, w, h);
}
case NATIVE_WINDOW_API_CONNECT: {
int api;
va_start(ap, op);
api = va_arg(ap, int);
va_end(ap);
return gnw->api_connect(window, api);
}
case NATIVE_WINDOW_API_DISCONNECT: {
int api;
va_start(ap, op);
api = va_arg(ap, int);
va_end(ap);
return gnw->api_disconnect(window, api);
}
default:
printf("Unsupported GonkNativeWindow operation! %d\n", op);
return -1;
}
}

View file

@ -1,883 +0,0 @@
/* 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/. */
//! A windowing implementation using gonk interfaces.
use compositing::compositor_thread::{self, CompositorProxy, CompositorReceiver};
use compositing::windowing::{WindowEvent, WindowMethods};
use egl::egl;
use egl::egl::EGLConfig;
use egl::egl::EGLContext;
use egl::egl::EGLDisplay;
use egl::egl::EGLSurface;
use egl::egl::EGLint;
use euclid::point::Point2D;
use euclid::scale_factor::ScaleFactor;
use euclid::size::{Size2D, TypedSize2D};
use gleam::gl;
use layers::geometry::DevicePixel;
use layers::platform::surface::NativeDisplay;
use libc::c_char;
use libc::c_int;
use libc::c_void;
use libc::close;
use libc::size_t;
use msg::constellation_msg::{Key, KeyModifiers};
use net_traits::net_error_list::NetError;
use std::ffi::CString;
use std::mem::{transmute, size_of, zeroed};
use std::ptr;
use std::rc::Rc;
use std::sync::mpsc::{channel, Sender, Receiver};
use style_traits::cursor::Cursor;
use url::Url;
use util::geometry::ScreenPx;
const GRALLOC_USAGE_HW_TEXTURE: c_int = 0x00000100;
const GRALLOC_USAGE_HW_RENDER: c_int = 0x00000200;
const GRALLOC_USAGE_HW_2D: c_int = 0x00000400;
const GRALLOC_USAGE_HW_COMPOSER: c_int = 0x00000800;
const GRALLOC_USAGE_HW_FB: c_int = 0x00001000;
// system/core/include/cutils/native_handle.h
#[repr(C)]
pub struct native_handle {
version: c_int,
numFds: c_int,
numInts: c_int,
data: [c_int; 0],
}
// system/core/include/system/window.h
#[repr(C)]
pub struct ANativeBase {
magic: u32,
version: u32,
reserved: [isize; 4],
incRef: extern fn(*mut ANativeBase),
decRef: extern fn(*mut ANativeBase),
}
#[repr(C)]
pub struct ANativeWindowBuffer {
common: ANativeBase,
width: c_int,
height: c_int,
stride: c_int,
format: c_int,
usage: c_int,
reserved: [*mut c_void; 2],
handle: *const native_handle,
reserved_proc: [*mut c_void; 8],
}
#[repr(C)]
pub struct ANativeWindow {
common: ANativeBase,
flags: u32,
minSwapInterval: c_int,
maxSwapInterval: c_int,
xdpi: f32,
ydpi: f32,
oem: [isize; 4],
setSwapInterval: extern fn(*mut ANativeWindow, c_int) -> c_int,
//dequeueBuffer_DEPRECATED: extern fn(*mut ANativeWindow, *mut *mut ANativeWindowBuffer) -> c_int,
//lockBuffer_DEPRECATED: extern fn(*mut ANativeWindow, *mut ANativeWindowBuffer) -> c_int,
//queueBuffer_DEPRECATED: extern fn(*mut ANativeWindow, *mut ANativeWindowBuffer) -> c_int,
dequeueBuffer_DEPRECATED: *const c_void,
lockBuffer_DEPRECATED: *const c_void,
queueBuffer_DEPRECATED: *const c_void,
query: extern fn(*const ANativeWindow, c_int, *mut c_int) -> c_int,
perform: extern fn(*mut ANativeWindow, c_int, ...) -> c_int,
//cancelBuffer_DEPRECATED: extern fn(*mut ANativeWindow, *mut ANativeWindowBuffer) -> c_int,
cancelBuffer_DEPRECATED: *const c_void,
dequeueBuffer: extern fn(*mut ANativeWindow, *mut *mut ANativeWindowBuffer, *mut c_int) -> c_int,
queueBuffer: extern fn(*mut ANativeWindow, *mut ANativeWindowBuffer, c_int) -> c_int,
cancelBuffer: extern fn(*mut ANativeWindow, *mut ANativeWindowBuffer, c_int) -> c_int,
}
// hardware/libhardware/include/hardware/hardware.h
#[repr(C)]
pub struct hw_module_methods {
open: extern fn(*const hw_module, *const c_char, *mut *const hw_device) -> c_int,
}
#[repr(C)]
pub struct hw_module {
tag: u32,
module_api_version: u16,
hal_api_version: u16,
id: *const c_char,
name: *const c_char,
author: *const c_char,
methods: *mut hw_module_methods,
dso: *mut u32,
reserved: [u32; (32 - 7)],
}
#[repr(C)]
pub struct hw_device {
tag: u32,
version: u32,
module: *mut hw_module,
reserved: [u32; 12],
close: extern fn(*mut hw_device) -> c_int,
}
#[link(name = "hardware")]
extern {
fn hw_get_module(id: *const c_char, module: *mut *const hw_module) -> c_int;
}
// hardware/libhardware/include/hardware/hwcomposer.h
#[repr(C)]
pub struct hwc_color {
r: u8,
g: u8,
b: u8,
a: u8,
}
#[repr(C)]
#[derive(Copy, Clone)]
pub struct hwc_rect {
left: c_int,
top: c_int,
right: c_int,
bottom: c_int,
}
#[repr(C)]
pub struct hwc_region {
numRects: i32,
rects: *const hwc_rect,
}
const HWC_FRAMEBUFFER: i32 = 0;
const HWC_OVERLAY: i32 = 1;
const HWC_BACKGROUND: i32 = 2;
const HWC_FRAMEBUFFER_TARGET: i32 = 3;
const HWC_BLIT: i32 = 4;
const HWC_SKIP_LAYER: u32 = 1;
#[repr(C)]
pub struct hwc_layer {
compositionType: i32,
hints: u32,
flags: u32,
handle: *const native_handle,
transform: u32,
blending: i32,
sourceCrop: hwc_rect, // If HWC 1.3, then this takes floats
displayFrame: hwc_rect,
visibleRegionScreen: hwc_region,
acquireFenceFd: c_int,
releaseFenceFd: c_int,
planeAlpha: u8,
pad: [u8; 3],
reserved: [i32; (24 - 19)],
}
#[repr(C)]
pub struct hwc_display_contents {
retireFenceFd: c_int,
// HWC 1.0 not supported
outbuf: *const u32,
outbufAcquireFenceFd: c_int,
flags: u32,
numHwLayers: size_t,
hwLayers: [hwc_layer; 2],
}
#[repr(C)]
pub struct hwc_procs {
invalidate: extern fn(*const hwc_procs),
vsync: extern fn(*const hwc_procs, c_int, i64),
hotplug: extern fn(*const hwc_procs, c_int, c_int),
}
const HWC_DISPLAY_NO_ATTRIBUTE: u32 = 0;
const HWC_DISPLAY_VSYNC_PERIOD: u32 = 1;
const HWC_DISPLAY_WIDTH: u32 = 2;
const HWC_DISPLAY_HEIGHT: u32 = 3;
const HWC_DISPLAY_DPI_X: u32 = 4;
const HWC_DISPLAY_DPI_Y: u32 = 5;
#[repr(C)]
pub struct hwc_composer_device {
common: hw_device,
prepare: extern fn(*mut hwc_composer_device, size_t, *mut *mut hwc_display_contents) -> c_int,
set: extern fn(*mut hwc_composer_device, size_t, *mut *mut hwc_display_contents) -> c_int,
eventControl: extern fn(*mut hwc_composer_device, c_int, c_int, c_int) -> c_int,
blank: extern fn(*mut hwc_composer_device, c_int, c_int) -> c_int,
query: extern fn(*mut hwc_composer_device, c_int, *mut c_int) -> c_int,
registerProcs: extern fn(*mut hwc_composer_device, *const hwc_procs),
dump: extern fn(*mut hwc_composer_device, *const c_char, c_int),
getDisplayConfigs: extern fn(*mut hwc_composer_device, c_int, *mut u32, *mut size_t) -> c_int,
getDisplayAttributes: extern fn(*mut hwc_composer_device, c_int, u32, *const u32, *mut i32) -> c_int,
reserved: [*mut c_void; 4],
}
// system/core/include/system/graphics.h
#[repr(C)]
pub struct android_ycbcr {
y: *mut c_void,
cb: *mut c_void,
cr: *mut c_void,
ystride: size_t,
cstride: size_t,
chroma_step: size_t,
reserved: [u32; 8],
}
// hardware/libhardware/include/hardware/gralloc.h
#[repr(C)]
pub struct gralloc_module {
common: hw_module,
registerBuffer: extern fn(*const gralloc_module, *const native_handle) -> c_int,
unregisterBuffer: extern fn(*const gralloc_module, *const native_handle) -> c_int,
lock: extern fn(*const gralloc_module, *const native_handle, c_int, c_int, c_int, c_int,
*mut *mut c_void) -> c_int,
unlock: extern fn(*const gralloc_module, *const native_handle) -> c_int,
perform: extern fn(*const gralloc_module, c_int, ...) -> c_int,
lock_ycbcr: extern fn(*const gralloc_module, *const native_handle, c_int, c_int, c_int, c_int,
c_int, *mut android_ycbcr) -> c_int,
reserved: [*mut c_void; 6],
}
#[repr(C)]
pub struct alloc_device {
common: hw_device,
allocSize: extern fn(*mut alloc_device, c_int, c_int, c_int, c_int, *mut *const native_handle,
*mut c_int, c_int) -> c_int,
alloc: extern fn(*mut alloc_device, c_int, c_int, c_int, c_int, *mut *const native_handle,
*mut c_int) -> c_int,
free: extern fn(*mut alloc_device, *const native_handle) -> c_int,
dump: Option<extern fn(*mut alloc_device, *mut c_char, c_int)>,
reserved: [*mut c_void; 7],
}
#[repr(C)]
pub struct GonkNativeWindow {
window: ANativeWindow,
set_usage: extern fn(*mut GonkNativeWindow, c_int) -> c_int,
set_format: extern fn(*mut GonkNativeWindow, c_int) -> c_int,
set_transform: extern fn(*mut GonkNativeWindow, c_int) -> c_int,
set_dimensions: extern fn(*mut GonkNativeWindow, c_int, c_int) -> c_int,
api_connect: extern fn(*mut GonkNativeWindow, c_int) -> c_int,
api_disconnect: extern fn(*mut GonkNativeWindow, c_int) -> c_int,
count: i32,
alloc_dev: *mut alloc_device,
hwc_dev: *mut hwc_composer_device,
width: i32,
height: i32,
format: c_int,
usage: c_int,
last_fence: c_int,
last_idx: i32,
bufs: [Option<*mut GonkNativeWindowBuffer>; 2],
fences: [c_int; 2],
}
impl ANativeBase {
fn magic(a: char, b: char, c: char, d: char) -> u32 {
(a as u32) << 24 | (b as u32) << 16 | (c as u32) << 8 | d as u32
}
}
#[repr(C)]
pub struct GonkNativeWindowBuffer {
buffer: ANativeWindowBuffer,
count: i32,
}
#[link(name = "native_window_glue", kind = "static")]
extern {
fn gnw_perform(win: *mut ANativeWindow, op: c_int, ...) -> c_int;
}
#[link(name = "suspend")]
extern {
fn autosuspend_disable();
}
#[allow(unused_variables)]
extern fn setSwapInterval(base: *mut ANativeWindow,
interval: c_int) -> c_int {
0
}
const NATIVE_WINDOW_WIDTH: c_int = 0;
const NATIVE_WINDOW_HEIGHT: c_int = 1;
const NATIVE_WINDOW_FORMAT: c_int = 2;
const NATIVE_WINDOW_DEFAULT_WIDTH: c_int = 6;
const NATIVE_WINDOW_DEFAULT_HEIGHT: c_int = 7;
const NATIVE_WINDOW_TRANSFORM_HINT: c_int = 8;
extern fn query(base: *const ANativeWindow,
what: c_int, value: *mut c_int) -> c_int {
unsafe {
let window: &GonkNativeWindow = transmute(base);
match what {
NATIVE_WINDOW_WIDTH => { *value = window.width; 0 }
NATIVE_WINDOW_HEIGHT => { *value = window.height; 0 }
NATIVE_WINDOW_FORMAT => { *value = window.format; 0 }
NATIVE_WINDOW_DEFAULT_WIDTH => { *value = window.width; 0 }
NATIVE_WINDOW_DEFAULT_HEIGHT => { *value = window.height; 0 }
NATIVE_WINDOW_TRANSFORM_HINT => { *value = 0; 0 }
_ => { println!("Unsupported query - {}", what); -1 }
}
}
}
extern fn dequeueBuffer(base: *mut ANativeWindow, buf: *mut *mut ANativeWindowBuffer, fence: *mut c_int) -> c_int {
unsafe {
let window: &mut GonkNativeWindow = transmute(base);
for idx in 0..window.bufs.len() {
if idx == window.last_idx as usize {
continue;
}
match window.bufs[idx] {
Some(entry) => {
(*buf) = transmute(entry);
window.bufs[idx] = None;
*fence = window.fences[idx];
window.fences[idx] = -1;
return 0;
},
None => (),
}
}
}
-1
}
extern fn queueBuffer(base: *mut ANativeWindow, buf: *mut ANativeWindowBuffer, fence: c_int) -> c_int {
unsafe {
let window: &mut GonkNativeWindow = transmute(base);
for idx in 0..window.bufs.len() {
match window.bufs[idx] {
Some(_) => (),
None => {
window.last_idx = idx as i32;
window.bufs[idx] = Some(transmute(buf));
window.fences[idx] = window.draw(buf, fence);
return 0;
},
}
}
}
-1
}
extern fn cancelBuffer(base: *mut ANativeWindow, buf: *mut ANativeWindowBuffer, fence: c_int) -> c_int {
unsafe {
let window: &mut GonkNativeWindow = transmute(base);
for idx in 0..window.bufs.len() {
match window.bufs[idx] {
Some(_) => (),
None => {
window.bufs[idx] = Some(transmute(buf));
window.fences[idx] = -1;
close(fence);
return 0;
},
}
}
}
-1
}
extern fn set_usage(window: *mut GonkNativeWindow,
usage: c_int) -> c_int {
println!("Setting usage flags to {}", usage);
unsafe {
(*window).usage = usage;
(*window).bufs[0] = Some(GonkNativeWindowBuffer::new(
(*window).alloc_dev, (*window).width, (*window).height,
(*window).format, (*window).usage));
(*window).bufs[1] = Some(GonkNativeWindowBuffer::new(
(*window).alloc_dev, (*window).width, (*window).height,
(*window).format, (*window).usage));
}
0
}
extern fn set_format(window: *mut GonkNativeWindow,
format: c_int) -> c_int {
println!("Setting format to {}", format);
unsafe {
(*window).format = format;
}
0
}
extern fn set_transform(_: *mut GonkNativeWindow,
_: c_int) -> c_int {
0
}
extern fn set_dimensions(_: *mut GonkNativeWindow,
_: c_int, _: c_int) -> c_int {
0
}
#[allow(unused_variables)]
extern fn api_connect(window: *mut GonkNativeWindow,
api: c_int) -> c_int {
0
}
#[allow(unused_variables)]
extern fn api_disconnect(window: *mut GonkNativeWindow,
api: c_int) -> c_int {
0
}
extern fn gnw_incRef(base: *mut ANativeBase) {
let win: &mut GonkNativeWindow = unsafe { transmute(base) };
win.count += 1;
}
extern fn gnw_decRef(base: *mut ANativeBase) {
let win: &mut GonkNativeWindow = unsafe { transmute(base) };
win.count -= 1;
if win.count == 0 {
unsafe { transmute::<_, Box<GonkNativeWindow>>(base) };
}
}
impl GonkNativeWindow {
pub fn new(alloc_dev: *mut alloc_device, hwc_dev: *mut hwc_composer_device, width: i32,
height: i32, usage: c_int) -> *mut GonkNativeWindow {
let win = box GonkNativeWindow {
window: ANativeWindow {
common: ANativeBase {
magic: ANativeBase::magic('_', 'w', 'n', 'd'),
version: size_of::<ANativeBase>() as u32,
reserved: unsafe { zeroed() },
incRef: gnw_incRef,
decRef: gnw_decRef,
},
flags: 0,
minSwapInterval: 0,
maxSwapInterval: 0,
xdpi: 0f32,
ydpi: 0f32,
oem: unsafe { zeroed() },
setSwapInterval: setSwapInterval,
dequeueBuffer_DEPRECATED: ptr::null(),
lockBuffer_DEPRECATED: ptr::null(),
queueBuffer_DEPRECATED: ptr::null(),
query: query,
perform: unsafe { transmute(gnw_perform) },
cancelBuffer_DEPRECATED: ptr::null(),
dequeueBuffer: dequeueBuffer,
queueBuffer: queueBuffer,
cancelBuffer: cancelBuffer,
},
set_usage: set_usage,
set_format: set_format,
set_transform: set_transform,
set_dimensions: set_dimensions,
api_connect: api_connect,
api_disconnect: api_disconnect,
count: 1,
alloc_dev: alloc_dev,
hwc_dev: hwc_dev,
width: width,
height: height,
format: 0,
usage: usage,
last_fence: -1,
last_idx: -1,
bufs: unsafe { zeroed() },
fences: [-1, -1],
};
unsafe { transmute(win) }
}
fn draw(&mut self, buf: *mut ANativeWindowBuffer, fence: c_int) -> c_int {
let gonkbuf: &mut GonkNativeWindowBuffer = unsafe { transmute(buf) };
let rect = hwc_rect {
left: 0, top: 0, right: gonkbuf.buffer.width, bottom: gonkbuf.buffer.height
};
let mut list = hwc_display_contents {
retireFenceFd: -1,
outbuf: ptr::null(),
outbufAcquireFenceFd: -1,
flags: 1, /* HWC_GEOMETRY_CHANGED */
numHwLayers: 2,
hwLayers: [
hwc_layer {
compositionType: HWC_FRAMEBUFFER,
hints: 0,
flags: HWC_SKIP_LAYER,
handle: ptr::null(),
transform: 0,
blending: 0,
sourceCrop: hwc_rect {
left: 0, top: 0, right: 0, bottom: 0
},
displayFrame: hwc_rect {
left: 0, top: 0, right: 0, bottom: 0
},
visibleRegionScreen: hwc_region {
numRects: 0,
rects: ptr::null(),
},
acquireFenceFd: -1,
releaseFenceFd: -1,
planeAlpha: 0xFF,
pad: [0, 0, 0],
reserved: [0, 0, 0, 0, 0],
},
hwc_layer {
compositionType: HWC_FRAMEBUFFER_TARGET,
hints: 0,
flags: 0,
handle: gonkbuf.buffer.handle,
transform: 0,
blending: 0,
sourceCrop: rect,
displayFrame: rect,
visibleRegionScreen: hwc_region {
numRects: 1,
rects: &rect,
},
acquireFenceFd: fence,
releaseFenceFd: -1,
planeAlpha: 0xFF,
pad: [0, 0, 0],
reserved: [0, 0, 0, 0, 0],
},
],
};
unsafe {
let mut displays: [*mut hwc_display_contents; 3] = [ &mut list, ptr::null_mut(), ptr::null_mut(), ];
let _ = ((*self.hwc_dev).prepare)(self.hwc_dev,
displays.len() as size_t,
transmute(displays.as_mut_ptr()));
let _ = ((*self.hwc_dev).set)(self.hwc_dev, displays.len() as size_t, transmute(displays.as_mut_ptr()));
if list.retireFenceFd >= 0 {
close(list.retireFenceFd);
}
}
list.hwLayers[1].releaseFenceFd
}
}
extern fn gnwb_incRef(base: *mut ANativeBase) {
let buf: &mut GonkNativeWindowBuffer = unsafe { transmute(base) };
buf.count += 1;
}
extern fn gnwb_decRef(base: *mut ANativeBase) {
let buf: &mut GonkNativeWindowBuffer = unsafe { transmute(base) };
buf.count -= 1;
if buf.count == 0 {
unsafe { transmute::<_, Box<GonkNativeWindowBuffer>>(base) };
}
}
impl GonkNativeWindowBuffer {
pub fn new(dev: *mut alloc_device,
width: i32,
height: i32,
format: c_int, usage: c_int) -> *mut GonkNativeWindowBuffer {
let mut buf = box GonkNativeWindowBuffer {
buffer: ANativeWindowBuffer {
common: ANativeBase {
magic: ANativeBase::magic('_', 'b', 'f', 'r'),
version: size_of::<ANativeBase>() as u32,
reserved: unsafe { zeroed() },
incRef: gnwb_incRef,
decRef: gnwb_decRef,
},
width: width,
height: height,
stride: 0,
format: format,
usage: usage,
reserved: unsafe { zeroed() },
handle: ptr::null(),
reserved_proc: unsafe { zeroed() },
},
count: 1,
};
let ret = unsafe {
((*dev).alloc)(dev, width, height, format, usage,
&mut buf.buffer.handle, &mut buf.buffer.stride)
};
assert!(ret == 0, "Failed to allocate gralloc buffer!");
unsafe { transmute(buf) }
}
}
/// The type of a window.
pub struct Window {
event_recv: Receiver<WindowEvent>,
pub event_send: Sender<WindowEvent>,
width: i32,
height: i32,
native_window: *mut GonkNativeWindow,
dpy: EGLDisplay,
ctx: EGLContext,
surf: EGLSurface,
}
impl Window {
/// Creates a new window.
pub fn new() -> Rc<Window> {
let mut hwc_mod = ptr::null();
unsafe {
let cstr = CString::new("hwcomposer").unwrap();
let ret = hw_get_module(cstr.as_ptr(), &mut hwc_mod);
assert!(ret == 0, "Failed to get HWC module!");
}
let hwc_device: *mut hwc_composer_device;
unsafe {
let mut device = ptr::null();
let cstr = CString::new("composer").unwrap();
let ret = ((*(*hwc_mod).methods).open)(hwc_mod, cstr.as_ptr(), &mut device);
assert!(ret == 0, "Failed to get HWC device!");
hwc_device = transmute(device);
// Require HWC 1.1 or newer
// XXX add HAL version function/macro
assert!((*hwc_device).common.version > (1 << 8), "HWC too old!");
}
let attrs: [u32; 4] = [
HWC_DISPLAY_WIDTH,
HWC_DISPLAY_HEIGHT,
HWC_DISPLAY_DPI_X,
HWC_DISPLAY_NO_ATTRIBUTE];
let mut values: [i32; 4] = [0, 0, 0, 0];
unsafe {
// In theory, we should check the return code.
// However, there are HALs which implement this wrong.
let _ = ((*hwc_device).getDisplayAttributes)(hwc_device, 0, 0, attrs.as_ptr(), values.as_mut_ptr());
}
let mut gralloc_mod = ptr::null();
let alloc_dev: *mut alloc_device;
unsafe {
let mut device = ptr::null();
let cstr = CString::new("gralloc").unwrap();
let ret1 = hw_get_module(cstr.as_ptr(), &mut gralloc_mod);
assert!(ret1 == 0, "Failed to get gralloc moudle!");
let cstr2 = CString::new("gpu0").unwrap();
let ret2 = ((*(*gralloc_mod).methods).open)(gralloc_mod, cstr2.as_ptr(), &mut device);
assert!(ret2 == 0, "Failed to get gralloc moudle!");
alloc_dev = transmute(device);
}
let width = values[0];
let height = values[1];
let dpy = egl::GetDisplay(unsafe { transmute(egl::EGL_DEFAULT_DISPLAY) });
let ret1 = {
let mut major: i32 = 0;
let mut minor: i32 = 0;
egl::Initialize(dpy, &mut major, &mut minor)
};
assert!(ret1 == 1, "Failed to initialize EGL!");
let conf_attr =
[egl::EGL_SURFACE_TYPE, egl::EGL_WINDOW_BIT,
egl::EGL_RENDERABLE_TYPE, egl::EGL_OPENGL_ES2_BIT,
egl::EGL_RED_SIZE, 8,
egl::EGL_GREEN_SIZE, 8,
egl::EGL_BLUE_SIZE, 8,
egl::EGL_ALPHA_SIZE, 0,
egl::EGL_NONE, 0];
let mut config: EGLConfig = unsafe { transmute(0isize) };
let mut num_config: EGLint = 0;
let ret2 = unsafe {
egl::ChooseConfig(dpy, transmute(conf_attr.as_ptr()), &mut config, 1, &mut num_config)
};
assert!(ret2 == 1, "Failed to choose a config");
let usage = GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER | GRALLOC_USAGE_HW_COMPOSER;
let native_window = GonkNativeWindow::new(alloc_dev, hwc_device, width, height, usage);
let eglwindow = unsafe { egl::CreateWindowSurface(dpy, config, transmute(native_window), ptr::null()) };
let ctx_attr =
[egl::EGL_CONTEXT_CLIENT_VERSION, 2,
egl::EGL_NONE, 0];
let ctx = unsafe {
egl::CreateContext(dpy, config, transmute(egl::EGL_NO_CONTEXT), transmute(ctx_attr.as_ptr()))
};
if ctx == unsafe { transmute(egl::EGL_NO_CONTEXT) } { panic!("Failed to create a context!") }
unsafe {
autosuspend_disable();
((*hwc_device).blank)(hwc_device, 0, 0);
}
let ret3 = egl::MakeCurrent(dpy, eglwindow, eglwindow, ctx);
assert!(ret3 == 1, "Failed to make current!");
unsafe {
autosuspend_disable();
((*hwc_device).blank)(hwc_device, 0, 0);
}
unsafe {
gl::ClearColor(1f32, 1f32, 1f32, 1f32);
gl::Clear(gl::COLOR_BUFFER_BIT);
}
egl::SwapBuffers(dpy, eglwindow);
let (tx, rx) = channel();
// Create our window object.
let window = Window {
event_recv: rx,
event_send: tx,
width: width,
height: height,
native_window: native_window,
dpy: dpy,
ctx: ctx,
surf: eglwindow,
};
Rc::new(window)
}
pub fn wait_events(&self) -> Vec<WindowEvent> {
vec![self.event_recv.recv().unwrap()]
}
}
impl Drop for Window {
fn drop (&mut self) {
unsafe {
((*self.native_window).window.common.decRef)(&mut (*self.native_window).window.common);
}
}
}
impl WindowMethods for Window {
/// Returns the size of the window in hardware pixels.
fn framebuffer_size(&self) -> TypedSize2D<DevicePixel, u32> {
Size2D::typed(self.width as u32, self.height as u32)
}
/// Returns the size of the window in density-independent "px" units.
fn size(&self) -> TypedSize2D<ScreenPx, f32> {
Size2D::typed(self.width as f32, self.height as f32)
}
fn client_window(&self) -> (Size2D<u32>, Point2D<i32>) {
let width = self.width as u32;
let height = self.height as u32;
(Size2D::new(width, height), Point2D::zero())
}
fn set_inner_size(&self, _: Size2D<u32>) {
}
fn set_position(&self, _: Point2D<i32>) {
}
/// Presents the window to the screen (perhaps by page flipping).
fn present(&self) {
let _ = egl::SwapBuffers(self.dpy, self.surf);
}
fn set_page_title(&self, _: Option<String>) {
}
fn set_page_url(&self, _: Url) {
}
fn status(&self, _: Option<String>) {
}
fn load_start(&self, _: bool, _: bool) {
}
fn load_end(&self, _: bool, _: bool, _: bool) {
}
fn load_error(&self, _: NetError, _: String) {
}
fn head_parsed(&self) {
}
fn hidpi_factor(&self) -> ScaleFactor<ScreenPx, DevicePixel, f32> {
ScaleFactor::new(1.0)
}
fn native_display(&self) -> NativeDisplay {
NativeDisplay::new_with_display(self.dpy)
}
fn handle_key(&self, _: Key, _: KeyModifiers) {
}
fn create_compositor_channel(&self)
-> (Box<CompositorProxy + Send>, Box<CompositorReceiver>) {
let (sender, receiver) = channel();
(box GonkCompositorProxy {
sender: sender,
event_sender: self.event_send.clone(),
} as Box<CompositorProxy + Send>,
box receiver as Box<CompositorReceiver>)
}
fn set_cursor(&self, _: Cursor) {
}
fn set_favicon(&self, _: Url) {
}
fn prepare_for_composite(&self, _width: usize, _height: usize) -> bool {
true
}
fn supports_clipboard(&self) -> bool {
true
}
}
struct GonkCompositorProxy {
sender: Sender<compositor_thread::Msg>,
event_sender: Sender<WindowEvent>,
}
impl CompositorProxy for GonkCompositorProxy {
fn send(&self, msg: compositor_thread::Msg) {
// Send a message and kick the OS event loop awake.
self.sender.send(msg).ok().unwrap();
self.event_sender.send(WindowEvent::Idle).ok().unwrap();
}
fn clone_compositor_proxy(&self) -> Box<CompositorProxy + Send> {
box GonkCompositorProxy {
sender: self.sender.clone(),
event_sender: self.event_sender.clone(),
} as Box<CompositorProxy + Send>
}
}

View file

@ -325,44 +325,6 @@ class MachCommands(CommandBase):
return ret return ret
@Command('build-gonk',
description='Build the Gonk port',
category='build')
@CommandArgument('--jobs', '-j',
default=None,
help='Number of jobs to run in parallel')
@CommandArgument('--verbose', '-v',
action='store_true',
help='Print verbose output')
@CommandArgument('--release', '-r',
action='store_true',
help='Build in release mode')
def build_gonk(self, jobs=None, verbose=False, release=False):
target = "arm-linux-androideabi"
self.ensure_bootstrapped(target=target)
opts = []
if jobs is not None:
opts += ["-j", jobs]
if verbose:
opts += ["-v"]
if release:
opts += ["--release"]
opts += ["--target", self.config["android"]["target"]]
env = self.build_env(gonk=True)
build_start = time()
with cd(path.join("ports", "gonk")):
ret = call(["cargo", "build"] + opts, env=env, verbose=verbose)
elapsed = time() - build_start
# Generate Desktop Notification if elapsed-time > some threshold value
notify_build_done(elapsed)
print("Gonk build completed in %s" % format_duration(elapsed))
return ret
@Command('clean', @Command('clean',
description='Clean the build directory.', description='Clean the build directory.',
category='build') category='build')

View file

@ -181,10 +181,6 @@ class CommandBase(object):
self.config["android"].setdefault("platform", "android-18") self.config["android"].setdefault("platform", "android-18")
self.config["android"].setdefault("target", "arm-linux-androideabi") self.config["android"].setdefault("target", "arm-linux-androideabi")
self.config.setdefault("gonk", {})
self.config["gonk"].setdefault("b2g", "")
self.config["gonk"].setdefault("product", "flame")
_rust_path = None _rust_path = None
_cargo_build_id = None _cargo_build_id = None
@ -257,7 +253,7 @@ class CommandBase(object):
" --release" if release else "")) " --release" if release else ""))
sys.exit() sys.exit()
def build_env(self, gonk=False, hosts_file_path=None, target=None): def build_env(self, hosts_file_path=None, target=None):
"""Return an extended environment dictionary.""" """Return an extended environment dictionary."""
env = os.environ.copy() env = os.environ.copy()
if sys.platform == "win32" and type(env['PATH']) == unicode: if sys.platform == "win32" and type(env['PATH']) == unicode:
@ -322,65 +318,6 @@ class CommandBase(object):
if self.config["android"]["platform"]: if self.config["android"]["platform"]:
env["ANDROID_PLATFORM"] = self.config["android"]["platform"] env["ANDROID_PLATFORM"] = self.config["android"]["platform"]
if gonk:
if self.config["gonk"]["b2g"]:
env["GONKDIR"] = self.config["gonk"]["b2g"]
if "GONKDIR" not in env:
# Things can get pretty opaque if this hasn't been set
print("Please set $GONKDIR in your environment or .servobuild file")
sys.exit(1)
if self.config["gonk"]["product"]:
env["GONK_PRODUCT"] = self.config["gonk"]["product"]
env["ARCH_DIR"] = "arch-arm"
env["CPPFLAGS"] = (
"-DANDROID -DTARGET_OS_GONK "
"-DANDROID_VERSION=19 "
"-DGR_GL_USE_NEW_SHADER_SOURCE_SIGNATURE=1 "
"-isystem %(gonkdir)s/bionic/libc/%(archdir)s/include "
"-isystem %(gonkdir)s/bionic/libc/include/ "
"-isystem %(gonkdir)s/bionic/libc/kernel/common "
"-isystem %(gonkdir)s/bionic/libc/kernel/%(archdir)s "
"-isystem %(gonkdir)s/bionic/libm/include "
"-I%(gonkdir)s/system "
"-I%(gonkdir)s/system/core/include "
"-I%(gonkdir)s/frameworks/native/opengl/include "
"-I%(gonkdir)s/external/zlib "
) % {"gonkdir": env["GONKDIR"], "archdir": env["ARCH_DIR"]}
env["CXXFLAGS"] = (
"-O2 -mandroid -fPIC "
"-isystem %(gonkdir)s/api/cpp/include "
"-isystem %(gonkdir)s/external/stlport/stlport "
"-isystem %(gonkdir)s/bionic "
"-isystem %(gonkdir)s/bionic/libstdc++/include "
"%(cppflags)s"
) % {"gonkdir": env["GONKDIR"], "cppflags": env["CPPFLAGS"]}
env["CFLAGS"] = (
"%(cxxflags)s"
) % {"cxxflags": env["CXXFLAGS"]}
another_extra_path = path.join(
env["GONKDIR"], "prebuilts", "gcc", "linux-x86", "arm", "arm-linux-androideabi-4.7", "bin")
env["gonkdir"] = env["GONKDIR"]
env["gonk_toolchain_prefix"] = (
"%(toolchain)s/arm-linux-androideabi-"
) % {"toolchain": another_extra_path}
env["PATH"] = "%s%s%s" % (another_extra_path, os.pathsep, env["PATH"])
env["LDFLAGS"] = (
"-mandroid -L%(gonkdir)s/out/target/product/%(gonkproduct)s/obj/lib "
"-Wl,-rpath-link=%(gonkdir)s/out/target/product/%(gonkproduct)s/obj/lib "
"--sysroot=%(gonkdir)s/out/target/product/%(gonkproduct)s/obj/"
) % {"gonkdir": env["GONKDIR"], "gonkproduct": env["GONK_PRODUCT"]}
# Not strictly necessary for a vanilla build, but might be when tweaking the openssl build
openssl_dir = (
"%(gonkdir)s/out/target/product/%(gonkproduct)s/obj/lib"
) % {"gonkdir": env["GONKDIR"], "gonkproduct": env["GONK_PRODUCT"]}
env["OPENSSL_LIB_DIR"] = openssl_dir
env['OPENSSL_INCLUDE_DIR'] = path.join(env["GONKDIR"], "external/openssl/include")
# These are set because they are the variable names that build-apk # These are set because they are the variable names that build-apk
# expects. However, other submodules have makefiles that reference # expects. However, other submodules have makefiles that reference
# the env var names above. Once glutin is enabled and set as the # the env var names above. Once glutin is enabled and set as the

View file

@ -83,8 +83,7 @@ class MachCommands(CommandBase):
cargo_paths = [path.join('components', 'servo'), cargo_paths = [path.join('components', 'servo'),
path.join('ports', 'cef'), path.join('ports', 'cef'),
path.join('ports', 'geckolib'), path.join('ports', 'geckolib')]
path.join('ports', 'gonk')]
for cargo_path in cargo_paths: for cargo_path in cargo_paths:
with cd(cargo_path): with cd(cargo_path):

View file

@ -33,7 +33,6 @@ file_patterns_to_ignore = [
# Files that are ignored for all tidy and lint checks. # Files that are ignored for all tidy and lint checks.
ignored_files = [ ignored_files = [
# Generated and upstream code combined with our own. Could use cleanup # Generated and upstream code combined with our own. Could use cleanup
os.path.join(".", "ports", "gonk", "src", "native_window_glue.cpp"),
os.path.join(".", "ports", "geckolib", "gecko_bindings", "bindings.rs"), os.path.join(".", "ports", "geckolib", "gecko_bindings", "bindings.rs"),
os.path.join(".", "ports", "geckolib", "gecko_bindings", "structs.rs"), os.path.join(".", "ports", "geckolib", "gecko_bindings", "structs.rs"),
os.path.join(".", "ports", "geckolib", "string_cache", "atom_macro.rs"), os.path.join(".", "ports", "geckolib", "string_cache", "atom_macro.rs"),

View file

@ -46,11 +46,3 @@ debug-mozjs = false
#ndk = "/opt/android-ndk" #ndk = "/opt/android-ndk"
#toolchain = "/opt/android-toolchain" #toolchain = "/opt/android-toolchain"
#platform = "android-18" #platform = "android-18"
# Gonk information
# Please fill the ndk/toolchain for Android too
[gonk]
# Path to B2G repo and build
# Defaults to the value of $GONKDIR
#b2g = "/opt/B2G"
product = "flame"