wayland_bridge/
linux_dmabuf.rs1use crate::buffer::Buffer;
6use crate::client::Client;
7use crate::object::{NewObjectExt, ObjectRef, RequestReceiver};
8use anyhow::Error;
9use fidl_fuchsia_math::Size;
10use std::rc::Rc;
11use zwp_linux_dmabuf_v1_server_protocol::{
12 ZwpLinuxBufferParamsV1, ZwpLinuxBufferParamsV1Request, ZwpLinuxDmabufV1, ZwpLinuxDmabufV1Event,
13 ZwpLinuxDmabufV1Request,
14};
15use zx::{EventPair, Handle, HandleBased};
16use {fidl_fuchsia_ui_composition as composition, fuchsia_wayland_core as wl};
17
18const DRM_FORMAT_ARGB8888: u32 = 0x34325241;
19const DRM_FORMAT_ABGR8888: u32 = 0x34324241;
20const DRM_FORMAT_XRGB8888: u32 = 0x34325258;
21const DRM_FORMAT_XBGR8888: u32 = 0x34324258;
22
23const DRM_FORMAT_MOD_LINEAR: u64 = 0;
24
25const SUPPORTED_PIXEL_FORMATS: &[(u32, bool)] = &[
27 (DRM_FORMAT_ARGB8888, true),
28 (DRM_FORMAT_ABGR8888, true),
29 (DRM_FORMAT_XRGB8888, false),
30 (DRM_FORMAT_XBGR8888, false),
31];
32
33#[cfg(feature = "i915")]
35const SUPPORTED_MODIFIERS: &[u64] = &[
36 DRM_FORMAT_MOD_LINEAR,
37 1 << 56 | 1, 1 << 56 | 2, ];
40#[cfg(not(feature = "i915"))]
41const SUPPORTED_MODIFIERS: &[u64] = &[DRM_FORMAT_MOD_LINEAR];
42
43pub struct LinuxDmabuf {
45 client_version: u32,
46}
47
48impl LinuxDmabuf {
49 pub fn new(client_version: u32) -> Self {
51 Self { client_version }
52 }
53
54 pub fn post_formats(&self, this: wl::ObjectId, client: &Client) -> Result<(), Error> {
56 for (format, _) in SUPPORTED_PIXEL_FORMATS.iter() {
57 client.event_queue().post(this, ZwpLinuxDmabufV1Event::Format { format: *format })?;
58 if self.client_version >= 3 {
59 for modifier in SUPPORTED_MODIFIERS.iter() {
60 client.event_queue().post(
61 this,
62 ZwpLinuxDmabufV1Event::Modifier {
63 format: *format,
64 modifier_hi: (modifier >> 32) as u32,
65 modifier_lo: (modifier & 0xffffffff) as u32,
66 },
67 )?;
68 }
69 }
70 }
71 Ok(())
72 }
73}
74
75impl RequestReceiver<ZwpLinuxDmabufV1> for LinuxDmabuf {
76 fn receive(
77 this: ObjectRef<Self>,
78 request: ZwpLinuxDmabufV1Request,
79 client: &mut Client,
80 ) -> Result<(), Error> {
81 match request {
82 ZwpLinuxDmabufV1Request::Destroy => {
83 client.delete_id(this.id())?;
84 }
85 ZwpLinuxDmabufV1Request::CreateParams { params_id } => {
86 params_id.implement(client, LinuxBufferParams::new())?;
87 }
88 }
89 Ok(())
90 }
91}
92
93pub struct LinuxBufferParams {
94 token: EventPair,
96}
97
98impl LinuxBufferParams {
99 pub fn new() -> Self {
101 LinuxBufferParams { token: Handle::invalid().into() }
102 }
103
104 pub fn create(&mut self, width: i32, height: i32, format: u32) -> Result<Buffer, Error> {
106 let image_size = Size { width, height };
107 let has_alpha = SUPPORTED_PIXEL_FORMATS
108 .iter()
109 .find_map(
110 |&(supported_format, has_alpha)| {
111 if supported_format == format {
112 Some(has_alpha)
113 } else {
114 None
115 }
116 },
117 )
118 .unwrap_or(false);
119 let raw_import_token = self.token.duplicate_handle(zx::Rights::SAME_RIGHTS)?;
120 let import_token = composition::BufferCollectionImportToken { value: raw_import_token };
121
122 Ok(Buffer::from_import_token(Rc::new(import_token), image_size, has_alpha))
123 }
124
125 pub fn set_plane(&mut self, token: EventPair) {
126 self.token = token;
127 }
128}
129
130impl RequestReceiver<ZwpLinuxBufferParamsV1> for LinuxBufferParams {
131 fn receive(
132 this: ObjectRef<Self>,
133 request: ZwpLinuxBufferParamsV1Request,
134 client: &mut Client,
135 ) -> Result<(), Error> {
136 match request {
137 ZwpLinuxBufferParamsV1Request::Destroy => {
138 client.delete_id(this.id())?;
139 }
140 ZwpLinuxBufferParamsV1Request::Add { fd, .. } => {
141 this.get_mut(client)?.set_plane(fd.into());
142 }
143 ZwpLinuxBufferParamsV1Request::Create { .. } => {}
144 ZwpLinuxBufferParamsV1Request::CreateImmed {
145 buffer_id, width, height, format, ..
146 } => {
147 let buffer = this.get_mut(client)?.create(width, height, format)?;
148 buffer_id.implement(client, buffer)?;
149 }
150 }
151 Ok(())
152 }
153}