Add DirectFB WSI support (#761)

This commit is contained in:
Nicolas Caramelli 2020-09-13 10:12:33 +02:00 committed by GitHub
parent ad6e36023f
commit c13a715ead
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 370 additions and 1 deletions

View file

@ -20,6 +20,7 @@ Use the provided CMakeLists.txt with [CMake](https://cmake.org) to generate a bu
##### [Window system integration](https://www.khronos.org/registry/vulkan/specs/1.0-wsi_extensions/html/vkspec.html#wsi)
- **XCB**: Default WSI (if no cmake option is specified)
- **Wayland**: Use cmake option ```USE_WAYLAND_WSI``` (```-DUSE_WAYLAND_WSI=ON```)
- **DirectFB**: Use cmake option ```USE_DIRECTFB_WSI``` (```-DUSE_DIRECTFB_WSI=ON```)
- **DirectToDisplay**: Use cmake option ```USE_D2D_WSI``` (```-DUSE_D2D_WSI=ON```)
## <img src="./images/androidlogo.png" alt="" height="32px"> [Android](android/)

View file

@ -16,6 +16,7 @@ include_directories(external/ktx/other_include)
include_directories(base)
OPTION(USE_D2D_WSI "Build the project using Direct to Display swapchain" OFF)
OPTION(USE_DIRECTFB_WSI "Build the project using DirectFB swapchain" OFF)
OPTION(USE_WAYLAND_WSI "Build the project using Wayland swapchain" OFF)
set(RESOURCE_INSTALL_DIR "" CACHE PATH "Path to install resources to (leave empty for running uninstalled)")
@ -51,6 +52,10 @@ ELSEIF(LINUX)
IF(USE_D2D_WSI)
MESSAGE("Using direct to display extension...")
add_definitions(-D_DIRECT2DISPLAY)
ELSEIF(USE_DIRECTFB_WSI)
find_package(DirectFB REQUIRED)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DVK_USE_PLATFORM_DIRECTFB_EXT")
include_directories(${DIRECTFB_INCLUDE_DIR})
ELSEIF(USE_WAYLAND_WSI)
find_program(PKG_CONFIG pkg-config)
if (NOT PKG_CONFIG)
@ -130,7 +135,7 @@ IF(WIN32)
ELSEIF(APPLE)
link_libraries(${Vulkan_LIBRARY} "-framework AppKit" "-framework QuartzCore")
ELSE(WIN32)
link_libraries(${XCB_LIBRARIES} ${Vulkan_LIBRARY} ${Vulkan_LIBRARY} ${WAYLAND_CLIENT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
link_libraries(${XCB_LIBRARIES} ${Vulkan_LIBRARY} ${Vulkan_LIBRARY} ${DIRECTFB_LIBRARIES} ${WAYLAND_CLIENT_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
ENDIF(WIN32)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/")

View file

@ -15,6 +15,8 @@
void VulkanSwapChain::initSurface(void* platformHandle, void* platformWindow)
#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
void VulkanSwapChain::initSurface(ANativeWindow* window)
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
void VulkanSwapChain::initSurface(IDirectFB* dfb, IDirectFBSurface* window)
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
void VulkanSwapChain::initSurface(wl_display *display, wl_surface *window)
#elif defined(VK_USE_PLATFORM_XCB_KHR)
@ -55,6 +57,12 @@ void VulkanSwapChain::initSurface(uint32_t width, uint32_t height)
err = vkCreateMacOSSurfaceMVK(instance, &surfaceCreateInfo, NULL, &surface);
#elif defined(_DIRECT2DISPLAY)
createDirect2DisplaySurface(width, height);
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
VkDirectFBSurfaceCreateInfoEXT surfaceCreateInfo = {};
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_DIRECTFB_SURFACE_CREATE_INFO_EXT;
surfaceCreateInfo.dfb = dfb;
surfaceCreateInfo.surface = window;
err = vkCreateDirectFBSurfaceEXT(instance, &surfaceCreateInfo, nullptr, &surface);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
VkWaylandSurfaceCreateInfoKHR surfaceCreateInfo = {};
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;

View file

@ -58,6 +58,8 @@ public:
void initSurface(void* platformHandle, void* platformWindow);
#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
void initSurface(ANativeWindow* window);
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
void initSurface(IDirectFB* dfb, IDirectFBSurface* window);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
void initSurface(wl_display* display, wl_surface* window);
#elif defined(VK_USE_PLATFORM_XCB_KHR)

View file

@ -89,6 +89,27 @@
#define KEY_O 0x1F
#define KEY_T 0x11
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
#define KEY_ESCAPE DIKS_ESCAPE
#define KEY_F1 DIKS_F1
#define KEY_F2 DIKS_F2
#define KEY_F3 DIKS_F3
#define KEY_F4 DIKS_F4
#define KEY_W DIKS_SMALL_W
#define KEY_A DIKS_SMALL_A
#define KEY_S DIKS_SMALL_S
#define KEY_D DIKS_SMALL_D
#define KEY_P DIKS_SMALL_P
#define KEY_SPACE DIKS_SPACE
#define KEY_KPADD DIKS_PLUS_SIGN
#define KEY_KPSUB DIKS_MINUS_SIGN
#define KEY_B DIKS_SMALL_B
#define KEY_F DIKS_SMALL_F
#define KEY_L DIKS_SMALL_L
#define KEY_N DIKS_SMALL_N
#define KEY_O DIKS_SMALL_O
#define KEY_T DIKS_SMALL_T
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
#include <linux/input.h>

View file

@ -41,6 +41,8 @@ VkResult VulkanExampleBase::createInstance(bool enableValidation)
instanceExtensions.push_back(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME);
#elif defined(_DIRECT2DISPLAY)
instanceExtensions.push_back(VK_KHR_DISPLAY_EXTENSION_NAME);
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
instanceExtensions.push_back(VK_EXT_DIRECTFB_SURFACE_EXTENSION_NAME);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
instanceExtensions.push_back(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME);
#elif defined(VK_USE_PLATFORM_XCB_KHR)
@ -437,6 +439,48 @@ void VulkanExampleBase::renderLoop()
}
updateOverlay();
}
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
while (!quit)
{
auto tStart = std::chrono::high_resolution_clock::now();
if (viewUpdated)
{
viewUpdated = false;
viewChanged();
}
DFBWindowEvent event;
while (!event_buffer->GetEvent(event_buffer, DFB_EVENT(&event)))
{
handleEvent(&event);
}
render();
frameCounter++;
auto tEnd = std::chrono::high_resolution_clock::now();
auto tDiff = std::chrono::duration<double, std::milli>(tEnd - tStart).count();
frameTimer = tDiff / 1000.0f;
camera.update(frameTimer);
if (camera.moving())
{
viewUpdated = true;
}
// Convert to clamped timer value
if (!paused)
{
timer += timerSpeed * frameTimer;
if (timer > 1.0)
{
timer -= 1.0f;
}
}
float fpsTimer = std::chrono::duration<double, std::milli>(tEnd - lastTimestamp).count();
if (fpsTimer > 1000.0f)
{
lastFPS = (float)frameCounter * (1000.0f / fpsTimer);
frameCounter = 0;
lastTimestamp = tEnd;
}
updateOverlay();
}
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
while (!quit)
{
@ -806,6 +850,17 @@ VulkanExampleBase::~VulkanExampleBase()
#if defined(_DIRECT2DISPLAY)
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
if (event_buffer)
event_buffer->Release(event_buffer);
if (surface)
surface->Release(surface);
if (window)
window->Release(window);
if (layer)
layer->Release(layer);
if (dfb)
dfb->Release(dfb);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
xdg_toplevel_destroy(xdg_toplevel);
xdg_surface_destroy(xdg_surface);
@ -1684,6 +1739,200 @@ void VulkanExampleBase::windowDidResize()
resizing = false;
}
#elif defined(_DIRECT2DISPLAY)
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
IDirectFBSurface *VulkanExampleBase::setupWindow()
{
DFBResult ret;
int posx = 0, posy = 0;
ret = DirectFBInit(NULL, NULL);
if (ret)
{
std::cout << "Could not initialize DirectFB!\n";
fflush(stdout);
exit(1);
}
ret = DirectFBCreate(&dfb);
if (ret)
{
std::cout << "Could not create main interface of DirectFB!\n";
fflush(stdout);
exit(1);
}
ret = dfb->GetDisplayLayer(dfb, DLID_PRIMARY, &layer);
if (ret)
{
std::cout << "Could not get DirectFB display layer interface!\n";
fflush(stdout);
exit(1);
}
DFBDisplayLayerConfig layer_config;
ret = layer->GetConfiguration(layer, &layer_config);
if (ret)
{
std::cout << "Could not get DirectFB display layer configuration!\n";
fflush(stdout);
exit(1);
}
if (settings.fullscreen)
{
width = layer_config.width;
height = layer_config.height;
}
else
{
if (layer_config.width > width)
posx = (layer_config.width - width) / 2;
if (layer_config.height > height)
posy = (layer_config.height - height) / 2;
}
DFBWindowDescription desc;
desc.flags = (DFBWindowDescriptionFlags)(DWDESC_WIDTH | DWDESC_HEIGHT | DWDESC_POSX | DWDESC_POSY);
desc.width = width;
desc.height = height;
desc.posx = posx;
desc.posy = posy;
ret = layer->CreateWindow(layer, &desc, &window);
if (ret)
{
std::cout << "Could not create DirectFB window interface!\n";
fflush(stdout);
exit(1);
}
ret = window->GetSurface(window, &surface);
if (ret)
{
std::cout << "Could not get DirectFB surface interface!\n";
fflush(stdout);
exit(1);
}
ret = window->CreateEventBuffer(window, &event_buffer);
if (ret)
{
std::cout << "Could not create DirectFB event buffer interface!\n";
fflush(stdout);
exit(1);
}
ret = window->SetOpacity(window, 0xFF);
if (ret)
{
std::cout << "Could not set DirectFB window opacity!\n";
fflush(stdout);
exit(1);
}
return surface;
}
void VulkanExampleBase::handleEvent(const DFBWindowEvent *event)
{
switch (event->type)
{
case DWET_CLOSE:
quit = true;
break;
case DWET_MOTION:
handleMouseMove(event->x, event->y);
break;
case DWET_BUTTONDOWN:
switch (event->button)
{
case DIBI_LEFT:
mouseButtons.left = true;
break;
case DIBI_MIDDLE:
mouseButtons.middle = true;
break;
case DIBI_RIGHT:
mouseButtons.right = true;
break;
default:
break;
}
break;
case DWET_BUTTONUP:
switch (event->button)
{
case DIBI_LEFT:
mouseButtons.left = false;
break;
case DIBI_MIDDLE:
mouseButtons.middle = false;
break;
case DIBI_RIGHT:
mouseButtons.right = false;
break;
default:
break;
}
break;
case DWET_KEYDOWN:
switch (event->key_symbol)
{
case KEY_W:
camera.keys.up = true;
break;
case KEY_S:
camera.keys.down = true;
break;
case KEY_A:
camera.keys.left = true;
break;
case KEY_D:
camera.keys.right = true;
break;
case KEY_P:
paused = !paused;
break;
case KEY_F1:
if (settings.overlay) {
settings.overlay = !settings.overlay;
}
break;
default:
break;
}
break;
case DWET_KEYUP:
switch (event->key_symbol)
{
case KEY_W:
camera.keys.up = false;
break;
case KEY_S:
camera.keys.down = false;
break;
case KEY_A:
camera.keys.left = false;
break;
case KEY_D:
camera.keys.right = false;
break;
case KEY_ESCAPE:
quit = true;
break;
default:
break;
}
keyPressed(event->key_symbol);
break;
case DWET_SIZE:
destWidth = event->w;
destHeight = event->h;
windowResize();
break;
default:
break;
}
}
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
/*static*/void VulkanExampleBase::registryGlobalCb(void *data,
wl_registry *registry, uint32_t name, const char *interface,
@ -2494,6 +2743,8 @@ void VulkanExampleBase::initSwapchain()
swapChain.initSurface(view);
#elif defined(_DIRECT2DISPLAY)
swapChain.initSurface(width, height);
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
swapChain.initSurface(dfb, surface);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
swapChain.initSurface(display, surface);
#elif defined(VK_USE_PLATFORM_XCB_KHR)

View file

@ -20,6 +20,8 @@
#include <android_native_app_glue.h>
#include <sys/system_properties.h>
#include "VulkanAndroid.h"
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
#include <directfb.h>
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
#include <wayland-client.h>
#include "xdg-shell-client-protocol.h"
@ -230,6 +232,13 @@ public:
int64_t lastTapTime = 0;
#elif (defined(VK_USE_PLATFORM_IOS_MVK) || defined(VK_USE_PLATFORM_MACOS_MVK))
void* view;
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
bool quit = false;
IDirectFB *dfb = nullptr;
IDirectFBDisplayLayer *layer = nullptr;
IDirectFBWindow *window = nullptr;
IDirectFBSurface *surface = nullptr;
IDirectFBEventBuffer *event_buffer = nullptr;
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
wl_display *display = nullptr;
wl_registry *registry = nullptr;
@ -273,6 +282,9 @@ public:
void mouseDragged(float x, float y);
void windowWillResize(float x, float y);
void windowDidResize();
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
IDirectFBSurface *setupWindow();
void handleEvent(const DFBWindowEvent *event);
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
struct xdg_surface *setupWindow();
void initWaylandConnection();
@ -425,6 +437,27 @@ int main(const int argc, const char *argv[]) \
delete(vulkanExample); \
return 0; \
}
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
#define VULKAN_EXAMPLE_MAIN() \
VulkanExample *vulkanExample; \
static void handleEvent(const DFBWindowEvent *event) \
{ \
if (vulkanExample != NULL) \
{ \
vulkanExample->handleEvent(event); \
} \
} \
int main(const int argc, const char *argv[]) \
{ \
for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); }; \
vulkanExample = new VulkanExample(); \
vulkanExample->initVulkan(); \
vulkanExample->setupWindow(); \
vulkanExample->prepare(); \
vulkanExample->renderLoop(); \
delete(vulkanExample); \
return 0; \
}
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
#define VULKAN_EXAMPLE_MAIN() \
VulkanExample *vulkanExample; \

28
cmake/FindDirectFB.cmake Normal file
View file

@ -0,0 +1,28 @@
# Try to find DirectFB
#
# This will define:
#
# DIRECTFB_FOUND - True if DirectFB is found
# DIRECTFB_LIBRARIES - Link these to use DirectFB
# DIRECTFB_INCLUDE_DIR - Include directory for DirectFB
# DIRECTFB_DEFINITIONS - Compiler flags for using DirectFB
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
IF (NOT WIN32)
FIND_PACKAGE(PkgConfig)
PKG_CHECK_MODULES(PKG_DIRECTFB QUIET directfb)
SET(DIRECTFB_DEFINITIONS ${PKG_DIRECTFB_CFLAGS})
FIND_PATH(DIRECTFB_INCLUDE_DIR NAMES directfb.h HINTS ${PKG_DIRECTFB_INCLUDE_DIRS})
FIND_LIBRARY(DIRECTFB_LIBRARIES NAMES directfb HINTS ${PKG_DIRECTFB_LIBRARY_DIRS})
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(DIRECTFB DEFAULT_MSG DIRECTFB_LIBRARIES DIRECTFB_INCLUDE_DIR)
MARK_AS_ADVANCED(DIRECTFB_INCLUDE_DIR DIRECTFB_LIBRARIES)
ENDIF ()

View file

@ -1151,6 +1151,26 @@ int main(const int argc, const char *argv[])
delete(vulkanExample);
return 0;
}
#elif defined(VK_USE_PLATFORM_DIRECTFB_EXT)
VulkanExample *vulkanExample;
static void handleEvent(const DFBWindowEvent *event)
{
if (vulkanExample != NULL)
{
vulkanExample->handleEvent(event);
}
}
int main(const int argc, const char *argv[])
{
for (size_t i = 0; i < argc; i++) { VulkanExample::args.push_back(argv[i]); };
vulkanExample = new VulkanExample();
vulkanExample->initVulkan();
vulkanExample->setupWindow();
vulkanExample->prepare();
vulkanExample->renderLoop();
delete(vulkanExample);
return 0;
}
#elif defined(VK_USE_PLATFORM_WAYLAND_KHR)
VulkanExample *vulkanExample;
int main(const int argc, const char *argv[])