use crate::backend::Facade;
use crate::context::Context;
use crate::ContextExt;
use crate::version::Api;
use crate::version::Version;
use crate::gl;
use std::rc::Rc;
pub use crate::context::DebugCallbackBehavior;
pub type DebugCallback = Box<dyn FnMut(Source, MessageType, Severity, u32, bool, &str)>;
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[repr(u32)]
pub enum Severity {
Notification = gl::DEBUG_SEVERITY_NOTIFICATION,
Low = gl::DEBUG_SEVERITY_LOW,
Medium = gl::DEBUG_SEVERITY_MEDIUM,
High = gl::DEBUG_SEVERITY_HIGH,
}
#[derive(Clone, Copy, Debug)]
#[repr(u32)]
pub enum Source {
Api = gl::DEBUG_SOURCE_API,
WindowSystem = gl::DEBUG_SOURCE_WINDOW_SYSTEM,
ShaderCompiler = gl::DEBUG_SOURCE_SHADER_COMPILER,
ThirdParty = gl::DEBUG_SOURCE_THIRD_PARTY,
Application = gl::DEBUG_SOURCE_APPLICATION,
OtherSource = gl::DEBUG_SOURCE_OTHER,
}
#[derive(Clone, Copy, Debug)]
#[repr(u32)]
pub enum MessageType {
Error = gl::DEBUG_TYPE_ERROR,
DeprecatedBehavior = gl::DEBUG_TYPE_DEPRECATED_BEHAVIOR,
UndefinedBehavior = gl::DEBUG_TYPE_UNDEFINED_BEHAVIOR,
Portability = gl::DEBUG_TYPE_PORTABILITY,
Performance = gl::DEBUG_TYPE_PERFORMANCE,
Marker = gl::DEBUG_TYPE_MARKER,
PushGroup = gl::DEBUG_TYPE_PUSH_GROUP,
PopGroup = gl::DEBUG_TYPE_POP_GROUP,
Other = gl::DEBUG_TYPE_OTHER,
}
pub struct TimestampQuery {
context: Rc<Context>,
id: gl::types::GLuint,
}
impl TimestampQuery {
pub fn new<F: ?Sized>(facade: &F) -> Option<TimestampQuery> where F: Facade {
let ctxt = facade.get_context().make_current();
let id = if ctxt.version >= &Version(Api::Gl, 3, 2) { unsafe {
let mut id = 0;
ctxt.gl.GenQueries(1, &mut id);
ctxt.gl.QueryCounter(id, gl::TIMESTAMP);
Some(id)
}
} else if ctxt.extensions.gl_ext_disjoint_timer_query {
unsafe {
let mut id = 0;
ctxt.gl.GenQueriesEXT(1, &mut id);
ctxt.gl.QueryCounterEXT(id, gl::TIMESTAMP);
Some(id)
}
} else {
None
};
id.map(|q| TimestampQuery {
context: facade.get_context().clone(),
id: q
})
}
pub fn is_ready(&self) -> bool {
let ctxt = self.context.make_current();
if ctxt.version >= &Version(Api::Gl, 3, 2) { unsafe {
let mut value = 0;
ctxt.gl.GetQueryObjectiv(self.id, gl::QUERY_RESULT_AVAILABLE, &mut value);
value != 0
}
} else if ctxt.extensions.gl_ext_disjoint_timer_query {
unsafe {
let mut value = 0;
ctxt.gl.GetQueryObjectivEXT(self.id, gl::QUERY_RESULT_AVAILABLE_EXT, &mut value);
value != 0
}
} else {
unreachable!();
}
}
pub fn get(self) -> u64 {
let ctxt = self.context.make_current();
if ctxt.version >= &Version(Api::Gl, 3, 2) { unsafe {
let mut value = 0;
ctxt.gl.GetQueryObjectui64v(self.id, gl::QUERY_RESULT, &mut value);
ctxt.gl.DeleteQueries(1, [self.id].as_ptr());
value
}
} else if ctxt.extensions.gl_ext_disjoint_timer_query {
unsafe {
let mut value = 0;
ctxt.gl.GetQueryObjectui64vEXT(self.id, gl::QUERY_RESULT_EXT, &mut value);
ctxt.gl.DeleteQueriesEXT(1, [self.id].as_ptr());
value
}
} else {
unreachable!();
}
}
}