Add safety check for update_buffer

This commit is contained in:
shivshank 2018-07-27 20:15:56 -04:00
parent 68cda2a7fb
commit c2702fa36b
4 changed files with 59 additions and 4 deletions

View file

@ -51,8 +51,6 @@ See the docs for more info.
Listed in rough order of importance and ease (which are surprisingly correlated here!). Listed in rough order of importance and ease (which are surprisingly correlated here!).
- Bounds check on `update_buffer` which will currently segfault if you pass the wrong size.
- Shader playground. Add a method for using shadertoy-like fragment shaders to be applied to - Shader playground. Add a method for using shadertoy-like fragment shaders to be applied to
your submitted pixel data. your submitted pixel data.

View file

@ -0,0 +1,20 @@
extern crate mini_gl_fb;
use mini_gl_fb::{Config, BufferFormat};
fn main() {
let mut fb = mini_gl_fb::get_fancy(Config {
window_title: "Hello world!",
window_size: (800.0, 600.0),
buffer_size: (2, 2),
.. Default::default()
});
fb.change_buffer_format::<u8>(BufferFormat::RG);
// This should panic! We should only be providing two components but we provide 4!
let buffer = vec![[0u8, 50, 128, 255]; 4];
fb.update_buffer(&buffer);
fb.persist();
}

View file

@ -17,6 +17,7 @@ use gl;
use gl::types::*; use gl::types::*;
use std::ptr::null; use std::ptr::null;
use std::mem::size_of_val;
/// Create a context using glutin given a configuration. /// Create a context using glutin given a configuration.
pub fn init_glutin_context<S: ToString>( pub fn init_glutin_context<S: ToString>(
@ -216,10 +217,22 @@ pub struct Framebuffer {
impl Framebuffer { impl Framebuffer {
pub fn update_buffer<T>(&mut self, image_data: &[T]) { pub fn update_buffer<T>(&mut self, image_data: &[T]) {
// TODO: Safety check on the length of the passed slice so this is actually a safe method // Check the length of the passed slice so this is actually a safe method.
let (format, kind) = self.texture_format;
let expected_size_in_bytes = size_of_gl_type_enum(kind)
* format.components()
* self.buffer_width as usize
* self.buffer_height as usize;
let actual_size_in_bytes = size_of_val(image_data);
if actual_size_in_bytes != expected_size_in_bytes {
panic!(
"Expected a buffer of {} bytes, instead recieved one of {} bytes",
expected_size_in_bytes,
actual_size_in_bytes
);
}
self.draw(|fb| { self.draw(|fb| {
unsafe { unsafe {
let (format, kind) = fb.texture_format;
gl::TexImage2D( gl::TexImage2D(
gl::TEXTURE_2D, gl::TEXTURE_2D,
0, 0,
@ -317,6 +330,18 @@ pub enum BufferFormat {
BGRA = gl::BGRA, BGRA = gl::BGRA,
} }
impl BufferFormat {
fn components(&self) -> usize {
use self::BufferFormat::*;
match self {
R => 1,
RG => 2,
RGB | BGR => 3,
RGBA | BGRA => 4,
}
}
}
pub trait ToGlType { pub trait ToGlType {
fn to_gl_enum() -> GLenum; fn to_gl_enum() -> GLenum;
} }
@ -342,6 +367,13 @@ impl_ToGlType!(
i8, gl::BYTE, i8, gl::BYTE,
); );
fn size_of_gl_type_enum(gl_enum: GLenum) -> usize {
match gl_enum {
gl::UNSIGNED_BYTE | gl::BYTE => 1,
_ => panic!("Must pass a GL enum representing a type"),
}
}
fn create_texture(width: i32, height: i32, format: BufferFormat, buffer_kind: GLenum) -> GLuint { fn create_texture(width: i32, height: i32, format: BufferFormat, buffer_kind: GLenum) -> GLuint {
unsafe { unsafe {
let mut tex = 0; let mut tex = 0;

View file

@ -160,6 +160,11 @@ impl MiniGlFb {
/// Updates the backing buffer and draws immediately (swaps buffers). /// Updates the backing buffer and draws immediately (swaps buffers).
/// ///
/// The main drawing function. /// The main drawing function.
///
/// # Panics
///
/// Panics if the size of the buffer does not exactly match the correct size of the texture
/// data required based on the buffers format.
pub fn update_buffer<T>(&mut self, image_data: &[T]) { pub fn update_buffer<T>(&mut self, image_data: &[T]) {
self.internal.update_buffer(image_data); self.internal.update_buffer(image_data);
} }