/* LICENSE BEGIN This file is part of the SixtyFPS Project -- https://sixtyfps.io Copyright (c) 2020 Olivier Goffart Copyright (c) 2020 Simon Hausmann SPDX-License-Identifier: GPL-3.0-only This file is also available under commercial licensing terms. Please contact info@sixtyfps.io for more information. LICENSE END */ use super::GLContext; use glow::HasContext; use std::marker::PhantomData; use std::{mem, rc::Rc}; struct GLBuffer { id: ::Buffer, context: Rc, } impl Drop for GLBuffer { fn drop(&mut self) { unsafe { self.context.delete_buffer(self.id); } } } impl std::ops::Deref for GLBuffer { type Target = ::Buffer; fn deref(&self) -> &Self::Target { &self.id } } pub struct GLArrayBuffer { buffer: GLBuffer, _type_marker: PhantomData, } impl GLArrayBuffer { pub fn new(gl: &Rc, data: &[ArrayMemberType]) -> Self { let buffer_id = unsafe { gl.create_buffer().expect("vertex buffer") }; unsafe { gl.bind_buffer(glow::ARRAY_BUFFER, Some(buffer_id)); let byte_len = mem::size_of_val(&data[0]) * data.len() / mem::size_of::(); let byte_slice = std::slice::from_raw_parts(data.as_ptr() as *const u8, byte_len); gl.buffer_data_u8_slice(glow::ARRAY_BUFFER, byte_slice, glow::STATIC_DRAW); } Self { buffer: GLBuffer { id: buffer_id, context: gl.clone() }, _type_marker: PhantomData } } pub fn bind(&self, gl: &glow::Context, attribute_location: u32) { unsafe { gl.bind_buffer(glow::ARRAY_BUFFER, Some(*self.buffer)); // TODO #5: generalize GL array buffer size/data_type handling beyond f32 gl.vertex_attrib_pointer_f32( attribute_location, (mem::size_of::() / mem::size_of::()) as i32, glow::FLOAT, false, 0, 0, ); gl.enable_vertex_attrib_array(attribute_location); } } } pub struct GLIndexBuffer { buffer: GLBuffer, pub len: i32, _vertex_marker: PhantomData, } impl GLIndexBuffer { pub fn new(gl: &Rc, data: &[IndexType]) -> Self { let buffer_id = unsafe { gl.create_buffer().expect("vertex buffer") }; unsafe { gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(buffer_id)); let byte_len = mem::size_of_val(&data[0]) * data.len() / mem::size_of::(); let byte_slice = std::slice::from_raw_parts(data.as_ptr() as *const u8, byte_len); gl.buffer_data_u8_slice(glow::ELEMENT_ARRAY_BUFFER, byte_slice, glow::STATIC_DRAW); } Self { buffer: GLBuffer { id: buffer_id, context: gl.clone() }, len: data.len() as i32, _vertex_marker: PhantomData, } } pub fn bind(&self, gl: &glow::Context) { unsafe { gl.bind_buffer(glow::ELEMENT_ARRAY_BUFFER, Some(*self.buffer)); } } }