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 "WaylandSurfaceKHR.hpp"
16
17 #include "Vulkan/VkDeviceMemory.hpp"
18 #include "Vulkan/VkImage.hpp"
19
20 #include <string.h>
21 #include <sys/mman.h>
22 #include <unistd.h>
23
24 namespace vk {
25
wl_registry_handle_global(void * data,struct wl_registry * registry,unsigned int name,const char * interface,unsigned int version)26 static void wl_registry_handle_global(void *data, struct wl_registry *registry, unsigned int name, const char *interface, unsigned int version)
27 {
28 struct wl_shm **pshm = (struct wl_shm **)data;
29 if(!strcmp(interface, "wl_shm"))
30 {
31 *pshm = static_cast<struct wl_shm *>(wl_registry_bind(registry, name, &wl_shm_interface, 1));
32 }
33 }
34
wl_registry_handle_global_remove(void * data,struct wl_registry * registry,unsigned int name)35 static void wl_registry_handle_global_remove(void *data, struct wl_registry *registry, unsigned int name)
36 {
37 }
38
39 static const struct wl_registry_listener wl_registry_listener = { wl_registry_handle_global, wl_registry_handle_global_remove };
40
WaylandSurfaceKHR(const VkWaylandSurfaceCreateInfoKHR * pCreateInfo,void * mem)41 WaylandSurfaceKHR::WaylandSurfaceKHR(const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, void *mem)
42 : display(pCreateInfo->display)
43 , surface(pCreateInfo->surface)
44 {
45 struct wl_registry *registry = wl_display_get_registry(display);
46 wl_registry_add_listener(registry, &wl_registry_listener, &shm);
47 wl_display_dispatch(display);
48 }
49
destroySurface(const VkAllocationCallbacks * pAllocator)50 void WaylandSurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator)
51 {
52 }
53
ComputeRequiredAllocationSize(const VkWaylandSurfaceCreateInfoKHR * pCreateInfo)54 size_t WaylandSurfaceKHR::ComputeRequiredAllocationSize(const VkWaylandSurfaceCreateInfoKHR *pCreateInfo)
55 {
56 return 0;
57 }
58
getSurfaceCapabilities(VkSurfaceCapabilitiesKHR * pSurfaceCapabilities) const59 VkResult WaylandSurfaceKHR::getSurfaceCapabilities(VkSurfaceCapabilitiesKHR *pSurfaceCapabilities) const
60 {
61 setCommonSurfaceCapabilities(pSurfaceCapabilities);
62
63 pSurfaceCapabilities->currentExtent = { 0xFFFFFFFF, 0xFFFFFFFF };
64 pSurfaceCapabilities->minImageExtent = { 1, 1 };
65 pSurfaceCapabilities->maxImageExtent = { 0xFFFFFFFF, 0xFFFFFFFF };
66 return VK_SUCCESS;
67 }
68
attachImage(PresentImage * image)69 void WaylandSurfaceKHR::attachImage(PresentImage *image)
70 {
71 WaylandImage *wlImage = new WaylandImage;
72 char path[] = "/tmp/XXXXXX";
73 int fd = mkstemp(path);
74 const VkExtent3D &extent = image->getImage()->getExtent();
75 int stride = image->getImage()->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
76 ftruncate(fd, extent.height * stride);
77 struct wl_shm_pool *pool = wl_shm_create_pool(shm, fd, extent.height * stride);
78 wlImage->buffer = wl_shm_pool_create_buffer(pool, 0, extent.width, extent.height, stride, WL_SHM_FORMAT_XRGB8888);
79 wlImage->data = static_cast<uint8_t *>(mmap(NULL, extent.height * stride, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
80 wl_shm_pool_destroy(pool);
81 close(fd);
82 imageMap[image] = wlImage;
83 }
84
detachImage(PresentImage * image)85 void WaylandSurfaceKHR::detachImage(PresentImage *image)
86 {
87 auto it = imageMap.find(image);
88 if(it != imageMap.end())
89 {
90 WaylandImage *wlImage = it->second;
91 const VkExtent3D &extent = image->getImage()->getExtent();
92 int stride = image->getImage()->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
93 munmap(wlImage->data, extent.height * stride);
94 wl_buffer_destroy(wlImage->buffer);
95 delete wlImage;
96 imageMap.erase(it);
97 }
98 }
99
present(PresentImage * image)100 VkResult WaylandSurfaceKHR::present(PresentImage *image)
101 {
102 auto it = imageMap.find(image);
103 if(it != imageMap.end())
104 {
105 WaylandImage *wlImage = it->second;
106 const VkExtent3D &extent = image->getImage()->getExtent();
107 int bufferRowPitch = image->getImage()->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0);
108 image->getImage()->copyTo(reinterpret_cast<uint8_t *>(wlImage->data), bufferRowPitch);
109 wl_surface_attach(surface, wlImage->buffer, 0, 0);
110 wl_surface_damage(surface, 0, 0, extent.width, extent.height);
111 wl_surface_commit(surface);
112 wl_display_roundtrip(display);
113 wl_display_sync(display);
114 }
115
116 return VK_SUCCESS;
117 }
118
119 } // namespace vk
120