Make gles2 renderer actually gles2

Fixes #6209.
This commit is contained in:
Kirill Chibisov 2023-02-07 22:08:24 +03:00 committed by GitHub
parent 8b3f229c3d
commit 2d27fff796
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 82 additions and 37 deletions

View File

@ -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` - Uppercase `-T` short form for `--title`
- Support for horizontal scrolling in mouse mode and alternative scrolling modes - Support for horizontal scrolling in mouse mode and alternative scrolling modes
- Support for fractional scaling on Wayland with wp-fractional-scale protocol - Support for fractional scaling on Wayland with wp-fractional-scale protocol
- Support for running on GLES context
### Changed ### Changed

24
Cargo.lock generated
View File

@ -688,42 +688,42 @@ dependencies = [
[[package]] [[package]]
name = "glutin" name = "glutin"
version = "0.30.3" version = "0.30.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "524d807cd49a0c56a53ef9a6738cd15e7c8c4e9d37a3b7fdb3c250c1cd5bf7a3" checksum = "373e3fbcfa6b9c313faa03625a08268168ba9be1003d1ecfcebd5266388aa131"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"cfg_aliases", "cfg_aliases",
"cgl", "cgl",
"cocoa",
"core-foundation", "core-foundation",
"dispatch",
"glutin_egl_sys", "glutin_egl_sys",
"glutin_glx_sys", "glutin_glx_sys",
"glutin_wgl_sys", "glutin_wgl_sys",
"libloading", "libloading",
"objc", "objc2",
"once_cell", "once_cell",
"raw-window-handle", "raw-window-handle",
"wayland-sys 0.30.0", "wayland-sys 0.30.0",
"windows-sys 0.36.1", "windows-sys 0.45.0",
"x11-dl", "x11-dl",
] ]
[[package]] [[package]]
name = "glutin_egl_sys" name = "glutin_egl_sys"
version = "0.3.1" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3adbb8fec0e18e340f990c78f79f5f0e142d0d83f46b10909aaa7d251c00afdf" checksum = "e5aaf0abb5c4148685b33101ae326a207946b4d3764d6cdc79f8316cdaa8367d"
dependencies = [ dependencies = [
"gl_generator", "gl_generator",
"windows-sys 0.36.1", "windows-sys 0.45.0",
] ]
[[package]] [[package]]
name = "glutin_glx_sys" name = "glutin_glx_sys"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "947c4850c58211c9627969c2b4e2674764b81ae5b47bab2c9a477d7942f96e0f" checksum = "1b53cb5fe568964aa066a3ba91eac5ecbac869fb0842cd0dc9e412434f1a1494"
dependencies = [ dependencies = [
"gl_generator", "gl_generator",
"x11-dl", "x11-dl",
@ -731,9 +731,9 @@ dependencies = [
[[package]] [[package]]
name = "glutin_wgl_sys" name = "glutin_wgl_sys"
version = "0.3.0" version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "20c33975a6c9d49d72c8f032a60079bf8df536954fbf9e4cee90396ace815c57" checksum = "ef89398e90033fc6bc65e9bd42fd29bbbfd483bda5b56dc5562f455550618165"
dependencies = [ dependencies = [
"gl_generator", "gl_generator",
] ]

View File

@ -29,7 +29,7 @@ fnv = "1"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }
serde_yaml = "0.8" serde_yaml = "0.8"
serde_json = "1" 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"] } winit = { version = "0.28.1", default-features = false, features = ["serde"] }
notify = "5.1.0" notify = "5.1.0"
parking_lot = "0.12.0" parking_lot = "0.12.0"

View File

@ -4,7 +4,7 @@ use std::fmt;
use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::atomic::{AtomicBool, Ordering};
use crossfont::Metrics; use crossfont::Metrics;
use glutin::context::PossiblyCurrentContext; use glutin::context::{ContextApi, GlContext, PossiblyCurrentContext};
use glutin::display::{GetGlDisplay, GlDisplay}; use glutin::display::{GetGlDisplay, GlDisplay};
use log::info; use log::info;
use once_cell::sync::OnceCell; use once_cell::sync::OnceCell;
@ -110,12 +110,14 @@ impl Renderer {
info!("Running on {}", 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. // Use the config option to enforce a particular renderer configuration.
let (use_glsl3, allow_dsb) = match renderer_prefernce { let (use_glsl3, allow_dsb) = match renderer_prefernce {
Some(RendererPreference::Glsl3) => (true, true), Some(RendererPreference::Glsl3) => (true, true),
Some(RendererPreference::Gles2) => (false, true), Some(RendererPreference::Gles2) => (false, true),
Some(RendererPreference::Gles2Pure) => (false, false), 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 { let (text_renderer, rect_renderer) = if use_glsl3 {
@ -123,7 +125,8 @@ impl Renderer {
let rect_renderer = RectRenderer::new(ShaderVersion::Glsl3)?; let rect_renderer = RectRenderer::new(ShaderVersion::Glsl3)?;
(text_renderer, rect_renderer) (text_renderer, rect_renderer)
} else { } 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)?; let rect_renderer = RectRenderer::new(ShaderVersion::Gles2)?;
(text_renderer, rect_renderer) (text_renderer, rect_renderer)
}; };

View File

@ -81,21 +81,31 @@ pub fn create_gl_context(
gl_config: &Config, gl_config: &Config,
raw_window_handle: Option<RawWindowHandle>, raw_window_handle: Option<RawWindowHandle>,
) -> GlutinResult<NotCurrentContext> { ) -> GlutinResult<NotCurrentContext> {
let context_attributes = ContextAttributesBuilder::new() let mut profiles = [
ContextAttributesBuilder::new()
.with_context_api(ContextApi::OpenGl(Some(Version::new(3, 3)))) .with_context_api(ContextApi::OpenGl(Some(Version::new(3, 3))))
.build(raw_window_handle); .build(raw_window_handle),
// Try gles before OpenGL 2.1 as it tends to be more stable.
unsafe { ContextAttributesBuilder::new()
if let Ok(gl_context) = gl_display.create_context(gl_config, &context_attributes) { .with_context_api(ContextApi::Gles(Some(Version::new(2, 0))))
Ok(gl_context) .build(raw_window_handle),
} else { ContextAttributesBuilder::new()
let context_attributes = ContextAttributesBuilder::new()
.with_profile(GlProfile::Compatibility) .with_profile(GlProfile::Compatibility)
.with_context_api(ContextApi::OpenGl(Some(Version::new(2, 1)))) .with_context_api(ContextApi::OpenGl(Some(Version::new(2, 1))))
.build(raw_window_handle); .build(raw_window_handle),
gl_display.create_context(gl_config, &context_attributes) ]
} .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( pub fn create_gl_surface(

View File

@ -1,3 +1,4 @@
use std::borrow::Cow;
use std::ptr; use std::ptr;
use crossfont::{BitmapBuffer, RasterizedGlyph}; use crossfont::{BitmapBuffer, RasterizedGlyph};
@ -52,6 +53,11 @@ pub struct Atlas {
/// ///
/// This is used as the advance when end of row is reached. /// This is used as the advance when end of row is reached.
row_tallest: i32, 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. /// Error that can happen when inserting a texture to the Atlas.
@ -64,7 +70,7 @@ pub enum AtlasInsertError {
} }
impl Atlas { impl Atlas {
pub fn new(size: i32) -> Self { pub fn new(size: i32, is_gles_context: bool) -> Self {
let mut id: GLuint = 0; let mut id: GLuint = 0;
unsafe { unsafe {
gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1); gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);
@ -92,7 +98,15 @@ impl Atlas {
gl::BindTexture(gl::TEXTURE_2D, 0); 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) { pub fn clear(&mut self) {
@ -144,11 +158,24 @@ impl Atlas {
let (format, buffer) = match &glyph.buffer { let (format, buffer) = match &glyph.buffer {
BitmapBuffer::Rgb(buffer) => { BitmapBuffer::Rgb(buffer) => {
multicolor = false; 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) => { BitmapBuffer::Rgba(buffer) => {
multicolor = true; multicolor = true;
(gl::RGBA, buffer) (gl::RGBA, Cow::Borrowed(buffer))
}, },
}; };
@ -234,7 +261,7 @@ impl Atlas {
Err(AtlasInsertError::Full) => { Err(AtlasInsertError::Full) => {
*current_atlas += 1; *current_atlas += 1;
if *current_atlas == atlas.len() { 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. *active_tex = 0; // Atlas::new binds a texture. Ugh this is sloppy.
atlas.push(new); atlas.push(new);
} }

View File

@ -37,13 +37,17 @@ pub struct Gles2Renderer {
} }
impl 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"); info!("Using OpenGL ES 2.0 renderer");
let dual_source_blending = allow_dsb let dual_source_blending = allow_dsb
&& (GlExtensions::contains("GL_EXT_blend_func_extended") && (GlExtensions::contains("GL_EXT_blend_func_extended")
|| GlExtensions::contains("GL_ARB_blend_func_extended")); || GlExtensions::contains("GL_ARB_blend_func_extended"));
if is_gles_context {
info!("Running on OpenGL ES context");
}
if dual_source_blending { if dual_source_blending {
info!("Using dual source blending"); info!("Using dual source blending");
} }
@ -145,7 +149,7 @@ impl Gles2Renderer {
vao, vao,
vbo, vbo,
ebo, ebo,
atlas: vec![Atlas::new(ATLAS_SIZE)], atlas: vec![Atlas::new(ATLAS_SIZE, is_gles_context)],
batch: Batch::new(), batch: Batch::new(),
current_atlas: 0, current_atlas: 0,
active_tex: 0, active_tex: 0,

View File

@ -137,7 +137,7 @@ impl Glsl3Renderer {
vao, vao,
ebo, ebo,
vbo_instance, vbo_instance,
atlas: vec![Atlas::new(ATLAS_SIZE)], atlas: vec![Atlas::new(ATLAS_SIZE, false)],
current_atlas: 0, current_atlas: 0,
active_tex: 0, active_tex: 0,
batch: Batch::new(), batch: Batch::new(),