1/*
2 * Copyright © 2017 Keith Packard
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that copyright
7 * notice and this permission notice appear in supporting documentation, and
8 * that the name of the copyright holders not be used in advertising or
9 * publicity pertaining to distribution of the software without specific,
10 * written prior permission.  The copyright holders make no representations
11 * about the suitability of this software for any purpose.  It is provided "as
12 * is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20 * OF THIS SOFTWARE.
21 */
22
23#include <amdgpu.h>
24#include <fcntl.h>
25#include <stdbool.h>
26#include <string.h>
27#include <unistd.h>
28#include <xf86drm.h>
29#include <xf86drmMode.h>
30#include "drm-uapi/amdgpu_drm.h"
31#include "util/debug.h"
32#include "util/disk_cache.h"
33#include "util/strtod.h"
34#include "winsys/amdgpu/radv_amdgpu_winsys_public.h"
35#include "radv_cs.h"
36#include "radv_private.h"
37#include "sid.h"
38#include "vk_format.h"
39#include "vk_util.h"
40#include "wsi_common_display.h"
41
42#define MM_PER_PIXEL (1.0 / 96.0 * 25.4)
43
44/* VK_EXT_display_control */
45
46VkResult
47radv_RegisterDeviceEventEXT(VkDevice _device, const VkDeviceEventInfoEXT *device_event_info,
48                            const VkAllocationCallbacks *allocator, VkFence *_fence)
49{
50   RADV_FROM_HANDLE(radv_device, device, _device);
51   VkResult ret;
52   int fd;
53
54   ret = radv_CreateFence(_device,
55                          &(VkFenceCreateInfo){
56                             .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
57                             .pNext =
58                                &(VkExportFenceCreateInfo){
59                                   .sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
60                                   .handleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT,
61                                },
62                          },
63                          allocator, _fence);
64   if (ret != VK_SUCCESS)
65      return ret;
66
67   RADV_FROM_HANDLE(radv_fence, fence, *_fence);
68
69   assert(fence->permanent.kind == RADV_FENCE_SYNCOBJ);
70
71   if (device->ws->export_syncobj(device->ws, fence->permanent.syncobj, &fd)) {
72      ret = VK_ERROR_OUT_OF_HOST_MEMORY;
73   } else {
74      ret = wsi_register_device_event(_device, &device->physical_device->wsi_device,
75                                      device_event_info, allocator, NULL, fd);
76      close(fd);
77   }
78
79   if (ret != VK_SUCCESS)
80      radv_DestroyFence(_device, *_fence, allocator);
81
82   return ret;
83}
84
85VkResult
86radv_RegisterDisplayEventEXT(VkDevice _device, VkDisplayKHR display,
87                             const VkDisplayEventInfoEXT *display_event_info,
88                             const VkAllocationCallbacks *allocator, VkFence *_fence)
89{
90   RADV_FROM_HANDLE(radv_device, device, _device);
91   VkResult ret;
92   int fd;
93
94   ret = radv_CreateFence(_device,
95                          &(VkFenceCreateInfo){
96                             .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO,
97                             .pNext =
98                                &(VkExportFenceCreateInfo){
99                                   .sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO,
100                                   .handleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_OPAQUE_FD_BIT,
101                                },
102                          },
103                          allocator, _fence);
104   if (ret != VK_SUCCESS)
105      return ret;
106
107   RADV_FROM_HANDLE(radv_fence, fence, *_fence);
108
109   assert(fence->permanent.kind == RADV_FENCE_SYNCOBJ);
110
111   if (device->ws->export_syncobj(device->ws, fence->permanent.syncobj, &fd)) {
112      ret = VK_ERROR_OUT_OF_HOST_MEMORY;
113   } else {
114      ret = wsi_register_display_event(_device, &device->physical_device->wsi_device, display,
115                                       display_event_info, allocator, NULL, fd);
116      close(fd);
117   }
118
119   if (ret != VK_SUCCESS)
120      radv_DestroyFence(_device, *_fence, allocator);
121
122   return ret;
123}
124