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