wl_proxy/protocols/wayland/
wl_buffer.rs

1//! content for a wl_surface
2//!
3//! A buffer provides the content for a wl_surface. Buffers are
4//! created through factory interfaces such as wl_shm, wp_linux_buffer_params
5//! (from the linux-dmabuf protocol extension) or similar. It has a width and
6//! a height and can be attached to a wl_surface, but the mechanism by which a
7//! client provides and updates the contents is defined by the buffer factory
8//! interface.
9//!
10//! Color channels are assumed to be electrical rather than optical (in other
11//! words, encoded with a transfer function) unless otherwise specified. If
12//! the buffer uses a format that has an alpha channel, the alpha channel is
13//! assumed to be premultiplied into the electrical color channel values
14//! (after transfer function encoding) unless otherwise specified.
15//!
16//! Note, because wl_buffer objects are created from multiple independent
17//! factory interfaces, the wl_buffer interface is frozen at version 1.
18
19use crate::protocol_helpers::prelude::*;
20use super::super::all_types::*;
21
22/// A wl_buffer object.
23///
24/// See the documentation of [the module][self] for the interface description.
25pub struct WlBuffer {
26    core: ObjectCore,
27    handler: HandlerHolder<dyn WlBufferHandler>,
28}
29
30struct DefaultHandler;
31
32impl WlBufferHandler for DefaultHandler { }
33
34impl ConcreteObject for WlBuffer {
35    const XML_VERSION: u32 = 1;
36    const INTERFACE: ObjectInterface = ObjectInterface::WlBuffer;
37    const INTERFACE_NAME: &str = "wl_buffer";
38}
39
40impl WlBuffer {
41    /// Sets a new handler.
42    pub fn set_handler(&self, handler: impl WlBufferHandler) {
43        self.set_boxed_handler(Box::new(handler));
44    }
45
46    /// Sets a new, already boxed handler.
47    pub fn set_boxed_handler(&self, handler: Box<dyn WlBufferHandler>) {
48        if self.core.state.destroyed.get() {
49            return;
50        }
51        self.handler.set(Some(handler));
52    }
53}
54
55impl Debug for WlBuffer {
56    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
57        f.debug_struct("WlBuffer")
58            .field("server_obj_id", &self.core.server_obj_id.get())
59            .field("client_id", &self.core.client_id.get())
60            .field("client_obj_id", &self.core.client_obj_id.get())
61            .finish()
62    }
63}
64
65impl WlBuffer {
66    /// Since when the destroy message is available.
67    pub const MSG__DESTROY__SINCE: u32 = 1;
68
69    /// destroy a buffer
70    ///
71    /// Destroy a buffer. If and how you need to release the backing
72    /// storage is defined by the buffer factory interface.
73    ///
74    /// For possible side-effects to a surface, see wl_surface.attach.
75    #[inline]
76    pub fn try_send_destroy(
77        &self,
78    ) -> Result<(), ObjectError> {
79        let core = self.core();
80        let Some(id) = core.server_obj_id.get() else {
81            return Err(ObjectError(ObjectErrorKind::ReceiverNoServerId));
82        };
83        #[cfg(feature = "logging")]
84        if self.core.state.log {
85            #[cold]
86            fn log(state: &State, id: u32) {
87                let (millis, micros) = time_since_epoch();
88                let prefix = &state.log_prefix;
89                let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      <= wl_buffer#{}.destroy()\n", id);
90                state.log(args);
91            }
92            log(&self.core.state, id);
93        }
94        let Some(endpoint) = &self.core.state.server else {
95            return Ok(());
96        };
97        if !endpoint.flush_queued.replace(true) {
98            self.core.state.add_flushable_endpoint(endpoint, None);
99        }
100        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
101        let outgoing = &mut *outgoing_ref;
102        let mut fmt = outgoing.formatter();
103        fmt.words([
104            id,
105            0,
106        ]);
107        self.core.handle_server_destroy();
108        Ok(())
109    }
110
111    /// destroy a buffer
112    ///
113    /// Destroy a buffer. If and how you need to release the backing
114    /// storage is defined by the buffer factory interface.
115    ///
116    /// For possible side-effects to a surface, see wl_surface.attach.
117    #[inline]
118    pub fn send_destroy(
119        &self,
120    ) {
121        let res = self.try_send_destroy(
122        );
123        if let Err(e) = res {
124            log_send("wl_buffer.destroy", &e);
125        }
126    }
127
128    /// Since when the release message is available.
129    pub const MSG__RELEASE__SINCE: u32 = 1;
130
131    /// compositor releases buffer
132    ///
133    /// Sent when this wl_buffer is no longer used by the compositor.
134    ///
135    /// For more information on when release events may or may not be sent,
136    /// and what consequences it has, please see the description of
137    /// wl_surface.attach.
138    ///
139    /// If a client receives a release event before the frame callback
140    /// requested in the same wl_surface.commit that attaches this
141    /// wl_buffer to a surface, then the client is immediately free to
142    /// reuse the buffer and its backing storage, and does not need a
143    /// second buffer for the next surface content update. Typically
144    /// this is possible, when the compositor maintains a copy of the
145    /// wl_surface contents, e.g. as a GL texture. This is an important
146    /// optimization for GL(ES) compositors with wl_shm clients.
147    #[inline]
148    pub fn try_send_release(
149        &self,
150    ) -> Result<(), ObjectError> {
151        let core = self.core();
152        let client_ref = core.client.borrow();
153        let Some(client) = &*client_ref else {
154            return Err(ObjectError(ObjectErrorKind::ReceiverNoClient));
155        };
156        let id = core.client_obj_id.get().unwrap_or(0);
157        #[cfg(feature = "logging")]
158        if self.core.state.log {
159            #[cold]
160            fn log(state: &State, client_id: u64, id: u32) {
161                let (millis, micros) = time_since_epoch();
162                let prefix = &state.log_prefix;
163                let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} <= wl_buffer#{}.release()\n", client_id, id);
164                state.log(args);
165            }
166            log(&self.core.state, client.endpoint.id, id);
167        }
168        let endpoint = &client.endpoint;
169        if !endpoint.flush_queued.replace(true) {
170            self.core.state.add_flushable_endpoint(endpoint, Some(client));
171        }
172        let mut outgoing_ref = endpoint.outgoing.borrow_mut();
173        let outgoing = &mut *outgoing_ref;
174        let mut fmt = outgoing.formatter();
175        fmt.words([
176            id,
177            0,
178        ]);
179        Ok(())
180    }
181
182    /// compositor releases buffer
183    ///
184    /// Sent when this wl_buffer is no longer used by the compositor.
185    ///
186    /// For more information on when release events may or may not be sent,
187    /// and what consequences it has, please see the description of
188    /// wl_surface.attach.
189    ///
190    /// If a client receives a release event before the frame callback
191    /// requested in the same wl_surface.commit that attaches this
192    /// wl_buffer to a surface, then the client is immediately free to
193    /// reuse the buffer and its backing storage, and does not need a
194    /// second buffer for the next surface content update. Typically
195    /// this is possible, when the compositor maintains a copy of the
196    /// wl_surface contents, e.g. as a GL texture. This is an important
197    /// optimization for GL(ES) compositors with wl_shm clients.
198    #[inline]
199    pub fn send_release(
200        &self,
201    ) {
202        let res = self.try_send_release(
203        );
204        if let Err(e) = res {
205            log_send("wl_buffer.release", &e);
206        }
207    }
208}
209
210/// A message handler for [`WlBuffer`] proxies.
211pub trait WlBufferHandler: Any {
212    /// Event handler for wl_display.delete_id messages deleting the ID of this object.
213    ///
214    /// The default handler forwards the event to the client, if any.
215    #[inline]
216    fn delete_id(&mut self, slf: &Rc<WlBuffer>) {
217        slf.core.delete_id();
218    }
219
220    /// destroy a buffer
221    ///
222    /// Destroy a buffer. If and how you need to release the backing
223    /// storage is defined by the buffer factory interface.
224    ///
225    /// For possible side-effects to a surface, see wl_surface.attach.
226    #[inline]
227    fn handle_destroy(
228        &mut self,
229        slf: &Rc<WlBuffer>,
230    ) {
231        if !slf.core.forward_to_server.get() {
232            return;
233        }
234        let res = slf.try_send_destroy(
235        );
236        if let Err(e) = res {
237            log_forward("wl_buffer.destroy", &e);
238        }
239    }
240
241    /// compositor releases buffer
242    ///
243    /// Sent when this wl_buffer is no longer used by the compositor.
244    ///
245    /// For more information on when release events may or may not be sent,
246    /// and what consequences it has, please see the description of
247    /// wl_surface.attach.
248    ///
249    /// If a client receives a release event before the frame callback
250    /// requested in the same wl_surface.commit that attaches this
251    /// wl_buffer to a surface, then the client is immediately free to
252    /// reuse the buffer and its backing storage, and does not need a
253    /// second buffer for the next surface content update. Typically
254    /// this is possible, when the compositor maintains a copy of the
255    /// wl_surface contents, e.g. as a GL texture. This is an important
256    /// optimization for GL(ES) compositors with wl_shm clients.
257    #[inline]
258    fn handle_release(
259        &mut self,
260        slf: &Rc<WlBuffer>,
261    ) {
262        if !slf.core.forward_to_client.get() {
263            return;
264        }
265        let res = slf.try_send_release(
266        );
267        if let Err(e) = res {
268            log_forward("wl_buffer.release", &e);
269        }
270    }
271}
272
273impl ObjectPrivate for WlBuffer {
274    fn new(state: &Rc<State>, version: u32) -> Rc<Self> {
275        Rc::<Self>::new_cyclic(|slf| Self {
276            core: ObjectCore::new(state, slf.clone(), ObjectInterface::WlBuffer, version),
277            handler: Default::default(),
278        })
279    }
280
281    fn delete_id(self: Rc<Self>) -> Result<(), (ObjectError, Rc<dyn Object>)> {
282        let Some(mut handler) = self.handler.try_borrow_mut() else {
283            return Err((ObjectError(ObjectErrorKind::HandlerBorrowed), self));
284        };
285        if let Some(handler) = &mut *handler {
286            handler.delete_id(&self);
287        } else {
288            self.core.delete_id();
289        }
290        Ok(())
291    }
292
293    fn handle_request(self: Rc<Self>, client: &Rc<Client>, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
294        let Some(mut handler) = self.handler.try_borrow_mut() else {
295            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
296        };
297        let handler = &mut *handler;
298        match msg[1] & 0xffff {
299            0 => {
300                if msg.len() != 2 {
301                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
302                }
303                #[cfg(feature = "logging")]
304                if self.core.state.log {
305                    #[cold]
306                    fn log(state: &State, client_id: u64, id: u32) {
307                        let (millis, micros) = time_since_epoch();
308                        let prefix = &state.log_prefix;
309                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}client#{:<4} -> wl_buffer#{}.destroy()\n", client_id, id);
310                        state.log(args);
311                    }
312                    log(&self.core.state, client.endpoint.id, msg[0]);
313                }
314                self.core.handle_client_destroy();
315                if let Some(handler) = handler {
316                    (**handler).handle_destroy(&self);
317                } else {
318                    DefaultHandler.handle_destroy(&self);
319                }
320            }
321            n => {
322                let _ = client;
323                let _ = msg;
324                let _ = fds;
325                let _ = handler;
326                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
327            }
328        }
329        Ok(())
330    }
331
332    fn handle_event(self: Rc<Self>, server: &Endpoint, msg: &[u32], fds: &mut VecDeque<Rc<OwnedFd>>) -> Result<(), ObjectError> {
333        let Some(mut handler) = self.handler.try_borrow_mut() else {
334            return Err(ObjectError(ObjectErrorKind::HandlerBorrowed));
335        };
336        let handler = &mut *handler;
337        match msg[1] & 0xffff {
338            0 => {
339                if msg.len() != 2 {
340                    return Err(ObjectError(ObjectErrorKind::WrongMessageSize(msg.len() as u32 * 4, 8)));
341                }
342                #[cfg(feature = "logging")]
343                if self.core.state.log {
344                    #[cold]
345                    fn log(state: &State, id: u32) {
346                        let (millis, micros) = time_since_epoch();
347                        let prefix = &state.log_prefix;
348                        let args = format_args!("[{millis:7}.{micros:03}] {prefix}server      -> wl_buffer#{}.release()\n", id);
349                        state.log(args);
350                    }
351                    log(&self.core.state, msg[0]);
352                }
353                if let Some(handler) = handler {
354                    (**handler).handle_release(&self);
355                } else {
356                    DefaultHandler.handle_release(&self);
357                }
358            }
359            n => {
360                let _ = server;
361                let _ = msg;
362                let _ = fds;
363                let _ = handler;
364                return Err(ObjectError(ObjectErrorKind::UnknownMessageId(n)));
365            }
366        }
367        Ok(())
368    }
369
370    fn get_request_name(&self, id: u32) -> Option<&'static str> {
371        let name = match id {
372            0 => "destroy",
373            _ => return None,
374        };
375        Some(name)
376    }
377
378    fn get_event_name(&self, id: u32) -> Option<&'static str> {
379        let name = match id {
380            0 => "release",
381            _ => return None,
382        };
383        Some(name)
384    }
385}
386
387impl Object for WlBuffer {
388    fn core(&self) -> &ObjectCore {
389        &self.core
390    }
391
392    fn unset_handler(&self) {
393        self.handler.set(None);
394    }
395
396    fn get_handler_any_ref(&self) -> Result<HandlerRef<'_, dyn Any>, HandlerAccessError> {
397        let borrowed = self.handler.try_borrow().ok_or(HandlerAccessError::AlreadyBorrowed)?;
398        if borrowed.is_none() {
399            return Err(HandlerAccessError::NoHandler);
400        }
401        Ok(HandlerRef::map(borrowed, |handler| &**handler.as_ref().unwrap() as &dyn Any))
402    }
403
404    fn get_handler_any_mut(&self) -> Result<HandlerMut<'_, dyn Any>, HandlerAccessError> {
405        let borrowed = self.handler.try_borrow_mut().ok_or(HandlerAccessError::AlreadyBorrowed)?;
406        if borrowed.is_none() {
407            return Err(HandlerAccessError::NoHandler);
408        }
409        Ok(HandlerMut::map(borrowed, |handler| &mut **handler.as_mut().unwrap() as &mut dyn Any))
410    }
411}
412