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

Commit

Permalink
Auto merge of #232 - jdm:egl_linux, r=glennw
Browse files Browse the repository at this point in the history
Support EGL on non-Android Linux.

Rebase and squash of #220.

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.svg" height="40" alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/rust-layers/232)
<!-- Reviewable:end -->
  • Loading branch information
bors-servo committed Feb 28, 2016
2 parents a68ac95 + 274ba0a commit 3cb5df4
Show file tree
Hide file tree
Showing 6 changed files with 219 additions and 22 deletions.
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

0 comments on commit 3cb5df4

Please # to comment.