diff --git a/CHANGELOG.md b/CHANGELOG.md index 4002aa35..abada71e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Uppercase `-T` short form for `--title` - Support for horizontal scrolling in mouse mode and alternative scrolling modes - Support for fractional scaling on Wayland with wp-fractional-scale protocol +- Support for running on GLES context ### Changed diff --git a/Cargo.lock b/Cargo.lock index 62024fa3..041aa3b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -688,42 +688,42 @@ dependencies = [ [[package]] name = "glutin" -version = "0.30.3" +version = "0.30.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "524d807cd49a0c56a53ef9a6738cd15e7c8c4e9d37a3b7fdb3c250c1cd5bf7a3" +checksum = "373e3fbcfa6b9c313faa03625a08268168ba9be1003d1ecfcebd5266388aa131" dependencies = [ "bitflags", "cfg_aliases", "cgl", - "cocoa", "core-foundation", + "dispatch", "glutin_egl_sys", "glutin_glx_sys", "glutin_wgl_sys", "libloading", - "objc", + "objc2", "once_cell", "raw-window-handle", "wayland-sys 0.30.0", - "windows-sys 0.36.1", + "windows-sys 0.45.0", "x11-dl", ] [[package]] name = "glutin_egl_sys" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3adbb8fec0e18e340f990c78f79f5f0e142d0d83f46b10909aaa7d251c00afdf" +checksum = "e5aaf0abb5c4148685b33101ae326a207946b4d3764d6cdc79f8316cdaa8367d" dependencies = [ "gl_generator", - "windows-sys 0.36.1", + "windows-sys 0.45.0", ] [[package]] name = "glutin_glx_sys" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "947c4850c58211c9627969c2b4e2674764b81ae5b47bab2c9a477d7942f96e0f" +checksum = "1b53cb5fe568964aa066a3ba91eac5ecbac869fb0842cd0dc9e412434f1a1494" dependencies = [ "gl_generator", "x11-dl", @@ -731,9 +731,9 @@ dependencies = [ [[package]] name = "glutin_wgl_sys" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20c33975a6c9d49d72c8f032a60079bf8df536954fbf9e4cee90396ace815c57" +checksum = "ef89398e90033fc6bc65e9bd42fd29bbbfd483bda5b56dc5562f455550618165" dependencies = [ "gl_generator", ] diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index ea26e98a..21f18bab 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -29,7 +29,7 @@ fnv = "1" serde = { version = "1", features = ["derive"] } serde_yaml = "0.8" serde_json = "1" -glutin = { version = "0.30.3", default-features = false, features = ["egl", "wgl"] } +glutin = { version = "0.30.4", default-features = false, features = ["egl", "wgl"] } winit = { version = "0.28.1", default-features = false, features = ["serde"] } notify = "5.1.0" parking_lot = "0.12.0" diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs index fc6c357f..8f708d33 100644 --- a/alacritty/src/renderer/mod.rs +++ b/alacritty/src/renderer/mod.rs @@ -4,7 +4,7 @@ use std::fmt; use std::sync::atomic::{AtomicBool, Ordering}; use crossfont::Metrics; -use glutin::context::PossiblyCurrentContext; +use glutin::context::{ContextApi, GlContext, PossiblyCurrentContext}; use glutin::display::{GetGlDisplay, GlDisplay}; use log::info; use once_cell::sync::OnceCell; @@ -110,12 +110,14 @@ impl Renderer { info!("Running on {}", renderer); + let is_gles_context = matches!(context.context_api(), ContextApi::Gles(_)); + // Use the config option to enforce a particular renderer configuration. let (use_glsl3, allow_dsb) = match renderer_prefernce { Some(RendererPreference::Glsl3) => (true, true), Some(RendererPreference::Gles2) => (false, true), Some(RendererPreference::Gles2Pure) => (false, false), - None => (version.as_ref() >= "3.3", true), + None => (version.as_ref() >= "3.3" && !is_gles_context, true), }; let (text_renderer, rect_renderer) = if use_glsl3 { @@ -123,7 +125,8 @@ impl Renderer { let rect_renderer = RectRenderer::new(ShaderVersion::Glsl3)?; (text_renderer, rect_renderer) } else { - let text_renderer = TextRendererProvider::Gles2(Gles2Renderer::new(allow_dsb)?); + let text_renderer = + TextRendererProvider::Gles2(Gles2Renderer::new(allow_dsb, is_gles_context)?); let rect_renderer = RectRenderer::new(ShaderVersion::Gles2)?; (text_renderer, rect_renderer) }; diff --git a/alacritty/src/renderer/platform.rs b/alacritty/src/renderer/platform.rs index 77826100..c9802e0a 100644 --- a/alacritty/src/renderer/platform.rs +++ b/alacritty/src/renderer/platform.rs @@ -81,21 +81,31 @@ pub fn create_gl_context( gl_config: &Config, raw_window_handle: Option, ) -> GlutinResult { - let context_attributes = ContextAttributesBuilder::new() - .with_context_api(ContextApi::OpenGl(Some(Version::new(3, 3)))) - .build(raw_window_handle); + let mut profiles = [ + ContextAttributesBuilder::new() + .with_context_api(ContextApi::OpenGl(Some(Version::new(3, 3)))) + .build(raw_window_handle), + // Try gles before OpenGL 2.1 as it tends to be more stable. + ContextAttributesBuilder::new() + .with_context_api(ContextApi::Gles(Some(Version::new(2, 0)))) + .build(raw_window_handle), + ContextAttributesBuilder::new() + .with_profile(GlProfile::Compatibility) + .with_context_api(ContextApi::OpenGl(Some(Version::new(2, 1)))) + .build(raw_window_handle), + ] + .into_iter(); - unsafe { - if let Ok(gl_context) = gl_display.create_context(gl_config, &context_attributes) { - Ok(gl_context) - } else { - let context_attributes = ContextAttributesBuilder::new() - .with_profile(GlProfile::Compatibility) - .with_context_api(ContextApi::OpenGl(Some(Version::new(2, 1)))) - .build(raw_window_handle); - gl_display.create_context(gl_config, &context_attributes) - } + // Try the optimal config first. + let mut picked_context = + unsafe { gl_display.create_context(gl_config, &profiles.next().unwrap()) }; + + // Try the fallback ones. + while let (Err(_), Some(profile)) = (picked_context.as_ref(), profiles.next()) { + picked_context = unsafe { gl_display.create_context(gl_config, &profile) }; } + + picked_context } pub fn create_gl_surface( diff --git a/alacritty/src/renderer/text/atlas.rs b/alacritty/src/renderer/text/atlas.rs index 662d767b..0d9b6cfd 100644 --- a/alacritty/src/renderer/text/atlas.rs +++ b/alacritty/src/renderer/text/atlas.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::ptr; use crossfont::{BitmapBuffer, RasterizedGlyph}; @@ -52,6 +53,11 @@ pub struct Atlas { /// /// This is used as the advance when end of row is reached. row_tallest: i32, + + /// Gles context. + /// + /// This affects the texture loading. + is_gles_context: bool, } /// Error that can happen when inserting a texture to the Atlas. @@ -64,7 +70,7 @@ pub enum AtlasInsertError { } impl Atlas { - pub fn new(size: i32) -> Self { + pub fn new(size: i32, is_gles_context: bool) -> Self { let mut id: GLuint = 0; unsafe { gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1); @@ -92,7 +98,15 @@ impl Atlas { gl::BindTexture(gl::TEXTURE_2D, 0); } - Self { id, width: size, height: size, row_extent: 0, row_baseline: 0, row_tallest: 0 } + Self { + id, + width: size, + height: size, + row_extent: 0, + row_baseline: 0, + row_tallest: 0, + is_gles_context, + } } pub fn clear(&mut self) { @@ -144,11 +158,24 @@ impl Atlas { let (format, buffer) = match &glyph.buffer { BitmapBuffer::Rgb(buffer) => { multicolor = false; - (gl::RGB, buffer) + // Gles context doesn't allow uploading RGB data into RGBA texture, so need + // explicit copy. + if self.is_gles_context { + let mut new_buffer = Vec::with_capacity(buffer.len() / 3 * 4); + for rgb in buffer.chunks_exact(3) { + new_buffer.push(rgb[0]); + new_buffer.push(rgb[1]); + new_buffer.push(rgb[2]); + new_buffer.push(u8::MAX); + } + (gl::RGBA, Cow::Owned(new_buffer)) + } else { + (gl::RGB, Cow::Borrowed(buffer)) + } }, BitmapBuffer::Rgba(buffer) => { multicolor = true; - (gl::RGBA, buffer) + (gl::RGBA, Cow::Borrowed(buffer)) }, }; @@ -234,7 +261,7 @@ impl Atlas { Err(AtlasInsertError::Full) => { *current_atlas += 1; if *current_atlas == atlas.len() { - let new = Atlas::new(ATLAS_SIZE); + let new = Atlas::new(ATLAS_SIZE, atlas[*current_atlas].is_gles_context); *active_tex = 0; // Atlas::new binds a texture. Ugh this is sloppy. atlas.push(new); } diff --git a/alacritty/src/renderer/text/gles2.rs b/alacritty/src/renderer/text/gles2.rs index 2f537e5c..427a60e3 100644 --- a/alacritty/src/renderer/text/gles2.rs +++ b/alacritty/src/renderer/text/gles2.rs @@ -37,13 +37,17 @@ pub struct Gles2Renderer { } impl Gles2Renderer { - pub fn new(allow_dsb: bool) -> Result { + pub fn new(allow_dsb: bool, is_gles_context: bool) -> Result { info!("Using OpenGL ES 2.0 renderer"); let dual_source_blending = allow_dsb && (GlExtensions::contains("GL_EXT_blend_func_extended") || GlExtensions::contains("GL_ARB_blend_func_extended")); + if is_gles_context { + info!("Running on OpenGL ES context"); + } + if dual_source_blending { info!("Using dual source blending"); } @@ -145,7 +149,7 @@ impl Gles2Renderer { vao, vbo, ebo, - atlas: vec![Atlas::new(ATLAS_SIZE)], + atlas: vec![Atlas::new(ATLAS_SIZE, is_gles_context)], batch: Batch::new(), current_atlas: 0, active_tex: 0, diff --git a/alacritty/src/renderer/text/glsl3.rs b/alacritty/src/renderer/text/glsl3.rs index 885023a0..7c32bf9f 100644 --- a/alacritty/src/renderer/text/glsl3.rs +++ b/alacritty/src/renderer/text/glsl3.rs @@ -137,7 +137,7 @@ impl Glsl3Renderer { vao, ebo, vbo_instance, - atlas: vec![Atlas::new(ATLAS_SIZE)], + atlas: vec![Atlas::new(ATLAS_SIZE, false)], current_atlas: 0, active_tex: 0, batch: Batch::new(),