Skip to content
This repository has been archived by the owner on Jul 10, 2023. It is now read-only.

Support EGL on non-Android Linux. #232

Merged
merged 1 commit into from
Feb 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ addons:
packages:
- libxxf86vm-dev
- libosmesa6-dev
- libgles2-mesa-dev
before_install:
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test; fi
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then sudo apt-get update; fi
Expand Down
8 changes: 6 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

name = "layers"
version = "0.2.3"
version = "0.2.4"
authors = ["The Servo Project Developers"]
license = "MIT/Apache-2.0"

Expand Down Expand Up @@ -33,19 +33,23 @@ io-surface = "0.2.0"

[target.i686-unknown-linux-gnu.dependencies]
glx = "0.1.0"
servo-egl = "0.2"
x11 = { version = "2.3.0", features = ["xlib"] }

[target.x86_64-unknown-linux-gnu.dependencies]
glx = "0.1.0"
servo-egl = "0.2"
x11 = { version = "2.3.0", features = ["xlib"] }

[target.arm-unknown-linux-gnueabihf.dependencies]
glx = "0.1.0"
servo-egl = "0.2"
x11 = { version = "2.3.0", features = ["xlib"] }

[target.aarch64-unknown-linux-gnu.dependencies]
glx = "0.1.0"
servo-egl = "0.2"
x11 = { version = "2.3.0", features = ["xlib"] }

[target.arm-linux-androideabi.dependencies]
servo-egl = "0.2"
servo-egl = "0.2"
7 changes: 5 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ extern crate x11;
#[cfg(target_os="linux")]
extern crate glx;

#[cfg(target_os="android")]
#[cfg(any(target_os = "linux", target_os = "android"))]
extern crate egl;

pub mod color;
Expand All @@ -65,10 +65,13 @@ pub mod platform {
pub mod android {
pub mod surface;
}
#[cfg(any(target_os="android",target_os="linux"))]
pub mod egl {
pub mod surface;
}
#[cfg(target_os="windows")]
pub mod windows {
pub mod surface;
}
pub mod surface;
}

136 changes: 136 additions & 0 deletions src/platform/egl/surface.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// Copyright 2015 The Servo Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Implementation of cross-process surfaces implementing EGL surface.

use texturegl::Texture;

use egl::eglext::EGLImageKHR;
use euclid::size::Size2D;
use gleam::gl::{TEXTURE_2D, TexImage2D, UNSIGNED_BYTE};
use skia::gl_context::GLContext;
use skia::gl_rasterization_context::GLRasterizationContext;
use std::iter::repeat;
use std::os::raw::c_void;
use std::sync::Arc;
use std::vec::Vec;

use gleam::gl;

#[cfg(target_os = "linux")]
const GL_FORMAT_BGRA: gl::GLuint = gl::BGRA;

#[cfg(any(target_os = "android", target_os = "gonk"))]
const GL_FORMAT_BGRA: gl::GLuint = gl::BGRA_EXT;

#[cfg(target_os="linux")]
pub use platform::linux::surface::NativeDisplay;

#[cfg(target_os="android")]
pub use platform::android::surface::NativeDisplay;

pub struct EGLImageNativeSurface {
/// An EGLImage for the case of GPU rendering.
image: Option<EGLImageKHR>,

/// A heap-allocated bitmap for the case of CPU rendering.
bitmap: Option<Vec<u8>>,

/// Whether this pixmap will leak if the destructor runs. This is for debugging purposes.
will_leak: bool,

/// The size of this surface.
pub size: Size2D<i32>,
}

unsafe impl Send for EGLImageNativeSurface {}

impl EGLImageNativeSurface {
pub fn new(_: &NativeDisplay, size: Size2D<i32>) -> EGLImageNativeSurface {
let len = size.width * size.height * 4;
let bitmap: Vec<u8> = repeat(0).take(len as usize).collect();

EGLImageNativeSurface {
image: None,
bitmap: Some(bitmap),
will_leak: true,
size: size,
}
}

/// This may only be called on the compositor side.
pub fn bind_to_texture(&self, _: &NativeDisplay, texture: &Texture) {
let _bound = texture.bind();
match self.image {
None => match self.bitmap {
Some(ref bitmap) => {
let data = bitmap.as_ptr() as *const c_void;
unsafe {
TexImage2D(TEXTURE_2D,
0,
GL_FORMAT_BGRA as i32,
self.size.width as i32,
self.size.height as i32,
0,
GL_FORMAT_BGRA as u32,
UNSIGNED_BYTE,
data);
}
}
None => {
debug!("Cannot bind the buffer(CPU rendering), there is no bitmap");
}
},
Some(_image_khr) => {
panic!("TODO: Support GPU rasterizer path on EGL");
}
}
}

/// This may only be called on the painting side.
pub fn upload(&mut self, _: &NativeDisplay, data: &[u8]) {
match self.bitmap {
Some(ref mut bitmap) => {
bitmap.clear();
bitmap.extend_from_slice(data);
}
None => {
debug!("Cannot upload the buffer(CPU rendering), there is no bitmap");
}
}
}

pub fn get_id(&self) -> isize {
match self.image {
None => 0,
Some(image_khr) => image_khr as isize,
}
}

pub fn destroy(&mut self, _graphics_context: &NativeDisplay) {
if self.image.is_some() {
panic!("TODO: Support GPU rendering path on Android");
}
self.mark_wont_leak()
}

pub fn mark_will_leak(&mut self) {
self.will_leak = true
}

pub fn mark_wont_leak(&mut self) {
self.will_leak = false
}

pub fn gl_rasterization_context(&mut self,
_gl_context: Arc<GLContext>)
-> Option<GLRasterizationContext> {
panic!("TODO: Support GL context on EGL");
}
}
59 changes: 52 additions & 7 deletions src/platform/linux/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@

#![allow(non_snake_case)]

//TODO: Linking EGL here is probably wrong - should it be done in gleam / glutin etc?
#[link(name = "EGL")]
extern {}

use texturegl::Texture;

use euclid::size::Size2D;
Expand All @@ -26,6 +30,8 @@ use std::str;
use std::sync::Arc;
use x11::xlib;

use egl::egl::{EGLDisplay, GetCurrentDisplay};

/// The display, visual info, and framebuffer configuration. This is needed in order to bind to a
/// texture on the compositor side. This holds only a *weak* reference to the display and does not
/// close it.
Expand All @@ -34,12 +40,25 @@ use x11::xlib;
/// to fix because the Display is given to us by the native windowing system, but we should fix it
/// someday.
/// FIXME(pcwalton): Mark nonsendable.

#[derive(Copy, Clone)]
pub struct NativeDisplay {
pub struct GLXDisplayInfo {
pub display: *mut xlib::Display,
visual_info: *mut xlib::XVisualInfo,
framebuffer_configuration: Option<glx::types::GLXFBConfig>,
}
#[derive(Copy, Clone)]
pub struct EGLDisplayInfo {
pub display: EGLDisplay,
}

#[derive(Copy, Clone)]
pub enum NativeDisplay {
EGL(EGLDisplayInfo),
GLX(GLXDisplayInfo),
}



unsafe impl Send for NativeDisplay {}

Expand All @@ -50,11 +69,11 @@ impl NativeDisplay {
let (compositor_visual_info, frambuffer_configuration) =
NativeDisplay::compositor_visual_info(display);

NativeDisplay {
NativeDisplay::GLX(GLXDisplayInfo {
display: display,
visual_info: compositor_visual_info,
framebuffer_configuration: frambuffer_configuration,
}
})
}

/// Chooses the compositor visual info using the same algorithm that the compositor uses.
Expand Down Expand Up @@ -141,11 +160,22 @@ impl NativeDisplay {
}

pub fn platform_display_data(&self) -> PlatformDisplayData {
PlatformDisplayData {
display: self.display,
visual_info: self.visual_info,
match *self {
NativeDisplay::GLX(info) => {
PlatformDisplayData {
display: info.display,
visual_info: info.visual_info,
}
}
NativeDisplay::EGL(_) => unreachable!(),
}
}

pub fn new_egl_display() -> NativeDisplay {
NativeDisplay::EGL(EGLDisplayInfo {
display: GetCurrentDisplay()
})
}
}

#[derive(RustcDecodable, RustcEncodable)]
Expand All @@ -170,7 +200,7 @@ impl Drop for PixmapNativeSurface {
}

impl PixmapNativeSurface {
pub fn new(display: &NativeDisplay, size: Size2D<i32>) -> PixmapNativeSurface {
pub fn new(display: &GLXDisplayInfo, size: Size2D<i32>) -> PixmapNativeSurface {
unsafe {
// Create the pixmap.
let screen = xlib::XDefaultScreen(display.display);
Expand All @@ -197,6 +227,11 @@ impl PixmapNativeSurface {
//
// FIXME(pcwalton): RAII for exception safety?
unsafe {
let display = match display {
&NativeDisplay::GLX(info) => info,
&NativeDisplay::EGL(_) => unreachable!(),
};

let pixmap_attributes = [
glx::TEXTURE_TARGET_EXT as i32, glx::TEXTURE_2D_EXT as i32,
glx::TEXTURE_FORMAT_EXT as i32, glx::TEXTURE_FORMAT_RGBA_EXT as i32,
Expand Down Expand Up @@ -228,6 +263,11 @@ impl PixmapNativeSurface {
/// This may only be called on the painting side.
pub fn upload(&mut self, display: &NativeDisplay, data: &[u8]) {
unsafe {
let display = match display {
&NativeDisplay::GLX(info) => info,
&NativeDisplay::EGL(_) => unreachable!(),
};

let image = xlib::XCreateImage(display.display,
(*display.visual_info).visual,
32,
Expand Down Expand Up @@ -259,6 +299,11 @@ impl PixmapNativeSurface {

pub fn destroy(&mut self, display: &NativeDisplay) {
unsafe {
let display = match display {
&NativeDisplay::GLX(info) => info,
&NativeDisplay::EGL(_) => unreachable!(),
};

assert!(self.pixmap != 0);
xlib::XFreePixmap(display.display, self.pixmap);
self.mark_wont_leak()
Expand Down
Loading