1b8e80941Smrg/*
2b8e80941Smrg * Copyright © 2017 Keith Packard
3b8e80941Smrg *
4b8e80941Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5b8e80941Smrg * documentation for any purpose is hereby granted without fee, provided that
6b8e80941Smrg * the above copyright notice appear in all copies and that both that copyright
7b8e80941Smrg * notice and this permission notice appear in supporting documentation, and
8b8e80941Smrg * that the name of the copyright holders not be used in advertising or
9b8e80941Smrg * publicity pertaining to distribution of the software without specific,
10b8e80941Smrg * written prior permission.  The copyright holders make no representations
11b8e80941Smrg * about the suitability of this software for any purpose.  It is provided "as
12b8e80941Smrg * is" without express or implied warranty.
13b8e80941Smrg *
14b8e80941Smrg * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15b8e80941Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16b8e80941Smrg * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17b8e80941Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18b8e80941Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19b8e80941Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20b8e80941Smrg * OF THIS SOFTWARE.
21b8e80941Smrg */
22b8e80941Smrg
23b8e80941Smrg#include <stdbool.h>
24b8e80941Smrg#include <string.h>
25b8e80941Smrg#include <unistd.h>
26b8e80941Smrg#include <fcntl.h>
27b8e80941Smrg#include "radv_private.h"
28b8e80941Smrg#include "radv_cs.h"
29b8e80941Smrg#include "util/disk_cache.h"
30b8e80941Smrg#include "util/strtod.h"
31b8e80941Smrg#include "vk_util.h"
32b8e80941Smrg#include <xf86drm.h>
33b8e80941Smrg#include <xf86drmMode.h>
34b8e80941Smrg#include <amdgpu.h>
35b8e80941Smrg#include <amdgpu_drm.h>
36b8e80941Smrg#include "winsys/amdgpu/radv_amdgpu_winsys_public.h"
37b8e80941Smrg#include "ac_llvm_util.h"
38b8e80941Smrg#include "vk_format.h"
39b8e80941Smrg#include "sid.h"
40b8e80941Smrg#include "util/debug.h"
41b8e80941Smrg#include "wsi_common_display.h"
42b8e80941Smrg
43b8e80941Smrg#define MM_PER_PIXEL     (1.0/96.0 * 25.4)
44b8e80941Smrg
45b8e80941SmrgVkResult
46b8e80941Smrgradv_GetPhysicalDeviceDisplayPropertiesKHR(VkPhysicalDevice physical_device,
47b8e80941Smrg                                           uint32_t *property_count,
48b8e80941Smrg                                           VkDisplayPropertiesKHR *properties)
49b8e80941Smrg{
50b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
51b8e80941Smrg
52b8e80941Smrg	return wsi_display_get_physical_device_display_properties(
53b8e80941Smrg		physical_device,
54b8e80941Smrg		&pdevice->wsi_device,
55b8e80941Smrg		property_count,
56b8e80941Smrg		properties);
57b8e80941Smrg}
58b8e80941Smrg
59b8e80941SmrgVkResult
60b8e80941Smrgradv_GetPhysicalDeviceDisplayProperties2KHR(VkPhysicalDevice physical_device,
61b8e80941Smrg                                            uint32_t *property_count,
62b8e80941Smrg                                            VkDisplayProperties2KHR *properties)
63b8e80941Smrg{
64b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
65b8e80941Smrg
66b8e80941Smrg	return wsi_display_get_physical_device_display_properties2(
67b8e80941Smrg		physical_device,
68b8e80941Smrg		&pdevice->wsi_device,
69b8e80941Smrg		property_count,
70b8e80941Smrg		properties);
71b8e80941Smrg}
72b8e80941Smrg
73b8e80941SmrgVkResult
74b8e80941Smrgradv_GetPhysicalDeviceDisplayPlanePropertiesKHR(
75b8e80941Smrg	VkPhysicalDevice physical_device,
76b8e80941Smrg	uint32_t *property_count,
77b8e80941Smrg	VkDisplayPlanePropertiesKHR *properties)
78b8e80941Smrg{
79b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
80b8e80941Smrg
81b8e80941Smrg	return wsi_display_get_physical_device_display_plane_properties(
82b8e80941Smrg		physical_device,
83b8e80941Smrg		&pdevice->wsi_device,
84b8e80941Smrg		property_count,
85b8e80941Smrg		properties);
86b8e80941Smrg}
87b8e80941Smrg
88b8e80941SmrgVkResult
89b8e80941Smrgradv_GetPhysicalDeviceDisplayPlaneProperties2KHR(
90b8e80941Smrg	VkPhysicalDevice physical_device,
91b8e80941Smrg	uint32_t *property_count,
92b8e80941Smrg	VkDisplayPlaneProperties2KHR *properties)
93b8e80941Smrg{
94b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
95b8e80941Smrg
96b8e80941Smrg	return wsi_display_get_physical_device_display_plane_properties2(
97b8e80941Smrg		physical_device,
98b8e80941Smrg		&pdevice->wsi_device,
99b8e80941Smrg		property_count,
100b8e80941Smrg		properties);
101b8e80941Smrg}
102b8e80941Smrg
103b8e80941SmrgVkResult
104b8e80941Smrgradv_GetDisplayPlaneSupportedDisplaysKHR(VkPhysicalDevice physical_device,
105b8e80941Smrg                                         uint32_t plane_index,
106b8e80941Smrg                                         uint32_t *display_count,
107b8e80941Smrg                                         VkDisplayKHR *displays)
108b8e80941Smrg{
109b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
110b8e80941Smrg
111b8e80941Smrg	return wsi_display_get_display_plane_supported_displays(
112b8e80941Smrg		physical_device,
113b8e80941Smrg		&pdevice->wsi_device,
114b8e80941Smrg		plane_index,
115b8e80941Smrg		display_count,
116b8e80941Smrg		displays);
117b8e80941Smrg}
118b8e80941Smrg
119b8e80941Smrg
120b8e80941SmrgVkResult
121b8e80941Smrgradv_GetDisplayModePropertiesKHR(VkPhysicalDevice physical_device,
122b8e80941Smrg                                 VkDisplayKHR display,
123b8e80941Smrg                                 uint32_t *property_count,
124b8e80941Smrg                                 VkDisplayModePropertiesKHR *properties)
125b8e80941Smrg{
126b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
127b8e80941Smrg
128b8e80941Smrg	return wsi_display_get_display_mode_properties(physical_device,
129b8e80941Smrg						       &pdevice->wsi_device,
130b8e80941Smrg						       display,
131b8e80941Smrg						       property_count,
132b8e80941Smrg						       properties);
133b8e80941Smrg}
134b8e80941Smrg
135b8e80941SmrgVkResult
136b8e80941Smrgradv_GetDisplayModeProperties2KHR(VkPhysicalDevice physical_device,
137b8e80941Smrg                                  VkDisplayKHR display,
138b8e80941Smrg                                  uint32_t *property_count,
139b8e80941Smrg                                  VkDisplayModeProperties2KHR *properties)
140b8e80941Smrg{
141b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
142b8e80941Smrg
143b8e80941Smrg	return wsi_display_get_display_mode_properties2(physical_device,
144b8e80941Smrg						        &pdevice->wsi_device,
145b8e80941Smrg						        display,
146b8e80941Smrg						        property_count,
147b8e80941Smrg						        properties);
148b8e80941Smrg}
149b8e80941Smrg
150b8e80941SmrgVkResult
151b8e80941Smrgradv_CreateDisplayModeKHR(VkPhysicalDevice physical_device,
152b8e80941Smrg                          VkDisplayKHR display,
153b8e80941Smrg                          const VkDisplayModeCreateInfoKHR *create_info,
154b8e80941Smrg                          const VkAllocationCallbacks *allocator,
155b8e80941Smrg                          VkDisplayModeKHR *mode)
156b8e80941Smrg{
157b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
158b8e80941Smrg
159b8e80941Smrg	return wsi_display_create_display_mode(physical_device,
160b8e80941Smrg					       &pdevice->wsi_device,
161b8e80941Smrg					       display,
162b8e80941Smrg					       create_info,
163b8e80941Smrg					       allocator,
164b8e80941Smrg					       mode);
165b8e80941Smrg}
166b8e80941Smrg
167b8e80941SmrgVkResult
168b8e80941Smrgradv_GetDisplayPlaneCapabilitiesKHR(VkPhysicalDevice physical_device,
169b8e80941Smrg                                    VkDisplayModeKHR mode_khr,
170b8e80941Smrg                                    uint32_t plane_index,
171b8e80941Smrg                                    VkDisplayPlaneCapabilitiesKHR *capabilities)
172b8e80941Smrg{
173b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
174b8e80941Smrg
175b8e80941Smrg	return wsi_get_display_plane_capabilities(physical_device,
176b8e80941Smrg						  &pdevice->wsi_device,
177b8e80941Smrg						  mode_khr,
178b8e80941Smrg						  plane_index,
179b8e80941Smrg						  capabilities);
180b8e80941Smrg}
181b8e80941Smrg
182b8e80941SmrgVkResult
183b8e80941Smrgradv_GetDisplayPlaneCapabilities2KHR(VkPhysicalDevice physical_device,
184b8e80941Smrg                                     const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo,
185b8e80941Smrg                                     VkDisplayPlaneCapabilities2KHR *capabilities)
186b8e80941Smrg{
187b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
188b8e80941Smrg
189b8e80941Smrg	return wsi_get_display_plane_capabilities2(physical_device,
190b8e80941Smrg						   &pdevice->wsi_device,
191b8e80941Smrg						   pDisplayPlaneInfo,
192b8e80941Smrg						   capabilities);
193b8e80941Smrg}
194b8e80941Smrg
195b8e80941SmrgVkResult
196b8e80941Smrgradv_CreateDisplayPlaneSurfaceKHR(
197b8e80941Smrg	VkInstance _instance,
198b8e80941Smrg	const VkDisplaySurfaceCreateInfoKHR *create_info,
199b8e80941Smrg	const VkAllocationCallbacks *allocator,
200b8e80941Smrg	VkSurfaceKHR *surface)
201b8e80941Smrg{
202b8e80941Smrg	RADV_FROM_HANDLE(radv_instance, instance, _instance);
203b8e80941Smrg	const VkAllocationCallbacks *alloc;
204b8e80941Smrg
205b8e80941Smrg	if (allocator)
206b8e80941Smrg		alloc = allocator;
207b8e80941Smrg	else
208b8e80941Smrg		alloc = &instance->alloc;
209b8e80941Smrg
210b8e80941Smrg	return wsi_create_display_surface(_instance, alloc,
211b8e80941Smrg					  create_info, surface);
212b8e80941Smrg}
213b8e80941Smrg
214b8e80941SmrgVkResult
215b8e80941Smrgradv_ReleaseDisplayEXT(VkPhysicalDevice physical_device,
216b8e80941Smrg		       VkDisplayKHR     display)
217b8e80941Smrg{
218b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
219b8e80941Smrg
220b8e80941Smrg	return wsi_release_display(physical_device,
221b8e80941Smrg				   &pdevice->wsi_device,
222b8e80941Smrg				   display);
223b8e80941Smrg}
224b8e80941Smrg
225b8e80941Smrg#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
226b8e80941SmrgVkResult
227b8e80941Smrgradv_AcquireXlibDisplayEXT(VkPhysicalDevice     physical_device,
228b8e80941Smrg			   Display              *dpy,
229b8e80941Smrg			   VkDisplayKHR         display)
230b8e80941Smrg{
231b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
232b8e80941Smrg
233b8e80941Smrg	return wsi_acquire_xlib_display(physical_device,
234b8e80941Smrg					&pdevice->wsi_device,
235b8e80941Smrg					dpy,
236b8e80941Smrg					display);
237b8e80941Smrg}
238b8e80941Smrg
239b8e80941SmrgVkResult
240b8e80941Smrgradv_GetRandROutputDisplayEXT(VkPhysicalDevice  physical_device,
241b8e80941Smrg			      Display           *dpy,
242b8e80941Smrg			      RROutput          output,
243b8e80941Smrg			      VkDisplayKHR      *display)
244b8e80941Smrg{
245b8e80941Smrg	RADV_FROM_HANDLE(radv_physical_device, pdevice, physical_device);
246b8e80941Smrg
247b8e80941Smrg	return wsi_get_randr_output_display(physical_device,
248b8e80941Smrg					    &pdevice->wsi_device,
249b8e80941Smrg					    dpy,
250b8e80941Smrg					    output,
251b8e80941Smrg					    display);
252b8e80941Smrg}
253b8e80941Smrg#endif /* VK_USE_PLATFORM_XLIB_XRANDR_EXT */
254b8e80941Smrg
255b8e80941Smrg/* VK_EXT_display_control */
256b8e80941Smrg
257b8e80941SmrgVkResult
258b8e80941Smrgradv_DisplayPowerControlEXT(VkDevice                    _device,
259b8e80941Smrg			    VkDisplayKHR                display,
260b8e80941Smrg			    const VkDisplayPowerInfoEXT *display_power_info)
261b8e80941Smrg{
262b8e80941Smrg	RADV_FROM_HANDLE(radv_device, device, _device);
263b8e80941Smrg
264b8e80941Smrg	return wsi_display_power_control(_device,
265b8e80941Smrg					 &device->physical_device->wsi_device,
266b8e80941Smrg					 display,
267b8e80941Smrg					 display_power_info);
268b8e80941Smrg}
269b8e80941Smrg
270b8e80941SmrgVkResult
271b8e80941Smrgradv_RegisterDeviceEventEXT(VkDevice                    _device,
272b8e80941Smrg			    const VkDeviceEventInfoEXT  *device_event_info,
273b8e80941Smrg			    const VkAllocationCallbacks *allocator,
274b8e80941Smrg			    VkFence                     *_fence)
275b8e80941Smrg{
276b8e80941Smrg	RADV_FROM_HANDLE(radv_device, device, _device);
277b8e80941Smrg	struct radv_fence            *fence;
278b8e80941Smrg	VkResult                     ret;
279b8e80941Smrg
280b8e80941Smrg	fence = vk_alloc2(&device->instance->alloc, allocator, sizeof (*fence),
281b8e80941Smrg			  8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
282b8e80941Smrg	if (!fence)
283b8e80941Smrg		return VK_ERROR_OUT_OF_HOST_MEMORY;
284b8e80941Smrg
285b8e80941Smrg	fence->fence = NULL;
286b8e80941Smrg	fence->submitted = true;
287b8e80941Smrg	fence->signalled = false;
288b8e80941Smrg	fence->syncobj = 0;
289b8e80941Smrg	fence->temp_syncobj = 0;
290b8e80941Smrg
291b8e80941Smrg	ret = wsi_register_device_event(_device,
292b8e80941Smrg					&device->physical_device->wsi_device,
293b8e80941Smrg					device_event_info,
294b8e80941Smrg					allocator,
295b8e80941Smrg					&fence->fence_wsi);
296b8e80941Smrg	if (ret == VK_SUCCESS)
297b8e80941Smrg		*_fence = radv_fence_to_handle(fence);
298b8e80941Smrg	else
299b8e80941Smrg		vk_free2(&device->instance->alloc, allocator, fence);
300b8e80941Smrg	return ret;
301b8e80941Smrg}
302b8e80941Smrg
303b8e80941SmrgVkResult
304b8e80941Smrgradv_RegisterDisplayEventEXT(VkDevice                           _device,
305b8e80941Smrg			     VkDisplayKHR                       display,
306b8e80941Smrg			     const VkDisplayEventInfoEXT        *display_event_info,
307b8e80941Smrg			     const VkAllocationCallbacks        *allocator,
308b8e80941Smrg			     VkFence                            *_fence)
309b8e80941Smrg{
310b8e80941Smrg	RADV_FROM_HANDLE(radv_device, device, _device);
311b8e80941Smrg
312b8e80941Smrg	struct radv_fence            *fence;
313b8e80941Smrg	VkResult                     ret;
314b8e80941Smrg
315b8e80941Smrg	fence = vk_alloc2(&device->instance->alloc, allocator, sizeof (*fence),
316b8e80941Smrg			  8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
317b8e80941Smrg	if (!fence)
318b8e80941Smrg		return VK_ERROR_OUT_OF_HOST_MEMORY;
319b8e80941Smrg
320b8e80941Smrg	fence->fence = NULL;
321b8e80941Smrg	fence->submitted = true;
322b8e80941Smrg	fence->signalled = false;
323b8e80941Smrg	fence->syncobj = 0;
324b8e80941Smrg	fence->temp_syncobj = 0;
325b8e80941Smrg
326b8e80941Smrg	ret = wsi_register_display_event(_device,
327b8e80941Smrg					 &device->physical_device->wsi_device,
328b8e80941Smrg					 display,
329b8e80941Smrg					 display_event_info,
330b8e80941Smrg					 allocator,
331b8e80941Smrg					 &(fence->fence_wsi));
332b8e80941Smrg
333b8e80941Smrg	if (ret == VK_SUCCESS)
334b8e80941Smrg		*_fence = radv_fence_to_handle(fence);
335b8e80941Smrg	else
336b8e80941Smrg		vk_free2(&device->instance->alloc, allocator, fence);
337b8e80941Smrg	return ret;
338b8e80941Smrg}
339b8e80941Smrg
340b8e80941SmrgVkResult
341b8e80941Smrgradv_GetSwapchainCounterEXT(VkDevice                    _device,
342b8e80941Smrg			    VkSwapchainKHR              swapchain,
343b8e80941Smrg			    VkSurfaceCounterFlagBitsEXT flag_bits,
344b8e80941Smrg			    uint64_t                    *value)
345b8e80941Smrg{
346b8e80941Smrg	RADV_FROM_HANDLE(radv_device, device, _device);
347b8e80941Smrg
348b8e80941Smrg	return wsi_get_swapchain_counter(_device,
349b8e80941Smrg					 &device->physical_device->wsi_device,
350b8e80941Smrg					 swapchain,
351b8e80941Smrg					 flag_bits,
352b8e80941Smrg					 value);
353b8e80941Smrg}
354b8e80941Smrg
355