1 /* 2 * Copyright (c) 2021 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 #include <chrono> 16 #include <thread> 17 #include <unistd.h> 18 #include <window.h> 19 #include <gtest/gtest.h> 20 #include <dlfcn.h> 21 #include <iostream> 22 #include <string> 23 #include <vector> 24 25 #include "refbase.h" 26 #include "surface.h" 27 #include "vulkan/vulkan.h" 28 #include "render_context/render_context.h" 29 #include "transaction/rs_transaction.h" 30 #include "ui/rs_surface_extractor.h" 31 #include "ui/rs_surface_node.h" 32 #include "wm/window.h" 33 34 using namespace testing; 35 using namespace testing::ext; 36 37 namespace OHOS::Rosen { 38 39 typedef bool (*PFN_IsSupportedVulkan)(); 40 41 class VulkanWrapperApiTest : public testing::Test { 42 public: SetUpTestCase()43 static void SetUpTestCase() {} TearDownTestCase()44 static void TearDownTestCase() 45 { 46 if (libVulkan != nullptr) { 47 dlclose(libVulkan); 48 libVulkan = nullptr; 49 } 50 } 51 52 static inline PFN_vkCreateInstance vkCreateInstance; 53 static inline PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR; 54 static inline PFN_vkCreateDevice vkCreateDevice; 55 static inline PFN_vkEnumerateInstanceExtensionProperties vkEnumerateInstanceExtensionProperties; 56 static inline PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr; 57 static inline PFN_vkGetInstanceProcAddr vkGetInstanceProcAddr; 58 static inline PFN_vkEnumeratePhysicalDevices vkEnumeratePhysicalDevices; 59 static inline PFN_vkCreateOHOSSurfaceOpenHarmony vkCreateOHOSSurfaceOpenHarmony; 60 static inline PFN_vkGetPhysicalDeviceSurfaceSupportKHR fpGetPhysicalDeviceSurfaceSupportKHR; 61 static inline PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR fpGetPhysicalDeviceSurfaceCapabilitiesKHR; 62 static inline PFN_vkGetPhysicalDeviceSurfaceFormatsKHR fpGetPhysicalDeviceSurfaceFormatsKHR; 63 static inline PFN_vkGetPhysicalDeviceSurfacePresentModesKHR fpGetPhysicalDeviceSurfacePresentModesKHR; 64 static inline PFN_vkCreateSwapchainKHR fpCreateSwapchainKHR; 65 static inline PFN_vkDestroySwapchainKHR fpDestroySwapchainKHR; 66 static inline PFN_vkGetSwapchainImagesKHR fpGetSwapchainImagesKHR; 67 static inline PFN_vkAcquireNextImageKHR fpAcquireNextImageKHR; 68 static inline PFN_vkQueuePresentKHR fpQueuePresentKHR; 69 static inline PFN_IsSupportedVulkan fpIsSupportedVulkan; 70 71 static inline void *libVulkan = nullptr; 72 static inline VkInstance instance = nullptr; 73 static inline VkSurfaceKHR surface = VK_NULL_HANDLE; 74 static inline VkPhysicalDevice physicalDevice = nullptr; 75 static inline VkDevice device = nullptr; 76 static inline VkSwapchainKHR swapChain = VK_NULL_HANDLE; 77 static inline bool isSupportedVulkan = false; 78 }; 79 80 /** 81 * @tc.name: dlopen libvulkan.so 82 * @tc.desc: dlopen libvulkan.so 83 * @tc.type: FUNC 84 * @tc.require: issueI5ODXM 85 */ 86 HWTEST_F(VulkanWrapperApiTest, dlopen_Test, TestSize.Level1) 87 { 88 #ifdef __aarch64__ 89 const char *path = "/system/lib64/libvulkan.so"; 90 #else 91 const char *path = "/system/lib/libvulkan.so"; 92 #endif 93 libVulkan = dlopen(path, RTLD_NOW | RTLD_LOCAL); 94 EXPECT_NE(libVulkan, nullptr); 95 } 96 97 /** 98 * @tc.name: Load base function pointers 99 * @tc.desc: Load base function pointers 100 * @tc.type: FUNC 101 * @tc.require: issueI5ODXM 102 */ 103 HWTEST_F(VulkanWrapperApiTest, LoadFuncPtr001, TestSize.Level1) 104 { 105 vkEnumerateInstanceExtensionProperties = reinterpret_cast<PFN_vkEnumerateInstanceExtensionProperties>( 106 dlsym(libVulkan, "vkEnumerateInstanceExtensionProperties")); 107 EXPECT_NE(vkEnumerateInstanceExtensionProperties, nullptr); 108 vkCreateInstance = reinterpret_cast<PFN_vkCreateInstance>(dlsym(libVulkan, "vkCreateInstance")); 109 EXPECT_NE(vkCreateInstance, nullptr); 110 vkGetInstanceProcAddr = reinterpret_cast<PFN_vkGetInstanceProcAddr>(dlsym(libVulkan, "vkGetInstanceProcAddr")); 111 EXPECT_NE(vkGetInstanceProcAddr, nullptr); 112 vkGetDeviceProcAddr = reinterpret_cast<PFN_vkGetDeviceProcAddr>(dlsym(libVulkan, "vkGetDeviceProcAddr")); 113 EXPECT_NE(vkGetDeviceProcAddr, nullptr); 114 fpIsSupportedVulkan = reinterpret_cast<PFN_IsSupportedVulkan>(dlsym(libVulkan, "IsSupportedVulkan")); 115 EXPECT_NE(fpIsSupportedVulkan, nullptr); 116 isSupportedVulkan = fpIsSupportedVulkan(); 117 std::cout << "support vulkan :" << isSupportedVulkan << std::endl; 118 } 119 120 /** 121 * @tc.name: create vkInstance 122 * @tc.desc: create vkInstance 123 * @tc.type: FUNC 124 * @tc.require: issueI5ODXM 125 */ 126 HWTEST_F(VulkanWrapperApiTest, createVkInstance_Test, TestSize.Level1) 127 { 128 if (isSupportedVulkan) { 129 VkApplicationInfo appInfo = {}; 130 appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; 131 appInfo.pApplicationName = "pApplicationName"; 132 appInfo.pEngineName = "pEngineName"; 133 appInfo.apiVersion = VK_API_VERSION_1_0; 134 135 std::vector<const char*> instanceExtensions = { VK_KHR_SURFACE_EXTENSION_NAME }; 136 instanceExtensions.push_back(VK_OPENHARMONY_OHOS_SURFACE_EXTENSION_NAME); 137 138 VkInstanceCreateInfo instanceCreateInfo = {}; 139 instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; 140 instanceCreateInfo.pNext = NULL; 141 instanceCreateInfo.pApplicationInfo = &appInfo; 142 143 if (instanceExtensions.size() > 0) { 144 instanceCreateInfo.enabledExtensionCount = (uint32_t)instanceExtensions.size(); 145 instanceCreateInfo.ppEnabledExtensionNames = instanceExtensions.data(); 146 } 147 148 VkResult err = vkCreateInstance(&instanceCreateInfo, nullptr, &instance); 149 EXPECT_EQ(err, VK_SUCCESS); 150 EXPECT_NE(instance, nullptr); 151 } 152 } 153 154 /** 155 * @tc.name: Load instance based Vulkan function pointers 156 * @tc.desc: Load instance based Vulkan function pointers 157 * @tc.type: FUNC 158 * @tc.require: issueI5ODXM 159 */ 160 HWTEST_F(VulkanWrapperApiTest, LoadFuncPtr002, TestSize.Level1) 161 { 162 if (isSupportedVulkan) { 163 vkEnumeratePhysicalDevices = reinterpret_cast<PFN_vkEnumeratePhysicalDevices>( 164 vkGetInstanceProcAddr(instance, "vkEnumeratePhysicalDevices")); 165 EXPECT_NE(vkEnumeratePhysicalDevices, nullptr); 166 vkCreateDevice = reinterpret_cast<PFN_vkCreateDevice>( 167 vkGetInstanceProcAddr(instance, "vkCreateDevice")); 168 EXPECT_NE(vkCreateDevice, nullptr); 169 vkCreateOHOSSurfaceOpenHarmony = reinterpret_cast<PFN_vkCreateOHOSSurfaceOpenHarmony>( 170 vkGetInstanceProcAddr(instance, "vkCreateOHOSSurfaceOpenHarmony")); 171 EXPECT_NE(vkCreateOHOSSurfaceOpenHarmony, nullptr); 172 vkDestroySurfaceKHR = reinterpret_cast<PFN_vkDestroySurfaceKHR>( 173 vkGetInstanceProcAddr(instance, "vkDestroySurfaceKHR")); 174 EXPECT_NE(vkDestroySurfaceKHR, nullptr); 175 fpGetPhysicalDeviceSurfaceSupportKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceSupportKHR>( 176 vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceSupportKHR")); 177 EXPECT_NE(fpGetPhysicalDeviceSurfaceSupportKHR, nullptr); 178 fpGetPhysicalDeviceSurfaceCapabilitiesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR>( 179 vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceCapabilitiesKHR")); 180 EXPECT_NE(fpGetPhysicalDeviceSurfaceCapabilitiesKHR, nullptr); 181 fpGetPhysicalDeviceSurfaceFormatsKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfaceFormatsKHR>( 182 vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfaceFormatsKHR")); 183 EXPECT_NE(fpGetPhysicalDeviceSurfaceFormatsKHR, nullptr); 184 fpGetPhysicalDeviceSurfacePresentModesKHR = reinterpret_cast<PFN_vkGetPhysicalDeviceSurfacePresentModesKHR>( 185 vkGetInstanceProcAddr(instance, "vkGetPhysicalDeviceSurfacePresentModesKHR")); 186 EXPECT_NE(fpGetPhysicalDeviceSurfacePresentModesKHR, nullptr); 187 } 188 } 189 190 /** 191 * @tc.name: create device 192 * @tc.desc: create device 193 * @tc.type: FUNC 194 * @tc.require: issueI5ODXM 195 */ 196 HWTEST_F(VulkanWrapperApiTest, createDevice_Test, TestSize.Level1) 197 { 198 if (isSupportedVulkan) { 199 uint32_t gpuCount = 0; 200 VkResult err = vkEnumeratePhysicalDevices(instance, &gpuCount, nullptr); 201 EXPECT_EQ(err, VK_SUCCESS); 202 EXPECT_NE(gpuCount, 0); 203 std::vector<VkPhysicalDevice> physicalDevices(gpuCount); 204 err = vkEnumeratePhysicalDevices(instance, &gpuCount, physicalDevices.data()); 205 EXPECT_EQ(err, VK_SUCCESS); 206 physicalDevice = physicalDevices[0]; 207 208 std::vector<const char*> deviceExtensions; 209 deviceExtensions.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME); 210 VkDeviceCreateInfo deviceCreateInfo = {}; 211 deviceCreateInfo.enabledExtensionCount = (uint32_t)deviceExtensions.size(); 212 deviceCreateInfo.ppEnabledExtensionNames = deviceExtensions.data(); 213 214 VkDevice logicalDevice; 215 err = vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &logicalDevice); 216 EXPECT_EQ(err, VK_SUCCESS); 217 EXPECT_NE(logicalDevice, nullptr); 218 device = logicalDevice; 219 } 220 } 221 222 /** 223 * @tc.name: Load device based Vulkan function pointers 224 * @tc.desc: Load device based Vulkan function pointers 225 * @tc.type: FUNC 226 * @tc.require: issueI5ODXM 227 */ 228 HWTEST_F(VulkanWrapperApiTest, LoadFuncPtr003, TestSize.Level1) 229 { 230 if (isSupportedVulkan) { 231 fpCreateSwapchainKHR = reinterpret_cast<PFN_vkCreateSwapchainKHR>( 232 vkGetDeviceProcAddr(device, "vkCreateSwapchainKHR")); 233 EXPECT_NE(fpCreateSwapchainKHR, nullptr); 234 fpDestroySwapchainKHR = reinterpret_cast<PFN_vkDestroySwapchainKHR>( 235 vkGetDeviceProcAddr(device, "vkDestroySwapchainKHR")); 236 EXPECT_NE(fpDestroySwapchainKHR, nullptr); 237 fpGetSwapchainImagesKHR = reinterpret_cast<PFN_vkGetSwapchainImagesKHR>( 238 vkGetDeviceProcAddr(device, "vkGetSwapchainImagesKHR")); 239 EXPECT_NE(fpGetSwapchainImagesKHR, nullptr); 240 fpAcquireNextImageKHR = reinterpret_cast<PFN_vkAcquireNextImageKHR>( 241 vkGetDeviceProcAddr(device, "vkAcquireNextImageKHR")); 242 EXPECT_NE(fpAcquireNextImageKHR, nullptr); 243 fpQueuePresentKHR = reinterpret_cast<PFN_vkQueuePresentKHR>(vkGetDeviceProcAddr(device, "vkQueuePresentKHR")); 244 EXPECT_NE(fpQueuePresentKHR, nullptr); 245 } 246 } 247 248 /** 249 * @tc.name: create surface 250 * @tc.desc: create surface 251 * @tc.type: FUNC 252 * @tc.require: issueI5ODXM 253 */ 254 HWTEST_F(VulkanWrapperApiTest, createSurface_Test, TestSize.Level1) 255 { 256 if (isSupportedVulkan) { 257 constexpr int windowLeft = 100; 258 constexpr int windowTop = 200; 259 constexpr int windowWidth = 360; 260 constexpr int windowHeight = 360; 261 OHOS::Rosen::Rect rect = {windowLeft, windowTop, windowWidth, windowHeight}; 262 OHOS::sptr<OHOS::Rosen::WindowOption> option(new OHOS::Rosen::WindowOption()); 263 option->SetDisplayId(0); 264 option->SetWindowRect(rect); 265 option->SetWindowType(OHOS::Rosen::WindowType::APP_MAIN_WINDOW_BASE); 266 option->SetWindowMode(OHOS::Rosen::WindowMode::WINDOW_MODE_FLOATING); 267 option->SetWindowName("createSurface_test"); 268 OHOS::sptr<OHOS::Rosen::Window> window = OHOS::Rosen::Window::Create(option->GetWindowName(), option); 269 EXPECT_NE(window, nullptr); 270 271 OHOS::Rosen::RSTransaction::FlushImplicitTransaction(); 272 window->Show(); 273 274 auto surfaceNode = window->GetSurfaceNode(); 275 OHOS::sptr<OHOS::Surface> surf = surfaceNode->GetSurface(); 276 OHNativeWindow* nativeWindow = CreateNativeWindowFromSurface(&surf); 277 EXPECT_NE(nativeWindow, nullptr); 278 VkOHOSSurfaceCreateInfoOpenHarmony surfaceCreateInfo = {}; 279 surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_OHOS_SURFACE_CREATE_INFO_OPENHARMONY; 280 surfaceCreateInfo.window = nativeWindow; 281 VkResult err = vkCreateOHOSSurfaceOpenHarmony(instance, &surfaceCreateInfo, NULL, &surface); 282 EXPECT_EQ(err, VK_SUCCESS); 283 EXPECT_NE(surface, VK_NULL_HANDLE); 284 } 285 } 286 287 /** 288 * @tc.name: create swapChain 289 * @tc.desc: create swapChain 290 * @tc.type: FUNC 291 * @tc.require: issueI5ODXM 292 */ 293 HWTEST_F(VulkanWrapperApiTest, createSwapChain_Test, TestSize.Level1) 294 { 295 if (isSupportedVulkan) { 296 VkSwapchainKHR oldSwapchain = swapChain; 297 VkSwapchainCreateInfoKHR swapchainCI = {}; 298 swapchainCI.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; 299 swapchainCI.surface = surface; 300 VkSurfaceCapabilitiesKHR surfCaps; 301 VkResult err = fpGetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, surface, &surfCaps); 302 EXPECT_EQ(err, VK_SUCCESS); 303 uint32_t desiredNumberOfSwapchainImages = surfCaps.minImageCount + 1; 304 swapchainCI.minImageCount = desiredNumberOfSwapchainImages; 305 swapchainCI.imageFormat = VK_FORMAT_B8G8R8A8_UNORM; 306 uint32_t formatCount; 307 err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, NULL); 308 EXPECT_EQ(err, VK_SUCCESS); 309 EXPECT_GT(formatCount, 0); 310 std::vector<VkSurfaceFormatKHR> surfaceFormats(formatCount); 311 err = fpGetPhysicalDeviceSurfaceFormatsKHR(physicalDevice, surface, &formatCount, surfaceFormats.data()); 312 EXPECT_EQ(err, VK_SUCCESS); 313 swapchainCI.imageColorSpace = surfaceFormats[0].colorSpace; 314 uint32_t width = 1280; 315 uint32_t height = 720; 316 swapchainCI.imageExtent = { width, height }; 317 swapchainCI.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; 318 swapchainCI.preTransform = (VkSurfaceTransformFlagBitsKHR)VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; 319 swapchainCI.imageArrayLayers = 1; 320 swapchainCI.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; 321 swapchainCI.queueFamilyIndexCount = 0; 322 swapchainCI.presentMode = VK_PRESENT_MODE_MAILBOX_KHR; 323 swapchainCI.oldSwapchain = oldSwapchain; 324 swapchainCI.clipped = VK_TRUE; 325 swapchainCI.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; 326 327 err = fpCreateSwapchainKHR(device, &swapchainCI, nullptr, &swapChain); 328 EXPECT_EQ(err, VK_SUCCESS); 329 EXPECT_NE(swapChain, VK_NULL_HANDLE); 330 } 331 } 332 }