diff options
Diffstat (limited to 'include/pugl/detail')
-rw-r--r-- | include/pugl/detail/mac_vulkan.m | 216 | ||||
-rw-r--r-- | include/pugl/detail/win_vulkan.c | 130 | ||||
-rw-r--r-- | include/pugl/detail/x11_vulkan.c | 134 |
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); +} |