diff options
Diffstat (limited to 'alacritty/src')
-rw-r--r-- | alacritty/src/renderer/mod.rs | 9 | ||||
-rw-r--r-- | alacritty/src/renderer/platform.rs | 38 | ||||
-rw-r--r-- | alacritty/src/renderer/text/atlas.rs | 37 | ||||
-rw-r--r-- | alacritty/src/renderer/text/gles2.rs | 8 | ||||
-rw-r--r-- | alacritty/src/renderer/text/glsl3.rs | 2 |
5 files changed, 69 insertions, 25 deletions
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<RawWindowHandle>, ) -> GlutinResult<NotCurrentContext> { - let context_attributes = ContextAttributesBuilder::new() - .with_context_api(ContextApi::OpenGl(Some(Version::new(3, 3)))) - .build(raw_window_handle); - - 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) - } + 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(); + + // 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<Self, Error> { + pub fn new(allow_dsb: bool, is_gles_context: bool) -> Result<Self, Error> { 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(), |