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