diff --git a/Cargo.toml b/Cargo.toml index 1ae8521671b..88ac1e29d5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" } diff --git a/examples/cube/main.rs b/examples/cube/main.rs index ce9867c7f89..5155ac6e54a 100644 --- a/examples/cube/main.rs +++ b/examples/cube/main.rs @@ -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 { @@ -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], } } } @@ -69,12 +69,14 @@ impl gfx_app::Application for App { 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() }; diff --git a/examples/cube/shader/cube.hlsl b/examples/cube/shader/cube.hlsl index e2db475fda1..30cbb764829 100644 --- a/examples/cube/shader/cube.hlsl +++ b/examples/cube/shader/cube.hlsl @@ -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, diff --git a/examples/cube/shader/cube_100_es.glslf b/examples/cube/shader/cube_100_es.glslf new file mode 100644 index 00000000000..74091339bae --- /dev/null +++ b/examples/cube/shader/cube_100_es.glslf @@ -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); +} diff --git a/examples/cube/shader/cube_100_es.glslv b/examples/cube/shader/cube_100_es.glslv new file mode 100644 index 00000000000..dbe4599e39e --- /dev/null +++ b/examples/cube/shader/cube_100_es.glslv @@ -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; +} diff --git a/examples/cube/shader/cube_120.glslv b/examples/cube/shader/cube_120.glslv index b85f6723421..600402c6d74 100644 --- a/examples/cube/shader/cube_120.glslv +++ b/examples/cube/shader/cube_120.glslv @@ -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; diff --git a/examples/cube/shader/cube_150.glslv b/examples/cube/shader/cube_150.glslv index e34c2fd2f51..36f71abbac8 100644 --- a/examples/cube/shader/cube_150.glslv +++ b/examples/cube/shader/cube_150.glslv @@ -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; diff --git a/examples/shadow/main.rs b/examples/shadow/main.rs index c4cda7ee14d..663b5e06078 100644 --- a/examples/shadow/main.rs +++ b/examples/shadow/main.rs @@ -604,7 +604,7 @@ impl gfx_app::ApplicationBase for App where // Section-6: main entry point pub fn main() { - as gfx_app::ApplicationGL2>::launch( + as gfx_app::ApplicationGL>::launch( "Multi-threaded shadow rendering example with gfx-rs", gfx_app::DEFAULT_CONFIG); } diff --git a/src/backend/gl/src/info.rs b/src/backend/gl/src/info.rs index 537ab061327..9a44de202f2 100644 --- a/src/backend/gl/src/info.rs +++ b/src/backend/gl/src/info.rs @@ -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, @@ -32,12 +33,23 @@ impl Version { pub fn new(major: u32, minor: u32, revision: Option, 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: @@ -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 { + pub fn parse(mut src: &'static str) -> Result { + 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, ""), }; @@ -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, @@ -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 @@ -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"), @@ -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, ""))); } } diff --git a/src/backend/gl/src/lib.rs b/src/backend/gl/src/lib.rs index 825a289e1b3..d15abfd1137 100644 --- a/src/backend/gl/src/lib.rs +++ b/src/backend/gl/src/lib.rs @@ -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); } @@ -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); diff --git a/src/backend/gl/src/state.rs b/src/backend/gl/src/state.rs index 5ceaf3f0d46..b52a1c4931a 100644 --- a/src/backend/gl/src/state.rs +++ b/src/backend/gl/src/state.rs @@ -44,7 +44,7 @@ pub fn bind_raster_method(gl: &gl::Gl, method: s::RasterMethod, offset: Option gl::CW, @@ -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) }, diff --git a/src/backend/gl/src/tex.rs b/src/backend/gl/src/tex.rs index 3b9f2c3ffeb..8b8c1d1413f 100644 --- a/src/backend/gl/src/tex.rs +++ b/src/backend/gl/src/tex.rs @@ -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 { @@ -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()); diff --git a/src/lib.rs b/src/lib.rs index 99a96c32515..20f9e6297c3 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -96,7 +96,7 @@ pub trait Application: Sized { WrapD3D11::::launch(name, DEFAULT_CONFIG); } #[cfg(not(target_os = "windows"))] - fn launch_default(name: &str) where WrapGL2: ApplicationGL2 { + fn launch_default(name: &str) where WrapGL2: ApplicationGL { WrapGL2::::launch(name, DEFAULT_CONFIG); } } @@ -137,7 +137,7 @@ impl ApplicationBase for Wrap where } -pub trait ApplicationGL2 { +pub trait ApplicationGL { fn launch(&str, Config); } @@ -146,7 +146,7 @@ pub trait ApplicationD3D11 { fn launch(&str, Config); } -impl ApplicationGL2 for A where +impl ApplicationGL for A where A: ApplicationBase { @@ -154,17 +154,27 @@ impl ApplicationGL2 for A where 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::(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, diff --git a/src/shade.rs b/src/shade.rs index b3f0544f9e3..c010cddd52e 100644 --- a/src/shade.rs +++ b/src/shade.rs @@ -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), } @@ -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], @@ -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, @@ -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, diff --git a/src/window/glutin/Cargo.toml b/src/window/glutin/Cargo.toml index 5c1db47b95a..5f85c27b332 100644 --- a/src/window/glutin/Cargo.toml +++ b/src/window/glutin/Cargo.toml @@ -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" }