servo: Merge #11474 - Remove the gonk port (from larsbergstrom:remove_gonk); r=metajack

<!-- Please describe your changes on the following line: -->
This removes the code and support infrastructure for the gonk port.

r? @metajack
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x ] `./mach build -d` does not report any errors
- [x ] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ x] These changes do not require tests because there are no tests

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

Source-Repo: https://github.com/servo/servo
Source-Revision: e3b2d6aef0bbf96cc55f1235461d757cf685f0e0
This commit is contained in:
Lars Bergstrom 2016-05-27 19:34:55 -05:00
parent 7f10c47c0a
commit 94c38d54c6
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
[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
[`CONTRIBUTING.md`](CONTRIBUTING.md) and [`HACKING_QUICKSTART.md`](docs/HACKING_QUICKSTART.md)

View File

@ -414,7 +414,6 @@ pub fn multiprocess() -> bool {
enum UserAgent {
Desktop,
Android,
Gonk,
}
#[derive(Clone, Debug, Eq, Deserialize, PartialEq, Serialize)]
@ -453,21 +452,13 @@ fn default_user_agent_string(agent: UserAgent) -> String {
UserAgent::Android => {
"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()
}
#[cfg(target_os = "android")]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::Android;
// FIXME: This requires https://github.com/servo/servo/issues/7138 to provide the
// 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")))]
#[cfg(not(target_os = "android"))]
const DEFAULT_USER_AGENT: UserAgent = UserAgent::Desktop;
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("u",
"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)");
opts.optflag("M", "multiprocess", "Run in multiprocess mode");
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") {
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(ua) => ua,
None => default_user_agent_string(DEFAULT_USER_AGENT),

View File

@ -55,8 +55,6 @@
* Embedding implementation for the Chrome Embedding Framework (CEF) API.
* glutin
* Embedding implementation for the `glutin` windowing library.
* gonk
* Embedding implementation for the Firefox OS devices.
* python
* servo
* 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"

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
@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',
description='Clean the build directory.',
category='build')

View File

@ -181,10 +181,6 @@ class CommandBase(object):
self.config["android"].setdefault("platform", "android-18")
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
_cargo_build_id = None
@ -257,7 +253,7 @@ class CommandBase(object):
" --release" if release else ""))
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."""
env = os.environ.copy()
if sys.platform == "win32" and type(env['PATH']) == unicode:
@ -322,65 +318,6 @@ class CommandBase(object):
if 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
# expects. However, other submodules have makefiles that reference
# 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'),
path.join('ports', 'cef'),
path.join('ports', 'geckolib'),
path.join('ports', 'gonk')]
path.join('ports', 'geckolib')]
for cargo_path in cargo_paths:
with cd(cargo_path):

View File

@ -33,7 +33,6 @@ file_patterns_to_ignore = [
# Files that are ignored for all tidy and lint checks.
ignored_files = [
# 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", "structs.rs"),
os.path.join(".", "ports", "geckolib", "string_cache", "atom_macro.rs"),

View File

@ -46,11 +46,3 @@ debug-mozjs = false
#ndk = "/opt/android-ndk"
#toolchain = "/opt/android-toolchain"
#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"