From 8138a073e7ea9b2e62b2b5d75b20e9bf3f63c364 Mon Sep 17 00:00:00 2001 From: Emil Ernerfeldt Date: Fri, 21 Jan 2022 19:51:52 +0100 Subject: [PATCH] glow: reuse the same GL texture when possible (#1142) --- egui_glow/src/misc_util.rs | 74 --------------------------- egui_glow/src/painter.rs | 100 ++++++++++++++++++++++++++++--------- 2 files changed, 76 insertions(+), 98 deletions(-) diff --git a/egui_glow/src/misc_util.rs b/egui_glow/src/misc_util.rs index 293e3ab1..83c736e2 100644 --- a/egui_glow/src/misc_util.rs +++ b/egui_glow/src/misc_util.rs @@ -2,80 +2,6 @@ use glow::HasContext; use std::option::Option::Some; -use crate::painter::TextureFilter; - -pub(crate) fn srgb_texture2d( - gl: &glow::Context, - is_webgl_1: bool, - srgb_support: bool, - texture_filter: TextureFilter, - data: &[u8], - w: usize, - h: usize, -) -> glow::Texture { - assert_eq!(data.len(), w * h * 4); - assert!(w >= 1); - assert!(h >= 1); - unsafe { - let tex = gl.create_texture().unwrap(); - gl.bind_texture(glow::TEXTURE_2D, Some(tex)); - - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_MAG_FILTER, - texture_filter.glow_code() as i32, - ); - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_MIN_FILTER, - texture_filter.glow_code() as i32, - ); - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_WRAP_S, - glow::CLAMP_TO_EDGE as i32, - ); - gl.tex_parameter_i32( - glow::TEXTURE_2D, - glow::TEXTURE_WRAP_T, - glow::CLAMP_TO_EDGE as i32, - ); - if is_webgl_1 { - let format = if srgb_support { - glow::SRGB_ALPHA - } else { - glow::RGBA - }; - gl.tex_image_2d( - glow::TEXTURE_2D, - 0, - format as i32, - w as i32, - h as i32, - 0, - format, - glow::UNSIGNED_BYTE, - Some(data), - ); - } else { - gl.tex_storage_2d(glow::TEXTURE_2D, 1, glow::SRGB8_ALPHA8, w as i32, h as i32); - gl.tex_sub_image_2d( - glow::TEXTURE_2D, - 0, - 0, - 0, - w as i32, - h as i32, - glow::RGBA, - glow::UNSIGNED_BYTE, - glow::PixelUnpackData::Slice(data), - ); - } - check_for_gl_error(gl, "srgb_texture2d"); - tex - } -} - pub fn check_for_gl_error(gl: &glow::Context, context: &str) { let error_code = unsafe { gl.get_error() }; if error_code != glow::NO_ERROR { diff --git a/egui_glow/src/painter.rs b/egui_glow/src/painter.rs index b11b09c3..b0eb2c87 100644 --- a/egui_glow/src/painter.rs +++ b/egui_glow/src/painter.rs @@ -9,9 +9,7 @@ use egui::{ use glow::HasContext; use memoffset::offset_of; -use crate::misc_util::{ - check_for_gl_error, compile_shader, glow_print, link_program, srgb_texture2d, -}; +use crate::misc_util::{check_for_gl_error, compile_shader, glow_print, link_program}; use crate::post_process::PostProcess; use crate::shader_version::ShaderVersion; use crate::vao_emulate; @@ -392,7 +390,15 @@ impl Painter { ) { self.assert_not_destroyed(); - let gl_texture = match image { + let glow_texture = *self + .textures + .entry(tex_id) + .or_insert_with(|| unsafe { gl.create_texture().unwrap() }); + unsafe { + gl.bind_texture(glow::TEXTURE_2D, Some(glow_texture)); + } + + match image { egui::ImageData::Color(image) => { assert_eq!( image.width() * image.height(), @@ -402,17 +408,15 @@ impl Painter { let data: &[u8] = bytemuck::cast_slice(image.pixels.as_ref()); - srgb_texture2d( - gl, - self.is_webgl_1, - self.srgb_support, - self.texture_filter, - data, - image.size[0], - image.size[1], - ) + self.upload_texture_srgb(gl, image.size, data); } egui::ImageData::Alpha(image) => { + assert_eq!( + image.width() * image.height(), + image.pixels.len(), + "Mismatch between texture size and texel count" + ); + let gamma = if self.is_embedded && self.post_process.is_none() { 1.0 / 2.2 } else { @@ -423,20 +427,68 @@ impl Painter { .flat_map(|a| a.to_array()) .collect(); - srgb_texture2d( - gl, - self.is_webgl_1, - self.srgb_support, - self.texture_filter, - &data, - image.size[0], - image.size[1], - ) + self.upload_texture_srgb(gl, image.size, &data); } }; + } - if let Some(old_tex) = self.textures.insert(tex_id, gl_texture) { - unsafe { gl.delete_texture(old_tex) }; + fn upload_texture_srgb(&mut self, gl: &glow::Context, [w, h]: [usize; 2], data: &[u8]) { + assert_eq!(data.len(), w * h * 4); + assert!(w >= 1 && h >= 1); + unsafe { + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MAG_FILTER, + self.texture_filter.glow_code() as i32, + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_MIN_FILTER, + self.texture_filter.glow_code() as i32, + ); + + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_WRAP_S, + glow::CLAMP_TO_EDGE as i32, + ); + gl.tex_parameter_i32( + glow::TEXTURE_2D, + glow::TEXTURE_WRAP_T, + glow::CLAMP_TO_EDGE as i32, + ); + + if self.is_webgl_1 { + let format = if self.srgb_support { + glow::SRGB_ALPHA + } else { + glow::RGBA + }; + gl.tex_image_2d( + glow::TEXTURE_2D, + 0, + format as i32, + w as i32, + h as i32, + 0, + format, + glow::UNSIGNED_BYTE, + Some(data), + ); + } else { + gl.tex_image_2d( + glow::TEXTURE_2D, + 0, + glow::SRGB8_ALPHA8 as i32, + w as i32, + h as i32, + 0, + glow::RGBA, + glow::UNSIGNED_BYTE, + Some(data), + ); + } + check_for_gl_error(gl, "upload_texture_srgb"); } }