diff options
Diffstat (limited to 'glow/src/quad/compatibility.rs')
-rw-r--r-- | glow/src/quad/compatibility.rs | 349 |
1 files changed, 0 insertions, 349 deletions
diff --git a/glow/src/quad/compatibility.rs b/glow/src/quad/compatibility.rs deleted file mode 100644 index e909162c..00000000 --- a/glow/src/quad/compatibility.rs +++ /dev/null @@ -1,349 +0,0 @@ -use crate::program::{self, Shader}; -use crate::Transformation; -use glow::HasContext; -use iced_graphics::layer; -use iced_native::Rectangle; - -// Only change `MAX_QUADS`, otherwise you could cause problems -// by splitting a triangle into different render passes. -const MAX_QUADS: usize = 100_000; -const MAX_VERTICES: usize = MAX_QUADS * 4; -const MAX_INDICES: usize = MAX_QUADS * 6; - -#[derive(Debug)] -pub struct Pipeline { - program: <glow::Context as HasContext>::Program, - vertex_array: <glow::Context as HasContext>::VertexArray, - vertex_buffer: <glow::Context as HasContext>::Buffer, - index_buffer: <glow::Context as HasContext>::Buffer, - transform_location: <glow::Context as HasContext>::UniformLocation, - scale_location: <glow::Context as HasContext>::UniformLocation, - screen_height_location: <glow::Context as HasContext>::UniformLocation, - current_transform: Transformation, - current_scale: f32, - current_target_height: u32, -} - -impl Pipeline { - pub fn new( - gl: &glow::Context, - shader_version: &program::Version, - ) -> Pipeline { - let program = unsafe { - let vertex_shader = Shader::vertex( - gl, - shader_version, - include_str!("../shader/compatibility/quad.vert"), - ); - let fragment_shader = Shader::fragment( - gl, - shader_version, - include_str!("../shader/compatibility/quad.frag"), - ); - - program::create( - gl, - &[vertex_shader, fragment_shader], - &[ - (0, "i_Pos"), - (1, "i_Scale"), - (2, "i_Color"), - (3, "i_BorderColor"), - (4, "i_BorderRadius"), - (5, "i_BorderWidth"), - ], - ) - }; - - let transform_location = - unsafe { gl.get_uniform_location(program, "u_Transform") } - .expect("Get transform location"); - - let scale_location = - unsafe { gl.get_uniform_location(program, "u_Scale") } - .expect("Get scale location"); - - let screen_height_location = - unsafe { gl.get_uniform_location(program, "u_ScreenHeight") } - .expect("Get target height location"); - - unsafe { - gl.use_program(Some(program)); - - gl.uniform_matrix_4_f32_slice( - Some(&transform_location), - false, - Transformation::identity().as_ref(), - ); - - gl.uniform_1_f32(Some(&scale_location), 1.0); - gl.uniform_1_f32(Some(&screen_height_location), 0.0); - - gl.use_program(None); - } - - let (vertex_array, vertex_buffer, index_buffer) = - unsafe { create_buffers(gl, MAX_VERTICES) }; - - Pipeline { - program, - vertex_array, - vertex_buffer, - index_buffer, - transform_location, - scale_location, - screen_height_location, - current_transform: Transformation::identity(), - current_scale: 1.0, - current_target_height: 0, - } - } - - pub fn draw( - &mut self, - gl: &glow::Context, - target_height: u32, - instances: &[layer::Quad], - transformation: Transformation, - scale: f32, - bounds: Rectangle<u32>, - ) { - // TODO: Remove this allocation (probably by changing the shader and removing the need of two `position`) - let vertices: Vec<Vertex> = - instances.iter().flat_map(Vertex::from_quad).collect(); - - // TODO: Remove this allocation (or allocate only when needed) - let indices: Vec<i32> = (0..instances.len().min(MAX_QUADS) as i32) - .flat_map(|i| { - [i * 4, 1 + i * 4, 2 + i * 4, 2 + i * 4, 1 + i * 4, 3 + i * 4] - }) - .cycle() - .take(instances.len() * 6) - .collect(); - - unsafe { - gl.enable(glow::SCISSOR_TEST); - gl.scissor( - bounds.x as i32, - (target_height - (bounds.y + bounds.height)) as i32, - bounds.width as i32, - bounds.height as i32, - ); - - gl.use_program(Some(self.program)); - gl.bind_vertex_array(Some(self.vertex_array)); - gl.bind_buffer(glow::ARRAY_BUFFER, Some(self.vertex_buffer)); - gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(self.index_buffer)); - } - - if transformation != self.current_transform { - unsafe { - gl.uniform_matrix_4_f32_slice( - Some(&self.transform_location), - false, - transformation.as_ref(), - ); - - self.current_transform = transformation; - } - } - - if scale != self.current_scale { - unsafe { - gl.uniform_1_f32(Some(&self.scale_location), scale); - } - - self.current_scale = scale; - } - - if target_height != self.current_target_height { - unsafe { - gl.uniform_1_f32( - Some(&self.screen_height_location), - target_height as f32, - ); - } - - self.current_target_height = target_height; - } - - let passes = vertices - .chunks(MAX_VERTICES) - .zip(indices.chunks(MAX_INDICES)); - - for (vertices, indices) in passes { - unsafe { - gl.buffer_sub_data_u8_slice( - glow::ARRAY_BUFFER, - 0, - bytemuck::cast_slice(vertices), - ); - - gl.buffer_sub_data_u8_slice( - glow::ELEMENT_ARRAY_BUFFER, - 0, - bytemuck::cast_slice(indices), - ); - - gl.draw_elements( - glow::TRIANGLES, - indices.len() as i32, - glow::UNSIGNED_INT, - 0, - ); - } - } - - unsafe { - gl.bind_vertex_array(None); - gl.use_program(None); - gl.disable(glow::SCISSOR_TEST); - } - } -} - -unsafe fn create_buffers( - gl: &glow::Context, - size: usize, -) -> ( - <glow::Context as HasContext>::VertexArray, - <glow::Context as HasContext>::Buffer, - <glow::Context as HasContext>::Buffer, -) { - let vertex_array = gl.create_vertex_array().expect("Create vertex array"); - let vertex_buffer = gl.create_buffer().expect("Create vertex buffer"); - let index_buffer = gl.create_buffer().expect("Create index buffer"); - - gl.bind_vertex_array(Some(vertex_array)); - - gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(index_buffer)); - gl.buffer_data_size( - glow::ELEMENT_ARRAY_BUFFER, - 12 * size as i32, - glow::DYNAMIC_DRAW, - ); - - gl.bind_buffer(glow::ARRAY_BUFFER, Some(vertex_buffer)); - gl.buffer_data_size( - glow::ARRAY_BUFFER, - (size * Vertex::SIZE) as i32, - glow::DYNAMIC_DRAW, - ); - - let stride = Vertex::SIZE as i32; - - gl.enable_vertex_attrib_array(0); - gl.vertex_attrib_pointer_f32(0, 2, glow::FLOAT, false, stride, 0); - - gl.enable_vertex_attrib_array(1); - gl.vertex_attrib_pointer_f32(1, 2, glow::FLOAT, false, stride, 4 * 2); - - gl.enable_vertex_attrib_array(2); - gl.vertex_attrib_pointer_f32(2, 4, glow::FLOAT, false, stride, 4 * (2 + 2)); - - gl.enable_vertex_attrib_array(3); - gl.vertex_attrib_pointer_f32( - 3, - 4, - glow::FLOAT, - false, - stride, - 4 * (2 + 2 + 4), - ); - - gl.enable_vertex_attrib_array(4); - gl.vertex_attrib_pointer_f32( - 4, - 4, - glow::FLOAT, - false, - stride, - 4 * (2 + 2 + 4 + 4), - ); - - gl.enable_vertex_attrib_array(5); - gl.vertex_attrib_pointer_f32( - 5, - 1, - glow::FLOAT, - false, - stride, - 4 * (2 + 2 + 4 + 4 + 4), - ); - - gl.enable_vertex_attrib_array(6); - gl.vertex_attrib_pointer_f32( - 6, - 2, - glow::FLOAT, - false, - stride, - 4 * (2 + 2 + 4 + 4 + 4 + 1), - ); - - gl.bind_vertex_array(None); - gl.bind_buffer(glow::ARRAY_BUFFER, None); - gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, None); - - (vertex_array, vertex_buffer, index_buffer) -} - -/// The vertex of a colored rectangle with a border. -/// -/// This type can be directly uploaded to GPU memory. -#[derive(Debug, Clone, Copy, bytemuck::Pod, bytemuck::Zeroable)] -#[repr(C)] -pub struct Vertex { - /// The position of the [`Vertex`]. - pub position: [f32; 2], - - /// The size of the [`Vertex`]. - pub size: [f32; 2], - - /// The color of the [`Vertex`], in __linear RGB__. - pub color: [f32; 4], - - /// The border color of the [`Vertex`], in __linear RGB__. - pub border_color: [f32; 4], - - /// The border radius of the [`Vertex`]. - pub border_radius: [f32; 4], - - /// The border width of the [`Vertex`]. - pub border_width: f32, - - /// The __quad__ position of the [`Vertex`]. - pub q_position: [f32; 2], -} - -impl Vertex { - const SIZE: usize = std::mem::size_of::<Self>(); - - fn from_quad(quad: &layer::Quad) -> [Vertex; 4] { - let base = Vertex { - position: quad.position, - size: quad.size, - color: quad.color, - border_color: quad.color, - border_radius: quad.border_radius, - border_width: quad.border_width, - q_position: [0.0, 0.0], - }; - - [ - base, - Self { - q_position: [0.0, 1.0], - ..base - }, - Self { - q_position: [1.0, 0.0], - ..base - }, - Self { - q_position: [1.0, 1.0], - ..base - }, - ] - } -} |