aboutsummaryrefslogtreecommitdiffstats
path: root/include/pugl/detail
diff options
context:
space:
mode:
authorDavid Robillard <d@drobilla.net>2020-10-26 20:48:49 +0100
committerDavid Robillard <d@drobilla.net>2020-10-26 20:48:49 +0100
commit1bcc437a37d80e3ad0e6f1dbd5ba858f933a0846 (patch)
tree52b03df6250be1c5af214ed0b1b043301b9dd0fe /include/pugl/detail
parent472d42f2678cfb60eef9ea181976c4389d4661df (diff)
downloadpugl-1bcc437a37d80e3ad0e6f1dbd5ba858f933a0846.tar.gz
pugl-1bcc437a37d80e3ad0e6f1dbd5ba858f933a0846.tar.bz2
pugl-1bcc437a37d80e3ad0e6f1dbd5ba858f933a0846.zip
Add Vulkan backends
Diffstat (limited to 'include/pugl/detail')
-rw-r--r--include/pugl/detail/mac_vulkan.m216
-rw-r--r--include/pugl/detail/win_vulkan.c130
-rw-r--r--include/pugl/detail/x11_vulkan.c134
3 files changed, 480 insertions, 0 deletions
diff --git a/include/pugl/detail/mac_vulkan.m b/include/pugl/detail/mac_vulkan.m
new file mode 100644
index 0000000..813e0ae
--- /dev/null
+++ b/include/pugl/detail/mac_vulkan.m
@@ -0,0 +1,216 @@
+/*
+ Copyright 2012-2020 David Robillard <http://drobilla.net>
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/**
+ @file mac_vulkan.m Vulkan graphics backend for MacOS.
+*/
+
+#define VK_NO_PROTOTYPES 1
+
+#include "pugl/detail/implementation.h"
+#include "pugl/detail/mac.h"
+#include "pugl/detail/stub.h"
+#include "pugl/detail/types.h"
+#include "pugl/pugl.h"
+#include "pugl/pugl_stub.h"
+#include "pugl/pugl_vulkan.h"
+
+#include <vulkan/vulkan_core.h>
+#include <vulkan/vulkan_macos.h>
+
+#import <Cocoa/Cocoa.h>
+#import <QuartzCore/CAMetalLayer.h>
+
+#include <dlfcn.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+
+@interface PuglVulkanView : NSView<CALayerDelegate>
+
+@end
+
+@implementation PuglVulkanView
+{
+@public
+ PuglView* puglview;
+}
+
+- (id)initWithFrame:(NSRect)frame
+{
+ self = [super initWithFrame:frame];
+
+ if (self) {
+ self.wantsLayer = YES;
+ self.layerContentsRedrawPolicy =
+ NSViewLayerContentsRedrawOnSetNeedsDisplay;
+ }
+
+ return self;
+}
+
+- (CALayer*)makeBackingLayer
+{
+ CAMetalLayer* layer = [CAMetalLayer layer];
+ [layer setDelegate:self];
+ return layer;
+}
+
+- (void)setFrameSize:(NSSize)newSize
+{
+ PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
+
+ [super setFrameSize:newSize];
+ [wrapper setReshaped];
+
+ self.layer.frame = self.bounds;
+}
+
+- (void)displayLayer:(CALayer*)layer
+{
+ (void)layer;
+ PuglWrapperView* wrapper = (PuglWrapperView*)[self superview];
+ [wrapper dispatchExpose:[self bounds]];
+}
+
+@end
+
+static PuglStatus
+puglMacVulkanCreate(PuglView* view)
+{
+ PuglInternals* impl = view->impl;
+ PuglVulkanView* drawView = [PuglVulkanView alloc];
+ const NSRect rect = NSMakeRect(0, 0, view->frame.width, view->frame.height);
+
+ drawView->puglview = view;
+ [drawView initWithFrame:rect];
+ if (view->hints[PUGL_RESIZABLE]) {
+ [drawView setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+ } else {
+ [drawView setAutoresizingMask:NSViewNotSizable];
+ }
+
+ impl->drawView = drawView;
+ return PUGL_SUCCESS;
+}
+
+static PuglStatus
+puglMacVulkanDestroy(PuglView* view)
+{
+ PuglVulkanView* const drawView = (PuglVulkanView*)view->impl->drawView;
+
+ [drawView removeFromSuperview];
+ [drawView release];
+
+ view->impl->drawView = nil;
+ return PUGL_SUCCESS;
+}
+
+struct PuglVulkanLoaderImpl {
+ void* libvulkan;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+ PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
+};
+
+PuglVulkanLoader*
+puglNewVulkanLoader(PuglWorld* PUGL_UNUSED(world))
+{
+ PuglVulkanLoader* loader = (PuglVulkanLoader*)
+ calloc(1, sizeof(PuglVulkanLoader));
+ if (!loader) {
+ return NULL;
+ }
+
+ if (!(loader->libvulkan = dlopen("libvulkan.dylib", RTLD_LAZY))) {
+ free(loader);
+ return NULL;
+ }
+
+ loader->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)
+ dlsym(loader->libvulkan, "vkGetInstanceProcAddr");
+
+ loader->vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)
+ dlsym(loader->libvulkan, "vkGetDeviceProcAddr");
+
+ return loader;
+}
+
+void
+puglFreeVulkanLoader(PuglVulkanLoader* loader)
+{
+ if (loader) {
+ dlclose(loader->libvulkan);
+ free(loader);
+ }
+}
+
+PFN_vkGetInstanceProcAddr
+puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader)
+{
+ return loader->vkGetInstanceProcAddr;
+}
+
+PFN_vkGetDeviceProcAddr
+puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader)
+{
+ return loader->vkGetDeviceProcAddr;
+}
+
+const PuglBackend*
+puglVulkanBackend(void)
+{
+ static const PuglBackend backend = {puglStubConfigure,
+ puglMacVulkanCreate,
+ puglMacVulkanDestroy,
+ puglStubEnter,
+ puglStubLeave,
+ puglStubGetContext};
+
+ return &backend;
+}
+
+const char* const*
+puglGetInstanceExtensions(uint32_t* const count)
+{
+ static const char* const extensions[] = {"VK_KHR_surface",
+ "VK_MVK_macos_surface"};
+
+ *count = 2;
+ return extensions;
+}
+
+VkResult
+puglCreateSurface(const PuglVulkanLoader* const loader,
+ PuglView* const view,
+ VkInstance instance,
+ const VkAllocationCallbacks* const allocator,
+ VkSurfaceKHR* const surface)
+{
+ PuglInternals* const impl = view->impl;
+
+ PFN_vkCreateMacOSSurfaceMVK vkCreateMacOSSurfaceMVK =
+ (PFN_vkCreateMacOSSurfaceMVK)puglGetInstanceProcAddrFunc(
+ loader)(instance, "vkCreateMacOSSurfaceMVK");
+
+ const VkMacOSSurfaceCreateInfoMVK info = {
+ VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK,
+ NULL,
+ 0,
+ impl->drawView,
+ };
+
+ return vkCreateMacOSSurfaceMVK(instance, &info, allocator, surface);
+}
diff --git a/include/pugl/detail/win_vulkan.c b/include/pugl/detail/win_vulkan.c
new file mode 100644
index 0000000..cfe3613
--- /dev/null
+++ b/include/pugl/detail/win_vulkan.c
@@ -0,0 +1,130 @@
+/*
+ Copyright 2012-2020 David Robillard <http://drobilla.net>
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/**
+ @file win_vulkan.c Vulkan graphics backend for Windows.
+*/
+
+#define VK_NO_PROTOTYPES 1
+
+#include "pugl/detail/stub.h"
+#include "pugl/detail/types.h"
+#include "pugl/detail/win.h"
+#include "pugl/pugl_stub.h"
+#include "pugl/pugl_vulkan.h"
+
+#include <vulkan/vulkan.h>
+#include <vulkan/vulkan_win32.h>
+
+#include <stdlib.h>
+
+struct PuglVulkanLoaderImpl
+{
+ HMODULE libvulkan;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+ PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
+};
+
+PuglVulkanLoader*
+puglNewVulkanLoader(PuglWorld* PUGL_UNUSED(world))
+{
+ PuglVulkanLoader* loader =
+ (PuglVulkanLoader*)calloc(1, sizeof(PuglVulkanLoader));
+ if (!loader) {
+ return NULL;
+ }
+
+ if (!(loader->libvulkan = LoadLibrary("vulkan-1.dll"))) {
+ free(loader);
+ return NULL;
+ }
+
+ loader->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)GetProcAddress(
+ loader->libvulkan, "vkGetInstanceProcAddr");
+
+ loader->vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)GetProcAddress(
+ loader->libvulkan, "vkGetDeviceProcAddr");
+
+ return loader;
+}
+
+void
+puglFreeVulkanLoader(PuglVulkanLoader* loader)
+{
+ if (loader) {
+ FreeLibrary(loader->libvulkan);
+ free(loader);
+ }
+}
+
+PFN_vkGetInstanceProcAddr
+puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader)
+{
+ return loader->vkGetInstanceProcAddr;
+}
+
+PFN_vkGetDeviceProcAddr
+puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader)
+{
+ return loader->vkGetDeviceProcAddr;
+}
+
+const PuglBackend*
+puglVulkanBackend()
+{
+ static const PuglBackend backend = {puglWinStubConfigure,
+ puglStubCreate,
+ puglStubDestroy,
+ puglWinStubEnter,
+ puglWinStubLeave,
+ puglStubGetContext};
+
+ return &backend;
+}
+
+const char* const*
+puglGetInstanceExtensions(uint32_t* const count)
+{
+ static const char* const extensions[] = {"VK_KHR_surface",
+ "VK_KHR_win32_surface"};
+
+ *count = 2;
+ return extensions;
+}
+
+VkResult
+puglCreateSurface(const PuglVulkanLoader* const loader,
+ PuglView* const view,
+ VkInstance instance,
+ const VkAllocationCallbacks* const pAllocator,
+ VkSurfaceKHR* const pSurface)
+{
+ PuglInternals* const impl = view->impl;
+
+ PFN_vkCreateWin32SurfaceKHR vkCreateWin32SurfaceKHR =
+ (PFN_vkCreateWin32SurfaceKHR)puglGetInstanceProcAddrFunc(loader)(
+ instance, "vkCreateWin32SurfaceKHR");
+
+ const VkWin32SurfaceCreateInfoKHR createInfo = {
+ VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR,
+ NULL,
+ 0,
+ GetModuleHandle(NULL),
+ impl->hwnd,
+ };
+
+ return vkCreateWin32SurfaceKHR(instance, &createInfo, pAllocator, pSurface);
+}
diff --git a/include/pugl/detail/x11_vulkan.c b/include/pugl/detail/x11_vulkan.c
new file mode 100644
index 0000000..0bd1532
--- /dev/null
+++ b/include/pugl/detail/x11_vulkan.c
@@ -0,0 +1,134 @@
+/*
+ Copyright 2012-2020 David Robillard <http://drobilla.net>
+
+ Permission to use, copy, modify, and/or distribute this software for any
+ purpose with or without fee is hereby granted, provided that the above
+ copyright notice and this permission notice appear in all copies.
+
+ THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+/**
+ @file x11_vulkan.c Vulkan graphics backend for X11.
+*/
+
+#define VK_NO_PROTOTYPES 1
+
+#include "pugl/detail/stub.h"
+#include "pugl/detail/types.h"
+#include "pugl/detail/x11.h"
+#include "pugl/pugl.h"
+#include "pugl/pugl_vulkan.h"
+
+#include <vulkan/vulkan_core.h>
+#include <vulkan/vulkan_xlib.h>
+
+#include <dlfcn.h>
+
+#include <stdint.h>
+#include <stdlib.h>
+
+struct PuglVulkanLoaderImpl
+{
+ void* libvulkan;
+ PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr;
+ PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr;
+};
+
+PuglVulkanLoader*
+puglNewVulkanLoader(PuglWorld* PUGL_UNUSED(world))
+{
+ PuglVulkanLoader* loader =
+ (PuglVulkanLoader*)calloc(1, sizeof(PuglVulkanLoader));
+ if (!loader) {
+ return NULL;
+ }
+
+ if (!(loader->libvulkan = dlopen("libvulkan.so", RTLD_LAZY))) {
+ free(loader);
+ return NULL;
+ }
+
+ loader->vkGetInstanceProcAddr = (PFN_vkGetInstanceProcAddr)dlsym(
+ loader->libvulkan, "vkGetInstanceProcAddr");
+
+ loader->vkGetDeviceProcAddr = (PFN_vkGetDeviceProcAddr)dlsym(
+ loader->libvulkan, "vkGetDeviceProcAddr");
+
+ return loader;
+}
+
+void
+puglFreeVulkanLoader(PuglVulkanLoader* loader)
+{
+ if (loader) {
+ dlclose(loader->libvulkan);
+ free(loader);
+ }
+}
+
+PFN_vkGetInstanceProcAddr
+puglGetInstanceProcAddrFunc(const PuglVulkanLoader* loader)
+{
+ return loader->vkGetInstanceProcAddr;
+}
+
+PFN_vkGetDeviceProcAddr
+puglGetDeviceProcAddrFunc(const PuglVulkanLoader* loader)
+{
+ return loader->vkGetDeviceProcAddr;
+}
+
+const PuglBackend*
+puglVulkanBackend(void)
+{
+ static const PuglBackend backend = {puglX11StubConfigure,
+ puglStubCreate,
+ puglStubDestroy,
+ puglStubEnter,
+ puglStubLeave,
+ puglStubGetContext};
+
+ return &backend;
+}
+
+const char* const*
+puglGetInstanceExtensions(uint32_t* const count)
+{
+ static const char* const extensions[] = {"VK_KHR_surface",
+ "VK_KHR_xlib_surface"};
+
+ *count = 2;
+ return extensions;
+}
+
+VkResult
+puglCreateSurface(const PuglVulkanLoader* const loader,
+ PuglView* const view,
+ VkInstance instance,
+ const VkAllocationCallbacks* const allocator,
+ VkSurfaceKHR* const surface)
+{
+ PuglInternals* const impl = view->impl;
+ PuglWorldInternals* world_impl = view->world->impl;
+
+ PFN_vkCreateXlibSurfaceKHR vkCreateXlibSurfaceKHR =
+ (PFN_vkCreateXlibSurfaceKHR)puglGetInstanceProcAddrFunc(loader)(
+ instance, "vkCreateXlibSurfaceKHR");
+
+ const VkXlibSurfaceCreateInfoKHR info = {
+ VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR,
+ NULL,
+ 0,
+ world_impl->display,
+ impl->win,
+ };
+
+ return vkCreateXlibSurfaceKHR(instance, &info, allocator, surface);
+}