parent
8b3f229c3d
commit
2d27fff796
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
]
|
]
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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)
|
||||||
};
|
};
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
Loading…
Reference in New Issue