video: Add Vulkan support for vivante fb
authorWladimir J. van der Laan
Sun, 19 May 2019 10:36:44 -0700
changeset 1273306d24c0395b3
parent 12732 0280fd2d02ca
child 12734 328690dfbdfb
video: Add Vulkan support for vivante fb
Vivante drivers use the VK_KHR_display extension for rendering directly
to the frame buffer. This patch adds support to the video driver for
Vulkan rendering using that method.

- Add an utility function SDL_Vulkan_Display_CreateSurface that creates
a surface using this extension. The display to use (if there are
multiple) can be overridden using the environment variable
"SDL_VULKAN_DISPLAY".

- Use this function in a new compilation unit SDL_vivantevideo.c,
which implements the SDL_VIDEO_VULKAN methods of the driver structure.
src/video/SDL_vulkan_internal.h
src/video/SDL_vulkan_utils.c
src/video/vivante/SDL_vivantevideo.c
src/video/vivante/SDL_vivantevulkan.c
src/video/vivante/SDL_vivantevulkan.h
     1.1 --- a/src/video/SDL_vulkan_internal.h	Sun May 19 01:45:15 2019 -0400
     1.2 +++ b/src/video/SDL_vulkan_internal.h	Sun May 19 10:36:44 2019 -0700
     1.3 @@ -73,6 +73,13 @@
     1.4                                                          unsigned nameCount,
     1.5                                                          const char *const *names);
     1.6  
     1.7 +/* Create a surface directly from a display connected to a physical device
     1.8 + * using the DisplayKHR extension.
     1.9 + * This needs to be passed an instance that was created with the VK_KHR_DISPLAY_EXTENSION_NAME
    1.10 + * exension. */
    1.11 +extern SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr,
    1.12 +                                                 VkInstance instance,
    1.13 +                                                 VkSurfaceKHR *surface);
    1.14  #else
    1.15  
    1.16  /* No SDL Vulkan support, just include the header for typedefs */
     2.1 --- a/src/video/SDL_vulkan_utils.c	Sun May 19 01:45:15 2019 -0400
     2.2 +++ b/src/video/SDL_vulkan_utils.c	Sun May 19 10:36:44 2019 -0700
     2.3 @@ -22,6 +22,7 @@
     2.4  
     2.5  #include "SDL_vulkan_internal.h"
     2.6  #include "SDL_error.h"
     2.7 +#include "SDL_log.h"
     2.8  
     2.9  #if SDL_VIDEO_VULKAN
    2.10  
    2.11 @@ -167,6 +168,346 @@
    2.12      return SDL_TRUE;
    2.13  }
    2.14  
    2.15 +/* Alpha modes, in order of preference */
    2.16 +static const VkDisplayPlaneAlphaFlagBitsKHR alphaModes[4] = {
    2.17 +    VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR,
    2.18 +    VK_DISPLAY_PLANE_ALPHA_GLOBAL_BIT_KHR,
    2.19 +    VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_BIT_KHR,
    2.20 +    VK_DISPLAY_PLANE_ALPHA_PER_PIXEL_PREMULTIPLIED_BIT_KHR,
    2.21 +};
    2.22 +
    2.23 +SDL_bool SDL_Vulkan_Display_CreateSurface(void *vkGetInstanceProcAddr_,
    2.24 +                                  VkInstance instance,
    2.25 +                                  VkSurfaceKHR *surface)
    2.26 +{
    2.27 +    PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
    2.28 +        (PFN_vkGetInstanceProcAddr)vkGetInstanceProcAddr_;
    2.29 +#define VULKAN_INSTANCE_FUNCTION(name)                                           \
    2.30 +    PFN_##name name = (PFN_##name)vkGetInstanceProcAddr((VkInstance)instance, #name)
    2.31 +    VULKAN_INSTANCE_FUNCTION(vkEnumeratePhysicalDevices);
    2.32 +    VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceDisplayPropertiesKHR);
    2.33 +    VULKAN_INSTANCE_FUNCTION(vkGetDisplayModePropertiesKHR);
    2.34 +    VULKAN_INSTANCE_FUNCTION(vkGetPhysicalDeviceDisplayPlanePropertiesKHR);
    2.35 +    VULKAN_INSTANCE_FUNCTION(vkGetDisplayPlaneCapabilitiesKHR);
    2.36 +    VULKAN_INSTANCE_FUNCTION(vkGetDisplayPlaneSupportedDisplaysKHR);
    2.37 +    VULKAN_INSTANCE_FUNCTION(vkCreateDisplayPlaneSurfaceKHR);
    2.38 +#undef VULKAN_INSTANCE_FUNCTION
    2.39 +    VkDisplaySurfaceCreateInfoKHR createInfo = {};
    2.40 +    VkResult result;
    2.41 +    uint32_t physicalDeviceCount = 0;
    2.42 +    VkPhysicalDevice *physicalDevices = NULL;
    2.43 +    uint32_t physicalDeviceIndex;
    2.44 +    const char *chosenDisplayId;
    2.45 +    int displayId = 0; /* Counting from physical device 0, display 0 */
    2.46 +
    2.47 +    if(!vkEnumeratePhysicalDevices ||
    2.48 +       !vkGetPhysicalDeviceDisplayPropertiesKHR ||
    2.49 +       !vkGetDisplayModePropertiesKHR ||
    2.50 +       !vkGetPhysicalDeviceDisplayPlanePropertiesKHR ||
    2.51 +       !vkGetDisplayPlaneCapabilitiesKHR ||
    2.52 +       !vkGetDisplayPlaneSupportedDisplaysKHR ||
    2.53 +       !vkCreateDisplayPlaneSurfaceKHR)
    2.54 +    {
    2.55 +        SDL_SetError(VK_KHR_DISPLAY_EXTENSION_NAME
    2.56 +                     " extension is not enabled in the Vulkan instance.");
    2.57 +        goto error;
    2.58 +    }
    2.59 +
    2.60 +    if ((chosenDisplayId = SDL_getenv("SDL_VULKAN_DISPLAY")) != NULL)
    2.61 +    {
    2.62 +        displayId = SDL_atoi(chosenDisplayId);
    2.63 +    }
    2.64 +
    2.65 +    /* Enumerate physical devices */
    2.66 +    result =
    2.67 +        vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, NULL);
    2.68 +    if(result != VK_SUCCESS)
    2.69 +    {
    2.70 +        SDL_SetError("Could not enumerate Vulkan physical devices");
    2.71 +        goto error;
    2.72 +    }
    2.73 +    if(physicalDeviceCount == 0)
    2.74 +    {
    2.75 +        SDL_SetError("No Vulkan physical devices");
    2.76 +        goto error;
    2.77 +    }
    2.78 +    physicalDevices = SDL_malloc(sizeof(VkPhysicalDevice) * physicalDeviceCount);
    2.79 +    if(!physicalDevices)
    2.80 +    {
    2.81 +        SDL_OutOfMemory();
    2.82 +        goto error;
    2.83 +    }
    2.84 +    result =
    2.85 +        vkEnumeratePhysicalDevices(instance, &physicalDeviceCount, physicalDevices);
    2.86 +    if(result != VK_SUCCESS)
    2.87 +    {
    2.88 +        SDL_SetError("Error enumerating physical devices");
    2.89 +        goto error;
    2.90 +    }
    2.91 +
    2.92 +    for(physicalDeviceIndex = 0; physicalDeviceIndex < physicalDeviceCount;
    2.93 +        physicalDeviceIndex++)
    2.94 +    {
    2.95 +		VkPhysicalDevice physicalDevice = physicalDevices[physicalDeviceIndex];
    2.96 +        uint32_t displayPropertiesCount = 0;
    2.97 +        VkDisplayPropertiesKHR *displayProperties = NULL;
    2.98 +        uint32_t displayModePropertiesCount = 0;
    2.99 +        VkDisplayModePropertiesKHR *displayModeProperties = NULL;
   2.100 +        int bestMatchIndex = -1;
   2.101 +        uint32_t refreshRate = 0;
   2.102 +        uint32_t i;
   2.103 +        uint32_t displayPlanePropertiesCount = 0;
   2.104 +        int planeIndex = -1;
   2.105 +        VkDisplayKHR display;
   2.106 +        VkDisplayPlanePropertiesKHR *displayPlaneProperties = NULL;
   2.107 +        VkExtent2D extent;
   2.108 +        VkDisplayPlaneCapabilitiesKHR planeCaps;
   2.109 +
   2.110 +        /* Get information about the physical displays */
   2.111 +        result =
   2.112 +            vkGetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, &displayPropertiesCount, NULL);
   2.113 +        if (result != VK_SUCCESS || displayPropertiesCount == 0)
   2.114 +        {
   2.115 +            /* This device has no physical device display properties, move on to next. */
   2.116 +            continue;
   2.117 +        }
   2.118 +        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of display properties for device %u: %u",
   2.119 +                physicalDeviceIndex, displayPropertiesCount);
   2.120 +
   2.121 +        if (displayId < 0 || displayId >= displayPropertiesCount)
   2.122 +        {
   2.123 +            /* Display id specified was higher than number of available displays, move to next physical device. */
   2.124 +            displayId -= displayPropertiesCount;
   2.125 +            continue;
   2.126 +        }
   2.127 +
   2.128 +        displayProperties = SDL_malloc(sizeof(VkDisplayPropertiesKHR) * displayPropertiesCount);
   2.129 +        if(!displayProperties)
   2.130 +        {
   2.131 +            SDL_OutOfMemory();
   2.132 +            goto error;
   2.133 +        }
   2.134 +
   2.135 +        result =
   2.136 +            vkGetPhysicalDeviceDisplayPropertiesKHR(physicalDevice, &displayPropertiesCount, displayProperties);
   2.137 +        if (result != VK_SUCCESS || displayPropertiesCount == 0) {
   2.138 +            SDL_free(displayProperties);
   2.139 +            SDL_SetError("Error enumerating physical device displays");
   2.140 +            goto error;
   2.141 +        }
   2.142 +
   2.143 +        display = displayProperties[displayId].display;
   2.144 +        extent = displayProperties[displayId].physicalResolution;
   2.145 +        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Display: %s Native resolution: %ux%u",
   2.146 +                displayProperties[displayId].displayName, extent.width, extent.height);
   2.147 +
   2.148 +        free(displayProperties);
   2.149 +        displayProperties = NULL;
   2.150 +
   2.151 +        /* Get display mode properties for the chosen display */
   2.152 +        result =
   2.153 +            vkGetDisplayModePropertiesKHR(physicalDevice, display, &displayModePropertiesCount, NULL);
   2.154 +        if (result != VK_SUCCESS || displayModePropertiesCount == 0)
   2.155 +        {
   2.156 +            SDL_SetError("Error enumerating display modes");
   2.157 +            goto error;
   2.158 +        }
   2.159 +        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of display modes: %u", displayModePropertiesCount);
   2.160 +
   2.161 +        displayModeProperties = SDL_malloc(sizeof(VkDisplayModePropertiesKHR) * displayModePropertiesCount);
   2.162 +        if(!displayModeProperties)
   2.163 +        {
   2.164 +            SDL_OutOfMemory();
   2.165 +            goto error;
   2.166 +        }
   2.167 +
   2.168 +        result =
   2.169 +            vkGetDisplayModePropertiesKHR(physicalDevice, display, &displayModePropertiesCount, displayModeProperties);
   2.170 +        if (result != VK_SUCCESS || displayModePropertiesCount == 0) {
   2.171 +            SDL_SetError("Error enumerating display modes");
   2.172 +            SDL_free(displayModeProperties);
   2.173 +            goto error;
   2.174 +        }
   2.175 +
   2.176 +        /* Try to find a display mode that matches the native resolution */
   2.177 +        for (i = 0; i < displayModePropertiesCount; ++i)
   2.178 +        {
   2.179 +            if (displayModeProperties[i].parameters.visibleRegion.width == extent.width &&
   2.180 +                displayModeProperties[i].parameters.visibleRegion.height == extent.height &&
   2.181 +                displayModeProperties[i].parameters.refreshRate > refreshRate)
   2.182 +            {
   2.183 +                bestMatchIndex = i;
   2.184 +                refreshRate = displayModeProperties[i].parameters.refreshRate;
   2.185 +            }
   2.186 +        }
   2.187 +        if (bestMatchIndex < 0)
   2.188 +        {
   2.189 +            SDL_SetError("Found no matching display mode");
   2.190 +            SDL_free(displayModeProperties);
   2.191 +            goto error;
   2.192 +        }
   2.193 +        createInfo.displayMode = displayModeProperties[bestMatchIndex].displayMode;
   2.194 +        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Matching mode %ux%u with refresh rate %u",
   2.195 +                displayModeProperties[bestMatchIndex].parameters.visibleRegion.width,
   2.196 +                displayModeProperties[bestMatchIndex].parameters.visibleRegion.height,
   2.197 +                refreshRate);
   2.198 +
   2.199 +        SDL_free(displayModeProperties);
   2.200 +        displayModeProperties = NULL;
   2.201 +
   2.202 +        /* Try to find a plane index that supports our display */
   2.203 +        result =
   2.204 +            vkGetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, &displayPlanePropertiesCount, NULL);
   2.205 +        if (result != VK_SUCCESS || displayPlanePropertiesCount == 0)
   2.206 +        {
   2.207 +            SDL_SetError("Error enumerating display planes");
   2.208 +            goto error;
   2.209 +        }
   2.210 +        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of display planes: %u", displayPlanePropertiesCount);
   2.211 +
   2.212 +        displayPlaneProperties = SDL_malloc(sizeof(VkDisplayPlanePropertiesKHR) * displayPlanePropertiesCount);
   2.213 +        if(!displayPlaneProperties)
   2.214 +        {
   2.215 +            SDL_OutOfMemory();
   2.216 +            goto error;
   2.217 +        }
   2.218 +
   2.219 +        result =
   2.220 +            vkGetPhysicalDeviceDisplayPlanePropertiesKHR(physicalDevice, &displayPlanePropertiesCount, displayPlaneProperties);
   2.221 +        if (result != VK_SUCCESS || displayPlanePropertiesCount == 0)
   2.222 +        {
   2.223 +            SDL_SetError("Error enumerating display plane properties");
   2.224 +            SDL_free(displayPlaneProperties);
   2.225 +            goto error;
   2.226 +        }
   2.227 +
   2.228 +        for (i = 0; i < displayPlanePropertiesCount; ++i)
   2.229 +        {
   2.230 +            uint32_t planeSupportedDisplaysCount = 0;
   2.231 +            VkDisplayKHR *planeSupportedDisplays = NULL;
   2.232 +            uint32_t j;
   2.233 +
   2.234 +            /* Check if plane is attached to a display, if not, continue. */
   2.235 +            if (displayPlaneProperties[i].currentDisplay == VK_NULL_HANDLE)
   2.236 +                continue;
   2.237 +
   2.238 +            /* Check supported displays for this plane. */
   2.239 +            result =
   2.240 +                vkGetDisplayPlaneSupportedDisplaysKHR(physicalDevice, i, &planeSupportedDisplaysCount, NULL);
   2.241 +            if (result != VK_SUCCESS || planeSupportedDisplaysCount == 0)
   2.242 +            {
   2.243 +                /* No supported displays, on to next plane. */
   2.244 +                SDL_free(displayPlaneProperties);
   2.245 +                continue;
   2.246 +            }
   2.247 +            SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Number of supported displays for plane %u: %u", i, planeSupportedDisplaysCount);
   2.248 +
   2.249 +            planeSupportedDisplays = SDL_malloc(sizeof(VkDisplayKHR) * planeSupportedDisplaysCount);
   2.250 +            if(!planeSupportedDisplays)
   2.251 +            {
   2.252 +                SDL_free(displayPlaneProperties);
   2.253 +                SDL_OutOfMemory();
   2.254 +                goto error;
   2.255 +            }
   2.256 +
   2.257 +            result =
   2.258 +                vkGetDisplayPlaneSupportedDisplaysKHR(physicalDevice, i, &planeSupportedDisplaysCount, planeSupportedDisplays);
   2.259 +            if (result != VK_SUCCESS || planeSupportedDisplaysCount == 0)
   2.260 +            {
   2.261 +                SDL_SetError("Error enumerating supported displays, or no supported displays");
   2.262 +                SDL_free(planeSupportedDisplays);
   2.263 +                SDL_free(displayPlaneProperties);
   2.264 +                goto error;
   2.265 +            }
   2.266 +
   2.267 +            for (j = 0; j < planeSupportedDisplaysCount && planeSupportedDisplays[j] != display; ++j)
   2.268 +                ;
   2.269 +
   2.270 +            SDL_free(planeSupportedDisplays);
   2.271 +            planeSupportedDisplays = NULL;
   2.272 +
   2.273 +            if (j == planeSupportedDisplaysCount)
   2.274 +            {
   2.275 +                /* This display is not supported for this plane, move on. */
   2.276 +                continue;
   2.277 +            }
   2.278 +
   2.279 +            result = vkGetDisplayPlaneCapabilitiesKHR(physicalDevice, createInfo.displayMode, i, &planeCaps);
   2.280 +            if (result != VK_SUCCESS)
   2.281 +            {
   2.282 +                SDL_SetError("Error getting display plane capabilities");
   2.283 +                SDL_free(displayPlaneProperties);
   2.284 +                goto error;
   2.285 +            }
   2.286 +
   2.287 +            /* Check if plane fulfills extent requirements. */
   2.288 +            if (extent.width >= planeCaps.minDstExtent.width && extent.height >= planeCaps.minDstExtent.height &&
   2.289 +                extent.width <= planeCaps.maxDstExtent.width && extent.height <= planeCaps.maxDstExtent.height)
   2.290 +            {
   2.291 +                /* If it does, choose this plane. */
   2.292 +                SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Choosing plane %d, minimum extent %dx%d maximum extent %dx%d", i,
   2.293 +                        planeCaps.minDstExtent.width, planeCaps.minDstExtent.height,
   2.294 +                        planeCaps.maxDstExtent.width, planeCaps.maxDstExtent.height);
   2.295 +                planeIndex = i;
   2.296 +                break;
   2.297 +            }
   2.298 +        }
   2.299 +
   2.300 +        if (planeIndex < 0)
   2.301 +        {
   2.302 +            SDL_SetError("No plane supports the selected resolution");
   2.303 +            SDL_free(displayPlaneProperties);
   2.304 +            goto error;
   2.305 +        }
   2.306 +
   2.307 +        createInfo.planeIndex = planeIndex;
   2.308 +        createInfo.planeStackIndex = displayPlaneProperties[planeIndex].currentStackIndex;
   2.309 +        SDL_free(displayPlaneProperties);
   2.310 +        displayPlaneProperties = NULL;
   2.311 +
   2.312 +        /* Find a supported alpha mode. Not all planes support OPAQUE */
   2.313 +        createInfo.alphaMode = VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR;
   2.314 +        for (uint32_t i = 0; i < SDL_arraysize(alphaModes); i++) {
   2.315 +            if (planeCaps.supportedAlpha & alphaModes[i]) {
   2.316 +                createInfo.alphaMode = alphaModes[i];
   2.317 +                break;
   2.318 +            }
   2.319 +        }
   2.320 +        SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Chose alpha mode 0x%x", createInfo.alphaMode);
   2.321 +
   2.322 +        /* Found a match, finally! Fill in extent, and break from loop */
   2.323 +        createInfo.imageExtent = extent;
   2.324 +        break;
   2.325 +    }
   2.326 +
   2.327 +    SDL_free(physicalDevices);
   2.328 +    physicalDevices = NULL;
   2.329 +
   2.330 +    if (physicalDeviceIndex == physicalDeviceCount)
   2.331 +    {
   2.332 +        SDL_SetError("No usable displays found or requested display out of range");
   2.333 +        return SDL_FALSE;
   2.334 +    }
   2.335 +
   2.336 +    createInfo.sType = VK_STRUCTURE_TYPE_DISPLAY_SURFACE_CREATE_INFO_KHR;
   2.337 +    createInfo.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;
   2.338 +    createInfo.globalAlpha = 1.0f;
   2.339 +
   2.340 +    result = vkCreateDisplayPlaneSurfaceKHR(instance, &createInfo,
   2.341 +                                       NULL, surface);
   2.342 +    if(result != VK_SUCCESS)
   2.343 +    {
   2.344 +        SDL_SetError("vkCreateDisplayPlaneSurfaceKHR failed: %s",
   2.345 +                     SDL_Vulkan_GetResultString(result));
   2.346 +        return SDL_FALSE;
   2.347 +    }
   2.348 +    SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vulkandisplay: Created surface");
   2.349 +    return SDL_TRUE;
   2.350 +error:
   2.351 +    SDL_free(physicalDevices);
   2.352 +    return SDL_FALSE;
   2.353 +}
   2.354 +
   2.355  #endif
   2.356  
   2.357  /* vi: set ts=4 sw=4 expandtab: */
     3.1 --- a/src/video/vivante/SDL_vivantevideo.c	Sun May 19 01:45:15 2019 -0400
     3.2 +++ b/src/video/vivante/SDL_vivantevideo.c	Sun May 19 10:36:44 2019 -0700
     3.3 @@ -37,6 +37,7 @@
     3.4  #include "SDL_vivantevideo.h"
     3.5  #include "SDL_vivanteplatform.h"
     3.6  #include "SDL_vivanteopengles.h"
     3.7 +#include "SDL_vivantevulkan.h"
     3.8  
     3.9  
    3.10  static int
    3.11 @@ -109,6 +110,13 @@
    3.12      device->GL_DeleteContext = VIVANTE_GLES_DeleteContext;
    3.13  #endif
    3.14  
    3.15 +#if SDL_VIDEO_VULKAN
    3.16 +    device->Vulkan_LoadLibrary = VIVANTE_Vulkan_LoadLibrary;
    3.17 +    device->Vulkan_UnloadLibrary = VIVANTE_Vulkan_UnloadLibrary;
    3.18 +    device->Vulkan_GetInstanceExtensions = VIVANTE_Vulkan_GetInstanceExtensions;
    3.19 +    device->Vulkan_CreateSurface = VIVANTE_Vulkan_CreateSurface;
    3.20 +#endif
    3.21 +
    3.22      device->PumpEvents = VIVANTE_PumpEvents;
    3.23  
    3.24      return device;
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/src/video/vivante/SDL_vivantevulkan.c	Sun May 19 10:36:44 2019 -0700
     4.3 @@ -0,0 +1,159 @@
     4.4 +/*
     4.5 +  Simple DirectMedia Layer
     4.6 +  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
     4.7 +
     4.8 +  This software is provided 'as-is', without any express or implied
     4.9 +  warranty.  In no event will the authors be held liable for any damages
    4.10 +  arising from the use of this software.
    4.11 +
    4.12 +  Permission is granted to anyone to use this software for any purpose,
    4.13 +  including commercial applications, and to alter it and redistribute it
    4.14 +  freely, subject to the following restrictions:
    4.15 +
    4.16 +  1. The origin of this software must not be misrepresented; you must not
    4.17 +     claim that you wrote the original software. If you use this software
    4.18 +     in a product, an acknowledgment in the product documentation would be
    4.19 +     appreciated but is not required.
    4.20 +  2. Altered source versions must be plainly marked as such, and must not be
    4.21 +     misrepresented as being the original software.
    4.22 +  3. This notice may not be removed or altered from any source distribution.
    4.23 +*/
    4.24 +
    4.25 +/*
    4.26 + * @author Wladimir J. van der Laan. Based on Jacob Lifshay's
    4.27 + * SDL_x11vulkan.c, Mark Callow's SDL_androidvulkan.c, and
    4.28 + * the FSL demo framework.
    4.29 + */
    4.30 +
    4.31 +#include "../../SDL_internal.h"
    4.32 +
    4.33 +#if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_VIVANTE
    4.34 +
    4.35 +#include "SDL_vivantevideo.h"
    4.36 +#include "SDL_assert.h"
    4.37 +
    4.38 +#include "SDL_loadso.h"
    4.39 +#include "SDL_vivantevulkan.h"
    4.40 +#include "SDL_syswm.h"
    4.41 +#include "SDL_log.h"
    4.42 +
    4.43 +int VIVANTE_Vulkan_LoadLibrary(_THIS, const char *path)
    4.44 +{
    4.45 +    VkExtensionProperties *extensions = NULL;
    4.46 +    Uint32 i, extensionCount = 0;
    4.47 +    SDL_bool hasSurfaceExtension = SDL_FALSE;
    4.48 +    SDL_bool hasDisplayExtension = SDL_FALSE;
    4.49 +    PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
    4.50 +    if(_this->vulkan_config.loader_handle)
    4.51 +        return SDL_SetError("Vulkan already loaded");
    4.52 +
    4.53 +    /* Load the Vulkan loader library */
    4.54 +    if(!path)
    4.55 +        path = SDL_getenv("SDL_VULKAN_LIBRARY");
    4.56 +    if(!path)
    4.57 +    {
    4.58 +        /* If no path set, try Vivante fb vulkan driver explicitly */
    4.59 +        path = "libvulkan-fb.so";
    4.60 +        _this->vulkan_config.loader_handle = SDL_LoadObject(path);
    4.61 +        if(!_this->vulkan_config.loader_handle)
    4.62 +        {
    4.63 +            /* If that couldn't be loaded, fall back to default name */
    4.64 +            path = "libvulkan.so";
    4.65 +            _this->vulkan_config.loader_handle = SDL_LoadObject(path);
    4.66 +        }
    4.67 +    } else {
    4.68 +        _this->vulkan_config.loader_handle = SDL_LoadObject(path);
    4.69 +    }
    4.70 +    if(!_this->vulkan_config.loader_handle)
    4.71 +        return -1;
    4.72 +    SDL_strlcpy(_this->vulkan_config.loader_path, path,
    4.73 +                SDL_arraysize(_this->vulkan_config.loader_path));
    4.74 +    SDL_LogDebug(SDL_LOG_CATEGORY_VIDEO, "vivante: Loaded vulkan driver %s", path);
    4.75 +    vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
    4.76 +        _this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
    4.77 +    if(!vkGetInstanceProcAddr)
    4.78 +        goto fail;
    4.79 +    _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
    4.80 +    _this->vulkan_config.vkEnumerateInstanceExtensionProperties =
    4.81 +        (void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
    4.82 +            VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
    4.83 +    if(!_this->vulkan_config.vkEnumerateInstanceExtensionProperties)
    4.84 +        goto fail;
    4.85 +    extensions = SDL_Vulkan_CreateInstanceExtensionsList(
    4.86 +        (PFN_vkEnumerateInstanceExtensionProperties)
    4.87 +            _this->vulkan_config.vkEnumerateInstanceExtensionProperties,
    4.88 +        &extensionCount);
    4.89 +    if(!extensions)
    4.90 +        goto fail;
    4.91 +    for(i = 0; i < extensionCount; i++)
    4.92 +    {
    4.93 +        if(SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
    4.94 +            hasSurfaceExtension = SDL_TRUE;
    4.95 +        else if(SDL_strcmp(VK_KHR_DISPLAY_EXTENSION_NAME, extensions[i].extensionName) == 0)
    4.96 +            hasDisplayExtension = SDL_TRUE;
    4.97 +    }
    4.98 +    SDL_free(extensions);
    4.99 +    if(!hasSurfaceExtension)
   4.100 +    {
   4.101 +        SDL_SetError("Installed Vulkan doesn't implement the "
   4.102 +                     VK_KHR_SURFACE_EXTENSION_NAME " extension");
   4.103 +        goto fail;
   4.104 +    }
   4.105 +    else if(!hasDisplayExtension)
   4.106 +    {
   4.107 +        SDL_SetError("Installed Vulkan doesn't implement the "
   4.108 +                     VK_KHR_DISPLAY_EXTENSION_NAME "extension");
   4.109 +        goto fail;
   4.110 +    }
   4.111 +    return 0;
   4.112 +
   4.113 +fail:
   4.114 +    SDL_UnloadObject(_this->vulkan_config.loader_handle);
   4.115 +    _this->vulkan_config.loader_handle = NULL;
   4.116 +    return -1;
   4.117 +}
   4.118 +
   4.119 +void VIVANTE_Vulkan_UnloadLibrary(_THIS)
   4.120 +{
   4.121 +    if(_this->vulkan_config.loader_handle)
   4.122 +    {
   4.123 +        SDL_UnloadObject(_this->vulkan_config.loader_handle);
   4.124 +        _this->vulkan_config.loader_handle = NULL;
   4.125 +    }
   4.126 +}
   4.127 +
   4.128 +SDL_bool VIVANTE_Vulkan_GetInstanceExtensions(_THIS,
   4.129 +                                          SDL_Window *window,
   4.130 +                                          unsigned *count,
   4.131 +                                          const char **names)
   4.132 +{
   4.133 +    static const char *const extensionsForVivante[] = {
   4.134 +        VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_DISPLAY_EXTENSION_NAME
   4.135 +    };
   4.136 +    if(!_this->vulkan_config.loader_handle)
   4.137 +    {
   4.138 +        SDL_SetError("Vulkan is not loaded");
   4.139 +        return SDL_FALSE;
   4.140 +    }
   4.141 +    return SDL_Vulkan_GetInstanceExtensions_Helper(
   4.142 +            count, names, SDL_arraysize(extensionsForVivante),
   4.143 +            extensionsForVivante);
   4.144 +}
   4.145 +
   4.146 +SDL_bool VIVANTE_Vulkan_CreateSurface(_THIS,
   4.147 +                                  SDL_Window *window,
   4.148 +                                  VkInstance instance,
   4.149 +                                  VkSurfaceKHR *surface)
   4.150 +{
   4.151 +    if(!_this->vulkan_config.loader_handle)
   4.152 +    {
   4.153 +        SDL_SetError("Vulkan is not loaded");
   4.154 +        return SDL_FALSE;
   4.155 +    }
   4.156 +    return SDL_Vulkan_Display_CreateSurface(_this->vulkan_config.vkGetInstanceProcAddr, instance, surface);
   4.157 +}
   4.158 +
   4.159 +#endif
   4.160 +
   4.161 +/* vi: set ts=4 sw=4 expandtab: */
   4.162 +
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/src/video/vivante/SDL_vivantevulkan.h	Sun May 19 10:36:44 2019 -0700
     5.3 @@ -0,0 +1,53 @@
     5.4 +/*
     5.5 +  Simple DirectMedia Layer
     5.6 +  Copyright (C) 1997-2017 Sam Lantinga <slouken@libsdl.org>
     5.7 +
     5.8 +  This software is provided 'as-is', without any express or implied
     5.9 +  warranty.  In no event will the authors be held liable for any damages
    5.10 +  arising from the use of this software.
    5.11 +
    5.12 +  Permission is granted to anyone to use this software for any purpose,
    5.13 +  including commercial applications, and to alter it and redistribute it
    5.14 +  freely, subject to the following restrictions:
    5.15 +
    5.16 +  1. The origin of this software must not be misrepresented; you must not
    5.17 +     claim that you wrote the original software. If you use this software
    5.18 +     in a product, an acknowledgment in the product documentation would be
    5.19 +     appreciated but is not required.
    5.20 +  2. Altered source versions must be plainly marked as such, and must not be
    5.21 +     misrepresented as being the original software.
    5.22 +  3. This notice may not be removed or altered from any source distribution.
    5.23 +*/
    5.24 +
    5.25 +/*
    5.26 + * @author Wladimir J. van der Laan. Based on Jacob Lifshay's
    5.27 + * SDL_x11vulkan.h and Mark Callow's SDL_vivantevulkan.h
    5.28 + */
    5.29 +
    5.30 +#include "../../SDL_internal.h"
    5.31 +
    5.32 +#ifndef SDL_vivantevulkan_h_
    5.33 +#define SDL_vivantevulkan_h_
    5.34 +
    5.35 +#include "../SDL_vulkan_internal.h"
    5.36 +#include "../SDL_sysvideo.h"
    5.37 +
    5.38 +#if SDL_VIDEO_VULKAN &&  SDL_VIDEO_DRIVER_VIVANTE
    5.39 +
    5.40 +int VIVANTE_Vulkan_LoadLibrary(_THIS, const char *path);
    5.41 +void VIVANTE_Vulkan_UnloadLibrary(_THIS);
    5.42 +SDL_bool VIVANTE_Vulkan_GetInstanceExtensions(_THIS,
    5.43 +                                          SDL_Window *window,
    5.44 +                                          unsigned *count,
    5.45 +                                          const char **names);
    5.46 +SDL_bool VIVANTE_Vulkan_CreateSurface(_THIS,
    5.47 +                                  SDL_Window *window,
    5.48 +                                  VkInstance instance,
    5.49 +                                  VkSurfaceKHR *surface);
    5.50 +
    5.51 +#endif
    5.52 +
    5.53 +#endif /* SDL_vivantevulkan_h_ */
    5.54 +
    5.55 +/* vi: set ts=4 sw=4 expandtab: */
    5.56 +