use backend::Facade;
use context::Context;
use context::CommandContext;
use ContextExt;
use DrawError;
use ToGlEnum;
use GlObject;
use QueryExt;
use std::cell::Cell;
use std::fmt;
use std::rc::Rc;
use std::error::Error;
use buffer::Buffer;
use buffer::BufferSlice;
use BufferExt;
use BufferSliceExt;
use gl;
use version::Api;
use version::Version;
pub struct RawQuery {
context: Rc<Context>,
id: gl::types::GLuint,
ty: QueryType,
has_been_used: Cell<bool>,
}
pub enum QueryType {
SamplesPassed,
AnySamplesPassed,
AnySamplesPassedConservative,
TimeElapsed,
Timestamp,
PrimitivesGenerated,
TransformFeedbackPrimitivesWritten,
}
impl ToGlEnum for QueryType {
#[inline]
fn to_glenum(&self) -> gl::types::GLenum {
match *self {
QueryType::SamplesPassed => gl::SAMPLES_PASSED,
QueryType::AnySamplesPassed => gl::ANY_SAMPLES_PASSED,
QueryType::AnySamplesPassedConservative => gl::ANY_SAMPLES_PASSED_CONSERVATIVE,
QueryType::TimeElapsed => gl::TIME_ELAPSED,
QueryType::Timestamp => gl::TIMESTAMP,
QueryType::PrimitivesGenerated => gl::PRIMITIVES_GENERATED,
QueryType::TransformFeedbackPrimitivesWritten => {
gl::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN
},
}
}
}
#[derive(Copy, Clone, Debug)]
pub enum QueryCreationError {
NotSupported,
}
impl fmt::Display for QueryCreationError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
use self::QueryCreationError::*;
let desc = match *self {
NotSupported => "The given query type is not supported",
};
fmt.write_str(desc)
}
}
impl Error for QueryCreationError {}
#[derive(Copy, Clone, Debug)]
pub enum ToBufferError {
NotSupported,
}
impl fmt::Display for ToBufferError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
use self::ToBufferError::*;
let desc = match *self {
NotSupported => "Writing the result to a buffer is not supported",
};
fmt.write_str(desc)
}
}
impl Error for ToBufferError {}
impl RawQuery {
pub fn new<F: ?Sized>(facade: &F, ty: QueryType) -> Result<RawQuery, QueryCreationError>
where F: Facade
{
let context = facade.get_context().clone();
let ctxt = facade.get_context().make_current();
let id = unsafe {
let mut id = 0;
if ctxt.version >= &Version(Api::Gl, 3, 3) {
match ty {
QueryType::AnySamplesPassed | QueryType::SamplesPassed |
QueryType::PrimitivesGenerated | QueryType::TimeElapsed |
QueryType::TransformFeedbackPrimitivesWritten => (),
QueryType::AnySamplesPassedConservative if
ctxt.extensions.gl_arb_es3_compatibility ||
ctxt.version >= &Version(Api:: Gl, 4, 3) => (),
_ => return Err(QueryCreationError::NotSupported)
};
if ctxt.version >= &Version(Api:: Gl, 4, 5) ||
ctxt.extensions.gl_arb_direct_state_access
{
ctxt.gl.CreateQueries(ty.to_glenum(), 1, &mut id);
} else {
ctxt.gl.GenQueries(1, &mut id);
}
} else if ctxt.version >= &Version(Api::Gl, 3, 0) {
match ty {
QueryType::SamplesPassed | QueryType::PrimitivesGenerated |
QueryType::TransformFeedbackPrimitivesWritten => (),
QueryType::AnySamplesPassed if ctxt.extensions.gl_arb_occlusion_query2 => (),
QueryType::AnySamplesPassedConservative if ctxt.extensions.gl_arb_es3_compatibility => (),
QueryType::TimeElapsed if ctxt.extensions.gl_arb_timer_query => (),
_ => return Err(QueryCreationError::NotSupported)
};
ctxt.gl.GenQueries(1, &mut id);
} else if ctxt.version >= &Version(Api::Gl, 1, 5) || ctxt.extensions.gl_arb_occlusion_query {
match ty {
QueryType::SamplesPassed => (),
QueryType::AnySamplesPassed if ctxt.extensions.gl_arb_occlusion_query2 => (),
QueryType::AnySamplesPassedConservative if ctxt.extensions.gl_arb_es3_compatibility => (),
QueryType::PrimitivesGenerated if ctxt.extensions.gl_ext_transform_feedback => (),
QueryType::TransformFeedbackPrimitivesWritten if ctxt.extensions.gl_ext_transform_feedback => (),
QueryType::TimeElapsed if ctxt.extensions.gl_arb_timer_query => (),
_ => return Err(QueryCreationError::NotSupported)
};
if ctxt.version >= &Version(Api::Gl, 1, 5) {
ctxt.gl.GenQueries(1, &mut id);
} else if ctxt.extensions.gl_arb_occlusion_query {
ctxt.gl.GenQueriesARB(1, &mut id);
} else {
unreachable!();
}
} else if ctxt.version >= &Version(Api::GlEs, 3, 0) {
match ty {
QueryType::AnySamplesPassed | QueryType::AnySamplesPassedConservative |
QueryType::TransformFeedbackPrimitivesWritten => (),
_ => return Err(QueryCreationError::NotSupported)
};
ctxt.gl.GenQueries(1, &mut id);
} else if ctxt.extensions.gl_ext_occlusion_query_boolean {
match ty {
QueryType::AnySamplesPassed | QueryType::AnySamplesPassedConservative => (),
_ => return Err(QueryCreationError::NotSupported)
};
ctxt.gl.GenQueriesEXT(1, &mut id);
} else {
return Err(QueryCreationError::NotSupported);
}
id
};
Ok(RawQuery {
context: context,
id: id,
ty: ty,
has_been_used: Cell::new(false),
})
}
pub fn is_ready(&self) -> bool {
let mut ctxt = self.context.make_current();
self.deactivate(&mut ctxt);
if !self.has_been_used.get() {
return false;
}
Buffer::<u8>::unbind_query(&mut ctxt);
unsafe {
let mut value = 0;
if ctxt.version >= &Version(Api::Gl, 1, 5) ||
ctxt.version >= &Version(Api::GlEs, 3, 0)
{
ctxt.gl.GetQueryObjectuiv(self.id, gl::QUERY_RESULT_AVAILABLE, &mut value);
} else if ctxt.extensions.gl_arb_occlusion_query {
ctxt.gl.GetQueryObjectuivARB(self.id, gl::QUERY_RESULT_AVAILABLE, &mut value);
} else if ctxt.extensions.gl_ext_occlusion_query_boolean {
ctxt.gl.GetQueryObjectuivEXT(self.id, gl::QUERY_RESULT_AVAILABLE, &mut value);
} else {
unreachable!();
}
value != 0
}
}
pub fn get_u32(&self) -> u32 {
let mut ctxt = self.context.make_current();
self.deactivate(&mut ctxt);
if !self.has_been_used.get() {
return 0;
}
Buffer::<u8>::unbind_query(&mut ctxt);
unsafe {
let mut value = 0;
self.raw_get_u32(&mut ctxt, &mut value);
value
}
}
pub fn write_u32_to_buffer(&self, target: BufferSlice<u32>) -> Result<(), ToBufferError> {
let mut ctxt = self.context.make_current();
if !(ctxt.version >= &Version(Api::Gl, 4, 4) || ctxt.extensions.gl_arb_query_buffer_object ||
ctxt.extensions.gl_amd_query_buffer_object)
{
return Err(ToBufferError::NotSupported);
}
self.deactivate(&mut ctxt);
if !self.has_been_used.get() {
panic!();
}
assert!(target.get_offset_bytes() % 4 == 0);
target.prepare_and_bind_for_query(&mut ctxt);
unsafe { self.raw_get_u32(&mut ctxt, target.get_offset_bytes() as *mut _); }
if let Some(fence) = target.add_fence() {
fence.insert(&mut ctxt);
}
Ok(())
}
unsafe fn raw_get_u32(&self, ctxt: &mut CommandContext, target: *mut gl::types::GLuint) {
if ctxt.version >= &Version(Api::Gl, 1, 5) || ctxt.version >= &Version(Api::GlEs, 3, 0) {
ctxt.gl.GetQueryObjectuiv(self.id, gl::QUERY_RESULT, target);
} else if ctxt.extensions.gl_arb_occlusion_query {
ctxt.gl.GetQueryObjectuivARB(self.id, gl::QUERY_RESULT, target);
} else if ctxt.extensions.gl_ext_occlusion_query_boolean {
ctxt.gl.GetQueryObjectuivEXT(self.id, gl::QUERY_RESULT, target);
} else {
unreachable!();
}
}
pub fn get_u64(&self) -> u64 {
let mut ctxt = self.context.make_current();
self.deactivate(&mut ctxt);
if !self.has_been_used.get() {
return 0;
}
Buffer::<u8>::unbind_query(&mut ctxt);
unsafe {
let mut value = 0;
if let Ok(_) = self.raw_get_u64(&mut ctxt, &mut value) {
return value;
}
let mut value = 0;
self.raw_get_u32(&mut ctxt, &mut value);
value as u64
}
}
unsafe fn raw_get_u64(&self, ctxt: &mut CommandContext, target: *mut gl::types::GLuint64)
-> Result<(), ()>
{
if ctxt.version >= &Version(Api::Gl, 3, 3) {
ctxt.gl.GetQueryObjectui64v(self.id, gl::QUERY_RESULT, target);
Ok(())
} else {
Err(())
}
}
#[inline]
pub fn get_bool(&self) -> bool {
self.get_u32() != 0
}
fn deactivate(&self, ctxt: &mut CommandContext) {
if ctxt.state.samples_passed_query == self.id {
unsafe { raw_end_query(ctxt, gl::SAMPLES_PASSED) };
ctxt.state.samples_passed_query = 0;
}
if ctxt.state.any_samples_passed_query == self.id {
unsafe { raw_end_query(ctxt, gl::ANY_SAMPLES_PASSED) };
ctxt.state.any_samples_passed_query = 0;
}
if ctxt.state.any_samples_passed_conservative_query == self.id {
unsafe { raw_end_query(ctxt, gl::ANY_SAMPLES_PASSED_CONSERVATIVE) };
ctxt.state.any_samples_passed_conservative_query = 0;
}
if ctxt.state.primitives_generated_query == self.id {
unsafe { raw_end_query(ctxt, gl::PRIMITIVES_GENERATED) };
ctxt.state.primitives_generated_query = 0;
}
if ctxt.state.transform_feedback_primitives_written_query == self.id {
unsafe { raw_end_query(ctxt, gl::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN) };
ctxt.state.transform_feedback_primitives_written_query = 0;
}
if ctxt.state.time_elapsed_query == self.id {
unsafe { raw_end_query(ctxt, gl::TIME_ELAPSED) };
ctxt.state.time_elapsed_query = 0;
}
}
}
impl Drop for RawQuery {
fn drop(&mut self) {
let mut ctxt = self.context.make_current();
self.deactivate(&mut ctxt);
if let Some((id, _)) = ctxt.state.conditional_render {
if id == self.id {
RawQuery::end_conditional_render(&mut ctxt);
}
}
unsafe {
if ctxt.version >= &Version(Api::Gl, 1, 5) ||
ctxt.version >= &Version(Api::GlEs, 3, 0)
{
ctxt.gl.DeleteQueries(1, [self.id].as_ptr());
} else if ctxt.extensions.gl_arb_occlusion_query {
ctxt.gl.DeleteQueriesARB(1, [self.id].as_ptr());
} else if ctxt.extensions.gl_ext_occlusion_query_boolean {
ctxt.gl.DeleteQueriesEXT(1, [self.id].as_ptr());
} else {
unreachable!();
}
}
}
}
impl QueryExt for RawQuery {
fn begin_query(&self, ctxt: &mut CommandContext) -> Result<(), DrawError> {
match self.ty {
QueryType::SamplesPassed => {
if ctxt.state.any_samples_passed_query != 0 {
ctxt.state.any_samples_passed_query = 0;
unsafe { raw_end_query(ctxt, gl::ANY_SAMPLES_PASSED); }
}
if ctxt.state.any_samples_passed_conservative_query != 0 {
ctxt.state.any_samples_passed_conservative_query = 0;
unsafe { raw_end_query(ctxt, gl::ANY_SAMPLES_PASSED_CONSERVATIVE); }
}
if ctxt.state.samples_passed_query != self.id {
if self.has_been_used.get() {
return Err(DrawError::WrongQueryOperation);
}
unsafe {
if ctxt.state.samples_passed_query != 0 {
raw_end_query(ctxt, gl::SAMPLES_PASSED);
}
raw_begin_query(ctxt, gl::SAMPLES_PASSED, self.id);
}
self.has_been_used.set(true);
ctxt.state.samples_passed_query = self.id;
}
},
QueryType::AnySamplesPassed => {
if ctxt.state.samples_passed_query != 0 {
ctxt.state.samples_passed_query = 0;
unsafe { raw_end_query(ctxt, gl::SAMPLES_PASSED); }
}
if ctxt.state.any_samples_passed_conservative_query != 0 {
ctxt.state.any_samples_passed_conservative_query = 0;
unsafe { raw_end_query(ctxt, gl::ANY_SAMPLES_PASSED_CONSERVATIVE); }
}
if ctxt.state.any_samples_passed_query != self.id {
if self.has_been_used.get() {
return Err(DrawError::WrongQueryOperation);
}
unsafe {
if ctxt.state.any_samples_passed_query != 0 {
raw_end_query(ctxt, gl::ANY_SAMPLES_PASSED);
}
raw_begin_query(ctxt, gl::ANY_SAMPLES_PASSED, self.id);
}
self.has_been_used.set(true);
ctxt.state.any_samples_passed_query = self.id;
}
},
QueryType::AnySamplesPassedConservative => {
if ctxt.state.samples_passed_query != 0 {
ctxt.state.samples_passed_query = 0;
unsafe { raw_end_query(ctxt, gl::SAMPLES_PASSED); }
}
if ctxt.state.any_samples_passed_query != 0 {
ctxt.state.any_samples_passed_query = 0;
unsafe { raw_end_query(ctxt, gl::ANY_SAMPLES_PASSED); }
}
if ctxt.state.any_samples_passed_conservative_query != self.id {
if self.has_been_used.get() {
return Err(DrawError::WrongQueryOperation);
}
unsafe {
if ctxt.state.any_samples_passed_conservative_query != 0 {
raw_end_query(ctxt, gl::ANY_SAMPLES_PASSED_CONSERVATIVE);
}
raw_begin_query(ctxt, gl::ANY_SAMPLES_PASSED_CONSERVATIVE, self.id);
}
self.has_been_used.set(true);
ctxt.state.any_samples_passed_conservative_query = self.id;
}
},
QueryType::TimeElapsed => {
if ctxt.state.time_elapsed_query != self.id {
if self.has_been_used.get() {
return Err(DrawError::WrongQueryOperation);
}
unsafe {
if ctxt.state.time_elapsed_query != 0 {
raw_end_query(ctxt, gl::TIME_ELAPSED);
}
raw_begin_query(ctxt, gl::TIME_ELAPSED, self.id);
}
self.has_been_used.set(true);
ctxt.state.time_elapsed_query = self.id;
}
},
QueryType::Timestamp => panic!(),
QueryType::PrimitivesGenerated => {
if ctxt.state.primitives_generated_query != self.id {
if self.has_been_used.get() {
return Err(DrawError::WrongQueryOperation);
}
unsafe {
if ctxt.state.primitives_generated_query != 0 {
raw_end_query(ctxt, gl::PRIMITIVES_GENERATED);
}
raw_begin_query(ctxt, gl::PRIMITIVES_GENERATED, self.id);
}
self.has_been_used.set(true);
ctxt.state.primitives_generated_query = self.id;
}
},
QueryType::TransformFeedbackPrimitivesWritten => {
if ctxt.state.transform_feedback_primitives_written_query != self.id {
if self.has_been_used.get() {
return Err(DrawError::WrongQueryOperation);
}
unsafe {
if ctxt.state.transform_feedback_primitives_written_query != 0 {
raw_end_query(ctxt, gl::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
}
raw_begin_query(ctxt, gl::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, self.id);
}
self.has_been_used.set(true);
ctxt.state.transform_feedback_primitives_written_query = self.id;
}
},
};
Ok(())
}
fn end_samples_passed_query(ctxt: &mut CommandContext) {
if ctxt.state.samples_passed_query != 0 {
ctxt.state.samples_passed_query = 0;
unsafe { raw_end_query(ctxt, gl::SAMPLES_PASSED); }
}
if ctxt.state.any_samples_passed_query != 0 {
ctxt.state.any_samples_passed_query = 0;
unsafe { raw_end_query(ctxt, gl::ANY_SAMPLES_PASSED); }
}
if ctxt.state.any_samples_passed_conservative_query != 0 {
ctxt.state.any_samples_passed_conservative_query = 0;
unsafe { raw_end_query(ctxt, gl::ANY_SAMPLES_PASSED_CONSERVATIVE); }
}
}
#[inline]
fn end_time_elapsed_query(ctxt: &mut CommandContext) {
if ctxt.state.time_elapsed_query != 0 {
ctxt.state.time_elapsed_query = 0;
unsafe { raw_end_query(ctxt, gl::TIME_ELAPSED); }
}
}
#[inline]
fn end_primitives_generated_query(ctxt: &mut CommandContext) {
if ctxt.state.primitives_generated_query != 0 {
ctxt.state.primitives_generated_query = 0;
unsafe { raw_end_query(ctxt, gl::PRIMITIVES_GENERATED); }
}
}
#[inline]
fn end_transform_feedback_primitives_written_query(ctxt: &mut CommandContext) {
if ctxt.state.transform_feedback_primitives_written_query != 0 {
ctxt.state.transform_feedback_primitives_written_query = 0;
unsafe { raw_end_query(ctxt, gl::TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN); }
}
}
fn begin_conditional_render(&self, ctxt: &mut CommandContext, wait: bool, per_region: bool) {
let new_mode = match (wait, per_region) {
(true, true) => gl::QUERY_BY_REGION_WAIT,
(true, false) => gl::QUERY_WAIT,
(false, true) => gl::QUERY_BY_REGION_NO_WAIT,
(false, false) => gl::QUERY_NO_WAIT,
};
if let Some((old_id, old_mode)) = ctxt.state.conditional_render {
if old_id == self.id {
match (new_mode, old_mode) {
(a, b) if a == b => return,
(gl::QUERY_NO_WAIT, gl::QUERY_WAIT) => return,
(gl::QUERY_BY_REGION_NO_WAIT, gl::QUERY_BY_REGION_WAIT) => return,
_ => (),
}
}
}
if ctxt.state.conditional_render.is_some() {
RawQuery::end_conditional_render(ctxt);
}
self.deactivate(ctxt);
if ctxt.version >= &Version(Api::Gl, 3, 0) {
unsafe { ctxt.gl.BeginConditionalRender(self.id, new_mode) };
} else if ctxt.extensions.gl_nv_conditional_render {
unsafe { ctxt.gl.BeginConditionalRenderNV(self.id, new_mode) };
} else {
unreachable!();
}
ctxt.state.conditional_render = Some((self.id, new_mode));
}
fn end_conditional_render(ctxt: &mut CommandContext) {
if ctxt.state.conditional_render.is_none() {
return;
}
if ctxt.version >= &Version(Api::Gl, 3, 0) {
unsafe { ctxt.gl.EndConditionalRender(); }
} else if ctxt.extensions.gl_nv_conditional_render {
unsafe { ctxt.gl.EndConditionalRenderNV(); }
} else {
unreachable!();
}
ctxt.state.conditional_render = None;
}
fn is_unused(&self) -> bool {
!self.has_been_used.get()
}
}
impl fmt::Debug for RawQuery {
#[inline]
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "Query object #{}", self.id)
}
}
impl GlObject for RawQuery {
type Id = gl::types::GLuint;
#[inline]
fn get_id(&self) -> gl::types::GLuint {
self.id
}
}
unsafe fn raw_begin_query(ctxt: &mut CommandContext, ty: gl::types::GLenum, id: gl::types::GLuint) {
if ctxt.version >= &Version(Api::Gl, 1, 5) ||
ctxt.version >= &Version(Api::GlEs, 3, 0)
{
ctxt.gl.BeginQuery(ty, id);
} else if ctxt.extensions.gl_arb_occlusion_query {
ctxt.gl.BeginQueryARB(ty, id);
} else if ctxt.extensions.gl_ext_occlusion_query_boolean {
ctxt.gl.BeginQueryEXT(ty, id);
} else {
unreachable!();
}
}
unsafe fn raw_end_query(ctxt: &mut CommandContext, ty: gl::types::GLenum) {
if ctxt.version >= &Version(Api::Gl, 1, 5) ||
ctxt.version >= &Version(Api::GlEs, 3, 0)
{
ctxt.gl.EndQuery(ty);
} else if ctxt.extensions.gl_arb_occlusion_query {
ctxt.gl.EndQueryARB(ty);
} else if ctxt.extensions.gl_ext_occlusion_query_boolean {
ctxt.gl.EndQueryEXT(ty);
} else {
unreachable!();
}
}
macro_rules! impl_helper {
($name:ident, $ret:ty, $get_fn:ident) => {
impl $name {
#[inline]
pub fn is_ready(&self) -> bool {
self.query.is_ready()
}
#[inline]
pub fn get(self) -> $ret {
self.query.$get_fn()
}
#[inline]
pub fn to_buffer_u32(&self, target: BufferSlice<u32>)
-> Result<(), ToBufferError>
{
self.query.write_u32_to_buffer(target)
}
}
impl GlObject for $name {
type Id = gl::types::GLuint;
#[inline]
fn get_id(&self) -> gl::types::GLuint {
self.query.get_id()
}
}
impl QueryExt for $name {
#[inline]
fn begin_query(&self, ctxt: &mut CommandContext) -> Result<(), DrawError> {
self.query.begin_query(ctxt)
}
#[inline]
fn end_samples_passed_query(ctxt: &mut CommandContext) {
RawQuery::end_samples_passed_query(ctxt)
}
#[inline]
fn end_time_elapsed_query(ctxt: &mut CommandContext) {
RawQuery::end_time_elapsed_query(ctxt)
}
#[inline]
fn end_primitives_generated_query(ctxt: &mut CommandContext) {
RawQuery::end_primitives_generated_query(ctxt)
}
#[inline]
fn end_transform_feedback_primitives_written_query(ctxt: &mut CommandContext) {
RawQuery::end_transform_feedback_primitives_written_query(ctxt)
}
#[inline]
fn begin_conditional_render(&self, ctxt: &mut CommandContext, wait: bool, per_region: bool) {
self.query.begin_conditional_render(ctxt, wait, per_region)
}
#[inline]
fn end_conditional_render(ctxt: &mut CommandContext) {
RawQuery::end_conditional_render(ctxt)
}
#[inline]
fn is_unused(&self) -> bool {
self.query.is_unused()
}
}
};
}
#[derive(Debug)]
pub struct SamplesPassedQuery {
query: RawQuery,
}
impl SamplesPassedQuery {
#[inline]
pub fn new<F: ?Sized>(facade: &F) -> Result<SamplesPassedQuery, QueryCreationError> where F: Facade {
RawQuery::new(facade, QueryType::SamplesPassed).map(|q| SamplesPassedQuery { query: q })
}
}
impl_helper!(SamplesPassedQuery, u32, get_u32);
#[derive(Debug)]
pub struct TimeElapsedQuery {
query: RawQuery,
}
impl TimeElapsedQuery {
#[inline]
pub fn new<F: ?Sized>(facade: &F) -> Result<TimeElapsedQuery, QueryCreationError> where F: Facade {
RawQuery::new(facade, QueryType::TimeElapsed).map(|q| TimeElapsedQuery { query: q })
}
}
impl_helper!(TimeElapsedQuery, u32, get_u32);
#[derive(Debug)]
pub struct AnySamplesPassedQuery {
query: RawQuery,
}
impl AnySamplesPassedQuery {
pub fn new<F: ?Sized>(facade: &F, conservative: bool)
-> Result<AnySamplesPassedQuery, QueryCreationError>
where F: Facade
{
if conservative {
if let Ok(q) = RawQuery::new(facade, QueryType::AnySamplesPassedConservative) {
return Ok(AnySamplesPassedQuery { query: q });
}
}
if let Ok(q) = RawQuery::new(facade, QueryType::AnySamplesPassed) {
return Ok(AnySamplesPassedQuery { query: q });
} else if let Ok(q) = RawQuery::new(facade, QueryType::SamplesPassed) {
return Ok(AnySamplesPassedQuery { query: q });
} else {
return Err(QueryCreationError::NotSupported);
}
}
}
impl_helper!(AnySamplesPassedQuery, bool, get_bool);
#[derive(Debug)]
pub struct PrimitivesGeneratedQuery {
query: RawQuery,
}
impl PrimitivesGeneratedQuery {
#[inline]
pub fn new<F: ?Sized>(facade: &F) -> Result<PrimitivesGeneratedQuery, QueryCreationError>
where F: Facade
{
RawQuery::new(facade, QueryType::PrimitivesGenerated)
.map(|q| PrimitivesGeneratedQuery { query: q })
}
}
impl_helper!(PrimitivesGeneratedQuery, u32, get_u32);
#[derive(Debug)]
pub struct TransformFeedbackPrimitivesWrittenQuery {
query: RawQuery,
}
impl TransformFeedbackPrimitivesWrittenQuery {
#[inline]
pub fn new<F: ?Sized>(facade: &F) -> Result<TransformFeedbackPrimitivesWrittenQuery, QueryCreationError>
where F: Facade
{
RawQuery::new(facade, QueryType::TransformFeedbackPrimitivesWritten)
.map(|q| TransformFeedbackPrimitivesWrittenQuery { query: q })
}
}
impl_helper!(TransformFeedbackPrimitivesWrittenQuery, u32, get_u32);