use state::StateRef;
use gl::{self, types::*};
#[derive(Debug)]
pub struct RenderBuffer{
id: GLuint,
w: u32,
h: u32,
samples: u32,
owned: bool,
gl: StateRef,
}
impl PartialEq for RenderBuffer{
fn eq(&self, other: &RenderBuffer) -> bool{
self.id == other.id
}
}
impl Eq for RenderBuffer{}
impl Drop for RenderBuffer{
fn drop(&mut self){
if self.owned {
unsafe{
self.gl.DeleteRenderbuffers(1, &self.id);
}
}
}
}
impl RenderBuffer{
pub fn width(&self) -> u32{
self.w
}
pub fn height(&self) -> u32{
self.h
}
pub fn samples(&self) -> u32{
self.samples
}
pub fn id(&self) -> GLuint{
self.id
}
}
#[cfg(not(any(target_os = "macos", feature = "webgl", feature = "gles")))]
fn internal_format_supported(gl: &StateRef, internal: GLenum) -> bool{
if gl.capabilities().is_supported("GL_ARB_internalformat_query"){
let mut supported = 0;
unsafe{
gl.GetInternalformativ(
gl::RENDERBUFFER,
internal,
gl::INTERNALFORMAT_SUPPORTED,
1,
&mut supported);
supported == gl::TRUE as i32
}
}else{
true
}
}
#[cfg(target_os = "macos")]
fn internal_format_supported(gl: &StateRef, internal: GLenum) -> bool{
true
}
pub struct RenderBufferBuilder<'a>(pub(crate) &'a StateRef);
impl<'a> RenderBufferBuilder<'a> {
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub fn create(&self, w: u32, h: u32, internal: GLenum) -> ::Result<RenderBuffer>{
let mut id = 0;
let mut maxsize = 0;
unsafe {
self.0.GetIntegerv(gl::MAX_RENDERBUFFER_SIZE, &mut maxsize);
if w > maxsize as u32 || h > maxsize as u32 {
return Err(::Error::new(::ErrorKind::SizeGreaterThanMaxSize, None));
}
}
if !internal_format_supported(self.0, internal) {
return Err(::Error::new(::ErrorKind::FormatNotSupported, None));
}
if self.0.capabilities().supports_dsa(){
unsafe{
self.0.CreateRenderbuffers(1, &mut id);
self.0.NamedRenderbufferStorage(id, internal, w as i32, h as i32);
}
}else{
unsafe{
self.0.GenRenderbuffers(1, &mut id);
self.0.BindRenderbuffer(gl::RENDERBUFFER, id);
self.0.RenderbufferStorage(gl::RENDERBUFFER, internal, w as i32, h as i32);
}
}
Ok(RenderBuffer{
id: id,
w: w,
h: h,
samples: 0,
owned: true,
gl: self.0.clone()
})
}
#[cfg(any(feature = "gles", feature="webgl"))]
pub fn create(&self, w: u32, h: u32, internal: GLenum) -> ::Result<RenderBuffer>{
let mut id = 0;
let maxsize = self.0.capabilities().max_renderbuffer_size;
if w > maxsize as u32 || h > maxsize as u32 {
return Err(::Error::new(::ErrorKind::SizeGreaterThanMaxSize, None));
}
unsafe{
self.0.GenRenderbuffers(1, &mut id);
self.0.BindRenderbuffer(gl::RENDERBUFFER, id);
self.0.RenderbufferStorage(gl::RENDERBUFFER, internal, w as i32, h as i32);
}
Ok(RenderBuffer{
id: id,
w: w,
h: h,
samples: 0,
owned: true,
gl: self.0.clone()
})
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub fn create_multisampled(&self, w: u32, h: u32, samples: u32, internal: GLenum) -> ::Result<RenderBuffer>{
let mut id = 0;
let mut maxsize = 0;
unsafe {
self.0.GetIntegerv(gl::MAX_RENDERBUFFER_SIZE, &mut maxsize);
if w > maxsize as u32 || h > maxsize as u32 {
return Err(::Error::new(::ErrorKind::SizeGreaterThanMaxSize, None));
}
}
if !internal_format_supported(self.0, internal) {
return Err(::Error::new(::ErrorKind::FormatNotSupported, None));
}
if self.0.capabilities().supports_dsa(){
unsafe{
self.0.CreateRenderbuffers(1, &mut id);
self.0.NamedRenderbufferStorageMultisample(id, samples as GLsizei, internal, w as i32, h as i32);
}
}else{
unsafe{
self.0.GenRenderbuffers(1, &mut id);
self.0.BindRenderbuffer(gl::RENDERBUFFER, id);
self.0.RenderbufferStorageMultisample(gl::RENDERBUFFER, samples as GLsizei, internal, w as i32, h as i32);
}
}
Ok(RenderBuffer{
id: id,
w: w,
h: h,
samples: samples,
owned: true,
gl: self.0.clone(),
})
}
#[cfg(any(feature = "gles", feature="webgl"))]
pub fn create_multisampled(&self, w: u32, h: u32, samples: u32, internal: GLenum) -> ::Result<RenderBuffer>{
let mut id = 0;
let mut maxsize = 0;
unsafe {
self.0.GetIntegerv(gl::MAX_RENDERBUFFER_SIZE, &mut maxsize);
if w > maxsize as u32 || h > maxsize as u32 {
return Err(::Error::new(::ErrorKind::SizeGreaterThanMaxSize, None));
}
}
unsafe{
self.0.GenRenderbuffers(1, &mut id);
self.0.BindRenderbuffer(gl::RENDERBUFFER, id);
#[cfg(target_os="emscripten")]
{
extern "C"{
fn emscripten_glRenderbufferStorageMultisample(target: GLenum,
samples: GLsizei,
internalformat: GLenum,
width: GLsizei,
height: GLsizei);
}
emscripten_glRenderbufferStorageMultisample(gl::RENDERBUFFER, samples as GLsizei, internal, w as i32, h as i32);
}
#[cfg(not(target_os="emscripten"))]
self.0.RenderbufferStorageMultisample(gl::RENDERBUFFER, samples as GLsizei, internal, w as i32, h as i32);
}
Ok(RenderBuffer{
id: id,
w: w,
h: h,
samples: samples,
owned: true,
gl: self.0.clone(),
})
}
pub unsafe fn from_allocated(&self, id: u32, owned: bool, w: u32, h: u32) -> RenderBuffer{
RenderBuffer{
id,
w,
h,
samples: 0,
owned,
gl: self.0.clone(),
}
}
pub unsafe fn from_allocated_multisample(&self, id: u32, owned: bool, w: u32, h: u32, samples: u32) -> RenderBuffer{
RenderBuffer{
id,
w,
h,
samples,
owned,
gl: self.0.clone(),
}
}
}