Home | History | Annotate | Line # | Download | only in vulkan
      1 /*
      2  * Copyright  2020 Raspberry Pi
      3  * based on intel anv code:
      4  * Copyright  2015 Intel Corporation
      5 
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice (including the next
     14  * paragraph) shall be included in all copies or substantial portions of the
     15  * Software.
     16  *
     17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     20  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     22  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
     23  * IN THE SOFTWARE.
     24  */
     25 
     26 #include "v3dv_private.h"
     27 #include "drm-uapi/drm_fourcc.h"
     28 #include "wsi_common_entrypoints.h"
     29 #include "vk_format_info.h"
     30 #include "vk_util.h"
     31 #include "wsi_common.h"
     32 
     33 static VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
     34 v3dv_wsi_proc_addr(VkPhysicalDevice physicalDevice, const char *pName)
     35 {
     36    V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, physicalDevice);
     37    PFN_vkVoidFunction func;
     38 
     39    func = vk_instance_dispatch_table_get(&pdevice->vk.instance->dispatch_table, pName);
     40    if (func != NULL)
     41       return func;
     42 
     43    func = vk_physical_device_dispatch_table_get(&pdevice->vk.dispatch_table, pName);
     44    if (func != NULL)
     45       return func;
     46 
     47    return vk_device_dispatch_table_get(&vk_device_trampolines, pName);
     48 }
     49 
     50 static bool
     51 v3dv_wsi_can_present_on_device(VkPhysicalDevice _pdevice, int fd)
     52 {
     53    V3DV_FROM_HANDLE(v3dv_physical_device, pdevice, _pdevice);
     54 
     55    drmDevicePtr fd_devinfo, display_devinfo;
     56    int ret;
     57 
     58    ret = drmGetDevice2(fd, 0, &fd_devinfo);
     59    if (ret)
     60       return false;
     61 
     62    ret = drmGetDevice2(pdevice->display_fd, 0, &display_devinfo);
     63    if (ret) {
     64       drmFreeDevice(&fd_devinfo);
     65       return false;
     66    }
     67 
     68    bool result = drmDevicesEqual(fd_devinfo, display_devinfo);
     69 
     70    drmFreeDevice(&fd_devinfo);
     71    drmFreeDevice(&display_devinfo);
     72    return result;
     73 }
     74 
     75 VkResult
     76 v3dv_wsi_init(struct v3dv_physical_device *physical_device)
     77 {
     78    VkResult result;
     79 
     80    result = wsi_device_init(&physical_device->wsi_device,
     81                             v3dv_physical_device_to_handle(physical_device),
     82                             v3dv_wsi_proc_addr,
     83                             &physical_device->vk.instance->alloc,
     84                             physical_device->master_fd, NULL, false);
     85 
     86    if (result != VK_SUCCESS)
     87       return result;
     88 
     89    physical_device->wsi_device.supports_modifiers = true;
     90    physical_device->wsi_device.can_present_on_device =
     91       v3dv_wsi_can_present_on_device;
     92 
     93    physical_device->vk.wsi_device = &physical_device->wsi_device;
     94 
     95    return VK_SUCCESS;
     96 }
     97 
     98 void
     99 v3dv_wsi_finish(struct v3dv_physical_device *physical_device)
    100 {
    101    physical_device->vk.wsi_device = NULL;
    102    wsi_device_finish(&physical_device->wsi_device,
    103                      &physical_device->vk.instance->alloc);
    104 }
    105 
    106 static void
    107 constraint_surface_capabilities(VkSurfaceCapabilitiesKHR *caps)
    108 {
    109    /* Our display pipeline requires that images are linear, so we cannot
    110     * ensure that our swapchain images can be sampled. If we are running under
    111     * a compositor in windowed mode, the DRM modifier negotiation should
    112     * probably end up selecting an UIF layout for the swapchain images but it
    113     * may still choose linear and send images directly for scanout if the
    114     * surface is in fullscreen mode for example. If we are not running under
    115     * a compositor, then we would always need them to be linear anyway.
    116     */
    117    caps->supportedUsageFlags &= ~VK_IMAGE_USAGE_SAMPLED_BIT;
    118 }
    119 
    120 VKAPI_ATTR VkResult VKAPI_CALL
    121 v3dv_GetPhysicalDeviceSurfaceCapabilitiesKHR(
    122     VkPhysicalDevice                            physicalDevice,
    123     VkSurfaceKHR                                surface,
    124     VkSurfaceCapabilitiesKHR*                   pSurfaceCapabilities)
    125 {
    126    VkResult result;
    127    result = wsi_GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice,
    128                                                         surface,
    129                                                         pSurfaceCapabilities);
    130    constraint_surface_capabilities(pSurfaceCapabilities);
    131    return result;
    132 }
    133 
    134 VKAPI_ATTR VkResult VKAPI_CALL
    135 v3dv_GetPhysicalDeviceSurfaceCapabilities2KHR(
    136     VkPhysicalDevice                            physicalDevice,
    137     const VkPhysicalDeviceSurfaceInfo2KHR*      pSurfaceInfo,
    138     VkSurfaceCapabilities2KHR*                  pSurfaceCapabilities)
    139 {
    140    VkResult result;
    141    result = wsi_GetPhysicalDeviceSurfaceCapabilities2KHR(physicalDevice,
    142                                                          pSurfaceInfo,
    143                                                          pSurfaceCapabilities);
    144    constraint_surface_capabilities(&pSurfaceCapabilities->surfaceCapabilities);
    145    return result;
    146 }
    147 
    148 VKAPI_ATTR VkResult VKAPI_CALL
    149 v3dv_CreateSwapchainKHR(
    150     VkDevice                                     _device,
    151     const VkSwapchainCreateInfoKHR*              pCreateInfo,
    152     const VkAllocationCallbacks*                 pAllocator,
    153     VkSwapchainKHR*                              pSwapchain)
    154 {
    155    V3DV_FROM_HANDLE(v3dv_device, device, _device);
    156    struct v3dv_instance *instance = device->instance;
    157    struct v3dv_physical_device *pdevice = &instance->physicalDevice;
    158 
    159    ICD_FROM_HANDLE(VkIcdSurfaceBase, surface, pCreateInfo->surface);
    160    VkResult result =
    161       v3dv_physical_device_acquire_display(instance, pdevice, surface);
    162    if (result != VK_SUCCESS)
    163       return result;
    164 
    165    return wsi_CreateSwapchainKHR(_device, pCreateInfo, pAllocator, pSwapchain);
    166 }
    167 
    168 struct v3dv_image *
    169 v3dv_wsi_get_image_from_swapchain(VkSwapchainKHR swapchain, uint32_t index)
    170 {
    171    uint32_t n_images = index + 1;
    172    VkImage *images = malloc(sizeof(*images) * n_images);
    173    VkResult result = wsi_common_get_images(swapchain, &n_images, images);
    174 
    175    if (result != VK_SUCCESS && result != VK_INCOMPLETE) {
    176       free(images);
    177       return NULL;
    178    }
    179 
    180    V3DV_FROM_HANDLE(v3dv_image, image, images[index]);
    181    free(images);
    182 
    183    return image;
    184 }
    185 
    186 VKAPI_ATTR VkResult VKAPI_CALL
    187 v3dv_AcquireNextImage2KHR(
    188     VkDevice                                     _device,
    189     const VkAcquireNextImageInfoKHR*             pAcquireInfo,
    190     uint32_t*                                    pImageIndex)
    191 {
    192    V3DV_FROM_HANDLE(v3dv_device, device, _device);
    193    V3DV_FROM_HANDLE(v3dv_fence, fence, pAcquireInfo->fence);
    194    V3DV_FROM_HANDLE(v3dv_semaphore, semaphore, pAcquireInfo->semaphore);
    195 
    196    struct v3dv_physical_device *pdevice = &device->instance->physicalDevice;
    197 
    198    VkResult result;
    199    result = wsi_common_acquire_next_image2(&pdevice->wsi_device, _device,
    200                                            pAcquireInfo, pImageIndex);
    201 
    202    if (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR) {
    203       if (fence)
    204          drmSyncobjSignal(pdevice->render_fd, &fence->sync, 1);
    205       if (semaphore)
    206          drmSyncobjSignal(pdevice->render_fd, &semaphore->sync, 1);
    207    }
    208 
    209    return result;
    210 }
    211