Commit 4121ab620073e98773bc8244c51788c5a3b3d40b

Sam Lantinga 2020-11-23T21:25:07

Fixed bug 5354 - DirectFB: Add Vulkan support Nicolas Caramelli This patch adds Vulkan support for the DirectFB video driver. A screenshot with SDL tests running on DirectFB is available on the HiGFXback project: https://github.com/caramelli/higfxback/wiki/DirectFB#sdl

diff --git a/src/video/SDL_vulkan_internal.h b/src/video/SDL_vulkan_internal.h
index 4e0ecbe..bc49ec4 100644
--- a/src/video/SDL_vulkan_internal.h
+++ b/src/video/SDL_vulkan_internal.h
@@ -38,6 +38,9 @@
 #if SDL_VIDEO_DRIVER_COCOA
 #define VK_USE_PLATFORM_MACOS_MVK
 #endif
+#if SDL_VIDEO_DRIVER_DIRECTFB
+#define VK_USE_PLATFORM_DIRECTFB_EXT
+#endif
 #if SDL_VIDEO_DRIVER_UIKIT
 #define VK_USE_PLATFORM_IOS_MVK
 #endif
diff --git a/src/video/directfb/SDL_DirectFB_video.c b/src/video/directfb/SDL_DirectFB_video.c
index 79fce94..bf52d98 100644
--- a/src/video/directfb/SDL_DirectFB_video.c
+++ b/src/video/directfb/SDL_DirectFB_video.c
@@ -27,6 +27,7 @@
  */
 #include "SDL_DirectFB_modes.h"
 #include "SDL_DirectFB_opengl.h"
+#include "SDL_DirectFB_vulkan.h"
 #include "SDL_DirectFB_window.h"
 #include "SDL_DirectFB_WM.h"
 
@@ -136,6 +137,13 @@ DirectFB_CreateDevice(int devindex)
     device->shape_driver.SetWindowShape = DirectFB_SetWindowShape;
     device->shape_driver.ResizeWindowShape = DirectFB_ResizeWindowShape;
 
+#if SDL_VIDEO_VULKAN
+    device->Vulkan_LoadLibrary = DirectFB_Vulkan_LoadLibrary;
+    device->Vulkan_UnloadLibrary = DirectFB_Vulkan_UnloadLibrary;
+    device->Vulkan_GetInstanceExtensions = DirectFB_Vulkan_GetInstanceExtensions;
+    device->Vulkan_CreateSurface = DirectFB_Vulkan_CreateSurface;
+#endif
+
     device->free = DirectFB_DeleteDevice;
 
     return device;
diff --git a/src/video/directfb/SDL_DirectFB_vulkan.c b/src/video/directfb/SDL_DirectFB_vulkan.c
new file mode 100644
index 0000000..3a2acae
--- /dev/null
+++ b/src/video/directfb/SDL_DirectFB_vulkan.c
@@ -0,0 +1,169 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+
+#if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_DIRECTFB
+
+#include "SDL_DirectFB_window.h"
+
+#include "SDL_loadso.h"
+#include "SDL_DirectFB_vulkan.h"
+
+int DirectFB_Vulkan_LoadLibrary(_THIS, const char *path)
+{
+    VkExtensionProperties *extensions = NULL;
+    Uint32 i, extensionCount = 0;
+    SDL_bool hasSurfaceExtension = SDL_FALSE;
+    SDL_bool hasDirectFBSurfaceExtension = SDL_FALSE;
+    PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr = NULL;
+    if(_this->vulkan_config.loader_handle)
+        return SDL_SetError("Vulkan already loaded");
+
+    /* Load the Vulkan loader library */
+    if(!path)
+        path = SDL_getenv("SDL_VULKAN_LIBRARY");
+    if(!path)
+        path = "libvulkan.so.1";
+    _this->vulkan_config.loader_handle = SDL_LoadObject(path);
+    if(!_this->vulkan_config.loader_handle)
+        return -1;
+    SDL_strlcpy(_this->vulkan_config.loader_path, path,
+                SDL_arraysize(_this->vulkan_config.loader_path));
+    vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)SDL_LoadFunction(
+        _this->vulkan_config.loader_handle, "vkGetInstanceProcAddr");
+    if(!vkGetInstanceProcAddr)
+        goto fail;
+    _this->vulkan_config.vkGetInstanceProcAddr = (void *)vkGetInstanceProcAddr;
+    _this->vulkan_config.vkEnumerateInstanceExtensionProperties =
+        (void *)((PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr)(
+            VK_NULL_HANDLE, "vkEnumerateInstanceExtensionProperties");
+    if(!_this->vulkan_config.vkEnumerateInstanceExtensionProperties)
+        goto fail;
+    extensions = SDL_Vulkan_CreateInstanceExtensionsList(
+        (PFN_vkEnumerateInstanceExtensionProperties)
+            _this->vulkan_config.vkEnumerateInstanceExtensionProperties,
+        &extensionCount);
+    if(!extensions)
+        goto fail;
+    for(i = 0; i < extensionCount; i++)
+    {
+        if(SDL_strcmp(VK_KHR_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
+            hasSurfaceExtension = SDL_TRUE;
+        else if(SDL_strcmp(VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME, extensions[i].extensionName) == 0)
+            hasDirectFBSurfaceExtension = SDL_TRUE;
+    }
+    SDL_free(extensions);
+    if(!hasSurfaceExtension)
+    {
+        SDL_SetError("Installed Vulkan doesn't implement the "
+                     VK_KHR_SURFACE_EXTENSION_NAME " extension");
+        goto fail;
+    }
+    else if(!hasDirectFBSurfaceExtension)
+    {
+        SDL_SetError("Installed Vulkan doesn't implement the "
+                     VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME "extension");
+        goto fail;
+    }
+    return 0;
+
+fail:
+    SDL_UnloadObject(_this->vulkan_config.loader_handle);
+    _this->vulkan_config.loader_handle = NULL;
+    return -1;
+}
+
+void DirectFB_Vulkan_UnloadLibrary(_THIS)
+{
+    if(_this->vulkan_config.loader_handle)
+    {
+        SDL_UnloadObject(_this->vulkan_config.loader_handle);
+        _this->vulkan_config.loader_handle = NULL;
+    }
+}
+
+SDL_bool DirectFB_Vulkan_GetInstanceExtensions(_THIS,
+                                          SDL_Window *window,
+                                          unsigned *count,
+                                          const char **names)
+{
+    static const char *const extensionsForDirectFB[] = {
+        VK_KHR_SURFACE_EXTENSION_NAME, VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME
+    };
+    if(!_this->vulkan_config.loader_handle)
+    {
+        SDL_SetError("Vulkan is not loaded");
+        return SDL_FALSE;
+    }
+    return SDL_Vulkan_GetInstanceExtensions_Helper(
+            count, names, SDL_arraysize(extensionsForDirectFB),
+            extensionsForDirectFB);
+}
+
+SDL_bool DirectFB_Vulkan_CreateSurface(_THIS,
+                                  SDL_Window *window,
+                                  VkInstance instance,
+                                  VkSurfaceKHR *surface)
+{
+    SDL_DFB_DEVICEDATA(_this);
+    SDL_DFB_WINDOWDATA(window);
+    PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr =
+        (PFN_vkGetInstanceProcAddr)_this->vulkan_config.vkGetInstanceProcAddr;
+    PFN_vkCreateDirectFBSurfaceEXT vkCreateDirectFBSurfaceEXT =
+        (PFN_vkCreateDirectFBSurfaceEXT)vkGetInstanceProcAddr(
+                                            instance,
+                                            "vkCreateDirectFBSurfaceEXT");
+    VkDirectFBSurfaceCreateInfoEXT createInfo;
+    VkResult result;
+
+    if(!_this->vulkan_config.loader_handle)
+    {
+        SDL_SetError("Vulkan is not loaded");
+        return SDL_FALSE;
+    }
+
+    if(!vkCreateDirectFBSurfaceEXT)
+    {
+        SDL_SetError(VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME
+                     " extension is not enabled in the Vulkan instance.");
+        return SDL_FALSE;
+    }
+    SDL_zero(createInfo);
+    createInfo.sType = VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT;
+    createInfo.pNext = NULL;
+    createInfo.flags = 0;
+    createInfo.dfb = devdata->dfb;
+    createInfo.surface =  windata->surface;
+    result = vkCreateDirectFBSurfaceEXT(instance, &createInfo,
+                                        NULL, surface);
+    if(result != VK_SUCCESS)
+    {
+        SDL_SetError("vkCreateDirectFBSurfaceEXT failed: %s",
+                     SDL_Vulkan_GetResultString(result));
+        return SDL_FALSE;
+    }
+    return SDL_TRUE;
+}
+
+#endif
+
+/* vim: set ts=4 sw=4 expandtab: */
diff --git a/src/video/directfb/SDL_DirectFB_vulkan.h b/src/video/directfb/SDL_DirectFB_vulkan.h
new file mode 100644
index 0000000..2e16980
--- /dev/null
+++ b/src/video/directfb/SDL_DirectFB_vulkan.h
@@ -0,0 +1,47 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2020 Sam Lantinga <slouken@libsdl.org>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "../../SDL_internal.h"
+
+#ifndef SDL_DirectFB_vulkan_h_
+#define SDL_DirectFB_vulkan_h_
+
+#include "../SDL_vulkan_internal.h"
+#include "../SDL_sysvideo.h"
+
+#if SDL_VIDEO_VULKAN && SDL_VIDEO_DRIVER_DIRECTFB
+
+int DirectFB_Vulkan_LoadLibrary(_THIS, const char *path);
+void DirectFB_Vulkan_UnloadLibrary(_THIS);
+SDL_bool DirectFB_Vulkan_GetInstanceExtensions(_THIS,
+                                          SDL_Window *window,
+                                          unsigned *count,
+                                          const char **names);
+SDL_bool DirectFB_Vulkan_CreateSurface(_THIS,
+                                  SDL_Window *window,
+                                  VkInstance instance,
+                                  VkSurfaceKHR *surface);
+
+#endif
+
+#endif /* SDL_DirectFB_vulkan_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */