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

First steps to allowing Linux to use EGL and OpenGLES #220

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
a7ceb05
crate egl for both android/linux, add pub mod egl {}
R00ney Dec 1, 2015
9282815
use egl::surface instead of android surface
R00ney Dec 1, 2015
bdc7a46
make egl for struct and EGLImageNativeSurface
R00ney Dec 1, 2015
60e75e7
add egl dependencies for linux
R00ney Dec 1, 2015
bfa31b4
more stubs
R00ney Dec 1, 2015
2252ee1
created a blank from_es2() function for ES2 render api function call
prashantgupta24 Dec 2, 2015
49ea03c
NativeDisplay to GlxDisplayInfo, new enum NativeDisplay, new struct …
R00ney Dec 3, 2015
b4225a5
NativeDislpay
R00ney Dec 3, 2015
1a1b2cf
new NativeDislpay
R00ney Dec 3, 2015
4ae78fa
fix typo
R00ney Dec 3, 2015
0fa7612
fixed import isssue
R00ney Dec 3, 2015
41c2a66
changed NativeDisplay to import from linux and android, panic Destro…
R00ney Dec 3, 2015
2006c19
fixed paramater types of several functions to NativeDisplay
R00ney Dec 3, 2015
5c004f9
fixed struct GlxDisplayInfo impl
R00ney Dec 3, 2015
57fc573
added GlxDisplay breakout to upload and destroy
R00ney Dec 3, 2015
9a6e271
pub structs
R00ney Dec 3, 2015
3d16dfd
EGLImage for both linux/android
R00ney Dec 3, 2015
fbc96d6
native_surface_property linux or android for EGLImage
R00ney Dec 3, 2015
b0e4430
NativeDisplay struct GlxDisplayInfo bindings fixed
R00ney Dec 3, 2015
dff0f87
fixed typo on line 69
R00ney Dec 3, 2015
d2fa780
fixed typo on line 62
R00ney Dec 3, 2015
5dea68a
fixed platform_display_data to unwrapped NativeDisplay enum
R00ney Dec 3, 2015
b50d1ce
fixed redunt code and typo
R00ney Dec 3, 2015
0443786
added from_es2
R00ney Dec 3, 2015
132c7cc
tricking linker with link extern...
R00ney Dec 3, 2015
bdc5d12
unpanicked TexImage2D
R00ney Dec 3, 2015
5b3363f
fixed import BGRA
R00ney Dec 3, 2015
3ee9c48
made review comments
prashantgupta24 Dec 7, 2015
cd78d85
Fixed extra spaces
prashantgupta24 Dec 7, 2015
c32236f
fixed BGRA/BGRA_EXT for Linux/Android
R00ney Dec 9, 2015
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
14 changes: 13 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

name = "layers"
version = "0.1.0"
version = "0.1.1"
authors = ["The Servo Project Developers"]

[features]
Expand Down Expand Up @@ -58,3 +58,15 @@ features = ["xlib"]

[target.arm-linux-androideabi.dependencies.egl]
git = "https://github.com/servo/rust-egl"

[target.i686-unknown-linux-gnu.dependencies.egl]
git = "https://github.com/servo/rust-egl"

[target.x86_64-unknown-linux-gnu.dependencies.egl]
git = "https://github.com/servo/rust-egl"

[target.arm-unknown-linux-gnueabihf.dependencies.egl]
git = "https://github.com/servo/rust-egl"

[target.aarch64-unknown-linux-gnu.dependencies.egl]
git = "https://github.com/servo/rust-egl"
7 changes: 5 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,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 @@ -62,10 +62,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;
}

142 changes: 142 additions & 0 deletions src/platform/egl/surface.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
// 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::egl::{EGLDisplay, GetCurrentDisplay};
use egl::eglext::{EGLImageKHR, DestroyImageKHR};
use euclid::size::Size2D;
use gleam::gl::{TEXTURE_2D, TexImage2D, BGRA, UNSIGNED_BYTE};
use libc::c_void;
use skia::gl_context::{GLContext, PlatformDisplayData};
use skia::gl_rasterization_context::GLRasterizationContext;
use std::iter::repeat;
use std::mem;
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.push_all(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) {
match self.image {
None => {},
Some(image_khr) => {
panic!("TODO: Support GPU rendering path on Android");
mem::replace(&mut self.image, None);
}
}
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) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should still be called GLX instead of Glx.

PlatformDisplayData {
display: info.display,
visual_info: info.visual_info,
}
}
NativeDisplay::Egl(_) => unreachable!(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And here EGL instead of Egl.

}
}

pub fn from_es2() -> NativeDisplay {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maybe this should be called new_egl_display instead of from_es2. GLES2 is a different concept than EGL.

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
30 changes: 19 additions & 11 deletions src/platform/surface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,11 @@ pub use platform::linux::surface::{NativeDisplay,
#[cfg(target_os="linux")]
use std::ptr;

#[cfg(any(target_os="android",target_os="linux"))]
pub use platform::egl::surface::{EGLImageNativeSurface};

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

#[cfg(target_os="windows")]
pub use platform::windows::surface::NativeDisplay;
Expand All @@ -44,20 +46,27 @@ pub enum NativeSurface {
Pixmap(PixmapNativeSurface),
#[cfg(target_os="macos")]
IOSurface(IOSurfaceNativeSurface),
#[cfg(target_os="android")]
#[cfg(any(target_os="android",target_os="linux"))]
EGLImage(EGLImageNativeSurface),
}

#[cfg(target_os="linux")]
impl NativeSurface {
/// Creates a new native surface with uninitialized data.
pub fn new(display: &NativeDisplay, size: Size2D<i32>) -> NativeSurface {
if display.display == ptr::null_mut() {
NativeSurface::MemoryBuffer(MemoryBufferNativeSurface::new(display, size))
} else {
NativeSurface::Pixmap(PixmapNativeSurface::new(display, size))
match display {
&NativeDisplay::Egl(info) => {
NativeSurface::EGLImage(EGLImageNativeSurface::new(display, size))
}
&NativeDisplay::Glx(info) => {
if info.display == ptr::null_mut() {
NativeSurface::MemoryBuffer(MemoryBufferNativeSurface::new(display, size))
} else {
NativeSurface::Pixmap(PixmapNativeSurface::new(&info, size))
}
}
}
}
}
}

#[cfg(target_os="macos")]
Expand Down Expand Up @@ -95,7 +104,7 @@ macro_rules! native_surface_method_with_mutability {
#[cfg(target_os="macos")]
NativeSurface::IOSurface($pattern) =>
$surface.$function_name($($argument), *),
#[cfg(target_os="android")]
#[cfg(any(target_os="android",target_os="linux"))]
NativeSurface::EGLImage($pattern) =>
$surface.$function_name($($argument), *),
}
Expand Down Expand Up @@ -132,7 +141,7 @@ macro_rules! native_surface_property {
NativeSurface::Pixmap(ref surface) => surface.$property_name,
#[cfg(target_os="macos")]
NativeSurface::IOSurface(ref surface) => surface.$property_name,
#[cfg(target_os="android")]
#[cfg(any(target_os="android",target_os="linux"))]
NativeSurface::EGLImage(ref surface) => surface.$property_name,
}
};
Expand Down Expand Up @@ -268,4 +277,3 @@ impl MemoryBufferNativeSurface {
None
}
}