1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © 2015 Intel Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include <wayland-client.h>
25bf215546Sopenharmony_ci
26bf215546Sopenharmony_ci#include <assert.h>
27bf215546Sopenharmony_ci#include <stdlib.h>
28bf215546Sopenharmony_ci#include <stdio.h>
29bf215546Sopenharmony_ci#include <unistd.h>
30bf215546Sopenharmony_ci#include <errno.h>
31bf215546Sopenharmony_ci#include <string.h>
32bf215546Sopenharmony_ci#include <pthread.h>
33bf215546Sopenharmony_ci#include <poll.h>
34bf215546Sopenharmony_ci#include <sys/mman.h>
35bf215546Sopenharmony_ci
36bf215546Sopenharmony_ci#include "drm-uapi/drm_fourcc.h"
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci#include "vk_instance.h"
39bf215546Sopenharmony_ci#include "vk_physical_device.h"
40bf215546Sopenharmony_ci#include "vk_util.h"
41bf215546Sopenharmony_ci#include "wsi_common_entrypoints.h"
42bf215546Sopenharmony_ci#include "wsi_common_private.h"
43bf215546Sopenharmony_ci#include "linux-dmabuf-unstable-v1-client-protocol.h"
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ci#include <util/compiler.h>
46bf215546Sopenharmony_ci#include <util/hash_table.h>
47bf215546Sopenharmony_ci#include <util/timespec.h>
48bf215546Sopenharmony_ci#include <util/u_vector.h>
49bf215546Sopenharmony_ci#include <util/anon_file.h>
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_cistruct wsi_wayland;
52bf215546Sopenharmony_ci
53bf215546Sopenharmony_cistruct wsi_wl_format {
54bf215546Sopenharmony_ci   VkFormat vk_format;
55bf215546Sopenharmony_ci   uint32_t flags;
56bf215546Sopenharmony_ci   struct u_vector modifiers;
57bf215546Sopenharmony_ci};
58bf215546Sopenharmony_ci
59bf215546Sopenharmony_cistruct wsi_wl_display {
60bf215546Sopenharmony_ci   /* The real wl_display */
61bf215546Sopenharmony_ci   struct wl_display *                          wl_display;
62bf215546Sopenharmony_ci   /* Actually a proxy wrapper around the event queue */
63bf215546Sopenharmony_ci   struct wl_display *                          wl_display_wrapper;
64bf215546Sopenharmony_ci   struct wl_event_queue *                      queue;
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_ci   struct wl_shm *                              wl_shm;
67bf215546Sopenharmony_ci   struct zwp_linux_dmabuf_v1 *                 wl_dmabuf;
68bf215546Sopenharmony_ci
69bf215546Sopenharmony_ci   struct wsi_wayland *wsi_wl;
70bf215546Sopenharmony_ci
71bf215546Sopenharmony_ci   /* Formats populated by zwp_linux_dmabuf_v1 or wl_shm interfaces */
72bf215546Sopenharmony_ci   struct u_vector                              formats;
73bf215546Sopenharmony_ci
74bf215546Sopenharmony_ci   /* Only used for displays created by wsi_wl_display_create */
75bf215546Sopenharmony_ci   uint32_t                                     refcount;
76bf215546Sopenharmony_ci
77bf215546Sopenharmony_ci   bool sw;
78bf215546Sopenharmony_ci};
79bf215546Sopenharmony_ci
80bf215546Sopenharmony_cistruct wsi_wayland {
81bf215546Sopenharmony_ci   struct wsi_interface                     base;
82bf215546Sopenharmony_ci
83bf215546Sopenharmony_ci   struct wsi_device *wsi;
84bf215546Sopenharmony_ci
85bf215546Sopenharmony_ci   const VkAllocationCallbacks *alloc;
86bf215546Sopenharmony_ci   VkPhysicalDevice physical_device;
87bf215546Sopenharmony_ci};
88bf215546Sopenharmony_ci
89bf215546Sopenharmony_cienum wsi_wl_fmt_flag {
90bf215546Sopenharmony_ci   WSI_WL_FMT_ALPHA = 1 << 0,
91bf215546Sopenharmony_ci   WSI_WL_FMT_OPAQUE = 1 << 1,
92bf215546Sopenharmony_ci};
93bf215546Sopenharmony_ci
94bf215546Sopenharmony_cistatic struct wsi_wl_format *
95bf215546Sopenharmony_cifind_format(struct u_vector *formats, VkFormat format)
96bf215546Sopenharmony_ci{
97bf215546Sopenharmony_ci   struct wsi_wl_format *f;
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_ci   u_vector_foreach(f, formats)
100bf215546Sopenharmony_ci      if (f->vk_format == format)
101bf215546Sopenharmony_ci         return f;
102bf215546Sopenharmony_ci
103bf215546Sopenharmony_ci   return NULL;
104bf215546Sopenharmony_ci}
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_cistatic struct wsi_wl_format *
107bf215546Sopenharmony_ciwsi_wl_display_add_vk_format(struct wsi_wl_display *display,
108bf215546Sopenharmony_ci                             struct u_vector *formats,
109bf215546Sopenharmony_ci                             VkFormat format, uint32_t flags)
110bf215546Sopenharmony_ci{
111bf215546Sopenharmony_ci   assert(flags & (WSI_WL_FMT_ALPHA | WSI_WL_FMT_OPAQUE));
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci   /* Don't add a format that's already in the list */
114bf215546Sopenharmony_ci   struct wsi_wl_format *f = find_format(formats, format);
115bf215546Sopenharmony_ci   if (f) {
116bf215546Sopenharmony_ci      f->flags |= flags;
117bf215546Sopenharmony_ci      return f;
118bf215546Sopenharmony_ci   }
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci   /* Don't add formats that aren't renderable. */
121bf215546Sopenharmony_ci   VkFormatProperties props;
122bf215546Sopenharmony_ci
123bf215546Sopenharmony_ci   display->wsi_wl->wsi->GetPhysicalDeviceFormatProperties(display->wsi_wl->physical_device,
124bf215546Sopenharmony_ci                                                           format, &props);
125bf215546Sopenharmony_ci   if (!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT))
126bf215546Sopenharmony_ci      return NULL;
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   struct u_vector modifiers;
129bf215546Sopenharmony_ci   if (!u_vector_init_pow2(&modifiers, 4, sizeof(uint64_t)))
130bf215546Sopenharmony_ci      return NULL;
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci   f = u_vector_add(formats);
133bf215546Sopenharmony_ci   if (!f) {
134bf215546Sopenharmony_ci      u_vector_finish(&modifiers);
135bf215546Sopenharmony_ci      return NULL;
136bf215546Sopenharmony_ci   }
137bf215546Sopenharmony_ci
138bf215546Sopenharmony_ci   f->vk_format = format;
139bf215546Sopenharmony_ci   f->flags = flags;
140bf215546Sopenharmony_ci   f->modifiers = modifiers;
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci   return f;
143bf215546Sopenharmony_ci}
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_cistatic void
146bf215546Sopenharmony_ciwsi_wl_format_add_modifier(struct wsi_wl_format *format, uint64_t modifier)
147bf215546Sopenharmony_ci{
148bf215546Sopenharmony_ci   uint64_t *mod;
149bf215546Sopenharmony_ci
150bf215546Sopenharmony_ci   if (modifier == DRM_FORMAT_MOD_INVALID)
151bf215546Sopenharmony_ci      return;
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci   u_vector_foreach(mod, &format->modifiers)
154bf215546Sopenharmony_ci      if (*mod == modifier)
155bf215546Sopenharmony_ci         return;
156bf215546Sopenharmony_ci
157bf215546Sopenharmony_ci   mod = u_vector_add(&format->modifiers);
158bf215546Sopenharmony_ci   if (mod)
159bf215546Sopenharmony_ci      *mod = modifier;
160bf215546Sopenharmony_ci}
161bf215546Sopenharmony_ci
162bf215546Sopenharmony_cistatic void
163bf215546Sopenharmony_ciwsi_wl_display_add_vk_format_modifier(struct wsi_wl_display *display,
164bf215546Sopenharmony_ci                                      struct u_vector *formats,
165bf215546Sopenharmony_ci                                      VkFormat vk_format, uint32_t flags,
166bf215546Sopenharmony_ci                                      uint64_t modifier)
167bf215546Sopenharmony_ci{
168bf215546Sopenharmony_ci   struct wsi_wl_format *format;
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci   format = wsi_wl_display_add_vk_format(display, formats, vk_format, flags);
171bf215546Sopenharmony_ci   if (format)
172bf215546Sopenharmony_ci      wsi_wl_format_add_modifier(format, modifier);
173bf215546Sopenharmony_ci}
174bf215546Sopenharmony_ci
175bf215546Sopenharmony_cistatic void
176bf215546Sopenharmony_ciwsi_wl_display_add_drm_format_modifier(struct wsi_wl_display *display,
177bf215546Sopenharmony_ci                                       struct u_vector *formats,
178bf215546Sopenharmony_ci                                       uint32_t drm_format, uint64_t modifier)
179bf215546Sopenharmony_ci{
180bf215546Sopenharmony_ci   switch (drm_format) {
181bf215546Sopenharmony_ci#if 0
182bf215546Sopenharmony_ci   /* TODO: These are only available when VK_EXT_4444_formats is enabled, so
183bf215546Sopenharmony_ci    * we probably need to make their use conditional on this extension. */
184bf215546Sopenharmony_ci   case DRM_FORMAT_ARGB4444:
185bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
186bf215546Sopenharmony_ci                                            VK_FORMAT_A4R4G4B4_UNORM_PACK16,
187bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
188bf215546Sopenharmony_ci      break;
189bf215546Sopenharmony_ci   case DRM_FORMAT_XRGB4444:
190bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
191bf215546Sopenharmony_ci                                            VK_FORMAT_A4R4G4B4_UNORM_PACK16,
192bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
193bf215546Sopenharmony_ci      break;
194bf215546Sopenharmony_ci   case DRM_FORMAT_ABGR4444:
195bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
196bf215546Sopenharmony_ci                                            VK_FORMAT_A4B4G4R4_UNORM_PACK16,
197bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
198bf215546Sopenharmony_ci      break;
199bf215546Sopenharmony_ci   case DRM_FORMAT_XBGR4444:
200bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
201bf215546Sopenharmony_ci                                            VK_FORMAT_A4B4G4R4_UNORM_PACK16,
202bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
203bf215546Sopenharmony_ci      break;
204bf215546Sopenharmony_ci#endif
205bf215546Sopenharmony_ci
206bf215546Sopenharmony_ci   /* Vulkan _PACKN formats have the same component order as DRM formats
207bf215546Sopenharmony_ci    * on little endian systems, on big endian there exists no analog. */
208bf215546Sopenharmony_ci#if MESA_LITTLE_ENDIAN
209bf215546Sopenharmony_ci   case DRM_FORMAT_RGBA4444:
210bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
211bf215546Sopenharmony_ci                                            VK_FORMAT_R4G4B4A4_UNORM_PACK16,
212bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
213bf215546Sopenharmony_ci      break;
214bf215546Sopenharmony_ci   case DRM_FORMAT_RGBX4444:
215bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
216bf215546Sopenharmony_ci                                            VK_FORMAT_R4G4B4A4_UNORM_PACK16,
217bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
218bf215546Sopenharmony_ci      break;
219bf215546Sopenharmony_ci   case DRM_FORMAT_BGRA4444:
220bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
221bf215546Sopenharmony_ci                                            VK_FORMAT_B4G4R4A4_UNORM_PACK16,
222bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
223bf215546Sopenharmony_ci      break;
224bf215546Sopenharmony_ci   case DRM_FORMAT_BGRX4444:
225bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
226bf215546Sopenharmony_ci                                            VK_FORMAT_B4G4R4A4_UNORM_PACK16,
227bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
228bf215546Sopenharmony_ci      break;
229bf215546Sopenharmony_ci   case DRM_FORMAT_RGB565:
230bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
231bf215546Sopenharmony_ci                                            VK_FORMAT_R5G6B5_UNORM_PACK16,
232bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA | WSI_WL_FMT_OPAQUE,
233bf215546Sopenharmony_ci                                            modifier);
234bf215546Sopenharmony_ci      break;
235bf215546Sopenharmony_ci   case DRM_FORMAT_BGR565:
236bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
237bf215546Sopenharmony_ci                                            VK_FORMAT_B5G6R5_UNORM_PACK16,
238bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA | WSI_WL_FMT_OPAQUE,
239bf215546Sopenharmony_ci                                            modifier);
240bf215546Sopenharmony_ci      break;
241bf215546Sopenharmony_ci   case DRM_FORMAT_ARGB1555:
242bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
243bf215546Sopenharmony_ci                                            VK_FORMAT_A1R5G5B5_UNORM_PACK16,
244bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
245bf215546Sopenharmony_ci      break;
246bf215546Sopenharmony_ci   case DRM_FORMAT_XRGB1555:
247bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
248bf215546Sopenharmony_ci                                            VK_FORMAT_A1R5G5B5_UNORM_PACK16,
249bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
250bf215546Sopenharmony_ci      break;
251bf215546Sopenharmony_ci   case DRM_FORMAT_RGBA5551:
252bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
253bf215546Sopenharmony_ci                                            VK_FORMAT_R5G5B5A1_UNORM_PACK16,
254bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
255bf215546Sopenharmony_ci      break;
256bf215546Sopenharmony_ci   case DRM_FORMAT_RGBX5551:
257bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
258bf215546Sopenharmony_ci                                            VK_FORMAT_R5G5B5A1_UNORM_PACK16,
259bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
260bf215546Sopenharmony_ci      break;
261bf215546Sopenharmony_ci   case DRM_FORMAT_BGRA5551:
262bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
263bf215546Sopenharmony_ci                                            VK_FORMAT_B5G5R5A1_UNORM_PACK16,
264bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
265bf215546Sopenharmony_ci      break;
266bf215546Sopenharmony_ci   case DRM_FORMAT_BGRX5551:
267bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
268bf215546Sopenharmony_ci                                            VK_FORMAT_B5G5R5A1_UNORM_PACK16,
269bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
270bf215546Sopenharmony_ci      break;
271bf215546Sopenharmony_ci   case DRM_FORMAT_ARGB2101010:
272bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
273bf215546Sopenharmony_ci                                            VK_FORMAT_A2R10G10B10_UNORM_PACK32,
274bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
275bf215546Sopenharmony_ci      break;
276bf215546Sopenharmony_ci   case DRM_FORMAT_XRGB2101010:
277bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
278bf215546Sopenharmony_ci                                            VK_FORMAT_A2R10G10B10_UNORM_PACK32,
279bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
280bf215546Sopenharmony_ci      break;
281bf215546Sopenharmony_ci   case DRM_FORMAT_ABGR2101010:
282bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
283bf215546Sopenharmony_ci                                            VK_FORMAT_A2B10G10R10_UNORM_PACK32,
284bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
285bf215546Sopenharmony_ci      break;
286bf215546Sopenharmony_ci   case DRM_FORMAT_XBGR2101010:
287bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
288bf215546Sopenharmony_ci                                            VK_FORMAT_A2B10G10R10_UNORM_PACK32,
289bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
290bf215546Sopenharmony_ci      break;
291bf215546Sopenharmony_ci#endif
292bf215546Sopenharmony_ci
293bf215546Sopenharmony_ci   /* Non-packed 8-bit formats have an inverted channel order compared to the
294bf215546Sopenharmony_ci    * little endian DRM formats, because the DRM channel ordering is high->low
295bf215546Sopenharmony_ci    * but the vulkan channel ordering is in memory byte order
296bf215546Sopenharmony_ci    *
297bf215546Sopenharmony_ci    * For all UNORM formats which have a SRGB variant, we must support both if
298bf215546Sopenharmony_ci    * we can. SRGB in this context means that rendering to it will result in a
299bf215546Sopenharmony_ci    * linear -> nonlinear SRGB colorspace conversion before the data is stored.
300bf215546Sopenharmony_ci    * The inverse function is applied when sampling from SRGB images.
301bf215546Sopenharmony_ci    * From Wayland's perspective nothing changes, the difference is just how
302bf215546Sopenharmony_ci    * Vulkan interprets the pixel data. */
303bf215546Sopenharmony_ci   case DRM_FORMAT_XBGR8888:
304bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
305bf215546Sopenharmony_ci                                            VK_FORMAT_R8G8B8_SRGB,
306bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA | WSI_WL_FMT_OPAQUE,
307bf215546Sopenharmony_ci                                            modifier);
308bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
309bf215546Sopenharmony_ci                                            VK_FORMAT_R8G8B8_UNORM,
310bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA | WSI_WL_FMT_OPAQUE,
311bf215546Sopenharmony_ci                                            modifier);
312bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
313bf215546Sopenharmony_ci                                            VK_FORMAT_R8G8B8A8_SRGB,
314bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
315bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
316bf215546Sopenharmony_ci                                            VK_FORMAT_R8G8B8A8_UNORM,
317bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
318bf215546Sopenharmony_ci      break;
319bf215546Sopenharmony_ci   case DRM_FORMAT_ABGR8888:
320bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
321bf215546Sopenharmony_ci                                            VK_FORMAT_R8G8B8A8_SRGB,
322bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
323bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
324bf215546Sopenharmony_ci                                            VK_FORMAT_R8G8B8A8_UNORM,
325bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
326bf215546Sopenharmony_ci      break;
327bf215546Sopenharmony_ci   case DRM_FORMAT_XRGB8888:
328bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
329bf215546Sopenharmony_ci                                            VK_FORMAT_B8G8R8_SRGB,
330bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA | WSI_WL_FMT_OPAQUE,
331bf215546Sopenharmony_ci                                            modifier);
332bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
333bf215546Sopenharmony_ci                                            VK_FORMAT_B8G8R8_UNORM,
334bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA | WSI_WL_FMT_OPAQUE,
335bf215546Sopenharmony_ci                                            modifier);
336bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
337bf215546Sopenharmony_ci                                            VK_FORMAT_B8G8R8A8_SRGB,
338bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
339bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
340bf215546Sopenharmony_ci                                            VK_FORMAT_B8G8R8A8_UNORM,
341bf215546Sopenharmony_ci                                            WSI_WL_FMT_OPAQUE, modifier);
342bf215546Sopenharmony_ci      break;
343bf215546Sopenharmony_ci   case DRM_FORMAT_ARGB8888:
344bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
345bf215546Sopenharmony_ci                                            VK_FORMAT_B8G8R8A8_SRGB,
346bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
347bf215546Sopenharmony_ci      wsi_wl_display_add_vk_format_modifier(display, formats,
348bf215546Sopenharmony_ci                                            VK_FORMAT_B8G8R8A8_UNORM,
349bf215546Sopenharmony_ci                                            WSI_WL_FMT_ALPHA, modifier);
350bf215546Sopenharmony_ci      break;
351bf215546Sopenharmony_ci   }
352bf215546Sopenharmony_ci}
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_cistatic uint32_t
355bf215546Sopenharmony_cidrm_format_for_wl_shm_format(enum wl_shm_format shm_format)
356bf215546Sopenharmony_ci{
357bf215546Sopenharmony_ci   /* wl_shm formats are identical to DRM, except ARGB8888 and XRGB8888 */
358bf215546Sopenharmony_ci   switch (shm_format) {
359bf215546Sopenharmony_ci   case WL_SHM_FORMAT_ARGB8888:
360bf215546Sopenharmony_ci      return DRM_FORMAT_ARGB8888;
361bf215546Sopenharmony_ci   case WL_SHM_FORMAT_XRGB8888:
362bf215546Sopenharmony_ci      return DRM_FORMAT_XRGB8888;
363bf215546Sopenharmony_ci   default:
364bf215546Sopenharmony_ci      return shm_format;
365bf215546Sopenharmony_ci   }
366bf215546Sopenharmony_ci}
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_cistatic void
369bf215546Sopenharmony_ciwsi_wl_display_add_wl_shm_format(struct wsi_wl_display *display,
370bf215546Sopenharmony_ci                                 struct u_vector *formats,
371bf215546Sopenharmony_ci                                 enum wl_shm_format shm_format)
372bf215546Sopenharmony_ci{
373bf215546Sopenharmony_ci   uint32_t drm_format = drm_format_for_wl_shm_format(shm_format);
374bf215546Sopenharmony_ci
375bf215546Sopenharmony_ci   wsi_wl_display_add_drm_format_modifier(display, formats, drm_format,
376bf215546Sopenharmony_ci                                          DRM_FORMAT_MOD_INVALID);
377bf215546Sopenharmony_ci}
378bf215546Sopenharmony_ci
379bf215546Sopenharmony_cistatic uint32_t
380bf215546Sopenharmony_ciwl_drm_format_for_vk_format(VkFormat vk_format, bool alpha)
381bf215546Sopenharmony_ci{
382bf215546Sopenharmony_ci   switch (vk_format) {
383bf215546Sopenharmony_ci#if 0
384bf215546Sopenharmony_ci   case VK_FORMAT_A4R4G4B4_UNORM_PACK16:
385bf215546Sopenharmony_ci      return alpha ? DRM_FORMAT_ARGB4444 : DRM_FORMAT_XRGB4444;
386bf215546Sopenharmony_ci   case VK_FORMAT_A4B4G4R4_UNORM_PACK16:
387bf215546Sopenharmony_ci      return alpha ? DRM_FORMAT_ABGR4444 : DRM_FORMAT_XBGR4444;
388bf215546Sopenharmony_ci#endif
389bf215546Sopenharmony_ci#if MESA_LITTLE_ENDIAN
390bf215546Sopenharmony_ci   case VK_FORMAT_R4G4B4A4_UNORM_PACK16:
391bf215546Sopenharmony_ci      return alpha ? DRM_FORMAT_RGBA4444 : DRM_FORMAT_RGBX4444;
392bf215546Sopenharmony_ci   case VK_FORMAT_B4G4R4A4_UNORM_PACK16:
393bf215546Sopenharmony_ci      return alpha ? DRM_FORMAT_BGRA4444 : DRM_FORMAT_BGRX4444;
394bf215546Sopenharmony_ci   case VK_FORMAT_R5G6B5_UNORM_PACK16:
395bf215546Sopenharmony_ci      return DRM_FORMAT_RGB565;
396bf215546Sopenharmony_ci   case VK_FORMAT_B5G6R5_UNORM_PACK16:
397bf215546Sopenharmony_ci      return DRM_FORMAT_BGR565;
398bf215546Sopenharmony_ci   case VK_FORMAT_A1R5G5B5_UNORM_PACK16:
399bf215546Sopenharmony_ci      return alpha ? DRM_FORMAT_ARGB1555 : DRM_FORMAT_XRGB1555;
400bf215546Sopenharmony_ci   case VK_FORMAT_R5G5B5A1_UNORM_PACK16:
401bf215546Sopenharmony_ci      return alpha ? DRM_FORMAT_RGBA5551 : DRM_FORMAT_RGBX5551;
402bf215546Sopenharmony_ci   case VK_FORMAT_B5G5R5A1_UNORM_PACK16:
403bf215546Sopenharmony_ci      return alpha ? DRM_FORMAT_BGRA5551 : DRM_FORMAT_BGRX5551;
404bf215546Sopenharmony_ci   case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
405bf215546Sopenharmony_ci      return alpha ? DRM_FORMAT_ARGB2101010 : DRM_FORMAT_XRGB2101010;
406bf215546Sopenharmony_ci   case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
407bf215546Sopenharmony_ci      return alpha ? DRM_FORMAT_ABGR2101010 : DRM_FORMAT_XBGR2101010;
408bf215546Sopenharmony_ci#endif
409bf215546Sopenharmony_ci   case VK_FORMAT_R8G8B8_UNORM:
410bf215546Sopenharmony_ci   case VK_FORMAT_R8G8B8_SRGB:
411bf215546Sopenharmony_ci      return DRM_FORMAT_XBGR8888;
412bf215546Sopenharmony_ci   case VK_FORMAT_R8G8B8A8_UNORM:
413bf215546Sopenharmony_ci   case VK_FORMAT_R8G8B8A8_SRGB:
414bf215546Sopenharmony_ci      return alpha ? DRM_FORMAT_ABGR8888 : DRM_FORMAT_XBGR8888;
415bf215546Sopenharmony_ci   case VK_FORMAT_B8G8R8_UNORM:
416bf215546Sopenharmony_ci   case VK_FORMAT_B8G8R8_SRGB:
417bf215546Sopenharmony_ci      return DRM_FORMAT_BGRX8888;
418bf215546Sopenharmony_ci   case VK_FORMAT_B8G8R8A8_UNORM:
419bf215546Sopenharmony_ci   case VK_FORMAT_B8G8R8A8_SRGB:
420bf215546Sopenharmony_ci      return alpha ? DRM_FORMAT_ARGB8888 : DRM_FORMAT_XRGB8888;
421bf215546Sopenharmony_ci
422bf215546Sopenharmony_ci   default:
423bf215546Sopenharmony_ci      assert(!"Unsupported Vulkan format");
424bf215546Sopenharmony_ci      return DRM_FORMAT_INVALID;
425bf215546Sopenharmony_ci   }
426bf215546Sopenharmony_ci}
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_cistatic enum wl_shm_format
429bf215546Sopenharmony_ciwl_shm_format_for_vk_format(VkFormat vk_format, bool alpha)
430bf215546Sopenharmony_ci{
431bf215546Sopenharmony_ci   uint32_t drm_format = wl_drm_format_for_vk_format(vk_format, alpha);
432bf215546Sopenharmony_ci   if (drm_format == DRM_FORMAT_INVALID) {
433bf215546Sopenharmony_ci      return 0;
434bf215546Sopenharmony_ci   }
435bf215546Sopenharmony_ci
436bf215546Sopenharmony_ci   /* wl_shm formats are identical to DRM, except ARGB8888 and XRGB8888 */
437bf215546Sopenharmony_ci   switch (drm_format) {
438bf215546Sopenharmony_ci   case DRM_FORMAT_ARGB8888:
439bf215546Sopenharmony_ci      return WL_SHM_FORMAT_ARGB8888;
440bf215546Sopenharmony_ci   case DRM_FORMAT_XRGB8888:
441bf215546Sopenharmony_ci      return WL_SHM_FORMAT_XRGB8888;
442bf215546Sopenharmony_ci   default:
443bf215546Sopenharmony_ci      return drm_format;
444bf215546Sopenharmony_ci   }
445bf215546Sopenharmony_ci}
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_cistatic void
448bf215546Sopenharmony_cidmabuf_handle_format(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
449bf215546Sopenharmony_ci                     uint32_t format)
450bf215546Sopenharmony_ci{
451bf215546Sopenharmony_ci   /* Formats are implicitly advertised by the modifier event, so we ignore
452bf215546Sopenharmony_ci    * them here. */
453bf215546Sopenharmony_ci}
454bf215546Sopenharmony_ci
455bf215546Sopenharmony_cistatic void
456bf215546Sopenharmony_cidmabuf_handle_modifier(void *data, struct zwp_linux_dmabuf_v1 *dmabuf,
457bf215546Sopenharmony_ci                       uint32_t format, uint32_t modifier_hi,
458bf215546Sopenharmony_ci                       uint32_t modifier_lo)
459bf215546Sopenharmony_ci{
460bf215546Sopenharmony_ci   struct wsi_wl_display *display = data;
461bf215546Sopenharmony_ci   uint64_t modifier;
462bf215546Sopenharmony_ci
463bf215546Sopenharmony_ci   modifier = ((uint64_t) modifier_hi << 32) | modifier_lo;
464bf215546Sopenharmony_ci   wsi_wl_display_add_drm_format_modifier(display, &display->formats,
465bf215546Sopenharmony_ci                                          format, modifier);
466bf215546Sopenharmony_ci}
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_cistatic const struct zwp_linux_dmabuf_v1_listener dmabuf_listener = {
469bf215546Sopenharmony_ci   dmabuf_handle_format,
470bf215546Sopenharmony_ci   dmabuf_handle_modifier,
471bf215546Sopenharmony_ci};
472bf215546Sopenharmony_ci
473bf215546Sopenharmony_cistatic void
474bf215546Sopenharmony_cishm_handle_format(void *data, struct wl_shm *shm, uint32_t format)
475bf215546Sopenharmony_ci{
476bf215546Sopenharmony_ci   struct wsi_wl_display *display = data;
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci   wsi_wl_display_add_wl_shm_format(display, &display->formats, format);
479bf215546Sopenharmony_ci}
480bf215546Sopenharmony_ci
481bf215546Sopenharmony_cistatic const struct wl_shm_listener shm_listener = {
482bf215546Sopenharmony_ci   .format = shm_handle_format
483bf215546Sopenharmony_ci};
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_cistatic void
486bf215546Sopenharmony_ciregistry_handle_global(void *data, struct wl_registry *registry,
487bf215546Sopenharmony_ci                       uint32_t name, const char *interface, uint32_t version)
488bf215546Sopenharmony_ci{
489bf215546Sopenharmony_ci   struct wsi_wl_display *display = data;
490bf215546Sopenharmony_ci
491bf215546Sopenharmony_ci   if (display->sw) {
492bf215546Sopenharmony_ci      if (strcmp(interface, "wl_shm") == 0) {
493bf215546Sopenharmony_ci         display->wl_shm = wl_registry_bind(registry, name, &wl_shm_interface, 1);
494bf215546Sopenharmony_ci         wl_shm_add_listener(display->wl_shm, &shm_listener, display);
495bf215546Sopenharmony_ci      }
496bf215546Sopenharmony_ci      return;
497bf215546Sopenharmony_ci   }
498bf215546Sopenharmony_ci
499bf215546Sopenharmony_ci   if (strcmp(interface, "zwp_linux_dmabuf_v1") == 0 && version >= 3) {
500bf215546Sopenharmony_ci      display->wl_dmabuf =
501bf215546Sopenharmony_ci         wl_registry_bind(registry, name, &zwp_linux_dmabuf_v1_interface, 3);
502bf215546Sopenharmony_ci      zwp_linux_dmabuf_v1_add_listener(display->wl_dmabuf,
503bf215546Sopenharmony_ci                                       &dmabuf_listener, display);
504bf215546Sopenharmony_ci   }
505bf215546Sopenharmony_ci}
506bf215546Sopenharmony_ci
507bf215546Sopenharmony_cistatic void
508bf215546Sopenharmony_ciregistry_handle_global_remove(void *data, struct wl_registry *registry,
509bf215546Sopenharmony_ci                              uint32_t name)
510bf215546Sopenharmony_ci{ /* No-op */ }
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_cistatic const struct wl_registry_listener registry_listener = {
513bf215546Sopenharmony_ci   registry_handle_global,
514bf215546Sopenharmony_ci   registry_handle_global_remove
515bf215546Sopenharmony_ci};
516bf215546Sopenharmony_ci
517bf215546Sopenharmony_cistatic void
518bf215546Sopenharmony_ciwsi_wl_display_finish(struct wsi_wl_display *display)
519bf215546Sopenharmony_ci{
520bf215546Sopenharmony_ci   assert(display->refcount == 0);
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_ci   struct wsi_wl_format *f;
523bf215546Sopenharmony_ci   u_vector_foreach(f, &display->formats)
524bf215546Sopenharmony_ci      u_vector_finish(&f->modifiers);
525bf215546Sopenharmony_ci   u_vector_finish(&display->formats);
526bf215546Sopenharmony_ci   if (display->wl_shm)
527bf215546Sopenharmony_ci      wl_shm_destroy(display->wl_shm);
528bf215546Sopenharmony_ci   if (display->wl_dmabuf)
529bf215546Sopenharmony_ci      zwp_linux_dmabuf_v1_destroy(display->wl_dmabuf);
530bf215546Sopenharmony_ci   if (display->wl_display_wrapper)
531bf215546Sopenharmony_ci      wl_proxy_wrapper_destroy(display->wl_display_wrapper);
532bf215546Sopenharmony_ci   if (display->queue)
533bf215546Sopenharmony_ci      wl_event_queue_destroy(display->queue);
534bf215546Sopenharmony_ci}
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_cistatic VkResult
537bf215546Sopenharmony_ciwsi_wl_display_init(struct wsi_wayland *wsi_wl,
538bf215546Sopenharmony_ci                    struct wsi_wl_display *display,
539bf215546Sopenharmony_ci                    struct wl_display *wl_display,
540bf215546Sopenharmony_ci                    bool get_format_list, bool sw)
541bf215546Sopenharmony_ci{
542bf215546Sopenharmony_ci   VkResult result = VK_SUCCESS;
543bf215546Sopenharmony_ci   memset(display, 0, sizeof(*display));
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_ci   if (!u_vector_init(&display->formats, 8, sizeof(struct wsi_wl_format)))
546bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci   display->wsi_wl = wsi_wl;
549bf215546Sopenharmony_ci   display->wl_display = wl_display;
550bf215546Sopenharmony_ci   display->sw = sw;
551bf215546Sopenharmony_ci
552bf215546Sopenharmony_ci   display->queue = wl_display_create_queue(wl_display);
553bf215546Sopenharmony_ci   if (!display->queue) {
554bf215546Sopenharmony_ci      result = VK_ERROR_OUT_OF_HOST_MEMORY;
555bf215546Sopenharmony_ci      goto fail;
556bf215546Sopenharmony_ci   }
557bf215546Sopenharmony_ci
558bf215546Sopenharmony_ci   display->wl_display_wrapper = wl_proxy_create_wrapper(wl_display);
559bf215546Sopenharmony_ci   if (!display->wl_display_wrapper) {
560bf215546Sopenharmony_ci      result = VK_ERROR_OUT_OF_HOST_MEMORY;
561bf215546Sopenharmony_ci      goto fail;
562bf215546Sopenharmony_ci   }
563bf215546Sopenharmony_ci
564bf215546Sopenharmony_ci   wl_proxy_set_queue((struct wl_proxy *) display->wl_display_wrapper,
565bf215546Sopenharmony_ci                      display->queue);
566bf215546Sopenharmony_ci
567bf215546Sopenharmony_ci   struct wl_registry *registry =
568bf215546Sopenharmony_ci      wl_display_get_registry(display->wl_display_wrapper);
569bf215546Sopenharmony_ci   if (!registry) {
570bf215546Sopenharmony_ci      result = VK_ERROR_OUT_OF_HOST_MEMORY;
571bf215546Sopenharmony_ci      goto fail;
572bf215546Sopenharmony_ci   }
573bf215546Sopenharmony_ci
574bf215546Sopenharmony_ci   wl_registry_add_listener(registry, &registry_listener, display);
575bf215546Sopenharmony_ci
576bf215546Sopenharmony_ci   /* Round-trip to get wl_shm and zwp_linux_dmabuf_v1 globals */
577bf215546Sopenharmony_ci   wl_display_roundtrip_queue(display->wl_display, display->queue);
578bf215546Sopenharmony_ci   if (!display->wl_dmabuf && !display->wl_shm) {
579bf215546Sopenharmony_ci      result = VK_ERROR_SURFACE_LOST_KHR;
580bf215546Sopenharmony_ci      goto fail_registry;
581bf215546Sopenharmony_ci   }
582bf215546Sopenharmony_ci
583bf215546Sopenharmony_ci   /* Caller doesn't expect us to query formats/modifiers, so return */
584bf215546Sopenharmony_ci   if (!get_format_list)
585bf215546Sopenharmony_ci      goto out;
586bf215546Sopenharmony_ci
587bf215546Sopenharmony_ci   /* Round-trip again to get formats and modifiers */
588bf215546Sopenharmony_ci   wl_display_roundtrip_queue(display->wl_display, display->queue);
589bf215546Sopenharmony_ci
590bf215546Sopenharmony_ci   if (wsi_wl->wsi->force_bgra8_unorm_first) {
591bf215546Sopenharmony_ci      /* Find BGRA8_UNORM in the list and swap it to the first position if we
592bf215546Sopenharmony_ci       * can find it.  Some apps get confused if SRGB is first in the list.
593bf215546Sopenharmony_ci       */
594bf215546Sopenharmony_ci      struct wsi_wl_format *first_fmt = u_vector_head(&display->formats);
595bf215546Sopenharmony_ci      struct wsi_wl_format *f, tmp_fmt;
596bf215546Sopenharmony_ci      f = find_format(&display->formats, VK_FORMAT_B8G8R8A8_UNORM);
597bf215546Sopenharmony_ci      if (f) {
598bf215546Sopenharmony_ci         tmp_fmt = *f;
599bf215546Sopenharmony_ci         *f = *first_fmt;
600bf215546Sopenharmony_ci         *first_fmt = tmp_fmt;
601bf215546Sopenharmony_ci      }
602bf215546Sopenharmony_ci   }
603bf215546Sopenharmony_ci
604bf215546Sopenharmony_ciout:
605bf215546Sopenharmony_ci   /* We don't need this anymore */
606bf215546Sopenharmony_ci   wl_registry_destroy(registry);
607bf215546Sopenharmony_ci
608bf215546Sopenharmony_ci   display->refcount = 0;
609bf215546Sopenharmony_ci
610bf215546Sopenharmony_ci   return VK_SUCCESS;
611bf215546Sopenharmony_ci
612bf215546Sopenharmony_cifail_registry:
613bf215546Sopenharmony_ci   if (registry)
614bf215546Sopenharmony_ci      wl_registry_destroy(registry);
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_cifail:
617bf215546Sopenharmony_ci   wsi_wl_display_finish(display);
618bf215546Sopenharmony_ci   return result;
619bf215546Sopenharmony_ci}
620bf215546Sopenharmony_ci
621bf215546Sopenharmony_cistatic VkResult
622bf215546Sopenharmony_ciwsi_wl_display_create(struct wsi_wayland *wsi, struct wl_display *wl_display,
623bf215546Sopenharmony_ci                      bool sw,
624bf215546Sopenharmony_ci                      struct wsi_wl_display **display_out)
625bf215546Sopenharmony_ci{
626bf215546Sopenharmony_ci   struct wsi_wl_display *display =
627bf215546Sopenharmony_ci      vk_alloc(wsi->alloc, sizeof(*display), 8,
628bf215546Sopenharmony_ci               VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
629bf215546Sopenharmony_ci   if (!display)
630bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
631bf215546Sopenharmony_ci
632bf215546Sopenharmony_ci   VkResult result = wsi_wl_display_init(wsi, display, wl_display, true,
633bf215546Sopenharmony_ci                                         sw);
634bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
635bf215546Sopenharmony_ci      vk_free(wsi->alloc, display);
636bf215546Sopenharmony_ci      return result;
637bf215546Sopenharmony_ci   }
638bf215546Sopenharmony_ci
639bf215546Sopenharmony_ci   display->refcount++;
640bf215546Sopenharmony_ci   *display_out = display;
641bf215546Sopenharmony_ci
642bf215546Sopenharmony_ci   return result;
643bf215546Sopenharmony_ci}
644bf215546Sopenharmony_ci
645bf215546Sopenharmony_cistatic struct wsi_wl_display *
646bf215546Sopenharmony_ciwsi_wl_display_ref(struct wsi_wl_display *display)
647bf215546Sopenharmony_ci{
648bf215546Sopenharmony_ci   display->refcount++;
649bf215546Sopenharmony_ci   return display;
650bf215546Sopenharmony_ci}
651bf215546Sopenharmony_ci
652bf215546Sopenharmony_cistatic void
653bf215546Sopenharmony_ciwsi_wl_display_unref(struct wsi_wl_display *display)
654bf215546Sopenharmony_ci{
655bf215546Sopenharmony_ci   if (display->refcount-- > 1)
656bf215546Sopenharmony_ci      return;
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_ci   struct wsi_wayland *wsi = display->wsi_wl;
659bf215546Sopenharmony_ci   wsi_wl_display_finish(display);
660bf215546Sopenharmony_ci   vk_free(wsi->alloc, display);
661bf215546Sopenharmony_ci}
662bf215546Sopenharmony_ci
663bf215546Sopenharmony_ciVKAPI_ATTR VkBool32 VKAPI_CALL
664bf215546Sopenharmony_ciwsi_GetPhysicalDeviceWaylandPresentationSupportKHR(VkPhysicalDevice physicalDevice,
665bf215546Sopenharmony_ci                                                   uint32_t queueFamilyIndex,
666bf215546Sopenharmony_ci                                                   struct wl_display *wl_display)
667bf215546Sopenharmony_ci{
668bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_physical_device, pdevice, physicalDevice);
669bf215546Sopenharmony_ci   struct wsi_device *wsi_device = pdevice->wsi_device;
670bf215546Sopenharmony_ci   struct wsi_wayland *wsi =
671bf215546Sopenharmony_ci      (struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND];
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci   struct wsi_wl_display display;
674bf215546Sopenharmony_ci   VkResult ret = wsi_wl_display_init(wsi, &display, wl_display, false,
675bf215546Sopenharmony_ci                                      wsi_device->sw);
676bf215546Sopenharmony_ci   if (ret == VK_SUCCESS)
677bf215546Sopenharmony_ci      wsi_wl_display_finish(&display);
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_ci   return ret == VK_SUCCESS;
680bf215546Sopenharmony_ci}
681bf215546Sopenharmony_ci
682bf215546Sopenharmony_cistatic VkResult
683bf215546Sopenharmony_ciwsi_wl_surface_get_support(VkIcdSurfaceBase *surface,
684bf215546Sopenharmony_ci                           struct wsi_device *wsi_device,
685bf215546Sopenharmony_ci                           uint32_t queueFamilyIndex,
686bf215546Sopenharmony_ci                           VkBool32* pSupported)
687bf215546Sopenharmony_ci{
688bf215546Sopenharmony_ci   *pSupported = true;
689bf215546Sopenharmony_ci
690bf215546Sopenharmony_ci   return VK_SUCCESS;
691bf215546Sopenharmony_ci}
692bf215546Sopenharmony_ci
693bf215546Sopenharmony_cistatic const VkPresentModeKHR present_modes[] = {
694bf215546Sopenharmony_ci   VK_PRESENT_MODE_MAILBOX_KHR,
695bf215546Sopenharmony_ci   VK_PRESENT_MODE_FIFO_KHR,
696bf215546Sopenharmony_ci};
697bf215546Sopenharmony_ci
698bf215546Sopenharmony_cistatic VkResult
699bf215546Sopenharmony_ciwsi_wl_surface_get_capabilities(VkIcdSurfaceBase *surface,
700bf215546Sopenharmony_ci                                struct wsi_device *wsi_device,
701bf215546Sopenharmony_ci                                VkSurfaceCapabilitiesKHR* caps)
702bf215546Sopenharmony_ci{
703bf215546Sopenharmony_ci   /* For true mailbox mode, we need at least 4 images:
704bf215546Sopenharmony_ci    *  1) One to scan out from
705bf215546Sopenharmony_ci    *  2) One to have queued for scan-out
706bf215546Sopenharmony_ci    *  3) One to be currently held by the Wayland compositor
707bf215546Sopenharmony_ci    *  4) One to render to
708bf215546Sopenharmony_ci    */
709bf215546Sopenharmony_ci   caps->minImageCount = 4;
710bf215546Sopenharmony_ci   /* There is no real maximum */
711bf215546Sopenharmony_ci   caps->maxImageCount = 0;
712bf215546Sopenharmony_ci
713bf215546Sopenharmony_ci   caps->currentExtent = (VkExtent2D) { UINT32_MAX, UINT32_MAX };
714bf215546Sopenharmony_ci   caps->minImageExtent = (VkExtent2D) { 1, 1 };
715bf215546Sopenharmony_ci   caps->maxImageExtent = (VkExtent2D) {
716bf215546Sopenharmony_ci      wsi_device->maxImageDimension2D,
717bf215546Sopenharmony_ci      wsi_device->maxImageDimension2D,
718bf215546Sopenharmony_ci   };
719bf215546Sopenharmony_ci
720bf215546Sopenharmony_ci   caps->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
721bf215546Sopenharmony_ci   caps->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
722bf215546Sopenharmony_ci   caps->maxImageArrayLayers = 1;
723bf215546Sopenharmony_ci
724bf215546Sopenharmony_ci   caps->supportedCompositeAlpha =
725bf215546Sopenharmony_ci      VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR |
726bf215546Sopenharmony_ci      VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
727bf215546Sopenharmony_ci
728bf215546Sopenharmony_ci   caps->supportedUsageFlags =
729bf215546Sopenharmony_ci      VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
730bf215546Sopenharmony_ci      VK_IMAGE_USAGE_SAMPLED_BIT |
731bf215546Sopenharmony_ci      VK_IMAGE_USAGE_TRANSFER_DST_BIT |
732bf215546Sopenharmony_ci      VK_IMAGE_USAGE_STORAGE_BIT |
733bf215546Sopenharmony_ci      VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
734bf215546Sopenharmony_ci      VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
735bf215546Sopenharmony_ci
736bf215546Sopenharmony_ci   return VK_SUCCESS;
737bf215546Sopenharmony_ci}
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_cistatic VkResult
740bf215546Sopenharmony_ciwsi_wl_surface_get_capabilities2(VkIcdSurfaceBase *surface,
741bf215546Sopenharmony_ci                                 struct wsi_device *wsi_device,
742bf215546Sopenharmony_ci                                 const void *info_next,
743bf215546Sopenharmony_ci                                 VkSurfaceCapabilities2KHR* caps)
744bf215546Sopenharmony_ci{
745bf215546Sopenharmony_ci   assert(caps->sType == VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR);
746bf215546Sopenharmony_ci
747bf215546Sopenharmony_ci   VkResult result =
748bf215546Sopenharmony_ci      wsi_wl_surface_get_capabilities(surface, wsi_device,
749bf215546Sopenharmony_ci                                      &caps->surfaceCapabilities);
750bf215546Sopenharmony_ci
751bf215546Sopenharmony_ci   vk_foreach_struct(ext, caps->pNext) {
752bf215546Sopenharmony_ci      switch (ext->sType) {
753bf215546Sopenharmony_ci      case VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR: {
754bf215546Sopenharmony_ci         VkSurfaceProtectedCapabilitiesKHR *protected = (void *)ext;
755bf215546Sopenharmony_ci         protected->supportsProtected = VK_FALSE;
756bf215546Sopenharmony_ci         break;
757bf215546Sopenharmony_ci      }
758bf215546Sopenharmony_ci
759bf215546Sopenharmony_ci      default:
760bf215546Sopenharmony_ci         /* Ignored */
761bf215546Sopenharmony_ci         break;
762bf215546Sopenharmony_ci      }
763bf215546Sopenharmony_ci   }
764bf215546Sopenharmony_ci
765bf215546Sopenharmony_ci   return result;
766bf215546Sopenharmony_ci}
767bf215546Sopenharmony_ci
768bf215546Sopenharmony_cistatic VkResult
769bf215546Sopenharmony_ciwsi_wl_surface_get_formats(VkIcdSurfaceBase *icd_surface,
770bf215546Sopenharmony_ci			   struct wsi_device *wsi_device,
771bf215546Sopenharmony_ci                           uint32_t* pSurfaceFormatCount,
772bf215546Sopenharmony_ci                           VkSurfaceFormatKHR* pSurfaceFormats)
773bf215546Sopenharmony_ci{
774bf215546Sopenharmony_ci   VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)icd_surface;
775bf215546Sopenharmony_ci   struct wsi_wayland *wsi =
776bf215546Sopenharmony_ci      (struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND];
777bf215546Sopenharmony_ci
778bf215546Sopenharmony_ci   struct wsi_wl_display display;
779bf215546Sopenharmony_ci   if (wsi_wl_display_init(wsi, &display, surface->display, true,
780bf215546Sopenharmony_ci                           wsi_device->sw))
781bf215546Sopenharmony_ci      return VK_ERROR_SURFACE_LOST_KHR;
782bf215546Sopenharmony_ci
783bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkSurfaceFormatKHR, out,
784bf215546Sopenharmony_ci                          pSurfaceFormats, pSurfaceFormatCount);
785bf215546Sopenharmony_ci
786bf215546Sopenharmony_ci   struct wsi_wl_format *disp_fmt;
787bf215546Sopenharmony_ci   u_vector_foreach(disp_fmt, &display.formats) {
788bf215546Sopenharmony_ci      /* Skip formats for which we can't support both alpha & opaque
789bf215546Sopenharmony_ci       * formats.
790bf215546Sopenharmony_ci       */
791bf215546Sopenharmony_ci      if (!(disp_fmt->flags & WSI_WL_FMT_ALPHA) ||
792bf215546Sopenharmony_ci          !(disp_fmt->flags & WSI_WL_FMT_OPAQUE))
793bf215546Sopenharmony_ci         continue;
794bf215546Sopenharmony_ci
795bf215546Sopenharmony_ci      vk_outarray_append_typed(VkSurfaceFormatKHR, &out, out_fmt) {
796bf215546Sopenharmony_ci         out_fmt->format = disp_fmt->vk_format;
797bf215546Sopenharmony_ci         out_fmt->colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
798bf215546Sopenharmony_ci      }
799bf215546Sopenharmony_ci   }
800bf215546Sopenharmony_ci
801bf215546Sopenharmony_ci   wsi_wl_display_finish(&display);
802bf215546Sopenharmony_ci
803bf215546Sopenharmony_ci   return vk_outarray_status(&out);
804bf215546Sopenharmony_ci}
805bf215546Sopenharmony_ci
806bf215546Sopenharmony_cistatic VkResult
807bf215546Sopenharmony_ciwsi_wl_surface_get_formats2(VkIcdSurfaceBase *icd_surface,
808bf215546Sopenharmony_ci			    struct wsi_device *wsi_device,
809bf215546Sopenharmony_ci                            const void *info_next,
810bf215546Sopenharmony_ci                            uint32_t* pSurfaceFormatCount,
811bf215546Sopenharmony_ci                            VkSurfaceFormat2KHR* pSurfaceFormats)
812bf215546Sopenharmony_ci{
813bf215546Sopenharmony_ci   VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)icd_surface;
814bf215546Sopenharmony_ci   struct wsi_wayland *wsi =
815bf215546Sopenharmony_ci      (struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND];
816bf215546Sopenharmony_ci
817bf215546Sopenharmony_ci   struct wsi_wl_display display;
818bf215546Sopenharmony_ci   if (wsi_wl_display_init(wsi, &display, surface->display, true,
819bf215546Sopenharmony_ci                           wsi_device->sw))
820bf215546Sopenharmony_ci      return VK_ERROR_SURFACE_LOST_KHR;
821bf215546Sopenharmony_ci
822bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkSurfaceFormat2KHR, out,
823bf215546Sopenharmony_ci                          pSurfaceFormats, pSurfaceFormatCount);
824bf215546Sopenharmony_ci
825bf215546Sopenharmony_ci   struct wsi_wl_format *disp_fmt;
826bf215546Sopenharmony_ci   u_vector_foreach(disp_fmt, &display.formats) {
827bf215546Sopenharmony_ci      /* Skip formats for which we can't support both alpha & opaque
828bf215546Sopenharmony_ci       * formats.
829bf215546Sopenharmony_ci       */
830bf215546Sopenharmony_ci      if (!(disp_fmt->flags & WSI_WL_FMT_ALPHA) ||
831bf215546Sopenharmony_ci          !(disp_fmt->flags & WSI_WL_FMT_OPAQUE))
832bf215546Sopenharmony_ci         continue;
833bf215546Sopenharmony_ci
834bf215546Sopenharmony_ci      vk_outarray_append_typed(VkSurfaceFormat2KHR, &out, out_fmt) {
835bf215546Sopenharmony_ci         out_fmt->surfaceFormat.format = disp_fmt->vk_format;
836bf215546Sopenharmony_ci         out_fmt->surfaceFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
837bf215546Sopenharmony_ci      }
838bf215546Sopenharmony_ci   }
839bf215546Sopenharmony_ci
840bf215546Sopenharmony_ci   wsi_wl_display_finish(&display);
841bf215546Sopenharmony_ci
842bf215546Sopenharmony_ci   return vk_outarray_status(&out);
843bf215546Sopenharmony_ci}
844bf215546Sopenharmony_ci
845bf215546Sopenharmony_cistatic VkResult
846bf215546Sopenharmony_ciwsi_wl_surface_get_present_modes(VkIcdSurfaceBase *surface,
847bf215546Sopenharmony_ci                                 uint32_t* pPresentModeCount,
848bf215546Sopenharmony_ci                                 VkPresentModeKHR* pPresentModes)
849bf215546Sopenharmony_ci{
850bf215546Sopenharmony_ci   if (pPresentModes == NULL) {
851bf215546Sopenharmony_ci      *pPresentModeCount = ARRAY_SIZE(present_modes);
852bf215546Sopenharmony_ci      return VK_SUCCESS;
853bf215546Sopenharmony_ci   }
854bf215546Sopenharmony_ci
855bf215546Sopenharmony_ci   *pPresentModeCount = MIN2(*pPresentModeCount, ARRAY_SIZE(present_modes));
856bf215546Sopenharmony_ci   typed_memcpy(pPresentModes, present_modes, *pPresentModeCount);
857bf215546Sopenharmony_ci
858bf215546Sopenharmony_ci   if (*pPresentModeCount < ARRAY_SIZE(present_modes))
859bf215546Sopenharmony_ci      return VK_INCOMPLETE;
860bf215546Sopenharmony_ci   else
861bf215546Sopenharmony_ci      return VK_SUCCESS;
862bf215546Sopenharmony_ci}
863bf215546Sopenharmony_ci
864bf215546Sopenharmony_cistatic VkResult
865bf215546Sopenharmony_ciwsi_wl_surface_get_present_rectangles(VkIcdSurfaceBase *surface,
866bf215546Sopenharmony_ci                                      struct wsi_device *wsi_device,
867bf215546Sopenharmony_ci                                      uint32_t* pRectCount,
868bf215546Sopenharmony_ci                                      VkRect2D* pRects)
869bf215546Sopenharmony_ci{
870bf215546Sopenharmony_ci   VK_OUTARRAY_MAKE_TYPED(VkRect2D, out, pRects, pRectCount);
871bf215546Sopenharmony_ci
872bf215546Sopenharmony_ci   vk_outarray_append_typed(VkRect2D, &out, rect) {
873bf215546Sopenharmony_ci      /* We don't know a size so just return the usual "I don't know." */
874bf215546Sopenharmony_ci      *rect = (VkRect2D) {
875bf215546Sopenharmony_ci         .offset = { 0, 0 },
876bf215546Sopenharmony_ci         .extent = { UINT32_MAX, UINT32_MAX },
877bf215546Sopenharmony_ci      };
878bf215546Sopenharmony_ci   }
879bf215546Sopenharmony_ci
880bf215546Sopenharmony_ci   return vk_outarray_status(&out);
881bf215546Sopenharmony_ci}
882bf215546Sopenharmony_ci
883bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL
884bf215546Sopenharmony_ciwsi_CreateWaylandSurfaceKHR(VkInstance _instance,
885bf215546Sopenharmony_ci                            const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
886bf215546Sopenharmony_ci                            const VkAllocationCallbacks *pAllocator,
887bf215546Sopenharmony_ci                            VkSurfaceKHR *pSurface)
888bf215546Sopenharmony_ci{
889bf215546Sopenharmony_ci   VK_FROM_HANDLE(vk_instance, instance, _instance);
890bf215546Sopenharmony_ci   VkIcdSurfaceWayland *surface;
891bf215546Sopenharmony_ci
892bf215546Sopenharmony_ci   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR);
893bf215546Sopenharmony_ci
894bf215546Sopenharmony_ci   surface = vk_alloc2(&instance->alloc, pAllocator, sizeof *surface, 8,
895bf215546Sopenharmony_ci                       VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
896bf215546Sopenharmony_ci   if (surface == NULL)
897bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
898bf215546Sopenharmony_ci
899bf215546Sopenharmony_ci   surface->base.platform = VK_ICD_WSI_PLATFORM_WAYLAND;
900bf215546Sopenharmony_ci   surface->display = pCreateInfo->display;
901bf215546Sopenharmony_ci   surface->surface = pCreateInfo->surface;
902bf215546Sopenharmony_ci
903bf215546Sopenharmony_ci   *pSurface = VkIcdSurfaceBase_to_handle(&surface->base);
904bf215546Sopenharmony_ci
905bf215546Sopenharmony_ci   return VK_SUCCESS;
906bf215546Sopenharmony_ci}
907bf215546Sopenharmony_ci
908bf215546Sopenharmony_cistruct wsi_wl_image {
909bf215546Sopenharmony_ci   struct wsi_image                             base;
910bf215546Sopenharmony_ci   struct wl_buffer *                           buffer;
911bf215546Sopenharmony_ci   bool                                         busy;
912bf215546Sopenharmony_ci   int                                          shm_fd;
913bf215546Sopenharmony_ci   void *                                       shm_ptr;
914bf215546Sopenharmony_ci   unsigned                                     shm_size;
915bf215546Sopenharmony_ci};
916bf215546Sopenharmony_ci
917bf215546Sopenharmony_cienum wsi_wl_buffer_type {
918bf215546Sopenharmony_ci   WSI_WL_BUFFER_NATIVE,
919bf215546Sopenharmony_ci   WSI_WL_BUFFER_GPU_SHM,
920bf215546Sopenharmony_ci   WSI_WL_BUFFER_SHM_MEMCPY,
921bf215546Sopenharmony_ci};
922bf215546Sopenharmony_ci
923bf215546Sopenharmony_cistruct wsi_wl_swapchain {
924bf215546Sopenharmony_ci   struct wsi_swapchain                         base;
925bf215546Sopenharmony_ci
926bf215546Sopenharmony_ci   struct wsi_wl_display                        *display;
927bf215546Sopenharmony_ci
928bf215546Sopenharmony_ci   struct wl_surface *                          surface;
929bf215546Sopenharmony_ci
930bf215546Sopenharmony_ci   struct wl_callback *                         frame;
931bf215546Sopenharmony_ci
932bf215546Sopenharmony_ci   VkExtent2D                                   extent;
933bf215546Sopenharmony_ci   VkFormat                                     vk_format;
934bf215546Sopenharmony_ci   enum wsi_wl_buffer_type                      buffer_type;
935bf215546Sopenharmony_ci   uint32_t                                     drm_format;
936bf215546Sopenharmony_ci   enum wl_shm_format                           shm_format;
937bf215546Sopenharmony_ci
938bf215546Sopenharmony_ci   uint32_t                                     num_drm_modifiers;
939bf215546Sopenharmony_ci   const uint64_t *                             drm_modifiers;
940bf215546Sopenharmony_ci
941bf215546Sopenharmony_ci   VkPresentModeKHR                             present_mode;
942bf215546Sopenharmony_ci   bool                                         fifo_ready;
943bf215546Sopenharmony_ci
944bf215546Sopenharmony_ci   struct wsi_wl_image                          images[0];
945bf215546Sopenharmony_ci};
946bf215546Sopenharmony_ciVK_DEFINE_NONDISP_HANDLE_CASTS(wsi_wl_swapchain, base.base, VkSwapchainKHR,
947bf215546Sopenharmony_ci                               VK_OBJECT_TYPE_SWAPCHAIN_KHR)
948bf215546Sopenharmony_ci
949bf215546Sopenharmony_cistatic struct wsi_image *
950bf215546Sopenharmony_ciwsi_wl_swapchain_get_wsi_image(struct wsi_swapchain *wsi_chain,
951bf215546Sopenharmony_ci                               uint32_t image_index)
952bf215546Sopenharmony_ci{
953bf215546Sopenharmony_ci   struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain;
954bf215546Sopenharmony_ci   return &chain->images[image_index].base;
955bf215546Sopenharmony_ci}
956bf215546Sopenharmony_ci
957bf215546Sopenharmony_cistatic VkResult
958bf215546Sopenharmony_ciwsi_wl_swapchain_acquire_next_image(struct wsi_swapchain *wsi_chain,
959bf215546Sopenharmony_ci                                    const VkAcquireNextImageInfoKHR *info,
960bf215546Sopenharmony_ci                                    uint32_t *image_index)
961bf215546Sopenharmony_ci{
962bf215546Sopenharmony_ci   struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain;
963bf215546Sopenharmony_ci   struct timespec start_time, end_time;
964bf215546Sopenharmony_ci   struct timespec rel_timeout;
965bf215546Sopenharmony_ci   int wl_fd = wl_display_get_fd(chain->display->wl_display);
966bf215546Sopenharmony_ci
967bf215546Sopenharmony_ci   timespec_from_nsec(&rel_timeout, info->timeout);
968bf215546Sopenharmony_ci
969bf215546Sopenharmony_ci   clock_gettime(CLOCK_MONOTONIC, &start_time);
970bf215546Sopenharmony_ci   timespec_add(&end_time, &rel_timeout, &start_time);
971bf215546Sopenharmony_ci
972bf215546Sopenharmony_ci   while (1) {
973bf215546Sopenharmony_ci      /* Try to dispatch potential events. */
974bf215546Sopenharmony_ci      int ret = wl_display_dispatch_queue_pending(chain->display->wl_display,
975bf215546Sopenharmony_ci                                                  chain->display->queue);
976bf215546Sopenharmony_ci      if (ret < 0)
977bf215546Sopenharmony_ci         return VK_ERROR_OUT_OF_DATE_KHR;
978bf215546Sopenharmony_ci
979bf215546Sopenharmony_ci      /* Try to find a free image. */
980bf215546Sopenharmony_ci      for (uint32_t i = 0; i < chain->base.image_count; i++) {
981bf215546Sopenharmony_ci         if (!chain->images[i].busy) {
982bf215546Sopenharmony_ci            /* We found a non-busy image */
983bf215546Sopenharmony_ci            *image_index = i;
984bf215546Sopenharmony_ci            chain->images[i].busy = true;
985bf215546Sopenharmony_ci            return VK_SUCCESS;
986bf215546Sopenharmony_ci         }
987bf215546Sopenharmony_ci      }
988bf215546Sopenharmony_ci
989bf215546Sopenharmony_ci      /* Check for timeout. */
990bf215546Sopenharmony_ci      struct timespec current_time;
991bf215546Sopenharmony_ci      clock_gettime(CLOCK_MONOTONIC, &current_time);
992bf215546Sopenharmony_ci      if (timespec_after(&current_time, &end_time))
993bf215546Sopenharmony_ci         return VK_NOT_READY;
994bf215546Sopenharmony_ci
995bf215546Sopenharmony_ci      /* Try to read events from the server. */
996bf215546Sopenharmony_ci      ret = wl_display_prepare_read_queue(chain->display->wl_display,
997bf215546Sopenharmony_ci                                          chain->display->queue);
998bf215546Sopenharmony_ci      if (ret < 0) {
999bf215546Sopenharmony_ci         /* Another thread might have read events for our queue already. Go
1000bf215546Sopenharmony_ci          * back to dispatch them.
1001bf215546Sopenharmony_ci          */
1002bf215546Sopenharmony_ci         if (errno == EAGAIN)
1003bf215546Sopenharmony_ci            continue;
1004bf215546Sopenharmony_ci         return VK_ERROR_OUT_OF_DATE_KHR;
1005bf215546Sopenharmony_ci      }
1006bf215546Sopenharmony_ci
1007bf215546Sopenharmony_ci      struct pollfd pollfd = {
1008bf215546Sopenharmony_ci         .fd = wl_fd,
1009bf215546Sopenharmony_ci         .events = POLLIN
1010bf215546Sopenharmony_ci      };
1011bf215546Sopenharmony_ci      timespec_sub(&rel_timeout, &end_time, &current_time);
1012bf215546Sopenharmony_ci      ret = ppoll(&pollfd, 1, &rel_timeout, NULL);
1013bf215546Sopenharmony_ci      if (ret <= 0) {
1014bf215546Sopenharmony_ci         int lerrno = errno;
1015bf215546Sopenharmony_ci         wl_display_cancel_read(chain->display->wl_display);
1016bf215546Sopenharmony_ci         if (ret < 0) {
1017bf215546Sopenharmony_ci            /* If ppoll() was interrupted, try again. */
1018bf215546Sopenharmony_ci            if (lerrno == EINTR || lerrno == EAGAIN)
1019bf215546Sopenharmony_ci               continue;
1020bf215546Sopenharmony_ci            return VK_ERROR_OUT_OF_DATE_KHR;
1021bf215546Sopenharmony_ci         }
1022bf215546Sopenharmony_ci         assert(ret == 0);
1023bf215546Sopenharmony_ci         continue;
1024bf215546Sopenharmony_ci      }
1025bf215546Sopenharmony_ci
1026bf215546Sopenharmony_ci      ret = wl_display_read_events(chain->display->wl_display);
1027bf215546Sopenharmony_ci      if (ret < 0)
1028bf215546Sopenharmony_ci         return VK_ERROR_OUT_OF_DATE_KHR;
1029bf215546Sopenharmony_ci   }
1030bf215546Sopenharmony_ci}
1031bf215546Sopenharmony_ci
1032bf215546Sopenharmony_cistatic void
1033bf215546Sopenharmony_ciframe_handle_done(void *data, struct wl_callback *callback, uint32_t serial)
1034bf215546Sopenharmony_ci{
1035bf215546Sopenharmony_ci   struct wsi_wl_swapchain *chain = data;
1036bf215546Sopenharmony_ci
1037bf215546Sopenharmony_ci   chain->frame = NULL;
1038bf215546Sopenharmony_ci   chain->fifo_ready = true;
1039bf215546Sopenharmony_ci
1040bf215546Sopenharmony_ci   wl_callback_destroy(callback);
1041bf215546Sopenharmony_ci}
1042bf215546Sopenharmony_ci
1043bf215546Sopenharmony_cistatic const struct wl_callback_listener frame_listener = {
1044bf215546Sopenharmony_ci   frame_handle_done,
1045bf215546Sopenharmony_ci};
1046bf215546Sopenharmony_ci
1047bf215546Sopenharmony_cistatic VkResult
1048bf215546Sopenharmony_ciwsi_wl_swapchain_queue_present(struct wsi_swapchain *wsi_chain,
1049bf215546Sopenharmony_ci                               uint32_t image_index,
1050bf215546Sopenharmony_ci                               const VkPresentRegionKHR *damage)
1051bf215546Sopenharmony_ci{
1052bf215546Sopenharmony_ci   struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain;
1053bf215546Sopenharmony_ci
1054bf215546Sopenharmony_ci   if (chain->buffer_type == WSI_WL_BUFFER_SHM_MEMCPY) {
1055bf215546Sopenharmony_ci      struct wsi_wl_image *image = &chain->images[image_index];
1056bf215546Sopenharmony_ci      memcpy(image->shm_ptr, image->base.cpu_map,
1057bf215546Sopenharmony_ci             image->base.row_pitches[0] * chain->extent.height);
1058bf215546Sopenharmony_ci   }
1059bf215546Sopenharmony_ci   if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) {
1060bf215546Sopenharmony_ci      while (!chain->fifo_ready) {
1061bf215546Sopenharmony_ci         int ret = wl_display_dispatch_queue(chain->display->wl_display,
1062bf215546Sopenharmony_ci                                             chain->display->queue);
1063bf215546Sopenharmony_ci         if (ret < 0)
1064bf215546Sopenharmony_ci            return VK_ERROR_OUT_OF_DATE_KHR;
1065bf215546Sopenharmony_ci      }
1066bf215546Sopenharmony_ci   }
1067bf215546Sopenharmony_ci
1068bf215546Sopenharmony_ci   assert(image_index < chain->base.image_count);
1069bf215546Sopenharmony_ci   wl_surface_attach(chain->surface, chain->images[image_index].buffer, 0, 0);
1070bf215546Sopenharmony_ci
1071bf215546Sopenharmony_ci   if (wl_surface_get_version(chain->surface) >= 4 && damage &&
1072bf215546Sopenharmony_ci       damage->pRectangles && damage->rectangleCount > 0) {
1073bf215546Sopenharmony_ci      for (unsigned i = 0; i < damage->rectangleCount; i++) {
1074bf215546Sopenharmony_ci         const VkRectLayerKHR *rect = &damage->pRectangles[i];
1075bf215546Sopenharmony_ci         assert(rect->layer == 0);
1076bf215546Sopenharmony_ci         wl_surface_damage_buffer(chain->surface,
1077bf215546Sopenharmony_ci                                  rect->offset.x, rect->offset.y,
1078bf215546Sopenharmony_ci                                  rect->extent.width, rect->extent.height);
1079bf215546Sopenharmony_ci      }
1080bf215546Sopenharmony_ci   } else {
1081bf215546Sopenharmony_ci      wl_surface_damage(chain->surface, 0, 0, INT32_MAX, INT32_MAX);
1082bf215546Sopenharmony_ci   }
1083bf215546Sopenharmony_ci
1084bf215546Sopenharmony_ci   if (chain->base.present_mode == VK_PRESENT_MODE_FIFO_KHR) {
1085bf215546Sopenharmony_ci      chain->frame = wl_surface_frame(chain->surface);
1086bf215546Sopenharmony_ci      wl_callback_add_listener(chain->frame, &frame_listener, chain);
1087bf215546Sopenharmony_ci      chain->fifo_ready = false;
1088bf215546Sopenharmony_ci   }
1089bf215546Sopenharmony_ci
1090bf215546Sopenharmony_ci   chain->images[image_index].busy = true;
1091bf215546Sopenharmony_ci   wl_surface_commit(chain->surface);
1092bf215546Sopenharmony_ci   wl_display_flush(chain->display->wl_display);
1093bf215546Sopenharmony_ci
1094bf215546Sopenharmony_ci   return VK_SUCCESS;
1095bf215546Sopenharmony_ci}
1096bf215546Sopenharmony_ci
1097bf215546Sopenharmony_cistatic void
1098bf215546Sopenharmony_cibuffer_handle_release(void *data, struct wl_buffer *buffer)
1099bf215546Sopenharmony_ci{
1100bf215546Sopenharmony_ci   struct wsi_wl_image *image = data;
1101bf215546Sopenharmony_ci
1102bf215546Sopenharmony_ci   assert(image->buffer == buffer);
1103bf215546Sopenharmony_ci
1104bf215546Sopenharmony_ci   image->busy = false;
1105bf215546Sopenharmony_ci}
1106bf215546Sopenharmony_ci
1107bf215546Sopenharmony_cistatic const struct wl_buffer_listener buffer_listener = {
1108bf215546Sopenharmony_ci   buffer_handle_release,
1109bf215546Sopenharmony_ci};
1110bf215546Sopenharmony_ci
1111bf215546Sopenharmony_cistatic uint8_t *
1112bf215546Sopenharmony_ciwsi_wl_alloc_image_shm(struct wsi_image *imagew, unsigned size)
1113bf215546Sopenharmony_ci{
1114bf215546Sopenharmony_ci   struct wsi_wl_image *image = (struct wsi_wl_image *)imagew;
1115bf215546Sopenharmony_ci
1116bf215546Sopenharmony_ci   /* Create a shareable buffer */
1117bf215546Sopenharmony_ci   int fd = os_create_anonymous_file(size, NULL);
1118bf215546Sopenharmony_ci   if (fd < 0)
1119bf215546Sopenharmony_ci      return NULL;
1120bf215546Sopenharmony_ci
1121bf215546Sopenharmony_ci   void *ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1122bf215546Sopenharmony_ci   if (ptr == MAP_FAILED) {
1123bf215546Sopenharmony_ci      close(fd);
1124bf215546Sopenharmony_ci      return NULL;
1125bf215546Sopenharmony_ci   }
1126bf215546Sopenharmony_ci
1127bf215546Sopenharmony_ci   image->shm_fd = fd;
1128bf215546Sopenharmony_ci   image->shm_ptr = ptr;
1129bf215546Sopenharmony_ci   image->shm_size = size;
1130bf215546Sopenharmony_ci
1131bf215546Sopenharmony_ci   return ptr;
1132bf215546Sopenharmony_ci}
1133bf215546Sopenharmony_ci
1134bf215546Sopenharmony_cistatic VkResult
1135bf215546Sopenharmony_ciwsi_wl_image_init(struct wsi_wl_swapchain *chain,
1136bf215546Sopenharmony_ci                  struct wsi_wl_image *image,
1137bf215546Sopenharmony_ci                  const VkSwapchainCreateInfoKHR *pCreateInfo,
1138bf215546Sopenharmony_ci                  const VkAllocationCallbacks* pAllocator)
1139bf215546Sopenharmony_ci{
1140bf215546Sopenharmony_ci   struct wsi_wl_display *display = chain->display;
1141bf215546Sopenharmony_ci   VkResult result;
1142bf215546Sopenharmony_ci
1143bf215546Sopenharmony_ci   result = wsi_create_image(&chain->base, &chain->base.image_info,
1144bf215546Sopenharmony_ci                             &image->base);
1145bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1146bf215546Sopenharmony_ci      return result;
1147bf215546Sopenharmony_ci
1148bf215546Sopenharmony_ci   switch (chain->buffer_type) {
1149bf215546Sopenharmony_ci   case WSI_WL_BUFFER_GPU_SHM:
1150bf215546Sopenharmony_ci   case WSI_WL_BUFFER_SHM_MEMCPY: {
1151bf215546Sopenharmony_ci      if (chain->buffer_type == WSI_WL_BUFFER_SHM_MEMCPY) {
1152bf215546Sopenharmony_ci         wsi_wl_alloc_image_shm(&image->base, image->base.row_pitches[0] *
1153bf215546Sopenharmony_ci                                              chain->extent.height);
1154bf215546Sopenharmony_ci      }
1155bf215546Sopenharmony_ci      assert(image->shm_ptr != NULL);
1156bf215546Sopenharmony_ci
1157bf215546Sopenharmony_ci      /* Share it in a wl_buffer */
1158bf215546Sopenharmony_ci      struct wl_shm_pool *pool = wl_shm_create_pool(display->wl_shm,
1159bf215546Sopenharmony_ci                                                    image->shm_fd,
1160bf215546Sopenharmony_ci                                                    image->shm_size);
1161bf215546Sopenharmony_ci      wl_proxy_set_queue((struct wl_proxy *)pool, display->queue);
1162bf215546Sopenharmony_ci      image->buffer = wl_shm_pool_create_buffer(pool, 0, chain->extent.width,
1163bf215546Sopenharmony_ci                                                chain->extent.height,
1164bf215546Sopenharmony_ci                                                image->base.row_pitches[0],
1165bf215546Sopenharmony_ci                                                chain->shm_format);
1166bf215546Sopenharmony_ci      wl_shm_pool_destroy(pool);
1167bf215546Sopenharmony_ci      break;
1168bf215546Sopenharmony_ci   }
1169bf215546Sopenharmony_ci
1170bf215546Sopenharmony_ci   case WSI_WL_BUFFER_NATIVE: {
1171bf215546Sopenharmony_ci      assert(display->wl_dmabuf);
1172bf215546Sopenharmony_ci
1173bf215546Sopenharmony_ci      struct zwp_linux_buffer_params_v1 *params =
1174bf215546Sopenharmony_ci         zwp_linux_dmabuf_v1_create_params(display->wl_dmabuf);
1175bf215546Sopenharmony_ci      if (!params)
1176bf215546Sopenharmony_ci         goto fail_image;
1177bf215546Sopenharmony_ci
1178bf215546Sopenharmony_ci      for (int i = 0; i < image->base.num_planes; i++) {
1179bf215546Sopenharmony_ci         zwp_linux_buffer_params_v1_add(params,
1180bf215546Sopenharmony_ci                                        image->base.dma_buf_fd,
1181bf215546Sopenharmony_ci                                        i,
1182bf215546Sopenharmony_ci                                        image->base.offsets[i],
1183bf215546Sopenharmony_ci                                        image->base.row_pitches[i],
1184bf215546Sopenharmony_ci                                        image->base.drm_modifier >> 32,
1185bf215546Sopenharmony_ci                                        image->base.drm_modifier & 0xffffffff);
1186bf215546Sopenharmony_ci      }
1187bf215546Sopenharmony_ci
1188bf215546Sopenharmony_ci      image->buffer =
1189bf215546Sopenharmony_ci         zwp_linux_buffer_params_v1_create_immed(params,
1190bf215546Sopenharmony_ci                                                 chain->extent.width,
1191bf215546Sopenharmony_ci                                                 chain->extent.height,
1192bf215546Sopenharmony_ci                                                 chain->drm_format,
1193bf215546Sopenharmony_ci                                                 0);
1194bf215546Sopenharmony_ci      zwp_linux_buffer_params_v1_destroy(params);
1195bf215546Sopenharmony_ci      break;
1196bf215546Sopenharmony_ci   }
1197bf215546Sopenharmony_ci
1198bf215546Sopenharmony_ci   default:
1199bf215546Sopenharmony_ci      unreachable("Invalid buffer type");
1200bf215546Sopenharmony_ci   }
1201bf215546Sopenharmony_ci
1202bf215546Sopenharmony_ci   if (!image->buffer)
1203bf215546Sopenharmony_ci      goto fail_image;
1204bf215546Sopenharmony_ci
1205bf215546Sopenharmony_ci   wl_buffer_add_listener(image->buffer, &buffer_listener, image);
1206bf215546Sopenharmony_ci
1207bf215546Sopenharmony_ci   return VK_SUCCESS;
1208bf215546Sopenharmony_ci
1209bf215546Sopenharmony_cifail_image:
1210bf215546Sopenharmony_ci   wsi_destroy_image(&chain->base, &image->base);
1211bf215546Sopenharmony_ci
1212bf215546Sopenharmony_ci   return VK_ERROR_OUT_OF_HOST_MEMORY;
1213bf215546Sopenharmony_ci}
1214bf215546Sopenharmony_ci
1215bf215546Sopenharmony_cistatic void
1216bf215546Sopenharmony_ciwsi_wl_swapchain_images_free(struct wsi_wl_swapchain *chain)
1217bf215546Sopenharmony_ci{
1218bf215546Sopenharmony_ci   for (uint32_t i = 0; i < chain->base.image_count; i++) {
1219bf215546Sopenharmony_ci      if (chain->images[i].buffer) {
1220bf215546Sopenharmony_ci         wl_buffer_destroy(chain->images[i].buffer);
1221bf215546Sopenharmony_ci         wsi_destroy_image(&chain->base, &chain->images[i].base);
1222bf215546Sopenharmony_ci         if (chain->images[i].shm_size) {
1223bf215546Sopenharmony_ci            close(chain->images[i].shm_fd);
1224bf215546Sopenharmony_ci            munmap(chain->images[i].shm_ptr, chain->images[i].shm_size);
1225bf215546Sopenharmony_ci         }
1226bf215546Sopenharmony_ci      }
1227bf215546Sopenharmony_ci   }
1228bf215546Sopenharmony_ci   wsi_destroy_image_info(&chain->base, &chain->base.image_info);
1229bf215546Sopenharmony_ci}
1230bf215546Sopenharmony_ci
1231bf215546Sopenharmony_cistatic void
1232bf215546Sopenharmony_ciwsi_wl_swapchain_chain_free(struct wsi_wl_swapchain *chain,
1233bf215546Sopenharmony_ci                            const VkAllocationCallbacks *pAllocator)
1234bf215546Sopenharmony_ci{
1235bf215546Sopenharmony_ci   if (chain->frame)
1236bf215546Sopenharmony_ci      wl_callback_destroy(chain->frame);
1237bf215546Sopenharmony_ci   if (chain->surface)
1238bf215546Sopenharmony_ci      wl_proxy_wrapper_destroy(chain->surface);
1239bf215546Sopenharmony_ci
1240bf215546Sopenharmony_ci   if (chain->display)
1241bf215546Sopenharmony_ci      wsi_wl_display_unref(chain->display);
1242bf215546Sopenharmony_ci
1243bf215546Sopenharmony_ci   wsi_swapchain_finish(&chain->base);
1244bf215546Sopenharmony_ci
1245bf215546Sopenharmony_ci   vk_free(pAllocator, chain);
1246bf215546Sopenharmony_ci}
1247bf215546Sopenharmony_ci
1248bf215546Sopenharmony_cistatic VkResult
1249bf215546Sopenharmony_ciwsi_wl_swapchain_destroy(struct wsi_swapchain *wsi_chain,
1250bf215546Sopenharmony_ci                         const VkAllocationCallbacks *pAllocator)
1251bf215546Sopenharmony_ci{
1252bf215546Sopenharmony_ci   struct wsi_wl_swapchain *chain = (struct wsi_wl_swapchain *)wsi_chain;
1253bf215546Sopenharmony_ci
1254bf215546Sopenharmony_ci   wsi_wl_swapchain_images_free(chain);
1255bf215546Sopenharmony_ci   wsi_wl_swapchain_chain_free(chain, pAllocator);
1256bf215546Sopenharmony_ci
1257bf215546Sopenharmony_ci   return VK_SUCCESS;
1258bf215546Sopenharmony_ci}
1259bf215546Sopenharmony_ci
1260bf215546Sopenharmony_cistatic VkResult
1261bf215546Sopenharmony_ciwsi_wl_surface_create_swapchain(VkIcdSurfaceBase *icd_surface,
1262bf215546Sopenharmony_ci                                VkDevice device,
1263bf215546Sopenharmony_ci                                struct wsi_device *wsi_device,
1264bf215546Sopenharmony_ci                                const VkSwapchainCreateInfoKHR* pCreateInfo,
1265bf215546Sopenharmony_ci                                const VkAllocationCallbacks* pAllocator,
1266bf215546Sopenharmony_ci                                struct wsi_swapchain **swapchain_out)
1267bf215546Sopenharmony_ci{
1268bf215546Sopenharmony_ci   VkIcdSurfaceWayland *surface = (VkIcdSurfaceWayland *)icd_surface;
1269bf215546Sopenharmony_ci   struct wsi_wayland *wsi =
1270bf215546Sopenharmony_ci      (struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND];
1271bf215546Sopenharmony_ci   struct wsi_wl_swapchain *chain;
1272bf215546Sopenharmony_ci   VkResult result;
1273bf215546Sopenharmony_ci
1274bf215546Sopenharmony_ci   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR);
1275bf215546Sopenharmony_ci
1276bf215546Sopenharmony_ci   int num_images = pCreateInfo->minImageCount;
1277bf215546Sopenharmony_ci
1278bf215546Sopenharmony_ci   size_t size = sizeof(*chain) + num_images * sizeof(chain->images[0]);
1279bf215546Sopenharmony_ci   chain = vk_zalloc(pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
1280bf215546Sopenharmony_ci   if (chain == NULL)
1281bf215546Sopenharmony_ci      return VK_ERROR_OUT_OF_HOST_MEMORY;
1282bf215546Sopenharmony_ci
1283bf215546Sopenharmony_ci   result = wsi_swapchain_init(wsi_device, &chain->base, device,
1284bf215546Sopenharmony_ci                               pCreateInfo, pAllocator, false);
1285bf215546Sopenharmony_ci   if (result != VK_SUCCESS) {
1286bf215546Sopenharmony_ci      vk_free(pAllocator, chain);
1287bf215546Sopenharmony_ci      return result;
1288bf215546Sopenharmony_ci   }
1289bf215546Sopenharmony_ci
1290bf215546Sopenharmony_ci   bool alpha = pCreateInfo->compositeAlpha ==
1291bf215546Sopenharmony_ci                      VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR;
1292bf215546Sopenharmony_ci
1293bf215546Sopenharmony_ci   chain->base.destroy = wsi_wl_swapchain_destroy;
1294bf215546Sopenharmony_ci   chain->base.get_wsi_image = wsi_wl_swapchain_get_wsi_image;
1295bf215546Sopenharmony_ci   chain->base.acquire_next_image = wsi_wl_swapchain_acquire_next_image;
1296bf215546Sopenharmony_ci   chain->base.queue_present = wsi_wl_swapchain_queue_present;
1297bf215546Sopenharmony_ci   chain->base.present_mode = wsi_swapchain_get_present_mode(wsi_device, pCreateInfo);
1298bf215546Sopenharmony_ci   chain->base.image_count = num_images;
1299bf215546Sopenharmony_ci   chain->extent = pCreateInfo->imageExtent;
1300bf215546Sopenharmony_ci   chain->vk_format = pCreateInfo->imageFormat;
1301bf215546Sopenharmony_ci   if (wsi_device->sw) {
1302bf215546Sopenharmony_ci      chain->buffer_type = (chain->base.wsi->has_import_memory_host &&
1303bf215546Sopenharmony_ci                            !(WSI_DEBUG & WSI_DEBUG_NOSHM)) ?
1304bf215546Sopenharmony_ci                           WSI_WL_BUFFER_GPU_SHM : WSI_WL_BUFFER_SHM_MEMCPY;
1305bf215546Sopenharmony_ci      chain->shm_format = wl_shm_format_for_vk_format(chain->vk_format, alpha);
1306bf215546Sopenharmony_ci   } else {
1307bf215546Sopenharmony_ci      chain->buffer_type = WSI_WL_BUFFER_NATIVE;
1308bf215546Sopenharmony_ci      chain->drm_format = wl_drm_format_for_vk_format(chain->vk_format, alpha);
1309bf215546Sopenharmony_ci   }
1310bf215546Sopenharmony_ci
1311bf215546Sopenharmony_ci   if (pCreateInfo->oldSwapchain) {
1312bf215546Sopenharmony_ci      /* If we have an oldSwapchain parameter, copy the display struct over
1313bf215546Sopenharmony_ci       * from the old one so we don't have to fully re-initialize it.
1314bf215546Sopenharmony_ci       */
1315bf215546Sopenharmony_ci      VK_FROM_HANDLE(wsi_wl_swapchain, old_chain, pCreateInfo->oldSwapchain);
1316bf215546Sopenharmony_ci      chain->display = wsi_wl_display_ref(old_chain->display);
1317bf215546Sopenharmony_ci   } else {
1318bf215546Sopenharmony_ci      chain->display = NULL;
1319bf215546Sopenharmony_ci      result = wsi_wl_display_create(wsi, surface->display,
1320bf215546Sopenharmony_ci                                     wsi_device->sw, &chain->display);
1321bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1322bf215546Sopenharmony_ci         goto fail;
1323bf215546Sopenharmony_ci   }
1324bf215546Sopenharmony_ci
1325bf215546Sopenharmony_ci   chain->surface = wl_proxy_create_wrapper(surface->surface);
1326bf215546Sopenharmony_ci   if (!chain->surface) {
1327bf215546Sopenharmony_ci      result = VK_ERROR_OUT_OF_HOST_MEMORY;
1328bf215546Sopenharmony_ci      goto fail;
1329bf215546Sopenharmony_ci   }
1330bf215546Sopenharmony_ci   wl_proxy_set_queue((struct wl_proxy *) chain->surface,
1331bf215546Sopenharmony_ci                      chain->display->queue);
1332bf215546Sopenharmony_ci
1333bf215546Sopenharmony_ci   chain->num_drm_modifiers = 0;
1334bf215546Sopenharmony_ci   chain->drm_modifiers = 0;
1335bf215546Sopenharmony_ci
1336bf215546Sopenharmony_ci   /* Use explicit DRM format modifiers when both the server and the driver
1337bf215546Sopenharmony_ci    * support them.
1338bf215546Sopenharmony_ci    */
1339bf215546Sopenharmony_ci   if (chain->display->wl_dmabuf && chain->base.wsi->supports_modifiers) {
1340bf215546Sopenharmony_ci      struct wsi_wl_format *f = find_format(&chain->display->formats, chain->vk_format);
1341bf215546Sopenharmony_ci      if (f) {
1342bf215546Sopenharmony_ci         chain->drm_modifiers = u_vector_tail(&f->modifiers);
1343bf215546Sopenharmony_ci         chain->num_drm_modifiers = u_vector_length(&f->modifiers);
1344bf215546Sopenharmony_ci      }
1345bf215546Sopenharmony_ci   }
1346bf215546Sopenharmony_ci
1347bf215546Sopenharmony_ci   chain->fifo_ready = true;
1348bf215546Sopenharmony_ci
1349bf215546Sopenharmony_ci   switch (chain->buffer_type) {
1350bf215546Sopenharmony_ci   case WSI_WL_BUFFER_NATIVE:
1351bf215546Sopenharmony_ci      result = wsi_configure_native_image(&chain->base, pCreateInfo,
1352bf215546Sopenharmony_ci                                          chain->num_drm_modifiers > 0 ? 1 : 0,
1353bf215546Sopenharmony_ci                                          &chain->num_drm_modifiers,
1354bf215546Sopenharmony_ci                                          &chain->drm_modifiers,
1355bf215546Sopenharmony_ci                                          &chain->base.image_info);
1356bf215546Sopenharmony_ci      break;
1357bf215546Sopenharmony_ci
1358bf215546Sopenharmony_ci   case WSI_WL_BUFFER_GPU_SHM:
1359bf215546Sopenharmony_ci      result = wsi_configure_cpu_image(&chain->base, pCreateInfo,
1360bf215546Sopenharmony_ci                                       wsi_wl_alloc_image_shm,
1361bf215546Sopenharmony_ci                                       &chain->base.image_info);
1362bf215546Sopenharmony_ci      break;
1363bf215546Sopenharmony_ci
1364bf215546Sopenharmony_ci   case WSI_WL_BUFFER_SHM_MEMCPY:
1365bf215546Sopenharmony_ci      result = wsi_configure_cpu_image(&chain->base, pCreateInfo,
1366bf215546Sopenharmony_ci                                       NULL, &chain->base.image_info);
1367bf215546Sopenharmony_ci      break;
1368bf215546Sopenharmony_ci
1369bf215546Sopenharmony_ci   default:
1370bf215546Sopenharmony_ci      unreachable("Invalid buffer type");
1371bf215546Sopenharmony_ci   }
1372bf215546Sopenharmony_ci   if (result != VK_SUCCESS)
1373bf215546Sopenharmony_ci      goto fail;
1374bf215546Sopenharmony_ci
1375bf215546Sopenharmony_ci   for (uint32_t i = 0; i < chain->base.image_count; i++) {
1376bf215546Sopenharmony_ci      result = wsi_wl_image_init(chain, &chain->images[i],
1377bf215546Sopenharmony_ci                                 pCreateInfo, pAllocator);
1378bf215546Sopenharmony_ci      if (result != VK_SUCCESS)
1379bf215546Sopenharmony_ci         goto fail_image_init;
1380bf215546Sopenharmony_ci      chain->images[i].busy = false;
1381bf215546Sopenharmony_ci   }
1382bf215546Sopenharmony_ci
1383bf215546Sopenharmony_ci   *swapchain_out = &chain->base;
1384bf215546Sopenharmony_ci
1385bf215546Sopenharmony_ci   return VK_SUCCESS;
1386bf215546Sopenharmony_ci
1387bf215546Sopenharmony_cifail_image_init:
1388bf215546Sopenharmony_ci   wsi_wl_swapchain_images_free(chain);
1389bf215546Sopenharmony_ci
1390bf215546Sopenharmony_cifail:
1391bf215546Sopenharmony_ci   wsi_wl_swapchain_chain_free(chain, pAllocator);
1392bf215546Sopenharmony_ci
1393bf215546Sopenharmony_ci   return result;
1394bf215546Sopenharmony_ci}
1395bf215546Sopenharmony_ci
1396bf215546Sopenharmony_ciVkResult
1397bf215546Sopenharmony_ciwsi_wl_init_wsi(struct wsi_device *wsi_device,
1398bf215546Sopenharmony_ci                const VkAllocationCallbacks *alloc,
1399bf215546Sopenharmony_ci                VkPhysicalDevice physical_device)
1400bf215546Sopenharmony_ci{
1401bf215546Sopenharmony_ci   struct wsi_wayland *wsi;
1402bf215546Sopenharmony_ci   VkResult result;
1403bf215546Sopenharmony_ci
1404bf215546Sopenharmony_ci   wsi = vk_alloc(alloc, sizeof(*wsi), 8,
1405bf215546Sopenharmony_ci                   VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
1406bf215546Sopenharmony_ci   if (!wsi) {
1407bf215546Sopenharmony_ci      result = VK_ERROR_OUT_OF_HOST_MEMORY;
1408bf215546Sopenharmony_ci      goto fail;
1409bf215546Sopenharmony_ci   }
1410bf215546Sopenharmony_ci
1411bf215546Sopenharmony_ci   wsi->physical_device = physical_device;
1412bf215546Sopenharmony_ci   wsi->alloc = alloc;
1413bf215546Sopenharmony_ci   wsi->wsi = wsi_device;
1414bf215546Sopenharmony_ci
1415bf215546Sopenharmony_ci   wsi->base.get_support = wsi_wl_surface_get_support;
1416bf215546Sopenharmony_ci   wsi->base.get_capabilities2 = wsi_wl_surface_get_capabilities2;
1417bf215546Sopenharmony_ci   wsi->base.get_formats = wsi_wl_surface_get_formats;
1418bf215546Sopenharmony_ci   wsi->base.get_formats2 = wsi_wl_surface_get_formats2;
1419bf215546Sopenharmony_ci   wsi->base.get_present_modes = wsi_wl_surface_get_present_modes;
1420bf215546Sopenharmony_ci   wsi->base.get_present_rectangles = wsi_wl_surface_get_present_rectangles;
1421bf215546Sopenharmony_ci   wsi->base.create_swapchain = wsi_wl_surface_create_swapchain;
1422bf215546Sopenharmony_ci
1423bf215546Sopenharmony_ci   wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND] = &wsi->base;
1424bf215546Sopenharmony_ci
1425bf215546Sopenharmony_ci   return VK_SUCCESS;
1426bf215546Sopenharmony_ci
1427bf215546Sopenharmony_cifail:
1428bf215546Sopenharmony_ci   wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND] = NULL;
1429bf215546Sopenharmony_ci
1430bf215546Sopenharmony_ci   return result;
1431bf215546Sopenharmony_ci}
1432bf215546Sopenharmony_ci
1433bf215546Sopenharmony_civoid
1434bf215546Sopenharmony_ciwsi_wl_finish_wsi(struct wsi_device *wsi_device,
1435bf215546Sopenharmony_ci                  const VkAllocationCallbacks *alloc)
1436bf215546Sopenharmony_ci{
1437bf215546Sopenharmony_ci   struct wsi_wayland *wsi =
1438bf215546Sopenharmony_ci      (struct wsi_wayland *)wsi_device->wsi[VK_ICD_WSI_PLATFORM_WAYLAND];
1439bf215546Sopenharmony_ci   if (!wsi)
1440bf215546Sopenharmony_ci      return;
1441bf215546Sopenharmony_ci
1442bf215546Sopenharmony_ci   vk_free(alloc, wsi);
1443bf215546Sopenharmony_ci}
1444