vulkan: rework driver::Get*ProcAddr

Introduce driver::ProcHook which is a struct to describe an intercepted
function.  Given a function name, GetProcHook returns a ProcHook if the
function is intercepted.  NULL otherwise.

A ProcHook has three function pointers.  ProcHook::proc points to the real
intercepting function.  ProcHook::disabled_proc points to a no-op function
that logs an error.  ProcHook::checked_proc points to a trampoline that
calls either ProcHook::proc or ProcHook::disabled_proc.

For core functions, driver::Get*ProcAddr simply return ProcHook::proc.
For extension functions, driver::Get*ProcAddr return ProcHook::proc when
the extension is known to be enabled.  They return ProcHook::disabled_proc
when the extension is known to be disabled.  Finally, they return
ProcHook::checked_proc when they do not know if the extension is enabled
or not.

All ProcHooks as well as their disabled_proc/checked_proc are generated in
driver_gen.cpp.  This allows us to get rid of all hand-written "_Disabled"
functions, all no-op "_Bottom" functions, and special cases for
VK_ANDROID_native_buffer.  The reworked driver::Get*ProcAddr also detects
more applications' errors and logs them.

Change-Id: I8e6f476f450688b5547fd75243c66cb603c516b5
diff --git a/vulkan/libvulkan/driver.cpp b/vulkan/libvulkan/driver.cpp
index 4acc867..68ae5c8 100644
--- a/vulkan/libvulkan/driver.cpp
+++ b/vulkan/libvulkan/driver.cpp
@@ -143,5 +143,67 @@
     return kDefaultAllocCallbacks;
 }
 
+PFN_vkVoidFunction GetInstanceProcAddr(VkInstance instance, const char* pName) {
+    const ProcHook* hook = GetProcHook(pName);
+    if (!hook)
+        return g_hwdevice->GetInstanceProcAddr(instance, pName);
+
+    if (!instance) {
+        if (hook->type == ProcHook::GLOBAL)
+            return hook->proc;
+
+        ALOGE(
+            "Invalid use of vkGetInstanceProcAddr to query %s without an "
+            "instance",
+            pName);
+
+        // Some naughty layers expect
+        //
+        //   vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkCreateDevice");
+        //
+        // to work.
+        return (strcmp(pName, "vkCreateDevice") == 0) ? hook->proc : nullptr;
+    }
+
+    PFN_vkVoidFunction proc;
+
+    switch (hook->type) {
+        case ProcHook::INSTANCE:
+            proc = (GetData(instance).hook_extensions[hook->extension])
+                       ? hook->proc
+                       : hook->disabled_proc;
+            break;
+        case ProcHook::DEVICE:
+            proc = (hook->extension == ProcHook::EXTENSION_CORE)
+                       ? hook->proc
+                       : hook->checked_proc;
+            break;
+        default:
+            ALOGE(
+                "Invalid use of vkGetInstanceProcAddr to query %s with an "
+                "instance",
+                pName);
+            proc = nullptr;
+            break;
+    }
+
+    return proc;
+}
+
+PFN_vkVoidFunction GetDeviceProcAddr(VkDevice device, const char* pName) {
+    const ProcHook* hook = GetProcHook(pName);
+    if (!hook)
+        return GetData(device).get_device_proc_addr(device, pName);
+
+    if (hook->type != ProcHook::DEVICE) {
+        ALOGE("Invalid use of vkGetDeviceProcAddr to query %s", pName);
+        return nullptr;
+    }
+
+    return (GetData(device).hook_extensions[hook->extension])
+               ? hook->proc
+               : hook->disabled_proc;
+}
+
 }  // namespace driver
 }  // namespace vulkan