| // Copyright 2020 The SwiftShader Authors. All Rights Reserved. | |
| // | |
| // Licensed under the Apache License, Version 2.0 (the "License"); | |
| // you may not use this file except in compliance with the License. | |
| // You may obtain a copy of the License at | |
| // | |
| // http://www.apache.org/licenses/LICENSE-2.0 | |
| // | |
| // Unless required by applicable law or agreed to in writing, software | |
| // distributed under the License is distributed on an "AS IS" BASIS, | |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| // See the License for the specific language governing permissions and | |
| // limitations under the License. | |
| #include "WaylandSurfaceKHR.hpp" | |
| #include "libWaylandClient.hpp" | |
| #include "Vulkan/VkDeviceMemory.hpp" | |
| #include "Vulkan/VkImage.hpp" | |
| #include <string.h> | |
| #include <sys/mman.h> | |
| #include <unistd.h> | |
| namespace vk { | |
| bool WaylandSurfaceKHR::isSupported() | |
| { | |
| return libWaylandClient.isPresent(); | |
| } | |
| static void wl_registry_handle_global(void *data, struct wl_registry *registry, unsigned int name, const char *interface, unsigned int version) | |
| { | |
| struct wl_shm **pshm = (struct wl_shm **)data; | |
| if(!strcmp(interface, "wl_shm")) | |
| { | |
| *pshm = static_cast<struct wl_shm *>(libWaylandClient->wl_registry_bind(registry, name, libWaylandClient->wl_shm_interface, 1)); | |
| } | |
| } | |
| static void wl_registry_handle_global_remove(void *data, struct wl_registry *registry, unsigned int name) | |
| { | |
| } | |
| static const struct wl_registry_listener wl_registry_listener = { wl_registry_handle_global, wl_registry_handle_global_remove }; | |
| WaylandSurfaceKHR::WaylandSurfaceKHR(const VkWaylandSurfaceCreateInfoKHR *pCreateInfo, void *mem) | |
| : display(pCreateInfo->display) | |
| , surface(pCreateInfo->surface) | |
| { | |
| struct wl_registry *registry = libWaylandClient->wl_display_get_registry(display); | |
| libWaylandClient->wl_registry_add_listener(registry, &wl_registry_listener, &shm); | |
| libWaylandClient->wl_display_dispatch(display); | |
| } | |
| void WaylandSurfaceKHR::destroySurface(const VkAllocationCallbacks *pAllocator) | |
| { | |
| } | |
| size_t WaylandSurfaceKHR::ComputeRequiredAllocationSize(const VkWaylandSurfaceCreateInfoKHR *pCreateInfo) | |
| { | |
| return 0; | |
| } | |
| VkResult WaylandSurfaceKHR::getSurfaceCapabilities(const void *pSurfaceInfoPNext, VkSurfaceCapabilitiesKHR *pSurfaceCapabilities, void *pSurfaceCapabilitiesPNext) const | |
| { | |
| pSurfaceCapabilities->currentExtent = { 0xFFFFFFFF, 0xFFFFFFFF }; | |
| pSurfaceCapabilities->minImageExtent = { 1, 1 }; | |
| pSurfaceCapabilities->maxImageExtent = { 0xFFFFFFFF, 0xFFFFFFFF }; | |
| setCommonSurfaceCapabilities(pSurfaceInfoPNext, pSurfaceCapabilities, pSurfaceCapabilitiesPNext); | |
| return VK_SUCCESS; | |
| } | |
| void WaylandSurfaceKHR::attachImage(PresentImage *image) | |
| { | |
| WaylandImage *wlImage = new WaylandImage; | |
| char path[] = "/tmp/XXXXXX"; | |
| int fd = mkstemp(path); | |
| const VkExtent3D &extent = image->getImage()->getExtent(); | |
| int stride = image->getImage()->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0); | |
| assert(ftruncate(fd, extent.height * stride) == 0); | |
| struct wl_shm_pool *pool = libWaylandClient->wl_shm_create_pool(shm, fd, extent.height * stride); | |
| wlImage->buffer = libWaylandClient->wl_shm_pool_create_buffer(pool, 0, extent.width, extent.height, stride, WL_SHM_FORMAT_XRGB8888); | |
| wlImage->data = static_cast<uint8_t *>(mmap(NULL, extent.height * stride, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)); | |
| libWaylandClient->wl_shm_pool_destroy(pool); | |
| close(fd); | |
| imageMap[image] = wlImage; | |
| } | |
| void WaylandSurfaceKHR::detachImage(PresentImage *image) | |
| { | |
| auto it = imageMap.find(image); | |
| if(it != imageMap.end()) | |
| { | |
| WaylandImage *wlImage = it->second; | |
| const VkExtent3D &extent = image->getImage()->getExtent(); | |
| int stride = image->getImage()->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0); | |
| munmap(wlImage->data, extent.height * stride); | |
| libWaylandClient->wl_buffer_destroy(wlImage->buffer); | |
| delete wlImage; | |
| imageMap.erase(it); | |
| } | |
| } | |
| VkResult WaylandSurfaceKHR::present(PresentImage *image) | |
| { | |
| auto it = imageMap.find(image); | |
| if(it != imageMap.end()) | |
| { | |
| WaylandImage *wlImage = it->second; | |
| const VkExtent3D &extent = image->getImage()->getExtent(); | |
| int bufferRowPitch = image->getImage()->rowPitchBytes(VK_IMAGE_ASPECT_COLOR_BIT, 0); | |
| image->getImage()->copyTo(reinterpret_cast<uint8_t *>(wlImage->data), bufferRowPitch); | |
| libWaylandClient->wl_surface_attach(surface, wlImage->buffer, 0, 0); | |
| libWaylandClient->wl_surface_damage(surface, 0, 0, extent.width, extent.height); | |
| libWaylandClient->wl_surface_commit(surface); | |
| libWaylandClient->wl_display_roundtrip(display); | |
| libWaylandClient->wl_display_sync(display); | |
| } | |
| return VK_SUCCESS; | |
| } | |
| } // namespace vk |