use __gl;
use __gl::types::{GLchar, GLenum, GLsizei, GLuint};
use std::os::raw::c_void;
use std::{ffi, mem};
use debug::{self, DebugCallback, DebugReport};
pub struct Device(pub(crate) __gl::Gl, Option<Box<DebugCallback>>);
pub enum Debug<F> {
Enable { callback: F, flags: DebugReport },
Disable,
}
impl Device {
pub fn new<F>(loader: F, debug: Debug<DebugCallback>) -> Self
where
F: FnMut(&str) -> *const c_void,
{
let ctxt = __gl::Gl::load_with(loader);
let cb = match debug {
Debug::Enable { callback, flags } => unsafe {
extern "system" fn callback_ffi(
source: GLenum,
gltype: GLenum,
id: GLuint,
severity: GLenum,
_length: GLsizei,
message: *const GLchar,
user_param: *mut c_void,
) {
unsafe {
let cb = Box::from_raw(user_param as *mut DebugCallback);
let msg = ffi::CStr::from_ptr(message).to_str().unwrap();
cb(
mem::transmute(severity),
mem::transmute(source),
mem::transmute(gltype),
id,
msg,
);
Box::into_raw(cb);
}
}
let cb = Box::new(callback);
let cb_raw = Box::into_raw(cb);
ctxt.Enable(__gl::DEBUG_OUTPUT);
ctxt.DebugMessageCallback(callback_ffi, cb_raw as *mut _);
ctxt.DebugMessageControl(
__gl::DONT_CARE,
__gl::DONT_CARE,
__gl::DONT_CARE,
0,
std::ptr::null(),
__gl::FALSE,
);
debug::set_debug_message_control(
&ctxt,
true,
debug::Filter::All,
debug::Filter::All,
flags,
None,
);
Some(Box::from_raw(cb_raw))
},
Debug::Disable => unsafe {
ctxt.Disable(__gl::DEBUG_OUTPUT);
None
},
};
unsafe {
ctxt.Enable(__gl::FRAMEBUFFER_SRGB);
ctxt.ClipControl(__gl::LOWER_LEFT, __gl::ZERO_TO_ONE);
ctxt.Enable(__gl::SCISSOR_TEST);
ctxt.Enable(__gl::TEXTURE_CUBE_MAP_SEAMLESS);
ctxt.Enable(__gl::PROGRAM_POINT_SIZE);
ctxt.Enable(__gl::SAMPLE_MASK);
}
Device(ctxt, cb)
}
pub fn limits(&self) -> DeviceLimits {
DeviceLimits {
max_compute_work_group_invocations: self
.get_u32(__gl::MAX_COMPUTE_WORK_GROUP_INVOCATIONS, None),
max_compute_work_group_count: [
self.get_u32(__gl::MAX_COMPUTE_WORK_GROUP_COUNT, Some(0)),
self.get_u32(__gl::MAX_COMPUTE_WORK_GROUP_COUNT, Some(1)),
self.get_u32(__gl::MAX_COMPUTE_WORK_GROUP_COUNT, Some(2)),
],
max_compute_work_group_size: [
self.get_u32(__gl::MAX_COMPUTE_WORK_GROUP_SIZE, Some(0)),
self.get_u32(__gl::MAX_COMPUTE_WORK_GROUP_SIZE, Some(1)),
self.get_u32(__gl::MAX_COMPUTE_WORK_GROUP_SIZE, Some(2)),
],
max_compute_shared_memory_size: self
.get_u32(__gl::MAX_COMPUTE_SHARED_MEMORY_SIZE, None),
max_clip_distances: self.get_u32(__gl::MAX_CLIP_DISTANCES, None),
max_cull_distances: self.get_u32(__gl::MAX_CULL_DISTANCES, None),
max_viewports: self.get_u32(__gl::MAX_VIEWPORTS, None),
max_framebuffer_width: self.get_u32(__gl::MAX_FRAMEBUFFER_WIDTH, None),
max_framebuffer_height: self.get_u32(__gl::MAX_FRAMEBUFFER_HEIGHT, None),
max_framebuffer_layers: self.get_u32(__gl::MAX_FRAMEBUFFER_LAYERS, None),
max_color_attachments: self.get_u32(__gl::MAX_COLOR_ATTACHMENTS, None),
max_viewport_dimensions: [
self.get_u32(__gl::MAX_VIEWPORT_DIMS, Some(0)),
self.get_u32(__gl::MAX_VIEWPORT_DIMS, Some(1)),
],
max_vertex_input_attributes: self.get_u32(__gl::MAX_VERTEX_ATTRIBS, None),
max_vertex_input_bindings: self.get_u32(__gl::MAX_VERTEX_ATTRIB_BINDINGS, None),
max_vertex_input_attribute_offset: self
.get_u32(__gl::MAX_VERTEX_ATTRIB_RELATIVE_OFFSET, None),
max_vertex_input_binding_stride: self.get_u32(__gl::MAX_VERTEX_ATTRIB_STRIDE, None),
max_vertex_output_components: self.get_u32(__gl::MAX_VERTEX_OUTPUT_COMPONENTS, None),
}
}
pub fn features(&self) -> DeviceFeatures {
DeviceFeatures {}
}
fn get_u32(&self, target: GLenum, index: Option<usize>) -> u32 {
self.get_i32(target, index) as _
}
fn get_i32(&self, target: GLenum, index: Option<usize>) -> i32 {
let mut value = 0;
unsafe {
match index {
Some(i) => self.0.GetIntegeri_v(target, i as _, &mut value),
None => self.0.GetIntegerv(target, &mut value),
}
}
value
}
}
#[derive(Clone, Debug)]
pub struct DeviceLimits {
pub max_compute_work_group_invocations: u32,
pub max_compute_work_group_count: [u32; 3],
pub max_compute_work_group_size: [u32; 3],
pub max_compute_shared_memory_size: u32,
pub max_clip_distances: u32,
pub max_cull_distances: u32,
pub max_viewports: u32,
pub max_viewport_dimensions: [u32; 2],
pub max_framebuffer_width: u32,
pub max_framebuffer_height: u32,
pub max_framebuffer_layers: u32,
pub max_color_attachments: u32,
pub max_vertex_input_attributes: u32,
pub max_vertex_input_bindings: u32,
pub max_vertex_input_attribute_offset: u32,
pub max_vertex_input_binding_stride: u32,
pub max_vertex_output_components: u32,
}
#[derive(Clone, Debug)]
pub struct DeviceFeatures {}