1 // Copyright 2020 The SwiftShader Authors. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "DisplaySurfaceKHR.hpp"
16
17 #include "Vulkan/VkDeviceMemory.hpp"
18 #include "Vulkan/VkImage.hpp"
19
20 #include <fcntl.h>
21 #include <string.h>
22 #include <sys/mman.h>
23 #include <unistd.h>
24 #include <xf86drm.h>
25
26 namespace vk {
27
GetDisplayModeProperties(uint32_t * pPropertyCount,VkDisplayModePropertiesKHR * pProperties)28 VkResult DisplaySurfaceKHR::GetDisplayModeProperties(uint32_t *pPropertyCount, VkDisplayModePropertiesKHR *pProperties)
29 {
30 *pPropertyCount = 1;
31
32 if(pProperties)
33 {
34 int fd = open("/dev/dri/card0", O_RDWR);
35 drmModeRes *res = drmModeGetResources(fd);
36 drmModeConnector *connector = drmModeGetConnector(fd, res->connectors[0]);
37 pProperties->displayMode = (uintptr_t)connector->modes[0].name;
38 pProperties->parameters.visibleRegion.width = connector->modes[0].hdisplay;
39 pProperties->parameters.visibleRegion.height = connector->modes[0].vdisplay;
40 pProperties->parameters.refreshRate = connector->modes[0].vrefresh * 1000;
41 drmModeFreeConnector(connector);
42 drmModeFreeResources(res);
43 close(fd);
44 }
45
46 return VK_SUCCESS;
47 }
48
GetDisplayPlaneCapabilities(VkDisplayPlaneCapabilitiesKHR * pCapabilities)49 VkResult DisplaySurfaceKHR::GetDisplayPlaneCapabilities(VkDisplayPlaneCapabilitiesKHR *pCapabilities)
50 {
51 int fd = open("/dev/dri/card0", O_RDWR);
52 drmModeRes *res = drmModeGetResources(fd);
53 drmModeConnector *connector = drmModeGetConnector(fd, res->connectors[0]);
54 pCapabilities->supportedAlpha = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR;
55 pCapabilities->minSrcPosition.x = 0;
56 pCapabilities->minSrcPosition.y = 0;
57 pCapabilities->maxSrcPosition.x = 0;
58 pCapabilities->maxSrcPosition.y = 0;
59 pCapabilities->minSrcExtent.width = connector->modes[0].hdisplay;
60 pCapabilities->minSrcExtent.height = connector->modes[0].vdisplay;
61 pCapabilities->maxSrcExtent.width = connector->modes[0].hdisplay;
62 pCapabilities->maxSrcExtent.height = connector->modes[0].vdisplay;
63 pCapabilities->minDstPosition.x = 0;
64 pCapabilities->minDstPosition.y = 0;
65 pCapabilities->maxDstPosition.x = 0;
66 pCapabilities->maxDstPosition.y = 0;
67 pCapabilities->minDstExtent.width = connector->modes[0].hdisplay;
68 pCapabilities->minDstExtent.height = connector->modes[0].vdisplay;
69 pCapabilities->maxDstExtent.width = connector->modes[0].hdisplay;
70 pCapabilities->maxDstExtent.height = connector->modes[0].vdisplay;
71 drmModeFreeConnector(connector);
72 drmModeFreeResources(res);
73 close(fd);
74
75 return VK_SUCCESS;
76 }
77
GetDisplayPlaneSupportedDisplays(uint32_t * pDisplayCount,VkDisplayKHR * pDisplays)78 VkResult DisplaySurfaceKHR::GetDisplayPlaneSupportedDisplays(uint32_t *pDisplayCount, VkDisplayKHR *pDisplays)
79 {
80 *pDisplayCount = 1;
81
82 if(pDisplays)
83 {
84 int fd = open("/dev/dri/card0", O_RDWR);
85 drmModeRes *res = drmModeGetResources(fd);
86 *pDisplays = res->connectors[0];
87 drmModeFreeResources(res);
88 close(fd);
89 }
90
91 return VK_SUCCESS;
92 }
93
GetPhysicalDeviceDisplayPlaneProperties(uint32_t * pPropertyCount,VkDisplayPlanePropertiesKHR * pProperties)94 VkResult DisplaySurfaceKHR::GetPhysicalDeviceDisplayPlaneProperties(uint32_t *pPropertyCount, VkDisplayPlanePropertiesKHR *pProperties)
95 {
96 *pPropertyCount = 1;
97
98 if(pProperties)
99 {
100 int fd = open("/dev/dri/card0", O_RDWR);
101 drmModeRes *res = drmModeGetResources(fd);
102 pProperties->currentDisplay = res->connectors[0];
103 pProperties->currentStackIndex = 0;
104 drmModeFreeResources(res);
105 close(fd);
106 }
107
108 return VK_SUCCESS;
109 }
110
GetPhysicalDeviceDisplayProperties(uint32_t * pPropertyCount,VkDisplayPropertiesKHR * pProperties)111 VkResult DisplaySurfaceKHR::GetPhysicalDeviceDisplayProperties(uint32_t *pPropertyCount, VkDisplayPropertiesKHR *pProperties)
112 {
113 *pPropertyCount = 1;
114
115 if(pProperties)
116 {
117 int fd = open("/dev/dri/card0", O_RDWR);
118 drmModeRes *res = drmModeGetResources(fd);
119 drmModeConnector *connector = drmModeGetConnector(fd, res->connectors[0]);
120 pProperties->display = res->connectors[0];
121 pProperties->displayName = "monitor";
122 pProperties->physicalDimensions.width = connector->mmWidth;
123 pProperties->physicalDimensions.height = connector->mmHeight;
124 if(pProperties->physicalDimensions.width <= 0 || pProperties->physicalDimensions.height <= 0)
125 {
126 pProperties->physicalDimensions.width = connector->modes[0].hdisplay * 25.4 / 96;
127 pProperties->physicalDimensions.height = connector->modes[0].vdisplay * 25.4 / 96;
128 }
129 pProperties->physicalResolution.width = connector->modes[0].hdisplay;
130 pProperties->physicalResolution.height = connector->modes[0].vdisplay;
131 pProperties->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
132 pProperties->planeReorderPossible = VK_FALSE;
133 pProperties->persistentContent = VK_FALSE;
134 drmModeFreeConnector(connector);
135 drmModeFreeResources(res);
136 close(fd);
137 }
138
139 return VK_SUCCESS;
140 }
141
DisplaySurfaceKHR(const VkDisplaySurfaceCreateInfoKHR * pCreateInfo,void * mem)142 DisplaySurfaceKHR::DisplaySurfaceKHR(const VkDisplaySurfaceCreateInfoKHR *pCreateInfo, void *mem)
143 {
144 fd = open("/dev/dri/card0", O_RDWR);
145 drmModeRes *res = drmModeGetResources(fd);
146 connector_id = res->connectors[0];
147 drmModeFreeResources(res);
148 drmModeConnector *connector = drmModeGetConnector(fd, connector_id);
149 encoder_id = connector->encoder_id;
150 memcpy(&mode_info, &connector->modes[0], sizeof(drmModeModeInfo));
151 drmModeFreeConnector(connector);
152 drmModeEncoder *encoder = drmModeGetEncoder(fd, encoder_id);
153 crtc_id = encoder->crtc_id;
154 drmModeFreeEncoder(encoder);
155
156 crtc = drmModeGetCrtc(fd, crtc_id);
157
158 struct drm_mode_create_dumb creq;
159 memset(&creq, 0, sizeof(struct drm_mode_create_dumb));
160 creq.width = mode_info.hdisplay;
161 creq.height = mode_info.vdisplay;
162 creq.bpp = 32;
163 drmIoctl(fd, DRM_IOCTL_MODE_CREATE_DUMB, &creq);
164
165 handle = creq.handle;
166 width = creq.width;
167 height = creq.height;
168 pitch = creq.pitch;
169 size = creq.size;
170
171 drmModeAddFB(fd, width, height, 24, 32, pitch, handle, &fb_id);
172
173 struct drm_mode_map_dumb mreq;
174 memset(&mreq, 0, sizeof(struct drm_mode_map_dumb));
175 mreq.handle = handle;
176 drmIoctl(fd, DRM_IOCTL_MODE_MAP_DUMB, &mreq);
177
178 fb_buffer = static_cast<uint8_t *>(mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, mreq.offset));
179 }
180
destroySurface(const VkAllocationCallbacks * pAllocator)181 void DisplaySurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator)
182 {
183 munmap(fb_buffer, size);
184
185 drmModeRmFB(fd, fb_id);
186
187 struct drm_mode_destroy_dumb dreq;
188 memset(&dreq, 0, sizeof(struct drm_mode_destroy_dumb));
189 dreq.handle = handle;
190 drmIoctl(fd, DRM_IOCTL_MODE_DESTROY_DUMB, &dreq);
191
192 drmModeSetCrtc(fd, crtc->crtc_id, crtc->buffer_id, crtc->x, crtc->y, &connector_id, 1, &crtc->mode);
193 drmModeFreeCrtc(crtc);
194
195 close(fd);
196 }
197
ComputeRequiredAllocationSize(const VkDisplaySurfaceCreateInfoKHR * pCreateInfo)198 size_t DisplaySurfaceKHR::ComputeRequiredAllocationSize(const VkDisplaySurfaceCreateInfoKHR *pCreateInfo)
199 {
200 return 0;
201 }
202
getSurfaceCapabilities(VkSurfaceCapabilitiesKHR * pSurfaceCapabilities) const203 VkResult DisplaySurfaceKHR::getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const
204 {
205 setCommonSurfaceCapabilities(pSurfaceCapabilities);
206
207 VkExtent2D extent = { width, height };
208
209 pSurfaceCapabilities->currentExtent = extent;
210 pSurfaceCapabilities->minImageExtent = extent;
211 pSurfaceCapabilities->maxImageExtent = extent;
212 return VK_SUCCESS;
213 }
214
attachImage(PresentImage * image)215 void DisplaySurfaceKHR::attachImage(PresentImage *image)
216 {
217 }
218
detachImage(PresentImage * image)219 void DisplaySurfaceKHR::detachImage(PresentImage *image)
220 {
221 }
222
present(PresentImage * image)223 VkResult DisplaySurfaceKHR::present(PresentImage *image)
224 {
225 image->getImage()->copyTo(fb_buffer, pitch);
226 drmModeSetCrtc(fd, crtc_id, fb_id, 0, 0, &connector_id, 1, &mode_info);
227
228 return VK_SUCCESS;
229 }
230
231 } // namespace vk
232