2016-03-16 14:25:35 -04:00
|
|
|
// Copyright 2016 Matthew Collins
|
2015-09-17 11:21:56 -04:00
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
// you may not use this file except in compliance with the License.
|
|
|
|
// You may obtain a copy of the License at
|
|
|
|
//
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
//
|
|
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
// See the License for the specific language governing permissions and
|
|
|
|
// limitations under the License.
|
|
|
|
|
2015-09-07 16:11:00 -04:00
|
|
|
extern crate steven_gl as gl;
|
2016-03-25 09:15:35 -04:00
|
|
|
use sdl2;
|
2015-09-07 16:11:00 -04:00
|
|
|
|
|
|
|
use std::ops::BitOr;
|
2015-09-17 11:04:25 -04:00
|
|
|
use std::ffi;
|
|
|
|
use std::mem;
|
|
|
|
use std::ptr;
|
|
|
|
use std::ops::{Deref, DerefMut};
|
2015-09-07 16:11:00 -04:00
|
|
|
|
2015-09-17 11:04:25 -04:00
|
|
|
/// Inits the gl library. This should be called once a context is ready.
|
2016-03-25 09:15:35 -04:00
|
|
|
pub fn init(vid: & sdl2::VideoSubsystem) {
|
|
|
|
gl::load_with(|s| vid.gl_get_proc_address(s) as *const _);
|
2015-09-07 16:11:00 -04:00
|
|
|
}
|
|
|
|
|
2015-09-17 11:04:25 -04:00
|
|
|
/// Dsed to specify how the vertices will be handled
|
|
|
|
/// to draw.
|
|
|
|
pub type DrawType = u32;
|
|
|
|
|
|
|
|
/// Treats each set of 3 vertices as a triangle
|
|
|
|
pub const TRIANGLES: DrawType = gl::TRIANGLES;
|
|
|
|
/// Means the previous vertex connects to the next
|
|
|
|
/// one in a continuous strip.
|
|
|
|
pub const LINE_STRIP: DrawType = gl::LINE_STRIP;
|
|
|
|
/// Treats each set of 2 vertices as a line
|
|
|
|
pub const LINES: DrawType = gl::LINES;
|
|
|
|
/// Treats each vertex as a point
|
|
|
|
pub const POINTS: DrawType = gl::POINTS;
|
|
|
|
|
2016-03-18 11:19:21 -04:00
|
|
|
pub fn draw_arrays(ty: DrawType, offset: usize, count: usize) {
|
|
|
|
unsafe {
|
|
|
|
gl::DrawArrays(ty, offset as i32, count as i32);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-27 18:31:57 -04:00
|
|
|
pub fn draw_elements(ty: DrawType, count: i32, dty: Type, offset: usize) {
|
2015-09-17 11:04:25 -04:00
|
|
|
unsafe {
|
2016-03-27 18:31:57 -04:00
|
|
|
gl::DrawElements(ty, count, dty, offset as *const gl::types::GLvoid);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn multi_draw_elements(ty: DrawType, count: &[i32], dty: Type, offsets: &[usize]) {
|
|
|
|
unsafe {
|
|
|
|
gl::MultiDrawElements(ty, count.as_ptr(), dty, offsets.as_ptr() as *const _, count.len() as i32);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the size of the viewport of this context.
|
|
|
|
pub fn viewport(x: i32, y: i32, w: i32, h: i32) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::Viewport(x, y, w, h);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the color the color buffer should be cleared to
|
|
|
|
/// when Clear is called with the color flag.
|
2015-09-07 16:11:00 -04:00
|
|
|
pub fn clear_color(r: f32, g: f32, b: f32, a: f32) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::ClearColor(r, g, b, a);
|
|
|
|
}
|
2015-09-07 16:11:00 -04:00
|
|
|
}
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// `ClearFlags` is a set of flags to mark what should be cleared during
|
2015-09-17 11:04:25 -04:00
|
|
|
/// a Clear call.
|
2015-09-07 16:11:00 -04:00
|
|
|
pub enum ClearFlags {
|
2015-09-17 11:04:25 -04:00
|
|
|
/// Marks the color buffer to be cleared
|
2015-09-07 16:11:00 -04:00
|
|
|
Color,
|
2015-09-17 11:04:25 -04:00
|
|
|
/// Marks the depth buffer to be cleared
|
2015-09-07 16:11:00 -04:00
|
|
|
Depth,
|
2015-10-07 14:36:59 -04:00
|
|
|
Internal(u32),
|
2015-09-07 16:11:00 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ClearFlags {
|
|
|
|
fn internal(self) -> u32 {
|
|
|
|
match self {
|
|
|
|
ClearFlags::Color => gl::COLOR_BUFFER_BIT,
|
|
|
|
ClearFlags::Depth => gl::DEPTH_BUFFER_BIT,
|
2015-10-07 14:36:59 -04:00
|
|
|
ClearFlags::Internal(val) => val,
|
2015-09-07 16:11:00 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl BitOr for ClearFlags {
|
|
|
|
type Output = ClearFlags;
|
|
|
|
|
|
|
|
fn bitor(self, rhs: ClearFlags) -> ClearFlags {
|
|
|
|
ClearFlags::Internal(self.internal() | rhs.internal())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-17 11:04:25 -04:00
|
|
|
/// Clears the buffers specified by the passed flags.
|
2015-09-07 16:11:00 -04:00
|
|
|
pub fn clear(flags: ClearFlags) {
|
|
|
|
unsafe { gl::Clear(flags.internal()) }
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
|
2016-03-18 11:19:21 -04:00
|
|
|
pub fn depth_mask(f: bool) {
|
|
|
|
unsafe { gl::DepthMask(f as u8); }
|
|
|
|
}
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// `Func` is a function to be preformed on two values.
|
2015-09-17 11:04:25 -04:00
|
|
|
pub type Func = u32;
|
|
|
|
|
|
|
|
pub const NEVER: Func = gl::NEVER;
|
|
|
|
pub const LESS: Func = gl::LESS;
|
|
|
|
pub const LESS_OR_EQUAL: Func = gl::LEQUAL;
|
|
|
|
pub const GREATER: Func = gl::GREATER;
|
|
|
|
pub const ALWAYS: Func = gl::ALWAYS;
|
|
|
|
pub const EQUAL: Func = gl::EQUAL;
|
|
|
|
|
|
|
|
pub fn depth_func(f: Func) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::DepthFunc(f);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Flag is a setting that can be enabled or disabled on the context.
|
|
|
|
pub type Flag = u32;
|
|
|
|
|
|
|
|
pub const DEPTH_TEST: Flag = gl::DEPTH_TEST;
|
|
|
|
pub const CULL_FACE_FLAG: Flag = gl::CULL_FACE;
|
|
|
|
pub const STENCIL_TEST: Flag = gl::STENCIL_TEST;
|
|
|
|
pub const BLEND: Flag = gl::BLEND;
|
|
|
|
pub const MULTISAMPLE: Flag = gl::MULTISAMPLE;
|
|
|
|
|
|
|
|
/// Enables the passed flag.
|
|
|
|
pub fn enable(f: Flag) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::Enable(f);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Disables the passed flag.
|
|
|
|
pub fn disable(f: Flag) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::Disable(f);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Sets the texture slot with the passed id as the
|
|
|
|
/// currently active one.
|
|
|
|
pub fn active_texture(id: u32) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::ActiveTexture(gl::TEXTURE0 + id);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// `Factor` is used in blending
|
2015-09-18 17:02:08 -04:00
|
|
|
pub type Factor = u32;
|
|
|
|
pub const SRC_ALPHA: Factor = gl::SRC_ALPHA;
|
|
|
|
pub const ONE_MINUS_SRC_ALPHA: Factor = gl::ONE_MINUS_SRC_ALPHA;
|
|
|
|
pub const ONE_FACTOR: Factor = gl::ONE;
|
|
|
|
pub const ZERO_FACTOR: Factor = gl::ZERO;
|
|
|
|
|
|
|
|
/// Sets the factors to be used when blending.
|
|
|
|
pub fn blend_func(s_factor: Factor, d_factor: Factor) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::BlendFunc(s_factor, d_factor);
|
|
|
|
}
|
2015-09-18 17:02:08 -04:00
|
|
|
}
|
|
|
|
|
2016-03-18 11:19:21 -04:00
|
|
|
pub fn blend_func_separate(s_factor_rgb: Factor, d_factor_rgb: Factor, s_factor_a: Factor, d_factor_a: Factor) {
|
|
|
|
unsafe {
|
|
|
|
gl::BlendFuncSeparate(s_factor_rgb, d_factor_rgb, s_factor_a, d_factor_a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-06 18:49:52 -04:00
|
|
|
// Face specifies a face to act on.
|
|
|
|
pub type Face = u32;
|
|
|
|
pub const BACK: Face = gl::BACK;
|
|
|
|
pub const FRONT: Face = gl::FRONT;
|
|
|
|
|
|
|
|
/// Sets the face to be culled by the gpu.
|
|
|
|
pub fn cull_face(face: Face) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::CullFace(face);
|
|
|
|
}
|
2015-10-06 18:49:52 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// FaceDirection is used to specify an order of vertices, normally
|
|
|
|
// used to set which is considered to be the front face.
|
|
|
|
pub type FaceDirection = u32;
|
|
|
|
pub const CLOCK_WISE: FaceDirection = gl::CW;
|
|
|
|
pub const COUNTER_CLOCK_WISE: FaceDirection = gl::CCW;
|
|
|
|
|
|
|
|
/// Sets the direction of vertices used to specify the
|
|
|
|
/// front face (e.g. for culling).
|
|
|
|
pub fn front_face(dir: FaceDirection) {
|
|
|
|
unsafe { gl::FrontFace(dir) }
|
|
|
|
}
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// `Type` is a type of data used by various operations.
|
2015-09-17 11:04:25 -04:00
|
|
|
pub type Type = u32;
|
|
|
|
pub const UNSIGNED_BYTE: Type = gl::UNSIGNED_BYTE;
|
|
|
|
pub const UNSIGNED_SHORT: Type = gl::UNSIGNED_SHORT;
|
|
|
|
pub const UNSIGNED_INT: Type = gl::UNSIGNED_INT;
|
|
|
|
pub const SHORT: Type = gl::SHORT;
|
|
|
|
pub const FLOAT: Type = gl::FLOAT;
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// `TextureTarget` is a target were a texture can be bound to
|
2015-09-17 11:04:25 -04:00
|
|
|
pub type TextureTarget = u32;
|
|
|
|
|
|
|
|
pub const TEXTURE_2D: TextureTarget = gl::TEXTURE_2D;
|
|
|
|
pub const TEXTURE_2D_MULTISAMPLE: TextureTarget = gl::TEXTURE_2D_MULTISAMPLE;
|
|
|
|
pub const TEXTURE_2D_ARRAY: TextureTarget = gl::TEXTURE_2D_ARRAY;
|
|
|
|
pub const TEXTURE_3D: TextureTarget = gl::TEXTURE_3D;
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// `TextureFormat` is the format of a texture either internally or
|
2015-09-17 11:04:25 -04:00
|
|
|
/// to be uploaded.
|
|
|
|
pub type TextureFormat = u32;
|
|
|
|
|
|
|
|
pub const RED: TextureFormat = gl::RED;
|
|
|
|
pub const RGB: TextureFormat = gl::RGB;
|
|
|
|
pub const RGBA: TextureFormat = gl::RGBA;
|
|
|
|
pub const RGBA8: TextureFormat = gl::RGBA8;
|
|
|
|
pub const RGBA16F: TextureFormat = gl::RGBA16F;
|
|
|
|
pub const R16F: TextureFormat = gl::R16F;
|
|
|
|
pub const DEPTH_COMPONENT24: TextureFormat = gl::DEPTH_COMPONENT24;
|
|
|
|
pub const DEPTH_COMPONENT: TextureFormat = gl::DEPTH_COMPONENT;
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// `TextureParameter` is a parameter that can be read or set on a texture.
|
2015-09-17 11:04:25 -04:00
|
|
|
pub type TextureParameter = u32;
|
|
|
|
|
|
|
|
pub const TEXTURE_MIN_FILTER: TextureParameter = gl::TEXTURE_MIN_FILTER;
|
|
|
|
pub const TEXTURE_MAG_FILTER: TextureParameter = gl::TEXTURE_MAG_FILTER;
|
|
|
|
pub const TEXTURE_WRAP_S: TextureParameter = gl::TEXTURE_WRAP_S;
|
|
|
|
pub const TEXTURE_WRAP_T: TextureParameter = gl::TEXTURE_WRAP_T;
|
|
|
|
pub const TEXTURE_MAX_LEVEL: TextureParameter = gl::TEXTURE_MAX_LEVEL;
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// `TextureValue` is a value that be set on a texture's parameter.
|
2015-09-17 11:04:25 -04:00
|
|
|
pub type TextureValue = i32;
|
|
|
|
|
|
|
|
pub const NEAREST: TextureValue = gl::NEAREST as TextureValue;
|
|
|
|
pub const LINEAR: TextureValue = gl::LINEAR as TextureValue;
|
|
|
|
pub const LINEAR_MIPMAP_LINEAR: TextureValue = gl::LINEAR_MIPMAP_LINEAR as TextureValue;
|
|
|
|
pub const LINEAR_MIPMAP_NEAREST: TextureValue = gl::LINEAR_MIPMAP_NEAREST as TextureValue;
|
|
|
|
pub const NEAREST_MIPMAP_NEAREST: TextureValue = gl::NEAREST_MIPMAP_NEAREST as TextureValue;
|
|
|
|
pub const NEAREST_MIPMAP_LINEAR: TextureValue = gl::NEAREST_MIPMAP_LINEAR as TextureValue;
|
|
|
|
pub const CLAMP_TO_EDGE: TextureValue = gl::CLAMP_TO_EDGE as TextureValue;
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// `Texture` is a buffer of data used by fragment shaders.
|
2015-09-27 14:50:29 -04:00
|
|
|
pub struct Texture(u32);
|
2015-09-17 11:04:25 -04:00
|
|
|
|
|
|
|
impl Texture {
|
|
|
|
// Allocates a new texture.
|
|
|
|
pub fn new() -> Texture {
|
2015-09-27 14:50:29 -04:00
|
|
|
let mut t = Texture(0);
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::GenTextures(1, &mut t.0);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
t
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Binds the texture to the passed target.
|
|
|
|
pub fn bind(&self, target: TextureTarget) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::BindTexture(target, self.0);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:36:59 -04:00
|
|
|
pub fn get_pixels(&self,
|
|
|
|
target: TextureTarget,
|
|
|
|
level: i32,
|
|
|
|
format: TextureFormat,
|
|
|
|
ty: Type,
|
|
|
|
pixels: &mut [u8]) {
|
2015-09-17 11:04:25 -04:00
|
|
|
unsafe {
|
2015-10-07 14:36:59 -04:00
|
|
|
gl::GetTexImage(target,
|
|
|
|
level,
|
|
|
|
format,
|
|
|
|
ty,
|
|
|
|
pixels.as_mut_ptr() as *mut gl::types::GLvoid);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-01 15:00:13 -04:00
|
|
|
pub fn image_2d(&self,
|
|
|
|
target: TextureTarget,
|
|
|
|
level: i32,
|
|
|
|
width: u32,
|
|
|
|
height: u32,
|
|
|
|
format: TextureFormat,
|
|
|
|
ty: Type,
|
|
|
|
pix: Option<&[u8]>) {
|
|
|
|
unsafe {
|
|
|
|
let ptr = match pix {
|
|
|
|
Some(val) => val.as_ptr() as *const gl::types::GLvoid,
|
|
|
|
None => ptr::null(),
|
|
|
|
};
|
|
|
|
gl::TexImage2D(target,
|
|
|
|
level,
|
|
|
|
format as i32,
|
|
|
|
width as i32,
|
|
|
|
height as i32,
|
|
|
|
0,
|
|
|
|
format,
|
|
|
|
ty,
|
|
|
|
ptr
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn sub_image_2d(&self,
|
|
|
|
target: TextureTarget,
|
|
|
|
level: i32,
|
|
|
|
x: u32,
|
|
|
|
y: u32,
|
|
|
|
width: u32,
|
|
|
|
height: u32,
|
|
|
|
format: TextureFormat,
|
|
|
|
ty: Type,
|
|
|
|
pix: &[u8]) {
|
|
|
|
unsafe {
|
|
|
|
gl::TexSubImage2D(target,
|
|
|
|
level,
|
|
|
|
x as i32,
|
|
|
|
y as i32,
|
|
|
|
width as i32,
|
|
|
|
height as i32,
|
|
|
|
format,
|
|
|
|
ty,
|
|
|
|
pix.as_ptr() as *const _
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-18 11:19:21 -04:00
|
|
|
pub fn image_2d_ex(&self,
|
|
|
|
target: TextureTarget,
|
|
|
|
level: i32,
|
|
|
|
width: u32,
|
|
|
|
height: u32,
|
|
|
|
internal_format: TextureFormat,
|
|
|
|
format: TextureFormat,
|
|
|
|
ty: Type,
|
|
|
|
pix: Option<&[u8]>) {
|
|
|
|
unsafe {
|
|
|
|
let ptr = match pix {
|
|
|
|
Some(val) => val.as_ptr() as *const gl::types::GLvoid,
|
|
|
|
None => ptr::null(),
|
|
|
|
};
|
|
|
|
gl::TexImage2D(target,
|
|
|
|
level,
|
|
|
|
internal_format as i32,
|
|
|
|
width as i32,
|
|
|
|
height as i32,
|
|
|
|
0,
|
|
|
|
format,
|
|
|
|
ty,
|
|
|
|
ptr
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn image_2d_sample(&self,
|
|
|
|
target: TextureTarget,
|
|
|
|
samples: i32,
|
|
|
|
width: u32,
|
|
|
|
height: u32,
|
|
|
|
format: TextureFormat,
|
|
|
|
fixed: bool) {
|
|
|
|
unsafe {
|
|
|
|
gl::TexImage2DMultisample(target,
|
|
|
|
samples,
|
|
|
|
format,
|
|
|
|
width as i32,
|
|
|
|
height as i32,
|
|
|
|
fixed as u8
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:36:59 -04:00
|
|
|
pub fn image_3d(&self,
|
|
|
|
target: TextureTarget,
|
|
|
|
level: i32,
|
|
|
|
width: u32,
|
|
|
|
height: u32,
|
|
|
|
depth: u32,
|
|
|
|
format: TextureFormat,
|
|
|
|
ty: Type,
|
|
|
|
pix: &[u8]) {
|
2015-09-17 11:04:25 -04:00
|
|
|
unsafe {
|
2015-10-07 14:36:59 -04:00
|
|
|
gl::TexImage3D(target,
|
|
|
|
level,
|
|
|
|
format as i32,
|
|
|
|
width as i32,
|
|
|
|
height as i32,
|
|
|
|
depth as i32,
|
|
|
|
0,
|
|
|
|
format,
|
|
|
|
ty,
|
|
|
|
pix.as_ptr() as *const gl::types::GLvoid);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:36:59 -04:00
|
|
|
pub fn sub_image_3d(&self,
|
|
|
|
target: TextureTarget,
|
|
|
|
level: i32,
|
|
|
|
x: u32,
|
|
|
|
y: u32,
|
|
|
|
z: u32,
|
|
|
|
width: u32,
|
|
|
|
height: u32,
|
|
|
|
depth: u32,
|
|
|
|
format: TextureFormat,
|
|
|
|
ty: Type,
|
|
|
|
pix: &[u8]) {
|
2015-09-17 11:04:25 -04:00
|
|
|
unsafe {
|
2015-10-07 14:36:59 -04:00
|
|
|
gl::TexSubImage3D(target,
|
|
|
|
level,
|
|
|
|
x as i32,
|
|
|
|
y as i32,
|
|
|
|
z as i32,
|
|
|
|
width as i32,
|
|
|
|
height as i32,
|
|
|
|
depth as i32,
|
|
|
|
format,
|
|
|
|
ty,
|
|
|
|
pix.as_ptr() as *const gl::types::GLvoid);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-07 14:36:59 -04:00
|
|
|
pub fn set_parameter(&self,
|
|
|
|
target: TextureTarget,
|
|
|
|
param: TextureParameter,
|
|
|
|
value: TextureValue) {
|
2015-09-17 11:04:25 -04:00
|
|
|
unsafe {
|
|
|
|
gl::TexParameteri(target, param, value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for Texture {
|
|
|
|
fn drop(&mut self) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::DeleteTextures(1, &self.0);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type ShaderType = u32;
|
|
|
|
|
|
|
|
pub const VERTEX_SHADER: ShaderType = gl::VERTEX_SHADER;
|
|
|
|
pub const FRAGMENT_SHADER: ShaderType = gl::FRAGMENT_SHADER;
|
|
|
|
pub const GEOMETRY_SHADER: ShaderType = gl::GEOMETRY_SHADER;
|
|
|
|
|
|
|
|
pub type ShaderParameter = u32;
|
|
|
|
|
|
|
|
pub const COMPILE_STATUS: ShaderParameter = gl::COMPILE_STATUS;
|
|
|
|
pub const INFO_LOG_LENGTH: ShaderParameter = gl::INFO_LOG_LENGTH;
|
|
|
|
|
2015-09-27 14:50:29 -04:00
|
|
|
pub struct Program(u32);
|
2015-09-17 11:04:25 -04:00
|
|
|
|
|
|
|
impl Program {
|
|
|
|
pub fn new() -> Program {
|
2015-09-27 14:50:29 -04:00
|
|
|
Program(unsafe { gl::CreateProgram() })
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn attach_shader(&self, shader: Shader) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::AttachShader(self.0, shader.0);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn link(&self) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::LinkProgram(self.0);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn use_program(&self) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::UseProgram(self.0);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn uniform_location(&self, name: &str) -> Uniform {
|
2015-10-07 14:36:59 -04:00
|
|
|
Uniform(unsafe {
|
|
|
|
gl::GetUniformLocation(self.0, ffi::CString::new(name).unwrap().as_ptr())
|
|
|
|
})
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn attribute_location(&self, name: &str) -> Attribute {
|
2015-10-07 14:36:59 -04:00
|
|
|
Attribute(unsafe {
|
|
|
|
gl::GetAttribLocation(self.0, ffi::CString::new(name).unwrap().as_ptr())
|
|
|
|
})
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for Program {
|
|
|
|
fn drop(&mut self) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::DeleteProgram(self.0);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-27 14:50:29 -04:00
|
|
|
pub struct Shader(u32);
|
2015-09-17 11:04:25 -04:00
|
|
|
|
|
|
|
impl Shader {
|
|
|
|
pub fn new(ty: ShaderType) -> Shader {
|
2015-09-27 14:50:29 -04:00
|
|
|
Shader(unsafe { gl::CreateShader(ty) })
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_source(&self, src: &str) {
|
|
|
|
unsafe {
|
2015-10-07 14:36:59 -04:00
|
|
|
gl::ShaderSource(self.0,
|
|
|
|
1,
|
|
|
|
&ffi::CString::new(src).unwrap().as_ptr(),
|
|
|
|
ptr::null());
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn compile(&self) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::CompileShader(self.0);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_parameter(&self, param: ShaderParameter) -> i32 {
|
2015-10-07 14:36:59 -04:00
|
|
|
let mut ret: i32 = 0;
|
|
|
|
unsafe {
|
|
|
|
gl::GetShaderiv(self.0, param, &mut ret);
|
|
|
|
}
|
2015-09-29 15:09:36 -04:00
|
|
|
ret
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_info_log(&self) -> String {
|
|
|
|
let len = self.get_parameter(INFO_LOG_LENGTH);
|
|
|
|
|
|
|
|
let mut data = Vec::<u8>::with_capacity(len as usize);
|
2015-10-01 15:07:27 -04:00
|
|
|
unsafe {
|
2015-09-17 11:04:25 -04:00
|
|
|
data.set_len(len as usize);
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::GetShaderInfoLog(self.0, len, ptr::null_mut(), data.as_mut_ptr() as *mut i8);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
String::from_utf8(data).unwrap()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-27 14:50:29 -04:00
|
|
|
pub struct Uniform(i32);
|
2015-09-17 11:04:25 -04:00
|
|
|
|
|
|
|
impl Uniform {
|
|
|
|
pub fn set_int(&self, val: i32) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::Uniform1i(self.0, val);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_int3(&self, x: i32, y: i32, z: i32) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::Uniform3i(self.0, x, y, z);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_float(&self, val: f32) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::Uniform1f(self.0, val);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_float2(&self, x: f32, y: f32) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::Uniform2f(self.0, x, y);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_float3(&self, x: f32, y: f32, z: f32) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::Uniform3f(self.0, x, y, z);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_float4(&self, x: f32, y: f32, z: f32, w: f32) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::Uniform4f(self.0, x, y, z, w);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
2016-03-18 13:16:03 -04:00
|
|
|
|
2016-03-27 18:31:57 -04:00
|
|
|
pub fn set_float_mutli_raw(&self, data: *const f32, len: usize) {
|
|
|
|
unsafe {
|
|
|
|
gl::Uniform4fv(self.0, len as i32, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-18 13:16:03 -04:00
|
|
|
pub fn set_matrix4(&self, m: &::cgmath::Matrix4<f32>) {
|
|
|
|
use cgmath::Matrix;
|
|
|
|
unsafe {
|
|
|
|
gl::UniformMatrix4fv(self.0, 1, false as u8, m.as_ptr());
|
|
|
|
}
|
|
|
|
}
|
2016-03-27 18:31:57 -04:00
|
|
|
|
|
|
|
pub fn set_matrix4_multi(&self, m: &[::cgmath::Matrix4<f32>]) {
|
|
|
|
use cgmath::Matrix;
|
|
|
|
unsafe {
|
|
|
|
gl::UniformMatrix4fv(self.0, m.len() as i32, false as u8, m.as_ptr() as *const _); // TODO: Most likely isn't safe
|
|
|
|
}
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
|
2015-09-27 14:50:29 -04:00
|
|
|
pub struct Attribute(i32);
|
2015-09-17 11:04:25 -04:00
|
|
|
|
|
|
|
impl Attribute {
|
|
|
|
pub fn enable(&self) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::EnableVertexAttribArray(self.0 as u32);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn disable(&self) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::DisableVertexAttribArray(self.0 as u32);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn vertex_pointer(&self, size: i32, ty: Type, normalized: bool, stride: i32, offset: i32) {
|
|
|
|
unsafe {
|
2015-10-07 14:36:59 -04:00
|
|
|
gl::VertexAttribPointer(self.0 as u32,
|
|
|
|
size,
|
|
|
|
ty,
|
|
|
|
normalized as u8,
|
|
|
|
stride,
|
|
|
|
offset as *const gl::types::GLvoid);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn vertex_pointer_int(&self, size: i32, ty: Type, stride: i32, offset: i32) {
|
|
|
|
unsafe {
|
2015-10-07 14:36:59 -04:00
|
|
|
gl::VertexAttribIPointer(self.0 as u32,
|
|
|
|
size,
|
|
|
|
ty,
|
|
|
|
stride,
|
|
|
|
offset as *const gl::types::GLvoid);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// VertexArray is used to store state needed to render vertices.
|
|
|
|
// This includes buffers, the format of the buffers and enabled
|
|
|
|
// attributes.
|
2015-09-27 14:50:29 -04:00
|
|
|
pub struct VertexArray(u32);
|
2015-09-17 11:04:25 -04:00
|
|
|
|
|
|
|
impl VertexArray {
|
2016-04-02 20:26:31 -04:00
|
|
|
/// Allocates a new `VertexArray`.
|
2015-09-17 11:04:25 -04:00
|
|
|
pub fn new() -> VertexArray {
|
2015-09-27 14:50:29 -04:00
|
|
|
let mut va = VertexArray(0);
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::GenVertexArrays(1, &mut va.0);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
va
|
|
|
|
}
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// Marks the `VertexArray` as the currently active one, this
|
2015-09-17 11:04:25 -04:00
|
|
|
/// means buffers/the format of the buffers etc will be bound to
|
2016-04-02 20:26:31 -04:00
|
|
|
/// this `VertexArray`.
|
2015-09-17 11:04:25 -04:00
|
|
|
pub fn bind(&self) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::BindVertexArray(self.0);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-10-01 15:07:27 -04:00
|
|
|
impl Drop for VertexArray {
|
2015-09-17 11:04:25 -04:00
|
|
|
fn drop(&mut self) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::DeleteVertexArrays(1, &self.0);
|
|
|
|
}
|
2015-09-27 14:50:29 -04:00
|
|
|
self.0 = 0;
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// `BufferTarget` is a target for a buffer to be bound to.
|
2015-09-17 11:04:25 -04:00
|
|
|
pub type BufferTarget = u32;
|
|
|
|
|
|
|
|
pub const ARRAY_BUFFER: BufferTarget = gl::ARRAY_BUFFER;
|
|
|
|
pub const ELEMENT_ARRAY_BUFFER: BufferTarget = gl::ELEMENT_ARRAY_BUFFER;
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// `BufferUsage` states how a buffer is going to be used by the program.
|
2015-09-17 11:04:25 -04:00
|
|
|
pub type BufferUsage = u32;
|
|
|
|
|
|
|
|
/// Marks the buffer as 'not going to change' after the
|
|
|
|
/// initial data upload to be rendered by the gpu.
|
|
|
|
pub const STATIC_DRAW: BufferUsage = gl::STATIC_DRAW;
|
|
|
|
/// Marks the buffer as 'changed frequently' during the
|
|
|
|
/// course of the program whilst being rendered by the gpu.
|
|
|
|
pub const DYNAMIC_DRAW: BufferUsage = gl::DYNAMIC_DRAW;
|
|
|
|
/// Marks the buffer as 'changed every frame' whilst being
|
|
|
|
/// rendered by the gpu.
|
|
|
|
pub const STREAM_DRAW: BufferUsage = gl::STREAM_DRAW;
|
|
|
|
|
|
|
|
/// Access states how a value will be accesed by the program.
|
|
|
|
pub type Access = u32;
|
|
|
|
|
|
|
|
/// States that the returned value will only be read.
|
|
|
|
pub const READ_ONLY: Access = gl::READ_ONLY;
|
|
|
|
/// States that the returned value will only be written
|
|
|
|
/// to.
|
|
|
|
pub const WRITE_ONLY: Access = gl::WRITE_ONLY;
|
|
|
|
|
2016-04-02 20:26:31 -04:00
|
|
|
/// `Buffer` is a storage for vertex data.
|
2015-09-27 14:50:29 -04:00
|
|
|
pub struct Buffer(u32);
|
2015-09-17 11:04:25 -04:00
|
|
|
|
|
|
|
impl Buffer {
|
2015-10-01 15:07:27 -04:00
|
|
|
/// Allocates a new Buffer.
|
2015-09-17 11:04:25 -04:00
|
|
|
pub fn new() -> Buffer {
|
2015-09-27 14:50:29 -04:00
|
|
|
let mut b = Buffer(0);
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::GenBuffers(1, &mut b.0);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
b
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Makes the buffer the currently active one for the given target.
|
|
|
|
/// This will allow it to be the source of operations that act on a buffer
|
|
|
|
/// (Data, Map etc).
|
2015-10-01 15:07:27 -04:00
|
|
|
pub fn bind(&self, target: BufferTarget) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::BindBuffer(target, self.0);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_data(&self, target: BufferTarget, data: &[u8], usage: BufferUsage) {
|
|
|
|
unsafe {
|
2015-10-07 14:36:59 -04:00
|
|
|
gl::BufferData(target,
|
2016-03-16 13:53:04 -04:00
|
|
|
data.len() as isize,
|
2015-10-07 14:36:59 -04:00
|
|
|
data.as_ptr() as *const gl::types::GLvoid,
|
|
|
|
usage);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-03-19 16:35:31 -04:00
|
|
|
pub fn re_set_data(&self, target: BufferTarget, data: &[u8]) {
|
|
|
|
unsafe {
|
|
|
|
gl::BufferSubData(target, 0, data.len() as isize, data.as_ptr() as *const _);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-09-17 11:04:25 -04:00
|
|
|
/// Maps the memory in the buffer on the gpu to memory which the program
|
|
|
|
/// can access. The access flag will specify how the program plans to use the
|
|
|
|
/// returned data. It'll unmap itself once the returned value is dropped.
|
|
|
|
///
|
|
|
|
/// Warning: the passed length value is not checked in anyway so it is
|
|
|
|
/// possible to overrun the memory. It is up to the program to ensure this
|
|
|
|
/// length is valid.
|
|
|
|
pub fn map(&self, target: BufferTarget, access: Access, length: usize) -> MappedBuffer {
|
|
|
|
unsafe {
|
2015-10-07 14:36:59 -04:00
|
|
|
MappedBuffer {
|
|
|
|
inner: Vec::from_raw_parts(gl::MapBuffer(target, access) as *mut u8, 0, length),
|
|
|
|
target: target,
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for Buffer {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
2015-09-27 14:50:29 -04:00
|
|
|
gl::DeleteBuffers(1, &self.0);
|
2015-09-17 11:04:25 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct MappedBuffer {
|
|
|
|
inner: Vec<u8>,
|
|
|
|
target: BufferTarget,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Deref for MappedBuffer {
|
|
|
|
type Target = Vec<u8>;
|
|
|
|
|
2015-09-29 15:09:36 -04:00
|
|
|
fn deref(&self) -> &Self::Target {
|
2015-09-17 11:04:25 -04:00
|
|
|
&self.inner
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl DerefMut for MappedBuffer {
|
2015-09-29 15:09:36 -04:00
|
|
|
fn deref_mut(&mut self) -> &mut Self::Target {
|
2015-09-17 11:04:25 -04:00
|
|
|
&mut self.inner
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for MappedBuffer {
|
|
|
|
fn drop(&mut self) {
|
2015-10-07 14:36:59 -04:00
|
|
|
unsafe {
|
|
|
|
gl::UnmapBuffer(self.target);
|
|
|
|
}
|
2015-09-17 11:04:25 -04:00
|
|
|
mem::forget(mem::replace(&mut self.inner, Vec::new()));
|
|
|
|
}
|
|
|
|
}
|
2016-03-16 13:33:06 -04:00
|
|
|
|
|
|
|
// Frame buffers
|
|
|
|
|
|
|
|
pub type Attachment = u32;
|
|
|
|
pub const COLOR_ATTACHMENT_0: Attachment = gl::COLOR_ATTACHMENT0;
|
|
|
|
pub const COLOR_ATTACHMENT_1: Attachment = gl::COLOR_ATTACHMENT1;
|
|
|
|
pub const COLOR_ATTACHMENT_2: Attachment = gl::COLOR_ATTACHMENT2;
|
|
|
|
pub const DEPTH_ATTACHMENT: Attachment = gl::DEPTH_ATTACHMENT;
|
|
|
|
|
|
|
|
pub struct Framebuffer(u32);
|
|
|
|
|
|
|
|
impl Framebuffer {
|
|
|
|
pub fn new() -> Framebuffer {
|
|
|
|
let mut fb = Framebuffer(0);
|
|
|
|
unsafe {
|
|
|
|
gl::GenFramebuffers(1, &mut fb.0);
|
|
|
|
}
|
|
|
|
fb
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn bind(&self) {
|
|
|
|
unsafe {
|
|
|
|
gl::BindFramebuffer(gl::FRAMEBUFFER, self.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn bind_read(&self) {
|
|
|
|
unsafe {
|
|
|
|
gl::BindFramebuffer(gl::READ_FRAMEBUFFER, self.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn bind_draw(&self) {
|
|
|
|
unsafe {
|
|
|
|
gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, self.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn texture_2d(&self, attachment: Attachment, target: TextureTarget, tex: &Texture, level: i32) {
|
|
|
|
unsafe {
|
|
|
|
gl::FramebufferTexture2D(gl::FRAMEBUFFER, attachment, target, tex.0, level);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for Framebuffer {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
|
|
|
gl::DeleteFramebuffers(1, &self.0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn unbind_framebuffer() {
|
|
|
|
unsafe {
|
|
|
|
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn unbind_framebuffer_read() {
|
|
|
|
unsafe {
|
|
|
|
gl::BindFramebuffer(gl::READ_FRAMEBUFFER, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn unbind_framebuffer_draw() {
|
|
|
|
unsafe {
|
|
|
|
gl::BindFramebuffer(gl::DRAW_FRAMEBUFFER, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn draw_buffers(bufs: &[Attachment]) {
|
|
|
|
unsafe {
|
|
|
|
gl::DrawBuffers(
|
|
|
|
bufs.len() as i32,
|
|
|
|
bufs.as_ptr()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn bind_frag_data_location(p: &Program, cn: u32, name: &str) {
|
|
|
|
unsafe {
|
|
|
|
gl::BindFragDataLocation(p.0, cn, ffi::CString::new(name).unwrap().as_ptr());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn blit_framebuffer(
|
|
|
|
sx0: i32, sy0: i32, sx1: i32, sy1: i32,
|
|
|
|
dx0: i32, dy0: i32, dx1: i32, dy1: i32,
|
|
|
|
mask: ClearFlags, filter: TextureValue) {
|
|
|
|
unsafe {
|
|
|
|
gl::BlitFramebuffer(
|
|
|
|
sx0, sy0, sx1, sy1,
|
|
|
|
dx0, dy0, dx1, dy1,
|
|
|
|
mask.internal(), filter as u32
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn read_buffer(a: Attachment) {
|
|
|
|
unsafe {
|
|
|
|
gl::ReadBuffer(a);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub type TargetBuffer = u32;
|
|
|
|
pub const COLOR: TargetBuffer = gl::COLOR;
|
|
|
|
|
|
|
|
pub fn clear_buffer(buffer: TargetBuffer, draw_buffer: i32, values: &[f32]) {
|
|
|
|
unsafe {
|
|
|
|
gl::ClearBufferfv(buffer, draw_buffer, values.as_ptr());
|
|
|
|
}
|
|
|
|
}
|