diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 01:47:29 +0000 |
commit | 0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch) | |
tree | a31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /gfx/wr/wr_glyph_rasterizer/examples/common/boilerplate.rs | |
parent | Initial commit. (diff) | |
download | firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip |
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'gfx/wr/wr_glyph_rasterizer/examples/common/boilerplate.rs')
-rw-r--r-- | gfx/wr/wr_glyph_rasterizer/examples/common/boilerplate.rs | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/gfx/wr/wr_glyph_rasterizer/examples/common/boilerplate.rs b/gfx/wr/wr_glyph_rasterizer/examples/common/boilerplate.rs new file mode 100644 index 0000000000..9590f92b4c --- /dev/null +++ b/gfx/wr/wr_glyph_rasterizer/examples/common/boilerplate.rs @@ -0,0 +1,298 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +use api::ImageFormat; +use euclid::{Transform3D, UnknownUnit}; +use glutin::{self, PossiblyCurrent}; +use gleam::gl; +use wr_glyph_rasterizer::{RasterizedGlyph, GlyphFormat}; + +use std::{ffi::CStr, rc::Rc}; + +#[allow(unused)] +pub struct Gl { + pub gl: Rc<dyn gl::Gl>, + program: gl::GLuint, + vb: gl::GLuint, + vao: gl::GLuint, + vs: gl::GLuint, + fs: gl::GLuint, + textures: Vec<gl::GLuint>, + u_transform: i32, + u_text_color: i32, + u_sampler_color: i32, + glyphs: Vec<RasterizedGlyph>, +} + +pub fn load(gl_context: &glutin::Context<PossiblyCurrent>, glyphs: Vec<RasterizedGlyph>) -> Gl { + env_logger::init(); + + #[cfg(target_os = "macos")] + { + use core_foundation::{self as cf, base::TCFType}; + let i = cf::bundle::CFBundle::main_bundle().info_dictionary(); + let mut i = unsafe { i.to_mutable() }; + i.set( + cf::string::CFString::new("NSSupportsAutomaticGraphicsSwitching"), + cf::boolean::CFBoolean::true_value().into_CFType(), + ); + } + + let gl = match gl_context.get_api() { + glutin::Api::OpenGl => unsafe { + gl::GlFns::load_with(|symbol| gl_context.get_proc_address(symbol) as *const _) + }, + glutin::Api::OpenGlEs => unsafe { + gl::GlesFns::load_with(|symbol| gl_context.get_proc_address(symbol) as *const _) + }, + glutin::Api::WebGl => unimplemented!(), + }; + + let version = unsafe { + let data = CStr::from_ptr(gl.get_string(gl::VERSION).as_ptr() as *const _) + .to_bytes() + .to_vec(); + String::from_utf8(data).unwrap() + }; + + println!("OpenGL version {}", version); + + let vs = gl.create_shader(gl::VERTEX_SHADER); + gl.shader_source(vs, &[VS_SRC]); + gl.compile_shader(vs); + + let fs = gl.create_shader(gl::FRAGMENT_SHADER); + gl.shader_source(fs, &[FS_SRC]); + gl.compile_shader(fs); + + let program = gl.create_program(); + gl.attach_shader(program, vs); + gl.attach_shader(program, fs); + gl.link_program(program); + gl.use_program(program); + + let vb = gl.gen_buffers(1)[0]; + gl.bind_buffer(gl::ARRAY_BUFFER, vb); + gl.buffer_data_untyped( + gl::ARRAY_BUFFER, + (6 * 4 * std::mem::size_of::<f32>()) as gl::types::GLsizeiptr, + std::ptr::null(), + gl::DYNAMIC_DRAW, + ); + + let vao = gl.gen_vertex_arrays(1)[0]; + gl.bind_vertex_array(vao); + + let u_transform = gl.get_uniform_location(program, "uTransform"); + let u_text_color = gl.get_uniform_location(program, "uTextColor"); + let u_sampler_color = gl.get_uniform_location(program, "uSamplerColor"); + let i_position = gl.get_attrib_location(program, "iPosition"); + let i_tex_coords = gl.get_attrib_location(program, "iTexCoords"); + gl.vertex_attrib_pointer( + i_position as gl::types::GLuint, + 2, + gl::FLOAT, + false, + 4 * std::mem::size_of::<f32>() as gl::types::GLsizei, + 0, + ); + gl.vertex_attrib_pointer( + i_tex_coords as gl::types::GLuint, + 2, + gl::FLOAT, + false, + 4 * std::mem::size_of::<f32>() as gl::types::GLsizei, + (2 * std::mem::size_of::<f32>()) as gl::types::GLuint, + ); + gl.enable_vertex_attrib_array(i_position as gl::types::GLuint); + gl.enable_vertex_attrib_array(i_tex_coords as gl::types::GLuint); + + let textures = create_texture(&gl, &glyphs); + + gl.bind_buffer(gl::ARRAY_BUFFER, 0); + gl.bind_vertex_array(0); + + unsafe { log_shader(&gl, vs) }; + unsafe { log_shader(&gl, fs) }; + + Gl { + gl, + program, + vb, + vao, + u_transform, + u_text_color, + u_sampler_color, + glyphs, + textures, + vs, + fs, + } +} + +fn create_texture(gl: &Rc<dyn gl::Gl>, glyphs: &[RasterizedGlyph]) -> Vec<gl::GLuint> { + let textures = gl.gen_textures(glyphs.len() as gl::types::GLsizei); + for (i, glyph) in glyphs.iter().enumerate() { + let (internal_format, external_format) = get_texture_format(&glyph.format); + let texture = textures[i]; + gl.bind_texture(gl::TEXTURE_2D, texture); + gl.tex_parameter_i( + gl::TEXTURE_2D, + gl::TEXTURE_MAG_FILTER, + gl::LINEAR as gl::GLint, + ); + gl.tex_parameter_i( + gl::TEXTURE_2D, + gl::TEXTURE_MIN_FILTER, + gl::LINEAR as gl::GLint, + ); + gl.tex_parameter_i( + gl::TEXTURE_2D, + gl::TEXTURE_WRAP_S, + gl::CLAMP_TO_EDGE as gl::GLint, + ); + gl.tex_parameter_i( + gl::TEXTURE_2D, + gl::TEXTURE_WRAP_T, + gl::CLAMP_TO_EDGE as gl::GLint, + ); + // TODO: use tex_storage_2d + gl.tex_image_2d( + gl::TEXTURE_2D, + 0, + internal_format as gl::GLint, + glyph.width, + glyph.height, + 0, + external_format, + gl::UNSIGNED_BYTE, + Some(&glyph.bytes), + ); + + gl.pixel_store_i(gl::UNPACK_ALIGNMENT, 1); + gl.enable(gl::BLEND); + gl.blend_func(gl::SRC_ALPHA, gl::ONE_MINUS_SRC_ALPHA); + } + + textures +} + +fn get_texture_format(format: &GlyphFormat) -> (gl::GLuint, gl::GLuint) { + match format.image_format(false) { + ImageFormat::BGRA8 => (gl::RGBA, gl::BGRA), + _ => unimplemented!(), + } +} + +unsafe fn log_shader(gl: &Rc<dyn gl::Gl>, shader: gl::GLuint) { + let log = gl.get_shader_info_log(shader); + if log.len() != 0 { + println!("[ERROR] {}", log); + } +} + +impl Gl { + pub fn draw_frame( + &self, + width: f32, + height: f32, + text_color: [f32; 4], + background_color: [f32; 4], + scale_factor: f32, + ) { + let projection: Transform3D<f32, UnknownUnit, UnknownUnit> = + Transform3D::ortho(0., width, height, 0., -1., 1.); + self.gl + .uniform_matrix_4fv(self.u_transform, false, &projection.to_array()); + self.gl.uniform_4fv(self.u_text_color, &text_color); + + self.gl.active_texture(gl::TEXTURE0); + + self.gl.bind_vertex_array(self.vao); + + self.gl.clear_color( + background_color[0], + background_color[1], + background_color[2], + background_color[3], + ); + self.gl.clear(gl::COLOR_BUFFER_BIT); + + let mut ax = 0.; + for (i, glyph) in self.glyphs.iter().enumerate() { + let texture = self.textures[i]; + + let x = ax + glyph.left; + let y = glyph.top; + + let w = (glyph.width as f32) * scale_factor; + let h = (glyph.height as f32) * scale_factor; + + #[rustfmt::skip] + let vertices = [ + x, y, 0.0, 0.0, + x, y + h, 0.0, 1.0, + x + w, y + h, 1.0, 1.0, + + x, y, 0.0, 0.0, + x + w, y + h, 1.0, 1.0, + x + w, y, 1.0, 0.0 + ]; + + self.gl.uniform_1i(self.u_sampler_color, 0); + self.gl.bind_texture(gl::TEXTURE_2D, texture); + self.gl.bind_buffer(gl::ARRAY_BUFFER, self.vb); + self.gl.buffer_data_untyped( + gl::ARRAY_BUFFER, + (vertices.len() * std::mem::size_of::<f32>()) as gl::GLsizeiptr, + vertices.as_ptr() as *const _, + gl::DYNAMIC_DRAW, + ); + self.gl.bind_buffer(gl::ARRAY_BUFFER, 0); + + self.gl.draw_arrays(gl::TRIANGLES, 0, 6); + + ax += (glyph.left * scale_factor) + (glyph.width as f32 * scale_factor); + } + self.gl.bind_vertex_array(0); + self.gl.bind_texture(gl::TEXTURE_2D, 0); + + unsafe { + log_shader(&self.gl, self.vs); + log_shader(&self.gl, self.fs); + }; + } +} + +const VS_SRC: &[u8] = b" +#version 150 + +in vec2 iPosition; +in vec2 iTexCoords; + +uniform mat4 uTransform; + +out vec2 vColorTexCoord; + +void main() { + gl_Position = uTransform * vec4(iPosition, 0.0, 1.0); + vColorTexCoord = iTexCoords; +} +\0"; + +const FS_SRC: &[u8] = b" +#version 150 + +in vec2 vColorTexCoord; + +uniform sampler2D uSamplerColor; +uniform vec4 uTextColor; + +out vec4 oFragmentColor; + +void main() { + vec4 alpha = vec4(1.0, 1.0, 1.0, texture(uSamplerColor, vColorTexCoord).r); + oFragmentColor = uTextColor * alpha; +} +\0"; |