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 <stdbool.h>
24#include <string.h>
25#include <unistd.h>
26#include <fcntl.h>
27#include "radv_private.h"
28#include "radv_cs.h"
29#include "util/disk_cache.h"
30#include "util/strtod.h"
31#include "vk_util.h"
32#include <xf86drm.h>
33#include <xf86drmMode.h>
34#include <amdgpu.h>
35#include <amdgpu_drm.h>
36#include "winsys/amdgpu/radv_amdgpu_winsys_public.h"
37#include "ac_llvm_util.h"
38#include "vk_format.h"
39#include "sid.h"
40#include "util/debug.h"
41#include "wsi_common_display.h"
42
43#define MM_PER_PIXEL     (1.0/96.0 * 25.4)
44
45VkResult
46radv_GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physical_device,
47                                           uint32_t *property_count,
48                                           VkDisplayPropertiesKHR *properties)
49{
50	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
51
52	return wsi_display_get_physical_device_display_properties(
53		physical_device,
54		&pdevice->wsi_device,
55		property_count,
56		properties);
57}
58
59VkResult
60radv_GetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physical_device,
61                                            uint32_t *property_count,
62                                            VkDisplayProperties2KHR *properties)
63{
64	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
65
66	return wsi_display_get_physical_device_display_properties2(
67		physical_device,
68		&pdevice->wsi_device,
69		property_count,
70		properties);
71}
72
73VkResult
74radv_GetPhysicalDeviceDisplayPlanePropertiesKHR(
75	VkPhysicalDevice physical_device,
76	uint32_t *property_count,
77	VkDisplayPlanePropertiesKHR *properties)
78{
79	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
80
81	return wsi_display_get_physical_device_display_plane_properties(
82		physical_device,
83		&pdevice->wsi_device,
84		property_count,
85		properties);
86}
87
88VkResult
89radv_GetPhysicalDeviceDisplayPlaneProperties2KHR(
90	VkPhysicalDevice physical_device,
91	uint32_t *property_count,
92	VkDisplayPlaneProperties2KHR *properties)
93{
94	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
95
96	return wsi_display_get_physical_device_display_plane_properties2(
97		physical_device,
98		&pdevice->wsi_device,
99		property_count,
100		properties);
101}
102
103VkResult
104radv_GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physical_device,
105                                         uint32_t plane_index,
106                                         uint32_t *display_count,
107                                         VkDisplayKHR *displays)
108{
109	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
110
111	return wsi_display_get_display_plane_supported_displays(
112		physical_device,
113		&pdevice->wsi_device,
114		plane_index,
115		display_count,
116		displays);
117}
118
119
120VkResult
121radv_GetDisplayModePropertiesKHR(VkPhysicalDevice physical_device,
122                                 VkDisplayKHR display,
123                                 uint32_t *property_count,
124                                 VkDisplayModePropertiesKHR *properties)
125{
126	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
127
128	return wsi_display_get_display_mode_properties(physical_device,
129						       &pdevice->wsi_device,
130						       display,
131						       property_count,
132						       properties);
133}
134
135VkResult
136radv_GetDisplayModeProperties2KHR(VkPhysicalDevice physical_device,
137                                  VkDisplayKHR display,
138                                  uint32_t *property_count,
139                                  VkDisplayModeProperties2KHR *properties)
140{
141	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
142
143	return wsi_display_get_display_mode_properties2(physical_device,
144						        &pdevice->wsi_device,
145						        display,
146						        property_count,
147						        properties);
148}
149
150VkResult
151radv_CreateDisplayModeKHR(VkPhysicalDevice physical_device,
152                          VkDisplayKHR display,
153                          const VkDisplayModeCreateInfoKHR *create_info,
154                          const VkAllocationCallbacks *allocator,
155                          VkDisplayModeKHR *mode)
156{
157	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
158
159	return wsi_display_create_display_mode(physical_device,
160					       &pdevice->wsi_device,
161					       display,
162					       create_info,
163					       allocator,
164					       mode);
165}
166
167VkResult
168radv_GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physical_device,
169                                    VkDisplayModeKHR mode_khr,
170                                    uint32_t plane_index,
171                                    VkDisplayPlaneCapabilitiesKHR *capabilities)
172{
173	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
174
175	return wsi_get_display_plane_capabilities(physical_device,
176						  &pdevice->wsi_device,
177						  mode_khr,
178						  plane_index,
179						  capabilities);
180}
181
182VkResult
183radv_GetDisplayPlaneCapabilities2KHR(VkPhysicalDevice physical_device,
184                                     const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo,
185                                     VkDisplayPlaneCapabilities2KHR *capabilities)
186{
187	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
188
189	return wsi_get_display_plane_capabilities2(physical_device,
190						   &pdevice->wsi_device,
191						   pDisplayPlaneInfo,
192						   capabilities);
193}
194
195VkResult
196radv_CreateDisplayPlaneSurfaceKHR(
197	VkInstance _instance,
198	const VkDisplaySurfaceCreateInfoKHR *create_info,
199	const VkAllocationCallbacks *allocator,
200	VkSurfaceKHR *surface)
201{
202	RADV_FROM_HANDLE(radv_instance, instance, _instance);
203	const VkAllocationCallbacks *alloc;
204
205	if (allocator)
206		alloc = allocator;
207	else
208		alloc = &instance->alloc;
209
210	return wsi_create_display_surface(_instance, alloc,
211					  create_info, surface);
212}
213
214VkResult
215radv_ReleaseDisplayEXT(VkPhysicalDevice physical_device,
216		       VkDisplayKHR     display)
217{
218	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
219
220	return wsi_release_display(physical_device,
221				   &pdevice->wsi_device,
222				   display);
223}
224
225#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
226VkResult
227radv_AcquireXlibDisplayEXT(VkPhysicalDevice     physical_device,
228			   Display              *dpy,
229			   VkDisplayKHR         display)
230{
231	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
232
233	return wsi_acquire_xlib_display(physical_device,
234					&pdevice->wsi_device,
235					dpy,
236					display);
237}
238
239VkResult
240radv_GetRandROutputDisplayEXT(VkPhysicalDevice  physical_device,
241			      Display           *dpy,
242			      RROutput          output,
243			      VkDisplayKHR      *display)
244{
245	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
246
247	return wsi_get_randr_output_display(physical_device,
248					    &pdevice->wsi_device,
249					    dpy,
250					    output,
251					    display);
252}
253#endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */
254
255/* VK_EXT_display_control */
256
257VkResult
258radv_DisplayPowerControlEXT(VkDevice                    _device,
259			    VkDisplayKHR                display,
260			    const VkDisplayPowerInfoEXT *display_power_info)
261{
262	RADV_FROM_HANDLE(radv_device, device, _device);
263
264	return wsi_display_power_control(_device,
265					 &device->physical_device->wsi_device,
266					 display,
267					 display_power_info);
268}
269
270VkResult
271radv_RegisterDeviceEventEXT(VkDevice                    _device,
272			    const VkDeviceEventInfoEXT  *device_event_info,
273			    const VkAllocationCallbacks *allocator,
274			    VkFence                     *_fence)
275{
276	RADV_FROM_HANDLE(radv_device, device, _device);
277	struct radv_fence            *fence;
278	VkResult                     ret;
279
280	fence = vk_alloc2(&device->instance->alloc, allocator, sizeof (*fence),
281			  8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
282	if (!fence)
283		return VK_ERROR_OUT_OF_HOST_MEMORY;
284
285	fence->fence = NULL;
286	fence->submitted = true;
287	fence->signalled = false;
288	fence->syncobj = 0;
289	fence->temp_syncobj = 0;
290
291	ret = wsi_register_device_event(_device,
292					&device->physical_device->wsi_device,
293					device_event_info,
294					allocator,
295					&fence->fence_wsi);
296	if (ret == VK_SUCCESS)
297		*_fence = radv_fence_to_handle(fence);
298	else
299		vk_free2(&device->instance->alloc, allocator, fence);
300	return ret;
301}
302
303VkResult
304radv_RegisterDisplayEventEXT(VkDevice                           _device,
305			     VkDisplayKHR                       display,
306			     const VkDisplayEventInfoEXT        *display_event_info,
307			     const VkAllocationCallbacks        *allocator,
308			     VkFence                            *_fence)
309{
310	RADV_FROM_HANDLE(radv_device, device, _device);
311
312	struct radv_fence            *fence;
313	VkResult                     ret;
314
315	fence = vk_alloc2(&device->instance->alloc, allocator, sizeof (*fence),
316			  8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
317	if (!fence)
318		return VK_ERROR_OUT_OF_HOST_MEMORY;
319
320	fence->fence = NULL;
321	fence->submitted = true;
322	fence->signalled = false;
323	fence->syncobj = 0;
324	fence->temp_syncobj = 0;
325
326	ret = wsi_register_display_event(_device,
327					 &device->physical_device->wsi_device,
328					 display,
329					 display_event_info,
330					 allocator,
331					 &(fence->fence_wsi));
332
333	if (ret == VK_SUCCESS)
334		*_fence = radv_fence_to_handle(fence);
335	else
336		vk_free2(&device->instance->alloc, allocator, fence);
337	return ret;
338}
339
340VkResult
341radv_GetSwapchainCounterEXT(VkDevice                    _device,
342			    VkSwapchainKHR              swapchain,
343			    VkSurfaceCounterFlagBitsEXT flag_bits,
344			    uint64_t                    *value)
345{
346	RADV_FROM_HANDLE(radv_device, device, _device);
347
348	return wsi_get_swapchain_counter(_device,
349					 &device->physical_device->wsi_device,
350					 swapchain,
351					 flag_bits,
352					 value);
353}
354
355