1 2/* 3 * Copyright 2019 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9#include "vk/GrVkVulkan.h" 10 11#include "vk/GrVkInterface.h" 12#include "vk/GrVkUtil.h" 13 14#include "vk/VkTestUtils.h" 15 16#include "WindowContextFactory_mac.h" 17#include "../VulkanWindowContext.h" 18#include "vulkan/vulkan_macos.h" 19 20#import <MetalKit/MetalKit.h> 21 22namespace sk_app { 23 24class VulkanWindowContext_mac : public VulkanWindowContext { 25public: 26 VulkanWindowContext_mac(MTKView* mtkView, 27 const DisplayParams& params, 28 CreateVkSurfaceFn createVkSurface, 29 CanPresentFn canPresent, 30 PFN_vkGetInstanceProcAddr instProc, 31 PFN_vkGetDeviceProcAddr devProc); 32 33 ~VulkanWindowContext_mac() override; 34 35 void resize(int w, int h) override; 36 37private: 38 MTKView* fMTKView; 39 40 typedef VulkanWindowContext INHERITED; 41}; 42 43VulkanWindowContext_mac::VulkanWindowContext_mac(MTKView* mtkView, 44 const DisplayParams& params, 45 CreateVkSurfaceFn createVkSurface, 46 CanPresentFn canPresent, 47 PFN_vkGetInstanceProcAddr instProc, 48 PFN_vkGetDeviceProcAddr devProc) 49 : INHERITED(params, createVkSurface, canPresent, instProc, devProc) 50 , fMTKView(mtkView) { 51 52 // any config code here (particularly for msaa)? 53} 54 55VulkanWindowContext_mac::~VulkanWindowContext_mac() { 56 [fMTKView removeFromSuperview]; 57 [fMTKView release]; 58 fMTKView = nil; 59} 60 61void VulkanWindowContext_mac::resize(int w, int h) { 62 CGSize newSize; 63 newSize.width = w; 64 newSize.height = h; 65 fMTKView.drawableSize = newSize; 66 this->INHERITED::resize(w, h); 67} 68 69namespace window_context_factory { 70 71WindowContext* NewVulkanForMac(const MacWindowInfo& info, const DisplayParams& displayParams) { 72 PFN_vkGetInstanceProcAddr instProc; 73 PFN_vkGetDeviceProcAddr devProc; 74 if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) { 75 return nullptr; 76 } 77 78 // Create mtkview 79 NSRect rect = info.fMainView.frame; 80 MTKView* mtkView = [[MTKView alloc] initWithFrame:rect device:nil]; 81 if (nil == mtkView) { 82 return nullptr; 83 } 84 85 mtkView.autoResizeDrawable = NO; 86 mtkView.colorPixelFormat = MTLPixelFormatBGRA8Unorm; 87 mtkView.drawableSize = rect.size; 88 89// if (fDisplayParams.fMSAASampleCount > 1) { 90// if (![fDevice supportsTextureSampleCount:fDisplayParams.fMSAASampleCount]) { 91// return nullptr; 92// } 93// } 94// mtkView.sampleCount = fDisplayParams.fMSAASampleCount; 95 96 // attach Metal view to main view 97 [mtkView setTranslatesAutoresizingMaskIntoConstraints:NO]; 98 99 [info.fMainView addSubview:mtkView]; 100 NSDictionary *views = NSDictionaryOfVariableBindings(mtkView); 101 102 [info.fMainView addConstraints: 103 [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[mtkView]|" 104 options:0 105 metrics:nil 106 views:views]]; 107 108 [info.fMainView addConstraints: 109 [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[mtkView]|" 110 options:0 111 metrics:nil 112 views:views]]; 113 114 auto createVkSurface = [mtkView, instProc](VkInstance instance) -> VkSurfaceKHR { 115 static PFN_vkCreateMacOSSurfaceMVK createMacOSSurfaceMVK = nullptr; 116 if (!createMacOSSurfaceMVK) { 117 createMacOSSurfaceMVK = 118 (PFN_vkCreateMacOSSurfaceMVK) instProc(instance, "vkCreateMacOSSurfaceMVK"); 119 } 120 121 VkSurfaceKHR surface; 122 123 VkMacOSSurfaceCreateInfoMVK surfaceCreateInfo; 124 memset(&surfaceCreateInfo, 0, sizeof(VkMacOSSurfaceCreateInfoMVK)); 125 surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; 126 surfaceCreateInfo.pNext = nullptr; 127 surfaceCreateInfo.flags = 0; 128 surfaceCreateInfo.pView = (__bridge void*)mtkView; 129 130 VkResult res = createMacOSSurfaceMVK(instance, &surfaceCreateInfo, nullptr, &surface); 131 if (VK_SUCCESS != res) { 132 return VK_NULL_HANDLE; 133 } 134 135 return surface; 136 }; 137 138 auto canPresent = [](VkInstance instance, VkPhysicalDevice physDev, uint32_t queueFamilyIndex) { 139 return true; 140 }; 141 WindowContext* context = new VulkanWindowContext_mac(mtkView, displayParams, createVkSurface, 142 canPresent, instProc, devProc); 143 if (!context->isValid()) { 144 delete context; 145 [mtkView removeFromSuperview]; 146 [mtkView release]; 147 return nullptr; 148 } 149 return context; 150} 151 152} // namespace VulkanWindowContextFactory 153 154} // namespace sk_app 155