use Geometry;
use ffi;
use libc;
use std::marker::PhantomData;
use std::mem;
#[cfg(feature = "wayland")]
use wayland::WlcSurface;
pub enum RenderInstance<'a> {
GLES2(GLES2Renderer<'a>),
None(NoRenderer<'a>),
}
pub trait PixelFormat {
#[doc(hidden)]
fn as_bits(&self) -> u32;
}
pub trait Texture {}
pub trait Renderer {
type PixelFormat: PixelFormat;
type Texture: Texture;
fn pixels_write(&mut self, format: Self::PixelFormat, geometry: Geometry, data: &[u8]);
fn pixels_read(&self, format: Self::PixelFormat, geometry: &mut Geometry) -> Vec<u8>;
#[cfg(feature = "wayland")]
fn render_surface(&mut self, surface: &mut WlcSurface, geometry: Geometry);
#[cfg(feature = "wayland")]
fn surface_textures(&self, surface: &mut WlcSurface) -> Result<([Self::Texture; 3], SurfaceFormat), ()>;
}
enum_from_primitive! {
#[derive(Clone, Copy, Debug)]
#[repr(u32)]
#[allow(non_camel_case_types, missing_docs)]
pub enum SurfaceFormat {
RGB = ffi::wlc_surface_format_SURFACE_RGB,
RGBA = ffi::wlc_surface_format_SURFACE_RGBA,
EGL = ffi::wlc_surface_format_SURFACE_EGL,
Y_UV = ffi::wlc_surface_format_SURFACE_Y_UV,
Y_U_V = ffi::wlc_surface_format_SURFACE_Y_U_V,
Y_XUXV = ffi::wlc_surface_format_SURFACE_Y_XUXV,
None,
}
}
pub struct NoPixelFormat;
impl PixelFormat for NoPixelFormat {
fn as_bits(&self) -> u32 {
0
}
}
pub struct NoTexture;
impl Texture for NoTexture {}
enum_from_primitive! {
#[derive(Clone, Copy, Debug)]
#[repr(u32)]
#[allow(missing_docs)]
pub enum GLES2PixelFormat {
RGBA8888 = ffi::wlc_pixel_format_WLC_RGBA8888,
}
}
impl PixelFormat for GLES2PixelFormat {
fn as_bits(&self) -> u32 {
*self as u32
}
}
pub type GLTexture = libc::c_uint;
impl Texture for GLTexture {}
pub struct NoRenderer<'a>(PhantomData<&'a ()>);
impl<'a> Renderer for NoRenderer<'a> {
type PixelFormat = NoPixelFormat;
type Texture = NoTexture;
fn pixels_write(&mut self, _format: NoPixelFormat, _geometry: Geometry, _data: &[u8]) {}
fn pixels_read(&self, _format: NoPixelFormat, _geometry: &mut Geometry) -> Vec<u8> {
Vec::new()
}
#[cfg(feature = "wayland")]
fn render_surface(&mut self, _surface: &mut WlcSurface, _geometry: Geometry) {}
#[cfg(feature = "wayland")]
fn surface_textures(&self, _surface: &mut WlcSurface) -> Result<([NoTexture; 3], SurfaceFormat), ()> {
Ok(([NoTexture, NoTexture, NoTexture], SurfaceFormat::None))
}
}
pub struct GLES2Renderer<'a>(PhantomData<&'a ()>);
#[cfg(not(feature = "unsafe-stable"))]
impl<'a> !Sync for GLES2Renderer<'a> {}
#[cfg(not(feature = "unsafe-stable"))]
impl<'a> !Send for GLES2Renderer<'a> {}
impl<'a> Renderer for GLES2Renderer<'a> {
type PixelFormat = GLES2PixelFormat;
type Texture = GLTexture;
fn pixels_write(&mut self, format: GLES2PixelFormat, geometry: Geometry, data: &[u8]) {
unsafe {
ffi::wlc_pixels_write(format as u32,
&geometry.into_ffi() as *const _,
data.as_ptr() as *const _)
}
}
fn pixels_read(&self, format: GLES2PixelFormat, geometry: &mut Geometry) -> Vec<u8> {
let size = geometry.size.w * geometry.size.h;
let mut data = Vec::with_capacity(size as usize * 4);
unsafe {
data.set_len(size as usize * 4);
let mut final_geometry: ffi::wlc_geometry = mem::uninitialized();
ffi::wlc_pixels_read(format as u32,
&geometry.into_ffi() as *const _,
&mut final_geometry as *mut _,
data.as_mut_slice().as_mut_ptr() as *mut _);
*geometry = Geometry::from_ffi(&final_geometry);
data.truncate((geometry.size.w * geometry.size.h) as usize * 4);
data
}
}
#[cfg(feature = "wayland")]
fn render_surface(&mut self, surface: &mut WlcSurface, geometry: Geometry) {
unsafe {
ffi::wlc_surface_render(*mem::transmute::<&mut WlcSurface, &mut libc::uintptr_t>(surface),
&geometry.into_ffi() as *const _)
}
}
#[cfg(feature = "wayland")]
fn surface_textures(&self, surface: &mut WlcSurface) -> Result<([GLTexture; 3], SurfaceFormat), ()> {
unsafe {
let mut textures: [GLTexture; 3] = mem::uninitialized();
let mut format: SurfaceFormat = mem::uninitialized();
if ffi::wlc_surface_get_textures(*mem::transmute::<&mut WlcSurface,
&mut libc::uintptr_t>(surface),
mem::transmute(&mut textures as *mut [u32; 3]),
mem::transmute::<&mut SurfaceFormat, &mut u32>(&mut format) as
*mut _) {
Ok((textures, format))
} else {
Err(())
}
}
}
}
mod output;
mod view;
pub use self::output::*;
pub use self::view::*;