1 /*
2 * Copyright © 2022 Imagination Technologies Ltd.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 */
23
24 #include <fcntl.h>
25 #include <stdbool.h>
26 #include <vulkan/vulkan.h>
27 #include <xf86drm.h>
28
29 #include "powervr/pvr_drm_public.h"
30 #include "pvr_private.h"
31 #include "pvr_winsys.h"
32 #include "vk_log.h"
33
34 #if defined(PVR_SUPPORT_SERVICES_DRIVER)
35 # include "pvrsrvkm/pvr_srv_public.h"
36 #endif
37
pvr_winsys_destroy(struct pvr_winsys * ws)38 void pvr_winsys_destroy(struct pvr_winsys *ws)
39 {
40 const int display_fd = ws->display_fd;
41 const int render_fd = ws->render_fd;
42
43 ws->ops->destroy(ws);
44
45 if (display_fd >= 0)
46 close(display_fd);
47
48 if (render_fd >= 0)
49 close(render_fd);
50 }
51
pvr_winsys_create(const char * render_path,const char * display_path,const VkAllocationCallbacks * alloc,struct pvr_winsys ** const ws_out)52 VkResult pvr_winsys_create(const char *render_path,
53 const char *display_path,
54 const VkAllocationCallbacks *alloc,
55 struct pvr_winsys **const ws_out)
56 {
57 drmVersionPtr version;
58 VkResult result;
59 int display_fd;
60 int render_fd;
61
62 render_fd = open(render_path, O_RDWR | O_CLOEXEC);
63 if (render_fd < 0) {
64 result = vk_errorf(NULL,
65 VK_ERROR_INITIALIZATION_FAILED,
66 "Failed to open render device %s",
67 render_path);
68 goto err_out;
69 }
70
71 if (display_path) {
72 display_fd = open(display_path, O_RDWR | O_CLOEXEC);
73 if (display_fd < 0) {
74 result = vk_errorf(NULL,
75 VK_ERROR_INITIALIZATION_FAILED,
76 "Failed to open display device %s",
77 display_path);
78 goto err_close_render_fd;
79 }
80 } else {
81 display_fd = -1;
82 }
83
84 version = drmGetVersion(render_fd);
85 if (!version) {
86 result = vk_errorf(NULL,
87 VK_ERROR_INCOMPATIBLE_DRIVER,
88 "Failed to query kernel driver version for device.");
89 goto err_close_display_fd;
90 }
91
92 if (strcmp(version->name, "powervr") == 0) {
93 result = pvr_drm_winsys_create(render_fd, display_fd, alloc, ws_out);
94 #if defined(PVR_SUPPORT_SERVICES_DRIVER)
95 } else if (strcmp(version->name, "pvr") == 0) {
96 result = pvr_srv_winsys_create(render_fd, display_fd, alloc, ws_out);
97 #endif
98 } else {
99 result = vk_errorf(
100 NULL,
101 VK_ERROR_INCOMPATIBLE_DRIVER,
102 "Device does not use any of the supported pvrsrvkm or powervr kernel driver.");
103 }
104
105 drmFreeVersion(version);
106
107 if (result != VK_SUCCESS)
108 goto err_close_display_fd;
109
110 return VK_SUCCESS;
111
112 err_close_display_fd:
113 if (display_fd >= 0)
114 close(display_fd);
115
116 err_close_render_fd:
117 close(render_fd);
118
119 err_out:
120 return result;
121 }
122