loader: Add support for NV instance extension

Added vkGetPhysicalDeviceExternalImageFormat API from the
VK_NV_external_memory_capabilities extension to the loader.

Change-Id: Ib87df7bae333d7944a4e181556bc2f99e1e19416
diff --git a/loader/extensions.c b/loader/extensions.c
new file mode 100644
index 0000000..47a3c12
--- /dev/null
+++ b/loader/extensions.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2015-2016 The Khronos Group Inc.
+ * Copyright (c) 2015-2016 Valve Corporation
+ * Copyright (c) 2015-2016 LunarG, Inc.
+ *
+ * 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.
+ *
+ * Author: Mark Lobodzinski <mark@lunarg.com>
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "vk_loader_platform.h"
+#include "loader.h"
+#include "extensions.h"
+#include <vulkan/vk_icd.h>
+
+ // Definitions for the VK_NV_external_memory_capabilities extension
+
+static const VkExtensionProperties
+    nv_external_memory_capabilities_extension_info = {
+        .extensionName = VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME,
+        .specVersion = VK_NV_EXTERNAL_MEMORY_CAPABILITIES_SPEC_VERSION,
+};
+
+LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
+vkGetPhysicalDeviceExternalImageFormatPropertiesNV(
+    VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
+    VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
+    VkExternalMemoryHandleTypeFlagsNV externalHandleType,
+    VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties) {
+
+    const VkLayerInstanceDispatchTable *disp;
+    VkPhysicalDevice unwrapped_phys_dev =
+        loader_unwrap_physical_device(physicalDevice);
+    disp = loader_get_instance_dispatch(physicalDevice);
+
+    return disp->GetPhysicalDeviceExternalImageFormatPropertiesNV(
+        unwrapped_phys_dev, format, type, tiling, usage, flags,
+        externalHandleType, pExternalImageFormatProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+terminator_GetPhysicalDeviceExternalImageFormatPropertiesNV(
+    VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
+    VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
+    VkExternalMemoryHandleTypeFlagsNV externalHandleType,
+    VkExternalImageFormatPropertiesNV *pExternalImageFormatProperties) {
+
+    struct loader_physical_device *phys_dev =
+        (struct loader_physical_device *)physicalDevice;
+    struct loader_icd *icd = phys_dev->this_icd;
+
+    assert(icd->GetPhysicalDeviceExternalImageFormatPropertiesNV &&
+           "loader: null GetPhysicalDeviceExternalImageFormatPropertiesNV ICD "
+           "pointer");
+
+    if (!icd->GetPhysicalDeviceExternalImageFormatPropertiesNV)
+        return VK_ERROR_INITIALIZATION_FAILED;
+
+    return icd->GetPhysicalDeviceExternalImageFormatPropertiesNV(
+        phys_dev->phys_dev, format, type, tiling, usage, flags,
+        externalHandleType, pExternalImageFormatProperties);
+}
+
+bool extension_instance_gpa(struct loader_instance *ptr_instance,
+                            const char *name, void **addr) {
+    *addr = NULL;
+
+    // Functions for the VK_NV_external_memory_capabilities extension
+    if (!strcmp("vkGetPhysicalDeviceExternalImageFormatPropertiesNV", name)) {
+        *addr = (void *)vkGetPhysicalDeviceExternalImageFormatPropertiesNV;
+        return true;
+    }
+
+    return false;
+}
+
+void extensions_create_instance(struct loader_instance *ptr_instance,
+                                const VkInstanceCreateInfo *pCreateInfo) {
+
+    for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
+        if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
+                   VK_NV_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME) == 0) {
+            // Nothing to do;
+            return;
+        }
+    }
+}