1 use crate::pipe::context::*; 2 3 use mesa_rust_gen::*; 4 5 use std::marker::*; 6 7 // Callers create new queries using PipeQueryGen<QueryType>::new(...) 8 pub struct PipeQueryGen<const Q: pipe_query_type::Type> {} 9 10 // We record the type that the given Query type will return into 11 // a trait we associate with a PipeQuery object we return 12 // QueryResultTrait is the type we'd like our PipeQueryGen to return 13 // for a given query 14 pub trait QueryResultTrait { 15 type ResType; 16 } 17 18 // Define this set of PipeQueryGen's for these queries 19 impl QueryResultTrait for PipeQueryGen<{ pipe_query_type::PIPE_QUERY_TIMESTAMP }> { 20 type ResType = u64; 21 } 22 23 impl<const Q: pipe_query_type::Type> PipeQueryGen<Q> 24 where 25 PipeQueryGen<Q>: QueryResultTrait, 26 { 27 // The external interface to create a new query new(ctx: &PipeContext) -> Option<PipeQuery<<Self as QueryResultTrait>::ResType>>28 pub fn new(ctx: &PipeContext) -> Option<PipeQuery<<Self as QueryResultTrait>::ResType>> { 29 PipeQuery::<<Self as QueryResultTrait>::ResType>::new(ctx, Q) 30 } 31 } 32 33 // Our higher level view of a 'pipe_query', created by a call to the 34 // 'create_query' method on the pipe context 35 pub struct PipeQuery<'a, R> { 36 query: *mut pipe_query, 37 ctx: &'a PipeContext, 38 39 _result_marker: PhantomData<R>, 40 } 41 42 impl<'a, R> PipeQuery<'a, R> { new(ctx: &'a PipeContext, query_type: u32) -> Option<Self>43 fn new(ctx: &'a PipeContext, query_type: u32) -> Option<Self> { 44 let pq = ctx.create_query(query_type, 0); 45 if pq.is_null() { 46 return None; 47 } 48 // SAFETY: we are the only owner of that valid pointer 49 unsafe { 50 if !ctx.end_query(pq) { 51 ctx.destroy_query(pq); 52 return None; 53 } 54 } 55 Some(Self { 56 query: pq, 57 ctx: ctx, 58 _result_marker: Default::default(), 59 }) 60 } 61 } 62 63 impl<'a, R> Drop for PipeQuery<'a, R> { drop(&mut self)64 fn drop(&mut self) { 65 // SAFETY: we are the only owner of that valid pointer 66 unsafe { 67 self.ctx.destroy_query(self.query); 68 } 69 } 70 } 71 72 pub trait QueryReadTrait { 73 type ResType; read(&mut self, wait: bool) -> Option<Self::ResType>74 fn read(&mut self, wait: bool) -> Option<Self::ResType>; 75 read_blocked(&mut self) -> Self::ResType76 fn read_blocked(&mut self) -> Self::ResType { 77 self.read(true).unwrap() 78 } 79 } 80 81 impl QueryReadTrait for PipeQuery<'_, u64> { 82 type ResType = u64; 83 read(&mut self, wait: bool) -> Option<u64>84 fn read(&mut self, wait: bool) -> Option<u64> { 85 let mut raw_result = pipe_query_result::default(); 86 // SAFETY: we guarentee unique access through our `&mut self` reference above. 87 if unsafe { self.ctx.get_query_result(self.query, wait, &mut raw_result) } { 88 // SAFETY: We know this is the right type 89 // because of the trait bound on PipeQueryGen binds the 90 // query type with the result type. 91 Some(unsafe { raw_result.u64_ }) 92 } else { 93 None 94 } 95 } 96 } 97