mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Remove the gonk port
This commit is contained in:
parent
3ec20d9cf5
commit
02c7e06d54
19 changed files with 5 additions and 4050 deletions
|
@ -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)
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -1,3 +0,0 @@
|
||||||
[target.arm-linux-androideabi]
|
|
||||||
ar = "arm-linux-androideabi-ar"
|
|
||||||
linker = "./fake-ld.sh"
|
|
2456
ports/gonk/Cargo.lock
generated
2456
ports/gonk/Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -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"
|
|
|
@ -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).
|
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
|
@ -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/
|
|
|
@ -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 $@ $<
|
|
|
@ -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);
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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>
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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')
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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"),
|
||||||
|
|
|
@ -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"
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue