| // Copyright 2019 The SwiftShader Authors. All Rights Reserved. | 
 | // | 
 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
 | // you may not use this file except in compliance with the License. | 
 | // You may obtain a copy of the License at | 
 | // | 
 | //    http://www.apache.org/licenses/LICENSE-2.0 | 
 | // | 
 | // Unless required by applicable law or agreed to in writing, software | 
 | // distributed under the License is distributed on an "AS IS" BASIS, | 
 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
 | // See the License for the specific language governing permissions and | 
 | // limitations under the License. | 
 |  | 
 | #include "Driver.hpp" | 
 |  | 
 | #if defined(_WIN32) | 
 | #	include "Windows.h" | 
 | #	define OS_WINDOWS 1 | 
 | #elif defined(__APPLE__) | 
 | #	include "dlfcn.h" | 
 | #	define OS_MAC 1 | 
 | #elif defined(__ANDROID__) | 
 | #	include "dlfcn.h" | 
 | #	define OS_ANDROID 1 | 
 | #elif defined(__linux__) | 
 | #	include "dlfcn.h" | 
 | #	define OS_LINUX 1 | 
 | #elif defined(__Fuchsia__) | 
 | #	include <zircon/dlfcn.h> | 
 | #	define OS_FUCHSIA 1 | 
 | #else | 
 | #	error Unimplemented platform | 
 | #endif | 
 |  | 
 | Driver::Driver() | 
 |     : vk_icdGetInstanceProcAddr(nullptr) | 
 |     , dll(nullptr){ | 
 | #define VK_GLOBAL(N, R, ...) N = nullptr | 
 | #include "VkGlobalFuncs.hpp" | 
 | #undef VK_GLOBAL | 
 |  | 
 | #define VK_INSTANCE(N, R, ...) N = nullptr | 
 | #include "VkInstanceFuncs.hpp" | 
 | #undef VK_INSTANCE | 
 |     } | 
 |  | 
 |     Driver::~Driver() | 
 | { | 
 | 	unload(); | 
 | } | 
 |  | 
 | bool Driver::loadSwiftShader() | 
 | { | 
 | #if OS_WINDOWS | 
 | #	if !defined(STANDALONE) | 
 | 	// The DLL is delay loaded (see BUILD.gn), so we can load | 
 | 	// the correct ones from Chrome's swiftshader subdirectory. | 
 | 	HMODULE libvulkan = LoadLibraryA("swiftshader\\libvulkan.dll"); | 
 | 	EXPECT_NE((HMODULE)NULL, libvulkan); | 
 | 	return true; | 
 | #	elif defined(NDEBUG) | 
 | #		if defined(_WIN64) | 
 | 	return load("./build/Release_x64/vk_swiftshader.dll") || | 
 | 	       load("./build/Release/vk_swiftshader.dll") || | 
 | 	       load("./vk_swiftshader.dll"); | 
 | #		else | 
 | 	return load("./build/Release_Win32/vk_swiftshader.dll") || | 
 | 	       load("./build/Release/vk_swiftshader.dll") || | 
 | 	       load("./vk_swiftshader.dll"); | 
 | #		endif | 
 | #	else | 
 | #		if defined(_WIN64) | 
 | 	return load("./build/Debug_x64/vk_swiftshader.dll") || | 
 | 	       load("./build/Debug/vk_swiftshader.dll") || | 
 | 	       load("./vk_swiftshader.dll"); | 
 | #		else | 
 | 	return load("./build/Debug_Win32/vk_swiftshader.dll") || | 
 | 	       load("./build/Debug/vk_swiftshader.dll") || | 
 | 	       load("./vk_swiftshader.dll"); | 
 | #		endif | 
 | #	endif | 
 | #elif OS_MAC | 
 | 	return load("./build/Darwin/libvk_swiftshader.dylib") || | 
 | 	       load("swiftshader/libvk_swiftshader.dylib") || | 
 | 	       load("libvk_swiftshader.dylib"); | 
 | #elif OS_LINUX | 
 | 	return load("./build/Linux/libvk_swiftshader.so") || | 
 | 	       load("swiftshader/libvk_swiftshader.so") || | 
 | 	       load("./libvk_swiftshader.so") || | 
 | 	       load("libvk_swiftshader.so"); | 
 | #elif OS_ANDROID || OS_FUCHSIA | 
 | 	return load("libvk_swiftshader.so"); | 
 | #else | 
 | #	error Unimplemented platform | 
 | #endif | 
 | } | 
 |  | 
 | bool Driver::loadSystem() | 
 | { | 
 | #if OS_LINUX | 
 | 	return load("libvulkan.so.1"); | 
 | #else | 
 | 	return false; | 
 | #endif | 
 | } | 
 |  | 
 | bool Driver::load(const char *path) | 
 | { | 
 | #if OS_WINDOWS | 
 | 	dll = LoadLibraryA(path); | 
 | #elif(OS_MAC || OS_LINUX || OS_ANDROID || OS_FUCHSIA) | 
 | 	dll = dlopen(path, RTLD_LAZY | RTLD_LOCAL); | 
 | #else | 
 | 	return false; | 
 | #endif | 
 | 	if(dll == nullptr) | 
 | 	{ | 
 | 		return false; | 
 | 	} | 
 |  | 
 | 	// Is the driver an ICD? | 
 | 	if(!lookup(&vk_icdGetInstanceProcAddr, "vk_icdGetInstanceProcAddr")) | 
 | 	{ | 
 | 		// Nope, attempt to use the loader version. | 
 | 		if(!lookup(&vk_icdGetInstanceProcAddr, "vkGetInstanceProcAddr")) | 
 | 		{ | 
 | 			return false; | 
 | 		} | 
 | 	} | 
 |  | 
 | #define VK_GLOBAL(N, R, ...)                              \ | 
 | 	if(auto pfn = vk_icdGetInstanceProcAddr(nullptr, #N)) \ | 
 | 	{                                                     \ | 
 | 		N = reinterpret_cast<decltype(N)>(pfn);           \ | 
 | 	} | 
 | #include "VkGlobalFuncs.hpp" | 
 | #undef VK_GLOBAL | 
 |  | 
 | 	return true; | 
 | } | 
 |  | 
 | void Driver::unload() | 
 | { | 
 | 	if(!isLoaded()) | 
 | 	{ | 
 | 		return; | 
 | 	} | 
 |  | 
 | #if OS_WINDOWS | 
 | 	FreeLibrary((HMODULE)dll); | 
 | #elif(OS_LINUX || OS_FUCHSIA) | 
 | 	dlclose(dll); | 
 | #endif | 
 |  | 
 | #define VK_GLOBAL(N, R, ...) N = nullptr | 
 | #include "VkGlobalFuncs.hpp" | 
 | #undef VK_GLOBAL | 
 |  | 
 | #define VK_INSTANCE(N, R, ...) N = nullptr | 
 | #include "VkInstanceFuncs.hpp" | 
 | #undef VK_INSTANCE | 
 | } | 
 |  | 
 | bool Driver::isLoaded() const | 
 | { | 
 | 	return dll != nullptr; | 
 | } | 
 |  | 
 | bool Driver::resolve(VkInstance instance) | 
 | { | 
 | 	if(!isLoaded()) | 
 | 	{ | 
 | 		return false; | 
 | 	} | 
 |  | 
 | #define VK_INSTANCE(N, R, ...)                             \ | 
 | 	if(auto pfn = vk_icdGetInstanceProcAddr(instance, #N)) \ | 
 | 	{                                                      \ | 
 | 		N = reinterpret_cast<decltype(N)>(pfn);            \ | 
 | 	}                                                      \ | 
 | 	else                                                   \ | 
 | 	{                                                      \ | 
 | 		return false;                                      \ | 
 | 	} | 
 | #include "VkInstanceFuncs.hpp" | 
 | #undef VK_INSTANCE | 
 |  | 
 | 	return true; | 
 | } | 
 |  | 
 | void *Driver::lookup(const char *name) | 
 | { | 
 | #if OS_WINDOWS | 
 | 	return GetProcAddress((HMODULE)dll, name); | 
 | #elif(OS_MAC || OS_LINUX || OS_ANDROID || OS_FUCHSIA) | 
 | 	return dlsym(dll, name); | 
 | #else | 
 | 	return nullptr; | 
 | #endif | 
 | } |