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 "include/gpu/vk/GrVkVulkan.h" 10 11#include "src/gpu/vk/GrVkInterface.h" 12#include "src/gpu/vk/GrVkUtil.h" 13 14#include "tools/gpu/vk/VkTestUtils.h" 15 16#include "include/third_party/vulkan/vulkan/vulkan_macos.h" 17#include "tools/sk_app/VulkanWindowContext.h" 18#include "tools/sk_app/mac/WindowContextFactory_mac.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 71std::unique_ptr<WindowContext> MakeVulkanForMac(const MacWindowInfo& info, 72 const DisplayParams& displayParams) { 73 PFN_vkGetInstanceProcAddr instProc; 74 PFN_vkGetDeviceProcAddr devProc; 75 if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) { 76 return nullptr; 77 } 78 79 // Create mtkview 80 NSRect rect = info.fMainView.frame; 81 MTKView* mtkView = [[MTKView alloc] initWithFrame:rect device:nil]; 82 if (nil == mtkView) { 83 return nullptr; 84 } 85 86 mtkView.autoResizeDrawable = NO; 87 mtkView.colorPixelFormat = MTLPixelFormatBGRA8Unorm; 88 mtkView.drawableSize = rect.size; 89 90// if (fDisplayParams.fMSAASampleCount > 1) { 91// if (![fDevice supportsTextureSampleCount:fDisplayParams.fMSAASampleCount]) { 92// return nullptr; 93// } 94// } 95// mtkView.sampleCount = fDisplayParams.fMSAASampleCount; 96 97 // attach Metal view to main view 98 [mtkView setTranslatesAutoresizingMaskIntoConstraints:NO]; 99 100 [info.fMainView addSubview:mtkView]; 101 NSDictionary *views = NSDictionaryOfVariableBindings(mtkView); 102 103 [info.fMainView addConstraints: 104 [NSLayoutConstraint constraintsWithVisualFormat:@"H:|[mtkView]|" 105 options:0 106 metrics:nil 107 views:views]]; 108 109 [info.fMainView addConstraints: 110 [NSLayoutConstraint constraintsWithVisualFormat:@"V:|[mtkView]|" 111 options:0 112 metrics:nil 113 views:views]]; 114 115 auto createVkSurface = [mtkView, instProc](VkInstance instance) -> VkSurfaceKHR { 116 static PFN_vkCreateMacOSSurfaceMVK createMacOSSurfaceMVK = nullptr; 117 if (!createMacOSSurfaceMVK) { 118 createMacOSSurfaceMVK = 119 (PFN_vkCreateMacOSSurfaceMVK) instProc(instance, "vkCreateMacOSSurfaceMVK"); 120 } 121 122 VkSurfaceKHR surface; 123 124 VkMacOSSurfaceCreateInfoMVK surfaceCreateInfo; 125 memset(&surfaceCreateInfo, 0, sizeof(VkMacOSSurfaceCreateInfoMVK)); 126 surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK; 127 surfaceCreateInfo.pNext = nullptr; 128 surfaceCreateInfo.flags = 0; 129 surfaceCreateInfo.pView = (__bridge void*)mtkView; 130 131 VkResult res = createMacOSSurfaceMVK(instance, &surfaceCreateInfo, nullptr, &surface); 132 if (VK_SUCCESS != res) { 133 return VK_NULL_HANDLE; 134 } 135 136 return surface; 137 }; 138 139 auto canPresent = [](VkInstance instance, VkPhysicalDevice physDev, uint32_t queueFamilyIndex) { 140 return true; 141 }; 142 std::unique_ptr<WindowContext> ctx(new VulkanWindowContext_mac( 143 mtkView, displayParams, createVkSurface, canPresent, instProc, devProc)); 144 if (!ctx->isValid()) { 145 ctx = nullptr; 146 [mtkView removeFromSuperview]; 147 [mtkView release]; 148 return nullptr; 149 } 150 return ctx; 151} 152 153} // namespace VulkanWindowContextFactory 154 155} // namespace sk_app 156