#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
use gl::{self, Gl};
#[cfg(feature="gles")]
use gl::{self, Gles2 as Gl};
#[cfg(feature="webgl")]
use gl::{self, GlinContext as Gl};
use gl::types::*;
use state::{State, Property, StateRef};
use program::{self, Program};
use vao::VaoDraw;
use fbo::{self, Fbo};
use texture;
use cubemap;
use buffer;
use ::Result;
#[cfg(feature="webgl")]
use ::Error;
#[cfg(feature="webgl")]
use ::ErrorKind;
use vao;
use simple_vao;
use offscreen_buffer::*;
use sampler::Sampler;
#[cfg(all(not(feature="gles"), not(feature="webgl")))]
use query::*;
use state::Capabilities;
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
use sync::Fence;
#[cfg(not(feature="webgl"))]
use std::os::raw::c_void;
use utils::Rect;
#[cfg(not(feature="webgl"))]
use crate::debug_group::DebugGroup;
use std::mem;
use std::rc::Rc;
use std::borrow::Borrow;
pub trait RenderSurface: Clone{
fn id(&self) -> u32;
fn bind_attachments(&self);
}
#[derive(Clone, Copy)]
pub struct Screen;
impl RenderSurface for Screen{
fn id(&self) -> u32{
0
}
fn bind_attachments(&self){}
}
impl<B: UntypedOffscreenBuffer + Clone> RenderSurface for B{
fn id(&self) -> u32{
(*self).id()
}
fn bind_attachments(&self){
self.bind_attachments()
}
}
static SCREEN: Screen = Screen;
pub struct Context<'c, R: RenderSurface + 'c = Screen>{
state: StateRef,
context_state: State<'c>,
creation_context: Rc<CreationProxy>,
surface: R,
}
pub trait Backend{}
impl Context<'static>{
#[cfg(not(feature="webgl"))]
pub fn new<W: ::GlWindow>(window: &mut W) -> Result<Context<'static>>{
let gl = Gl::load_with(|s| window.proc_address(s) as *const c_void );
let default_state = StateRef::from_gl(gl);
Ok(Context{
state: default_state.clone(),
context_state: default_state.state().clone(),
creation_context: Rc::new(CreationProxy{state: default_state}),
surface: SCREEN,
})
}
#[cfg(not(feature="webgl"))]
pub fn from_properties<'a, P, W>(window: &mut W, properties: P) -> Result<Context<'static>>
where
P: IntoIterator<Item = &'a Property>,
W: ::GlWindow
{
let gl = Gl::load_with(|s| window.proc_address(s) as *const c_void );
let current_state = StateRef::from_gl(gl);
{
let original_state = State::with_properties(current_state.state(), properties);
current_state.state_mut().apply(&original_state);
}
Ok(Context{
state: current_state.clone(),
context_state: current_state.state().clone(),
creation_context: Rc::new(CreationProxy{state: current_state}),
surface: SCREEN,
})
}
#[cfg(feature="webgl")]
pub fn new<W: ::WebGlWindow>(window: &mut W) -> Result<Context<'static>>{
let gl = Gl::from_context(window.context())
.map_err(|err| Error::with_cause(ErrorKind::ContextCreationError, Some(format!("{}", err).as_str()), err))?;
let default_state = StateRef::from_gl(gl);
Ok(Context{
state: default_state.clone(),
context_state: default_state.state().clone(),
creation_context: Rc::new(CreationProxy{state: default_state}),
surface: SCREEN,
})
}
#[cfg(feature="webgl")]
pub fn from_properties<'a, P, W>(window: &mut W, properties: P) -> Result<Context<'static>>
where
P: IntoIterator<Item = &'a Property>,
W: ::WebGlWindow
{
let gl = Gl::from_context(window.context())
.map_err(|err| Error::with_cause(ErrorKind::ContextCreationError, Some(format!("{}", err).as_str()), err))?;
let current_state = StateRef::from_gl(gl);
{
let original_state = State::with_properties(current_state.state(), properties);
current_state.state_mut().apply(&original_state);
}
Ok(Context{
state: current_state.clone(),
context_state: current_state.state().clone(),
creation_context: Rc::new(CreationProxy{state: current_state}),
surface: SCREEN,
})
}
}
impl<'c> Context<'c> {
pub unsafe fn reset_default_state(&mut self, state: State<'static>){
*self.state.state_mut() = state;
}
}
impl<'c, R: RenderSurface + 'c> Context<'c, R> {
pub unsafe fn gl(&self) -> &Gl{
&self.state
}
fn draw_with_opt_properties<'a, V, U, I, P>(&self, vao_range: V, program: &Program, uniforms: I, properties: Option<P>) -> Result<()>
where V: VaoDraw,
U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
P: IntoIterator<Item = &'a Property>,
{
self.surface.bind_attachments();
let state = self.context_state();
unsafe{
state.set_program_id(program.id());
state.set_vao(vao_range.id());
}
if let Some(state) = properties
.map(|properties| self.context_state().with_properties(properties))
{
self.state_mut().apply(&state);
}else{
self.state_mut().apply(state);
}
let ret = program.set_uniforms(uniforms);
unsafe{
if vao_range.has_indices() {
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
match (vao_range.base_vertex(), vao_range.base_instance()){
(Some(base_vertex), Some(base_instance)) => {
self.gl().DrawElementsInstancedBaseVertexBaseInstance(
vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void,
1,
base_vertex,
base_instance);
}
(Some(base_vertex), None) if base_vertex > 0 => {
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
self.gl().DrawElementsBaseVertex(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void,
base_vertex);
}
(Some(_), None) | (None, None) => {
self.gl().DrawElements(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void);
}
_ => unreachable!(),
}
#[cfg(feature = "gles")]
self.gl().DrawElements(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void);
#[cfg(feature="webgl")]
self.gl().DrawElements(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as isize);
}else{
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
{
if let Some(base_instance) = vao_range.base_instance(){
self.gl().DrawArraysInstancedBaseInstance(vao_range.mode(),
vao_range.start() as i32,
vao_range.count() as i32,
1 as i32,
base_instance);
}else{
self.gl().DrawArrays(vao_range.mode(),
vao_range.start() as i32,
vao_range.count() as i32);
}
}
#[cfg(any(feature = "gles", feature="webgl"))]
self.gl().DrawArrays(vao_range.mode(),
vao_range.start() as i32,
vao_range.count() as i32);
}
}
ret
}
pub fn draw_with_properties<'a, V, U, I, P>(&self, vao_range: V, program: &Program, uniforms: I, properties: P) -> Result<()>
where V: VaoDraw,
U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
P: IntoIterator<Item = &'a Property>,
{
self.draw_with_opt_properties(vao_range, program, uniforms, Some(properties))
}
pub fn draw<V, U, I>(&self, vao_range: V, program: &Program, uniforms: I) -> Result<()>
where V: VaoDraw,
U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>
{
self.draw_with_opt_properties::<_,_,_,&[_]>(vao_range, program, uniforms, None)
}
pub fn draw_instanced_with_opt_properties<'a, V, U, I, P>(&self,
vao_range: V,
num_instances: usize,
program: &Program,
uniforms: I,
properties: Option<P>) -> Result<()>
where V: VaoDraw,
U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
P: IntoIterator<Item = &'a Property>,
{
self.surface.bind_attachments();
let state = self.context_state();
unsafe{
state.set_program_id(program.id());
state.set_vao(vao_range.id());
}
if let Some(state) = properties
.map(|properties| self.context_state().with_properties(properties))
{
self.state_mut().apply(&state);
}else{
self.state_mut().apply(state);
}
let ret = program.set_uniforms(uniforms);
#[cfg(not(any(feature="gles", feature="webgl")))]
unsafe{
if vao_range.num_indices() > 0{
match (vao_range.base_vertex(), vao_range.base_instance()){
(Some(base_vertex), Some(base_instance)) => {
self.gl().DrawElementsInstancedBaseVertexBaseInstance(
vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void,
num_instances as i32,
base_vertex,
base_instance);
}
(Some(base_vertex), None) => {
self.gl().DrawElementsInstancedBaseVertex(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void,
num_instances as i32,
base_vertex);
}
(None, None) => {
self.gl().DrawElementsInstanced(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void,
num_instances as i32);
}
_ => unreachable!(),
}
}else if let Some(base_instance) = vao_range.base_instance(){
self.gl().DrawArraysInstancedBaseInstance(vao_range.mode(),
vao_range.start() as i32,
vao_range.count() as i32,
num_instances as i32,
base_instance);
}else{
self.gl().DrawArraysInstanced(vao_range.mode(),
vao_range.start() as i32,
vao_range.count() as i32,
num_instances as i32);
}
}
#[cfg(feature="gles")]
unsafe{
if vao_range.num_indices() > 0{
self.gl().DrawElementsInstanced(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void,
num_instances as i32);
}else{
self.gl().DrawArraysInstanced(vao_range.mode(),
vao_range.start() as i32,
vao_range.count() as i32,
num_instances as i32);
}
}
#[cfg(feature="webgl")]
unsafe{
if vao_range.num_indices() > 0{
self.gl().DrawElementsInstanced(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as isize,
num_instances as i32);
}else{
self.gl().DrawArraysInstanced(vao_range.mode(),
vao_range.start() as i32,
vao_range.count() as i32,
num_instances as i32);
}
}
ret
}
pub fn draw_instanced<V, U, I>(&self,
vao_range: V,
num_instances: usize,
program: &Program,
uniforms: I) -> Result<()>
where V: VaoDraw,
U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
{
self.draw_instanced_with_opt_properties::<_,_,_,&[_]>(
vao_range,
num_instances,
program,
uniforms,
None)
}
pub fn draw_instanced_with_properties<'a, V, U, I, P>(&self,
vao_range: V,
num_instances: usize,
program: &Program,
uniforms: I,
properties: P) -> Result<()>
where V: VaoDraw,
U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
P: IntoIterator<Item = &'a Property>,
{
self.draw_instanced_with_opt_properties(vao_range, num_instances, program, uniforms, Some(properties))
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub fn draw_elements_command<V, T, B, U, I>(&self,
vao_range: V,
command_buffer: B,
program: &Program,
uniforms: I) -> Result<()>
where V: VaoDraw,
U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
B: ::BufferRange<T>,
{
self.surface.bind_attachments();
let mut state = self.context_state().shallow_clone();
unsafe{
state.set_program_id(program.id());
state.set_vao(vao_range.id());
state.set_buffer_binding(gl::DRAW_INDIRECT_BUFFER, command_buffer.id());
}
self.state_mut().apply(&state);
let ret = program.set_uniforms(uniforms);
let offset = command_buffer.start() * mem::size_of::<T>();
unsafe{
self.gl().DrawElementsIndirect(vao_range.mode(),
gl::UNSIGNED_INT,
offset as *const c_void);
}
ret
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub fn draw_arrays_command<V, T, U, I, B>(&self,
vao_range: V,
command_buffer: B,
program: &Program,
uniforms: I) -> Result<()>
where V: VaoDraw,
U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
B: ::BufferRange<T>,
{
self.surface.bind_attachments();
let mut state = self.context_state().shallow_clone();
unsafe{
state.set_program_id(program.id());
state.set_vao(vao_range.id());
state.set_buffer_binding(gl::DRAW_INDIRECT_BUFFER, command_buffer.id());
}
self.state_mut().apply(&state);
let ret = program.set_uniforms(uniforms);
let offset = command_buffer.start() * mem::size_of::<T>();
unsafe{
self.gl().DrawArraysIndirect(vao_range.mode(), offset as *const c_void);
}
ret
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub fn multi_draw_elements_command<V, T, B, U, I>(&self,
vao_range: V,
command_buffer: B,
program: &Program,
uniforms: I) -> Result<()>
where V: VaoDraw,
U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
B: ::BufferRange<T>,
{
self.surface.bind_attachments();
let mut state = self.context_state().shallow_clone();
unsafe{
state.set_program_id(program.id());
state.set_vao(vao_range.id());
state.set_buffer_binding(gl::DRAW_INDIRECT_BUFFER, command_buffer.id());
}
self.state_mut().apply(&state);
let ret = program.set_uniforms(uniforms);
unsafe{
self.gl().MultiDrawElementsIndirect(vao_range.mode(),
gl::UNSIGNED_INT,
(command_buffer.start() * mem::size_of::<T>()) as *const c_void,
command_buffer.len() as GLsizei,
mem::size_of::<T>() as GLsizei);
}
ret
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub fn multi_draw_arrays_command<V, T, B, U, I>(&self,
vao_range: V,
command_buffer: B,
program: &Program,
uniforms: I) -> Result<()>
where V: VaoDraw,
U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
B: ::BufferRange<T>,
{
self.surface.bind_attachments();
let mut state = self.context_state().shallow_clone();
unsafe{
state.set_program_id(program.id());
state.set_vao(vao_range.id());
state.set_buffer_binding(gl::DRAW_INDIRECT_BUFFER, command_buffer.id());
}
self.state_mut().apply(&state);
let ret = program.set_uniforms(uniforms);
unsafe{
self.gl().MultiDrawArraysIndirect(vao_range.mode(),
(command_buffer.start() * mem::size_of::<T>()) as *const c_void,
command_buffer.len() as GLsizei,
mem::size_of::<T>() as GLsizei);
}
ret
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub unsafe fn multi_draw_elements_command_vao_id<T, B, U, I>(&self,
vao_id: u32,
mode: GLenum,
command_buffer: B,
program: &Program,
uniforms: I) -> Result<()>
where U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
B: ::BufferRange<T>,
{
self.surface.bind_attachments();
let mut state = self.context_state().shallow_clone();
state.set_program_id(program.id());
state.set_vao(vao_id);
state.set_buffer_binding(gl::DRAW_INDIRECT_BUFFER, command_buffer.id());
self.state_mut().apply(&state);
let ret = program.set_uniforms(uniforms);
self.gl().MultiDrawElementsIndirect(mode,
gl::UNSIGNED_INT,
(command_buffer.start() * mem::size_of::<T>()) as *const c_void,
command_buffer.len() as GLsizei,
mem::size_of::<T>() as GLsizei);
ret
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub unsafe fn multi_draw_arrays_command_vao_id<T, B, U, I>(&self,
vao_id: u32,
mode: GLenum,
command_buffer: B,
program: &Program,
uniforms: I) -> Result<()>
where U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
B: ::BufferRange<T>,
{
self.surface.bind_attachments();
let mut state = self.context_state().shallow_clone();
state.set_program_id(program.id());
state.set_vao(vao_id);
state.set_buffer_binding(gl::DRAW_INDIRECT_BUFFER, command_buffer.id());
self.state_mut().apply(&state);
let ret = program.set_uniforms(uniforms);
self.gl().MultiDrawArraysIndirect(mode,
(command_buffer.start() * mem::size_of::<T>()) as *const c_void,
command_buffer.len() as GLsizei,
mem::size_of::<T>() as GLsizei);
ret
}
pub unsafe fn draw_with_program_id<V, U, I>(&self, vao_range: V, program: u32, uniforms: I) -> Result<()>
where V: VaoDraw,
U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
{
self.surface.bind_attachments();
let state = self.context_state();
state.set_program_id(program);
state.set_vao(vao_range.id());
self.state_mut().apply(state);
for uniform in uniforms.into_iter() {
let uniform = uniform.borrow();
let (location, value) = match uniform {
#[cfg(not(feature="webgl"))]
program::Uniform::Name(name, v) => match v {
program::UniformValue::UniformBlockBinding(_binding_point) =>
(self.gl().GetUniformBlockIndex(program, to_c_str!(name.clone())) as i32, v.clone()),
#[cfg(not(feature="gles"))]
program::UniformValue::ShaderStorageBlockBinding(_binding_point) =>
(self.gl().GetProgramResourceIndex(program,
gl::SHADER_STORAGE_BLOCK,
to_c_str!(name.clone())) as i32, v.clone()),
_ => (self.gl().GetUniformLocation(program, to_c_str!(name.clone())), v.clone()),
},
#[cfg(feature="webgl")]
program::Uniform::Name(name, v) => match v {
program::UniformValue::UniformBlockBinding(_binding_point) =>
(self.gl().GetUniformBlockIndex(program,name) as i32, v.clone()),
_ => (self.gl().GetUniformLocation(program, name), v.clone()),
}
program::Uniform::Location(loc, v) => (*loc as i32, v.clone())
};
if location != -1 {
match value{
program::UniformValue::Float(v) => self.gl().Uniform1f( location, v ),
program::UniformValue::Int(v) => self.gl().Uniform1i( location, v ),
program::UniformValue::Bool(v) => self.gl().Uniform1i( location, v as i32),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::UInt(v) => self.gl().Uniform1ui( location, v ),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::UVec2(v0,v1) => self.gl().Uniform2ui( location, v0, v1 ),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::UVec3(v0,v1,v2) => self.gl().Uniform3ui( location, v0, v1, v2 ),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::UVec4(v0,v1,v2,v3) => self.gl().Uniform4ui( location, v0, v1, v2, v3 ),
program::UniformValue::Vec2(v0,v1) => self.gl().Uniform2f( location, v0, v1 ),
program::UniformValue::Vec3(v0,v1,v2) => self.gl().Uniform3f( location, v0, v1, v2 ),
program::UniformValue::Vec4(v0,v1,v2,v3) => self.gl().Uniform4f( location, v0, v1, v2, v3 ),
program::UniformValue::IVec2(v0,v1) => self.gl().Uniform2i( location, v0, v1 ),
program::UniformValue::IVec3(v0,v1,v2) => self.gl().Uniform3i( location, v0, v1, v2 ),
program::UniformValue::IVec4(v0,v1,v2,v3) => self.gl().Uniform4i( location, v0, v1, v2, v3 ),
program::UniformValue::ArrayFloat(v) => self.gl().Uniform1fv(location as i32, v.len() as i32, v.as_ptr() as *const f32),
program::UniformValue::ArrayVec2(v) => self.gl().Uniform2fv(location as i32, v.len() as i32, v.as_ptr() as *const f32),
program::UniformValue::ArrayVec3(v) => self.gl().Uniform2fv(location as i32, v.len() as i32, v.as_ptr() as *const f32),
program::UniformValue::ArrayVec4(v) => self.gl().Uniform4fv(location as i32, v.len() as i32, v.as_ptr() as *const f32),
program::UniformValue::ArrayInt(v) => self.gl().Uniform1iv(location as i32, v.len() as i32, v.as_ptr() as *const i32),
program::UniformValue::ArrayIVec2(v) => self.gl().Uniform2iv(location as i32, v.len() as i32, v.as_ptr() as *const i32),
program::UniformValue::ArrayIVec3(v) => self.gl().Uniform3iv(location as i32, v.len() as i32, v.as_ptr() as *const i32),
program::UniformValue::ArrayIVec4(v) => self.gl().Uniform4iv(location as i32, v.len() as i32, v.as_ptr() as *const i32),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::ArrayUInt(v) => self.gl().Uniform1uiv(location as i32, v.len() as i32, v.as_ptr() as *const u32),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::ArrayUVec2(v) => self.gl().Uniform2uiv(location as i32, v.len() as i32, v.as_ptr() as *const u32),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::ArrayUVec3(v) => self.gl().Uniform3uiv(location as i32, v.len() as i32, v.as_ptr() as *const u32),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::ArrayUVec4(v) => self.gl().Uniform4uiv(location as i32, v.len() as i32, v.as_ptr() as *const u32),
program::UniformValue::Mat2(v) => self.gl().UniformMatrix2fv( location, 1, gl::FALSE, v.as_ptr() as *const f32 ),
program::UniformValue::Mat3(v) => self.gl().UniformMatrix3fv( location, 1, gl::FALSE, v.as_ptr() as *const f32 ),
program::UniformValue::Mat4(v) => self.gl().UniformMatrix4fv( location, 1, gl::FALSE, v.as_ptr() as *const f32 ),
program::UniformValue::Texture(tex, tex_location, target) => {
if self.state.capabilities().supports_dsa(){
#[cfg(not(any(feature="gles", feature="webgl")))]
{
self.gl().BindTextures(tex_location, 1, &tex);
self.gl().ProgramUniform1i(program, location as i32, tex_location as i32 );
self.gl().BindSampler(tex_location, 0);
}
}else{
self.gl().ActiveTexture(gl::TEXTURE0 + tex_location);
self.gl().BindTexture(target, tex);
self.gl().Uniform1i(location, tex_location as i32 );
self.gl().ActiveTexture(gl::TEXTURE0);
self.gl().BindSampler(tex_location, 0);
}
},
program::UniformValue::TextureSampler(tex, tex_location, target, sampler) => {
if self.state.capabilities().supports_dsa(){
#[cfg(not(any(feature="gles", feature="webgl")))]
{
self.gl().BindTextures(tex_location, 1, &tex);
self.gl().ProgramUniform1i(program, location as i32, tex_location as i32 );
self.gl().BindSampler(tex_location, sampler);
}
}else{
self.gl().ActiveTexture(gl::TEXTURE0 + tex_location);
self.gl().BindTexture(target, tex);
self.gl().Uniform1i(location, tex_location as i32 );
self.gl().ActiveTexture(gl::TEXTURE0);
self.gl().BindSampler(tex_location, sampler);
}
},
program::UniformValue::UniformBlockBinding(binding_point) => {
let block_index = location;
self.gl().UniformBlockBinding(program, block_index as u32, binding_point);
},
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::ShaderStorageBlockBinding(binding_point) => {
let block_index = location;
self.gl().ShaderStorageBlockBinding(program, block_index as u32, binding_point);
},
}
}
}
if vao_range.has_indices() {
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
{
if let Some(base_vertex) = vao_range.base_vertex(){
self.gl().DrawElementsBaseVertex(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void,
base_vertex);
}else{
self.gl().DrawElements(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void);
}
}
#[cfg(any(feature = "gles", feature="webgl"))]
self.gl().DrawElements(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
mem::transmute(vao_range.start() * mem::size_of::<::IndexT>()));
}else{
self.gl().DrawArrays(vao_range.mode(),
vao_range.start() as i32,
vao_range.count() as i32);
}
Ok(())
}
pub unsafe fn draw_instanced_with_program_id<V, U, I>(&self, vao_range: V, num_instances: usize, program: u32, uniforms: I) -> Result<()>
where V: VaoDraw,
U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>
{
self.surface.bind_attachments();
let state = self.context_state();
state.set_program_id(program);
state.set_vao(vao_range.id());
self.state_mut().apply(state);
for uniform in uniforms.into_iter() {
let uniform = uniform.borrow();
let (location, value) = match uniform {
#[cfg(not(feature="webgl"))]
program::Uniform::Name(name, v) => match v {
program::UniformValue::UniformBlockBinding(_binding_point) =>
(self.gl().GetUniformBlockIndex(program, to_c_str!(name.clone())) as i32, v.clone()),
#[cfg(not(any(feature="gles", feature="webgl")))]
program::UniformValue::ShaderStorageBlockBinding(_binding_point) =>
(self.gl().GetProgramResourceIndex(program,
gl::SHADER_STORAGE_BLOCK,
to_c_str!(name.clone())) as i32, v.clone()),
_ => (self.gl().GetUniformLocation(program, to_c_str!(name.clone())), v.clone()),
},
#[cfg(feature="webgl")]
program::Uniform::Name(name, v) => match v {
program::UniformValue::UniformBlockBinding(_binding_point) =>
(self.gl().GetUniformBlockIndex(program, name) as i32, v.clone()),
_ => (self.gl().GetUniformLocation(program, name), v.clone()),
}
program::Uniform::Location(loc, v) => (*loc as i32, v.clone())
};
if location != -1 {
match value{
program::UniformValue::Float(v) => self.gl().Uniform1f( location, v ),
program::UniformValue::Int(v) => self.gl().Uniform1i( location, v ),
program::UniformValue::Bool(v) => self.gl().Uniform1i( location, v as i32),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::UInt(v) => self.gl().Uniform1ui( location, v ),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::UVec2(v0,v1) => self.gl().Uniform2ui( location, v0, v1 ),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::UVec3(v0,v1,v2) => self.gl().Uniform3ui( location, v0, v1, v2 ),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::UVec4(v0,v1,v2,v3) => self.gl().Uniform4ui( location, v0, v1, v2, v3 ),
program::UniformValue::Vec2(v0,v1) => self.gl().Uniform2f( location, v0, v1 ),
program::UniformValue::Vec3(v0,v1,v2) => self.gl().Uniform3f( location, v0, v1, v2 ),
program::UniformValue::Vec4(v0,v1,v2,v3) => self.gl().Uniform4f( location, v0, v1, v2, v3 ),
program::UniformValue::IVec2(v0,v1) => self.gl().Uniform2i( location, v0, v1 ),
program::UniformValue::IVec3(v0,v1,v2) => self.gl().Uniform3i( location, v0, v1, v2 ),
program::UniformValue::IVec4(v0,v1,v2,v3) => self.gl().Uniform4i( location, v0, v1, v2, v3 ),
program::UniformValue::Mat2(v) => self.gl().UniformMatrix2fv( location, 1, gl::FALSE, v.as_ptr() as *const f32 ),
program::UniformValue::Mat3(v) => self.gl().UniformMatrix3fv( location, 1, gl::FALSE, v.as_ptr() as *const f32 ),
program::UniformValue::Mat4(v) => self.gl().UniformMatrix4fv( location, 1, gl::FALSE, v.as_ptr() as *const f32 ),
program::UniformValue::ArrayFloat(v) => self.gl().Uniform1fv(location as i32, v.len() as i32, v.as_ptr() as *const f32),
program::UniformValue::ArrayVec2(v) => self.gl().Uniform2fv(location as i32, v.len() as i32, v.as_ptr() as *const f32),
program::UniformValue::ArrayVec3(v) => self.gl().Uniform2fv(location as i32, v.len() as i32, v.as_ptr() as *const f32),
program::UniformValue::ArrayVec4(v) => self.gl().Uniform4fv(location as i32, v.len() as i32, v.as_ptr() as *const f32),
program::UniformValue::ArrayInt(v) => self.gl().Uniform1iv(location as i32, v.len() as i32, v.as_ptr() as *const i32),
program::UniformValue::ArrayIVec2(v) => self.gl().Uniform2iv(location as i32, v.len() as i32, v.as_ptr() as *const i32),
program::UniformValue::ArrayIVec3(v) => self.gl().Uniform3iv(location as i32, v.len() as i32, v.as_ptr() as *const i32),
program::UniformValue::ArrayIVec4(v) => self.gl().Uniform4iv(location as i32, v.len() as i32, v.as_ptr() as *const i32),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::ArrayUInt(v) => self.gl().Uniform1uiv(location as i32, v.len() as i32, v.as_ptr() as *const u32),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::ArrayUVec2(v) => self.gl().Uniform2uiv(location as i32, v.len() as i32, v.as_ptr() as *const u32),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::ArrayUVec3(v) => self.gl().Uniform3uiv(location as i32, v.len() as i32, v.as_ptr() as *const u32),
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::ArrayUVec4(v) => self.gl().Uniform4uiv(location as i32, v.len() as i32, v.as_ptr() as *const u32),
program::UniformValue::Texture(tex, tex_location, target) => {
if self.state.capabilities().supports_dsa(){
#[cfg(not(any(feature="gles", feature="webgl")))]
{
self.gl().BindTextures(tex_location, 1, &tex);
self.gl().ProgramUniform1i(program, location as i32, tex_location as i32 );
self.gl().BindSampler(tex_location, 0);
}
}else{
self.gl().ActiveTexture(gl::TEXTURE0 + tex_location);
self.gl().BindTexture(target, tex);
self.gl().Uniform1i(location, tex_location as i32 );
self.gl().ActiveTexture(gl::TEXTURE0);
self.gl().BindSampler(tex_location, 0);
}
},
program::UniformValue::TextureSampler(tex, tex_location, target, sampler) => {
if self.state.capabilities().supports_dsa(){
#[cfg(not(any(feature="gles", feature="webgl")))]
{
self.gl().BindTextures(tex_location, 1, &tex);
self.gl().ProgramUniform1i(program, location as i32, tex_location as i32 );
self.gl().BindSampler(tex_location, sampler);
}
}else{
self.gl().ActiveTexture(gl::TEXTURE0 + tex_location);
self.gl().BindTexture(target, tex);
self.gl().Uniform1i(location, tex_location as i32 );
self.gl().ActiveTexture(gl::TEXTURE0);
self.gl().BindSampler(tex_location, sampler);
}
},
program::UniformValue::UniformBlockBinding(binding_point) => {
let block_index = location;
self.gl().UniformBlockBinding(program, block_index as u32, binding_point);
},
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
program::UniformValue::ShaderStorageBlockBinding(binding_point) => {
let block_index = location;
self.gl().ShaderStorageBlockBinding(program, block_index as u32, binding_point);
},
}
}
}
self.state_mut().apply(&state);
#[cfg(not(any(feature="gles", feature="webgl")))]
{
if vao_range.num_indices() > 0{
match (vao_range.base_vertex(), vao_range.base_instance()){
(Some(base_vertex), Some(base_instance)) => {
self.gl().DrawElementsInstancedBaseVertexBaseInstance(
vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void,
num_instances as i32,
base_vertex,
base_instance);
}
(Some(base_vertex), None) => {
self.gl().DrawElementsInstancedBaseVertex(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void,
num_instances as i32,
base_vertex);
}
(None, None) => {
self.gl().DrawElementsInstanced(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void,
num_instances as i32);
}
_ => unreachable!(),
}
}else if let Some(base_instance) = vao_range.base_instance(){
self.gl().DrawArraysInstancedBaseInstance(vao_range.mode(),
vao_range.start() as i32,
vao_range.count() as i32,
num_instances as i32,
base_instance);
}else{
self.gl().DrawArraysInstanced(vao_range.mode(),
vao_range.start() as i32,
vao_range.count() as i32,
num_instances as i32);
}
}
#[cfg(feature="gles")]
{
if vao_range.num_indices() > 0{
self.gl().DrawElementsInstanced(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as *const c_void,
num_instances as i32);
}else{
self.gl().DrawArraysInstanced(vao_range.mode(),
vao_range.start() as i32,
vao_range.count() as i32,
num_instances as i32);
}
}
#[cfg(feature="webgl")]
{
if vao_range.num_indices() > 0{
self.gl().DrawElementsInstanced(vao_range.mode(),
vao_range.count() as i32,
gl::UNSIGNED_INT,
(vao_range.start() * mem::size_of::<::IndexT>()) as isize,
num_instances as i32);
}else{
self.gl().DrawArraysInstanced(vao_range.mode(),
vao_range.start() as i32,
vao_range.count() as i32,
num_instances as i32);
}
}
Ok(())
}
pub fn with<'a, P: IntoIterator<Item = &'a Property>>(&self, properties: P) -> Context<R> {
let new_state = State::with_properties(self.context_state(), properties);
Context{
state: self.state.clone(),
context_state: new_state,
creation_context: self.creation_context.clone(),
surface: self.surface.clone(),
}
}
pub fn set_properties<'a, P: IntoIterator<Item = &'a Property>>(&mut self, properties: P) {
State::set_properties(&mut self.context_state, properties);
}
pub fn with_fbo<F: UntypedOffscreenBuffer + Clone>(&self, fbo: F) -> Context<F> {
let viewport = fbo.viewport();
let properties = &[
Property::Viewport(viewport),
];
let new_state = State::from_properties_fbo_draw_id(
self.context_state(),
properties,
&fbo);
Context{
state: self.state.clone(),
context_state: new_state,
creation_context: self.creation_context.clone(),
surface: fbo,
}
}
pub fn into_with_fbo<F: UntypedOffscreenBuffer + Clone>(mut self, fbo: F) -> Context<'c, F> {
let viewport = fbo.viewport();
let properties = &[
Property::Viewport(viewport),
];
State::set_properties_fbo_draw_id(
&mut self.context_state,
properties,
&fbo);
Context{
state: self.state,
context_state: self.context_state,
creation_context: self.creation_context.clone(),
surface: fbo,
}
}
pub fn capture_state(&self) -> State<'static>{
self.state().clone()
}
pub fn clear_color<C: ::utils::Color<T> + ?Sized, T: ?Sized>(&self, color: &C) where Self: Sized{
self.surface.bind_attachments();
self.state_mut().apply_fbo(self.context_state());
self.state_mut().apply_mask(self.context_state());
self.state_mut().apply_enable(self.context_state());
self.state_mut().apply_scissor(self.context_state());
unsafe{
let c = color.as_slice();
self.gl().ClearColor(c[0], c[1], c[2], c[3]);
self.gl().Clear(gl::COLOR_BUFFER_BIT);
}
}
pub fn clear_depth(&self, depth: f64){
self.surface.bind_attachments();
self.state_mut().apply_fbo(self.context_state());
self.state_mut().apply_mask(self.context_state());
self.state_mut().apply_depth(self.context_state());
self.state_mut().apply_enable(self.context_state());
self.state_mut().apply_scissor(self.context_state());
unsafe{
#[cfg(not(any(feature="gles", feature="webgl")))]
self.gl().ClearDepth(depth);
#[cfg(feature = "webgl")]
self.gl().ClearDepth(depth as f32);
#[cfg(feature="gles")]
self.gl().ClearDepthf(depth as f32);
self.gl().Clear(gl::DEPTH_BUFFER_BIT);
}
}
pub fn clear_stencil(&self, stencil: i32){
self.surface.bind_attachments();
self.state_mut().apply_fbo(self.context_state());
self.state_mut().apply_mask(self.context_state());
self.state_mut().apply_stencil(self.context_state());
self.state_mut().apply_scissor(self.context_state());
unsafe{
self.gl().ClearStencil(stencil as GLint);
self.gl().Clear(gl::STENCIL_BUFFER_BIT);
}
}
pub fn clear<C>(&self, color: Option<C>, depth: Option<f64>, stencil: Option<i32>)
where C: Borrow<[f32;4]>
{
let mut flags = 0;
unsafe{
if let Some(color) = color {
let color = color.borrow();
self.gl().ClearColor(color[0], color[1], color[2], color[3]);
flags |= gl::COLOR_BUFFER_BIT;
}
if let Some(depth) = depth {
self.state_mut().apply_depth(self.context_state());
#[cfg(not(any(feature="gles", feature="webgl")))]
self.gl().ClearDepth(depth);
#[cfg(feature = "webgl")]
self.gl().ClearDepth(depth as f32);
#[cfg(feature="gles")]
self.gl().ClearDepthf(depth as f32);
flags |= gl::DEPTH_BUFFER_BIT;
}
if let Some(stencil) = stencil {
self.state_mut().apply_stencil(self.context_state());
self.gl().ClearStencil(stencil as GLint);
flags |= gl::STENCIL_BUFFER_BIT;
}
if flags != 0 {
self.surface.bind_attachments();
self.state_mut().apply_fbo(self.context_state());
self.state_mut().apply_mask(self.context_state());
self.state_mut().apply_enable(self.context_state());
self.state_mut().apply_scissor(self.context_state());
self.gl().Clear(flags);
}
}
}
pub fn new_texture(&self) -> texture::Builder{
texture::Builder(&self.state)
}
pub fn new_cubemap(&self) -> cubemap::Builder{
cubemap::Builder(&self.state)
}
pub fn new_fbo(&self) -> fbo::Builder{
if self.state().fbo().read() != 0 || self.state().fbo().draw() != 0 {
self.state_mut().set_fbo(0,0);
}
fbo::Builder(&self.state)
}
pub fn new_fbo_color_attachment(&self) -> fbo::ColorAttachmentBuilder{
if self.state().fbo().read() != 0 || self.state().fbo().draw() != 0 {
self.state_mut().set_fbo(0,0);
}
fbo::ColorAttachmentBuilder(&self.state)
}
pub fn new_fbo_depth_attachment(&self) -> fbo::DepthAttachmentBuilder{
if self.state().fbo().read() != 0 || self.state().fbo().draw() != 0 {
self.state_mut().set_fbo(0,0);
}
fbo::DepthAttachmentBuilder(&self.state)
}
pub fn new_render_buffer(&self) -> fbo::RenderBufferBuilder{
if self.state().fbo().read() != 0 || self.state().fbo().draw() != 0 {
self.state_mut().set_fbo(0,0);
}
fbo::RenderBufferBuilder(&self.state)
}
pub fn new_buffer(&self) -> buffer::Builder{
buffer::Builder(&self.state)
}
pub fn new_shared_buffer(&self) -> buffer::SharedBuilder{
buffer::SharedBuilder(&self.state)
}
pub fn new_vao(&self) -> vao::Builder{
vao::Builder::new(&self.state)
}
pub fn new_simple_vao(&self) -> simple_vao::Builder{
simple_vao::Builder(&self.creation_context, &self.state)
}
pub fn new_program(&self) -> program::Builder{
program::Builder(&self.state)
}
pub fn new_sampler(&self) -> Sampler{
Sampler::new(&self.state)
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub fn new_timestamp_query(&self) -> TimeStamp{
TimeStamp::new(&self.state)
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub fn new_duration_query(&self) -> Duration{
Duration::new(&self.state)
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub fn new_fence(&self) -> Fence{
Fence::new(&self.state)
}
#[cfg(not(feature="webgl"))]
pub fn new_debug_group(&self, id: u32, message: &str) -> DebugGroup {
unsafe{
self.gl().PushDebugGroup(
gl::DEBUG_SOURCE_APPLICATION,
0,
-1,
std::ffi::CString::new(message).unwrap().as_ptr() as *const i8
)
}
DebugGroup{
gl: self.state.clone()
}
}
pub fn creation_proxy(&self) -> &Rc<CreationProxy> {
&self.creation_context
}
pub fn state(&self) -> &State<'static>{
self.state.state()
}
pub fn shallow_clone(&self) -> Context<R>{
Context{
state: self.state.clone(),
context_state: self.context_state.shallow_clone(),
creation_context: self.creation_context.clone(),
surface: self.surface.clone(),
}
}
#[allow(clippy::mut_from_ref)]
fn state_mut(&self) -> &mut State<'static>{
self.state.state_mut()
}
fn context_state(&self) -> &State{
&self.context_state
}
pub fn blit<C1,D1,C2,D2>(
&self,
fbo_src: &Fbo<C1,D1>,
fbo_dst: &mut Fbo<C2,D2>,
src_rect: &Rect,
dst_rect: &Rect)
{
fbo_src.blit_(
fbo::AttachmentTy::Color(0),
fbo_dst,
src_rect,
dst_rect,
Some(self.context_state())
)
}
pub fn blit_color_attachment<C1,D1,C2,D2>(
&self,
fbo_src: &Fbo<C1,D1>,
fbo_dst: &mut Fbo<C2,D2>,
attachment: u32,
src_rect: &Rect,
dst_rect: &Rect)
{
fbo_src.blit_(
fbo::AttachmentTy::Color(attachment),
fbo_dst,
src_rect,
dst_rect,
Some(self.context_state())
)
}
pub fn blit_depth<C1,D1,C2,D2>(
&self,
fbo_src: &Fbo<C1,D1>,
fbo_dst: &mut Fbo<C2,D2>,
src_rect: &Rect,
dst_rect: &Rect)
{
fbo_src.blit_(
fbo::AttachmentTy::Depth,
fbo_dst,
src_rect,
dst_rect,
Some(self.context_state())
)
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
pub fn dispatch_compute<U,I>(&self, program: &Program, x: u32, y: u32, z: u32, uniforms: I) -> Result<()>
where U: Borrow<program::Uniform>,
I: IntoIterator<Item=U>,
{
self.surface.bind_attachments();
let mut state = self.context_state().shallow_clone();
unsafe{
state.set_program_id(program.id());
}
self.state_mut().apply(&state);
let err = program.set_uniforms(uniforms);
unsafe{
self.gl().DispatchCompute(x, y, z)
}
err
}
}
impl<'c, R: RenderSurface> Context<'c, R>{
pub fn surface(&self) -> &R{
&self.surface
}
}
impl<'c, R: RenderSurface> Clone for Context<'c, R>{
fn clone(&self) -> Context<'c, R>{
Context{
state: self.state.clone(),
context_state: self.context_state.clone(),
creation_context: self.creation_context.clone(),
surface: self.surface.clone(),
}
}
}
pub struct CreationProxy{
state: StateRef,
}
impl CreationProxy{
fn state(&self) -> &State<'static>{
self.state.state()
}
#[allow(clippy::mut_from_ref)]
fn state_mut(&self) -> &mut State<'static>{
self.state.state_mut()
}
}
pub trait CreationContext{
fn capabilities(&self) -> &Capabilities;
fn new_texture(&self) -> texture::Builder;
fn new_cubemap(&self) -> cubemap::Builder;
fn new_buffer(&self) -> buffer::Builder;
fn new_shared_buffer(&self) -> buffer::SharedBuilder;
fn new_vao(&self) -> vao::Builder;
fn new_simple_vao(&self) -> simple_vao::Builder;
fn new_program(&self) -> program::Builder;
fn new_sampler(&self) -> Sampler;
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
fn new_timestamp_query(&self) -> TimeStamp;
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
fn new_duration_query(&self) -> Duration;
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
fn new_fence(&self) -> Fence;
fn creation_proxy(&self) -> &Rc<CreationProxy>;
}
pub trait CreationContextMut{
fn capabilities_mut(&mut self) -> &mut Capabilities;
}
pub trait SurfaceCreationContext{
fn new_fbo(&self) -> fbo::Builder;
fn new_fbo_color_attachment(&self) -> fbo::ColorAttachmentBuilder;
fn new_fbo_depth_attachment(&self) -> fbo::DepthAttachmentBuilder;
fn new_render_buffer(&self) -> fbo::RenderBufferBuilder;
}
impl CreationContext for Rc<CreationProxy>{
fn capabilities(&self) -> &Capabilities{
self.state.capabilities()
}
fn new_texture(&self) -> texture::Builder{
texture::Builder(&self.state)
}
fn new_cubemap(&self) -> cubemap::Builder{
cubemap::Builder(&self.state)
}
fn new_buffer(&self) -> buffer::Builder{
buffer::Builder(&self.state)
}
fn new_shared_buffer(&self) -> buffer::SharedBuilder{
buffer::SharedBuilder(&self.state)
}
fn new_vao(&self) -> vao::Builder{
vao::Builder::new(&self.state)
}
fn new_simple_vao(&self) -> simple_vao::Builder{
simple_vao::Builder(self, &self.state)
}
fn new_program(&self) -> program::Builder{
program::Builder(&self.state)
}
fn new_sampler(&self) -> Sampler{
Sampler::new(&self.state)
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
fn new_timestamp_query(&self) -> TimeStamp{
TimeStamp::new(&self.state)
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
fn new_duration_query(&self) -> Duration{
Duration::new(&self.state)
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
fn new_fence(&self) -> Fence{
Fence::new(&self.state)
}
fn creation_proxy(&self) -> &Rc<CreationProxy>{
self
}
}
impl SurfaceCreationContext for Rc<CreationProxy>{
fn new_fbo(&self) -> fbo::Builder{
if self.state().fbo().read() != 0 || self.state().fbo().draw() != 0 {
self.state_mut().set_fbo(0,0);
}
fbo::Builder(&self.state)
}
fn new_fbo_color_attachment(&self) -> fbo::ColorAttachmentBuilder{
if self.state().fbo().read() != 0 || self.state().fbo().draw() != 0 {
self.state_mut().set_fbo(0,0);
}
fbo::ColorAttachmentBuilder(&self.state)
}
fn new_fbo_depth_attachment(&self) -> fbo::DepthAttachmentBuilder{
if self.state().fbo().read() != 0 || self.state().fbo().draw() != 0 {
self.state_mut().set_fbo(0,0);
}
fbo::DepthAttachmentBuilder(&self.state)
}
fn new_render_buffer(&self) -> fbo::RenderBufferBuilder{
if self.state().fbo().read() != 0 || self.state().fbo().draw() != 0 {
self.state_mut().set_fbo(0,0);
}
fbo::RenderBufferBuilder(&self.state)
}
}
impl<'c, R: RenderSurface> CreationContext for Context<'c, R>{
fn capabilities(&self) -> &Capabilities{
self.state.capabilities()
}
fn new_texture(&self) -> texture::Builder{
texture::Builder(&self.state)
}
fn new_cubemap(&self) -> cubemap::Builder{
cubemap::Builder(&self.state)
}
fn new_buffer(&self) -> buffer::Builder{
buffer::Builder(&self.state)
}
fn new_shared_buffer(&self) -> buffer::SharedBuilder{
buffer::SharedBuilder(&self.state)
}
fn new_vao(&self) -> vao::Builder{
vao::Builder::new(&self.state)
}
fn new_simple_vao(&self) -> simple_vao::Builder{
simple_vao::Builder(&self.creation_context, &self.state)
}
fn new_program(&self) -> program::Builder{
program::Builder(&self.state)
}
fn new_sampler(&self) -> Sampler{
Sampler::new(&self.state)
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
fn new_timestamp_query(&self) -> TimeStamp{
TimeStamp::new(&self.state)
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
fn new_duration_query(&self) -> Duration{
Duration::new(&self.state)
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
fn new_fence(&self) -> Fence{
Fence::new(&self.state)
}
fn creation_proxy(&self) -> &Rc<CreationProxy>{
self.creation_proxy()
}
}
impl<'c, R: RenderSurface> CreationContextMut for Context<'c,R>{
fn capabilities_mut(&mut self) -> &mut Capabilities{
self.state.capabilities_mut()
}
}
impl<'c> SurfaceCreationContext for Context<'c>{
fn new_fbo(&self) -> fbo::Builder{
if self.state().fbo().read() != 0 || self.state().fbo().draw() != 0 {
self.state_mut().set_fbo(0,0);
}
fbo::Builder(&self.state)
}
fn new_fbo_color_attachment(&self) -> fbo::ColorAttachmentBuilder{
if self.state().fbo().read() != 0 || self.state().fbo().draw() != 0 {
self.state_mut().set_fbo(0,0);
}
fbo::ColorAttachmentBuilder(&self.state)
}
fn new_fbo_depth_attachment(&self) -> fbo::DepthAttachmentBuilder{
if self.state().fbo().read() != 0 || self.state().fbo().draw() != 0 {
self.state_mut().set_fbo(0,0);
}
fbo::DepthAttachmentBuilder(&self.state)
}
fn new_render_buffer(&self) -> fbo::RenderBufferBuilder{
if self.state().fbo().read() != 0 || self.state().fbo().draw() != 0 {
self.state_mut().set_fbo(0,0);
}
fbo::RenderBufferBuilder(&self.state)
}
}
impl<'a, C: CreationContext> CreationContext for &'a C{
fn capabilities(&self) -> &Capabilities{
(*self).capabilities()
}
fn new_texture(&self) -> texture::Builder{
(*self).new_texture()
}
fn new_cubemap(&self) -> cubemap::Builder{
(*self).new_cubemap()
}
fn new_buffer(&self) -> buffer::Builder{
(*self).new_buffer()
}
fn new_shared_buffer(&self) -> buffer::SharedBuilder{
(*self).new_shared_buffer()
}
fn new_vao(&self) -> vao::Builder{
(*self).new_vao()
}
fn new_simple_vao(&self) -> simple_vao::Builder{
(*self).new_simple_vao()
}
fn new_program(&self) -> program::Builder{
(*self).new_program()
}
fn new_sampler(&self) -> Sampler{
(*self).new_sampler()
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
fn new_timestamp_query(&self) -> TimeStamp{
(*self).new_timestamp_query()
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
fn new_duration_query(&self) -> Duration{
(*self).new_duration_query()
}
#[cfg(all(not(feature = "gles"), not(feature="webgl")))]
fn new_fence(&self) -> Fence{
(*self).new_fence()
}
fn creation_proxy(&self) -> &Rc<CreationProxy>{
(*self).creation_proxy()
}
}
impl<'a, C: SurfaceCreationContext> SurfaceCreationContext for &'a C{
fn new_fbo(&self) -> fbo::Builder{
(*self).new_fbo()
}
fn new_fbo_color_attachment(&self) -> fbo::ColorAttachmentBuilder{
(*self).new_fbo_color_attachment()
}
fn new_fbo_depth_attachment(&self) -> fbo::DepthAttachmentBuilder{
(*self).new_fbo_depth_attachment()
}
fn new_render_buffer(&self) -> fbo::RenderBufferBuilder{
(*self).new_render_buffer()
}
}
impl<'a, C: CreationContextMut> CreationContextMut for &'a mut C{
fn capabilities_mut(&mut self) -> &mut Capabilities{
(*self).capabilities_mut()
}
}