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
46 VkResult
radv_RegisterDeviceEventEXT(VkDevice _device,const VkDeviceEventInfoEXT * device_event_info,const VkAllocationCallbacks * allocator,VkFence * _fence)47 radv_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
85 VkResult
radv_RegisterDisplayEventEXT(VkDevice _device,VkDisplayKHR display,const VkDisplayEventInfoEXT * display_event_info,const VkAllocationCallbacks * allocator,VkFence * _fence)86 radv_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