Skip to content

Basic Android / GLES support #993

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jun 22, 2016
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ name = "gfx_app"
env_logger = "0.3"
getopts = "0.2"
time = "0.1"
glutin = "0.5"
glutin = "0.6"
gfx_core = { path = "src/core", version = "0.3" }
gfx_device_gl = { path = "src/backend/gl", version = "0.10" }
gfx_window_glutin = { path = "src/window/glutin", version = "0.11" }
Expand Down
10 changes: 6 additions & 4 deletions examples/cube/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ use gfx::Bundle;
// Notice the use of FixedPoint.
gfx_defines!{
vertex Vertex {
pos: [i8; 4] = "a_Pos",
tex_coord: [i8; 2] = "a_TexCoord",
pos: [f32; 4] = "a_Pos",
tex_coord: [f32; 2] = "a_TexCoord",
}

constant Locals {
Expand All @@ -49,8 +49,8 @@ gfx_defines!{
impl Vertex {
fn new(p: [i8; 3], t: [i8; 2]) -> Vertex {
Vertex {
pos: [p[0], p[1], p[2], 1],
tex_coord: t,
pos: [p[0] as f32, p[1] as f32, p[2] as f32, 1.0],
tex_coord: [t[0] as f32, t[1] as f32],
}
}
}
Expand All @@ -69,12 +69,14 @@ impl<R: gfx::Resources> gfx_app::Application<R> for App<R> {
let vs = gfx_app::shade::Source {
glsl_120: include_bytes!("shader/cube_120.glslv"),
glsl_150: include_bytes!("shader/cube_150.glslv"),
glsl_es_100: include_bytes!("shader/cube_100_es.glslv"),
hlsl_40: include_bytes!("data/vertex.fx"),
.. gfx_app::shade::Source::empty()
};
let ps = gfx_app::shade::Source {
glsl_120: include_bytes!("shader/cube_120.glslf"),
glsl_150: include_bytes!("shader/cube_150.glslf"),
glsl_es_100: include_bytes!("shader/cube_100_es.glslf"),
hlsl_40: include_bytes!("data/pixel.fx"),
.. gfx_app::shade::Source::empty()
};
Expand Down
2 changes: 1 addition & 1 deletion examples/cube/shader/cube.hlsl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ cbuffer Locals {
float4x4 u_Transform;
};

VsOutput Vertex(int4 pos: a_Pos, int2 tc: a_TexCoord) {
VsOutput Vertex(float4 pos: a_Pos, float2 tc: a_TexCoord) {
VsOutput output = {
mul(u_Transform, pos),
tc,
Expand Down
13 changes: 13 additions & 0 deletions examples/cube/shader/cube_100_es.glslf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#version 100

precision mediump float;
precision mediump int;

varying vec2 v_TexCoord;
uniform sampler2D t_Color;

void main() {
vec4 tex = texture2D(t_Color, v_TexCoord);
float blend = dot(v_TexCoord-vec2(0.5,0.5), v_TexCoord-vec2(0.5,0.5));
gl_FragColor = mix(tex, vec4(0.0,0.0,0.0,0.0), blend*1.0);
}
12 changes: 12 additions & 0 deletions examples/cube/shader/cube_100_es.glslv
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#version 100

attribute vec4 a_Pos;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;

uniform mat4 u_Transform;

void main() {
v_TexCoord = a_TexCoord;
gl_Position = u_Transform * a_Pos;
}
4 changes: 2 additions & 2 deletions examples/cube/shader/cube_120.glslv
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#version 120

attribute ivec4 a_Pos;
attribute ivec2 a_TexCoord;
attribute vec4 a_Pos;
attribute vec2 a_TexCoord;
varying vec2 v_TexCoord;

uniform mat4 u_Transform;
Expand Down
4 changes: 2 additions & 2 deletions examples/cube/shader/cube_150.glslv
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#version 150 core

in ivec4 a_Pos;
in ivec2 a_TexCoord;
in vec4 a_Pos;
in vec2 a_TexCoord;
out vec2 v_TexCoord;

uniform mat4 u_Transform;
Expand Down
2 changes: 1 addition & 1 deletion examples/shadow/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -604,7 +604,7 @@ impl<R, C> gfx_app::ApplicationBase<R, C> for App<R, C> where
// Section-6: main entry point

pub fn main() {
<App<_, _> as gfx_app::ApplicationGL2>::launch(
<App<_, _> as gfx_app::ApplicationGL>::launch(
"Multi-threaded shadow rendering example with gfx-rs",
gfx_app::DEFAULT_CONFIG);
}
37 changes: 33 additions & 4 deletions src/backend/gl/src/info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use gfx_core::Capabilities;
/// A version number for a specific component of an OpenGL implementation
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd)]
pub struct Version {
pub is_embedded: bool,
pub major: u32,
pub minor: u32,
pub revision: Option<u32>,
Expand All @@ -32,12 +33,23 @@ impl Version {
pub fn new(major: u32, minor: u32, revision: Option<u32>,
vendor_info: &'static str) -> Version {
Version {
is_embedded: false,
major: major,
minor: minor,
revision: revision,
vendor_info: vendor_info,
}
}
/// Create a new OpenGL ES version number
pub fn new_embedded(major: u32, minor: u32, vendor_info: &'static str) -> Version {
Version {
is_embedded: true,
major: major,
minor: minor,
revision: None,
vendor_info: vendor_info,
}
}

/// According to the OpenGL specification, the version information is
/// expected to follow the following syntax:
Expand All @@ -54,9 +66,17 @@ impl Version {
/// Note that this function is intentionally lenient in regards to parsing,
/// and will try to recover at least the first two version numbers without
/// resulting in an `Err`.
pub fn parse(src: &'static str) -> Result<Version, &'static str> {
pub fn parse(mut src: &'static str) -> Result<Version, &'static str> {
let es_sig = " ES ";
let is_es = match src.rfind(es_sig) {
Some(pos) => {
src = &src[pos + es_sig.len() ..];
true
},
None => false,
};
let (version, vendor_info) = match src.find(' ') {
Some(i) => (&src[..i], &src[(i + 1)..]),
Some(i) => (&src[..i], &src[i+1..]),
None => (src, ""),
};

Expand All @@ -69,6 +89,7 @@ impl Version {

match (major, minor, revision) {
(Some(major), Some(minor), revision) => Ok(Version {
is_embedded: is_es,
major: major,
minor: minor,
revision: revision,
Expand Down Expand Up @@ -185,7 +206,11 @@ impl Info {
}

pub fn is_version_supported(&self, major: u32, minor: u32) -> bool {
self.version >= Version::new(major, minor, None, "")
!self.version.is_embedded && self.version >= Version::new(major, minor, None, "")
}

pub fn is_embedded_version_supported(&self, major: u32, minor: u32) -> bool {
self.version.is_embedded && self.version >= Version::new(major, minor, None, "")
}

/// Returns `true` if the implementation supports the extension
Expand Down Expand Up @@ -218,7 +243,8 @@ pub fn get(gl: &gl::Gl) -> (Info, Capabilities, PrivateCaps) {
};
let private = PrivateCaps {
array_buffer_supported: info.is_version_or_extension_supported(3, 0, "GL_ARB_vertex_array_object"),
frame_buffer_supported: info.is_version_or_extension_supported(3, 0, "GL_ARB_framebuffer_object"),
frame_buffer_supported: info.is_version_or_extension_supported(3, 0, "GL_ARB_framebuffer_object") |
info.is_embedded_version_supported(2, 0),
immutable_storage_supported: info.is_version_or_extension_supported(4, 2, "GL_ARB_texture_storage"),
sampler_objects_supported: info.is_version_or_extension_supported(3, 3, "GL_ARB_sampler_objects"),
program_interface_supported: info.is_version_or_extension_supported(4, 3, "GL_ARB_program_interface_query"),
Expand All @@ -243,5 +269,8 @@ mod tests {
assert_eq!(Version::parse("1.2. h3l1o. W0rld"), Ok(Version::new(1, 2, None, "h3l1o. W0rld")));
assert_eq!(Version::parse("1.2.3.h3l1o. W0rld"), Ok(Version::new(1, 2, Some(3), "W0rld")));
assert_eq!(Version::parse("1.2.3 h3l1o. W0rld"), Ok(Version::new(1, 2, Some(3), "h3l1o. W0rld")));
assert_eq!(Version::parse("OpenGL ES 3.1"), Ok(Version::new_embedded(3, 1, "")));
assert_eq!(Version::parse("OpenGL ES 2.0 Google Nexus"), Ok(Version::new_embedded(2, 0, "Google Nexus")));
assert_eq!(Version::parse("GLSL ES 1.1"), Ok(Version::new_embedded(1, 1, "")));
}
}
4 changes: 2 additions & 2 deletions src/backend/gl/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ impl Device {
assert!(d::MAX_SAMPLERS <= d::MAX_RESOURCE_VIEWS);
debug_assert_eq!(sampler.object, 0);
if let Some(bind) = bind_opt {
tex::bind_sampler(gl, bind, &sampler.info);
tex::bind_sampler(gl, bind, &sampler.info, self.info.version.is_embedded);
}else {
error!("Trying to bind a sampler to slot {}, when sampler objects are not supported, and no texture is bound there", slot);
}
Expand Down Expand Up @@ -480,7 +480,7 @@ impl Device {
state::bind_draw_color_buffers(&self.share.context, mask);
},
Command::SetRasterizer(rast) => {
state::bind_rasterizer(&self.share.context, &rast);
state::bind_rasterizer(&self.share.context, &rast, self.info.version.is_embedded);
},
Command::SetViewport(rect) => {
state::bind_viewport(&self.share.context, rect);
Expand Down
8 changes: 5 additions & 3 deletions src/backend/gl/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ pub fn bind_raster_method(gl: &gl::Gl, method: s::RasterMethod, offset: Option<s
}
}

pub fn bind_rasterizer(gl: &gl::Gl, r: &s::Rasterizer) {
pub fn bind_rasterizer(gl: &gl::Gl, r: &s::Rasterizer, is_embedded: bool) {
unsafe {
gl.FrontFace(match r.front_face {
FrontFace::Clockwise => gl::CW,
Expand All @@ -63,8 +63,10 @@ pub fn bind_rasterizer(gl: &gl::Gl, r: &s::Rasterizer) {
gl.CullFace(gl::BACK);
}}
}

bind_raster_method(gl, r.method, r.offset);

if !is_embedded {
bind_raster_method(gl, r.method, r.offset);
}
match r.samples {
Some(_) => unsafe { gl.Enable(gl::MULTISAMPLE) },
None => unsafe { gl.Disable(gl::MULTISAMPLE) },
Expand Down
10 changes: 6 additions & 4 deletions src/backend/gl/src/tex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,7 @@ pub fn make_with_storage(gl: &gl::Gl, desc: &t::Descriptor, cty: ChannelType) ->

/// Bind a sampler using a given binding anchor.
/// Used for GL compatibility profile only. The core profile has sampler objects
pub fn bind_sampler(gl: &gl::Gl, target: GLenum, info: &t::SamplerInfo) { unsafe {
pub fn bind_sampler(gl: &gl::Gl, target: GLenum, info: &t::SamplerInfo, is_embedded: bool) { unsafe {
let (min, mag) = filter_to_gl(info.filter);

match info.filter {
Expand All @@ -551,9 +551,11 @@ pub fn bind_sampler(gl: &gl::Gl, target: GLenum, info: &t::SamplerInfo) { unsafe
gl.TexParameteri(target, gl::TEXTURE_WRAP_T, wrap_to_gl(t) as GLint);
gl.TexParameteri(target, gl::TEXTURE_WRAP_R, wrap_to_gl(r) as GLint);

gl.TexParameterf(target, gl::TEXTURE_LOD_BIAS, info.lod_bias.into());
let border: [f32; 4] = info.border.into();
gl.TexParameterfv(target, gl::TEXTURE_BORDER_COLOR, &border[0]);
if !is_embedded {
let border: [f32; 4] = info.border.into();
gl.TexParameterfv(target, gl::TEXTURE_BORDER_COLOR, &border[0]);
gl.TexParameterf(target, gl::TEXTURE_LOD_BIAS, info.lod_bias.into());
}

let (min, max) = info.lod_range;
gl.TexParameterf(target, gl::TEXTURE_MIN_LOD, min.into());
Expand Down
18 changes: 14 additions & 4 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ pub trait Application<R: gfx::Resources>: Sized {
WrapD3D11::<Self>::launch(name, DEFAULT_CONFIG);
}
#[cfg(not(target_os = "windows"))]
fn launch_default(name: &str) where WrapGL2<Self>: ApplicationGL2 {
fn launch_default(name: &str) where WrapGL2<Self>: ApplicationGL {
WrapGL2::<Self>::launch(name, DEFAULT_CONFIG);
}
}
Expand Down Expand Up @@ -137,7 +137,7 @@ impl<R, C, A> ApplicationBase<R, C> for Wrap<R, C, A> where
}


pub trait ApplicationGL2 {
pub trait ApplicationGL {
fn launch(&str, Config);
}

Expand All @@ -146,25 +146,35 @@ pub trait ApplicationD3D11 {
fn launch(&str, Config);
}

impl<A> ApplicationGL2 for A where
impl<A> ApplicationGL for A where
A: ApplicationBase<gfx_device_gl::Resources,
gfx_device_gl::CommandBuffer>
{
fn launch(title: &str, config: Config) {
use gfx::traits::Device;

env_logger::init().unwrap();
let gl_version = glutin::GlRequest::GlThenGles {
opengl_version: (3, 2), //TODO: try more versions
opengles_version: (2, 0),
};
let builder = glutin::WindowBuilder::new()
.with_title(title.to_string())
.with_dimensions(config.size.0 as u32, config.size.1 as u32)
.with_gl(gl_version)
.with_vsync();
let (window, mut device, mut factory, main_color, main_depth) =
gfx_window_glutin::init::<ColorFormat, DepthFormat>(builder);
let (width, height) = window.get_inner_size().unwrap();
let combuf = factory.create_command_buffer();
let shade_lang = device.get_info().shading_language;

let mut app = Self::new(factory, combuf.into(), Init {
backend: shade::Backend::Glsl(device.get_info().shading_language),
backend: if shade_lang.is_embedded {
shade::Backend::GlslEs(shade_lang)
} else {
shade::Backend::Glsl(shade_lang)
},
color: main_color,
depth: main_depth,
aspect_ratio: width as f32 / height as f32,
Expand Down
16 changes: 16 additions & 0 deletions src/shade.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub use gfx_device_dx11::ShaderModel as DxShaderModel;
#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Backend {
Glsl(GlslVersion),
GlslEs(GlslVersion),
#[cfg(target_os = "windows")]
Hlsl(DxShaderModel),
}
Expand All @@ -35,6 +36,9 @@ pub struct Source<'a> {
pub glsl_140: &'a [u8],
pub glsl_150: &'a [u8],
pub glsl_430: &'a [u8],
pub glsl_es_100: &'a [u8],
pub glsl_es_200: &'a [u8],
pub glsl_es_300: &'a [u8],
pub hlsl_30 : &'a [u8],
pub hlsl_40 : &'a [u8],
pub hlsl_41 : &'a [u8],
Expand All @@ -51,6 +55,9 @@ impl<'a> Source<'a> {
glsl_140: EMPTY,
glsl_150: EMPTY,
glsl_430: EMPTY,
glsl_es_100: EMPTY,
glsl_es_200: EMPTY,
glsl_es_300: EMPTY,
hlsl_30: EMPTY,
hlsl_40: EMPTY,
hlsl_41: EMPTY,
Expand All @@ -72,6 +79,15 @@ impl<'a> Source<'a> {
_ => return Err(())
}
},
Backend::GlslEs(version) => {
let v = version.major * 100 + version.minor;
match *self {
Source { glsl_es_100: s, .. } if s != EMPTY && v >= 100 => s,
Source { glsl_es_200: s, .. } if s != EMPTY && v >= 200 => s,
Source { glsl_es_300: s, .. } if s != EMPTY && v >= 300 => s,
_ => return Err(())
}
},
#[cfg(target_os = "windows")]
Backend::Hlsl(model) => match *self {
Source { hlsl_50: s, .. } if s != EMPTY && model >= 50 => s,
Expand Down
2 changes: 1 addition & 1 deletion src/window/glutin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ authors = ["The Gfx-rs Developers"]
name = "gfx_window_glutin"

[dependencies]
glutin = "0.5"
glutin = "0.6"
gfx_core = { path = "../../core", version = "0.3" }
gfx_device_gl = { path = "../../backend/gl", version = "0.10" }