Add default callbacks in the loader.

Change-Id: I23d7945efb0fd372e614f895278fc86a853fe429
(cherry picked from commit 9b9938127d1c68cda9b709524aea44ffb0de77b9)
diff --git a/vulkan/include/vulkan/vk_debug_report_lunarg.h b/vulkan/include/vulkan/vk_debug_report_lunarg.h
new file mode 100644
index 0000000..8ff5654
--- /dev/null
+++ b/vulkan/include/vulkan/vk_debug_report_lunarg.h
@@ -0,0 +1,188 @@
+//
+// File: vk_debug_report_lunarg.h
+//
+/*
+ * Vulkan
+ *
+ * Copyright (C) 2015 LunarG, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ *   Jon Ashburn <jon@lunarg.com>
+ *   Courtney Goeltzenleuchter <courtney@lunarg.com>
+ */
+
+#ifndef __VK_DEBUG_REPORT_LUNARG_H__
+#define __VK_DEBUG_REPORT_LUNARG_H__
+
+#include <vulkan/vulkan.h>
+
+#define VK_DEBUG_REPORT_EXTENSION_NUMBER 5
+#define VK_DEBUG_REPORT_EXTENSION_REVISION 1
+#ifdef __cplusplus
+extern "C" {
+#endif  // __cplusplus
+
+/*
+***************************************************************************************************
+*   DebugReport Vulkan Extension API
+***************************************************************************************************
+*/
+typedef enum {
+    VK_OBJECT_TYPE_INSTANCE = 0,
+    VK_OBJECT_TYPE_PHYSICAL_DEVICE = 1,
+    VK_OBJECT_TYPE_DEVICE = 2,
+    VK_OBJECT_TYPE_QUEUE = 3,
+    VK_OBJECT_TYPE_COMMAND_BUFFER = 4,
+    VK_OBJECT_TYPE_DEVICE_MEMORY = 5,
+    VK_OBJECT_TYPE_BUFFER = 6,
+    VK_OBJECT_TYPE_BUFFER_VIEW = 7,
+    VK_OBJECT_TYPE_IMAGE = 8,
+    VK_OBJECT_TYPE_IMAGE_VIEW = 9,
+    VK_OBJECT_TYPE_ATTACHMENT_VIEW = 10,
+    VK_OBJECT_TYPE_SHADER_MODULE = 12,
+    VK_OBJECT_TYPE_SHADER = 13,
+    VK_OBJECT_TYPE_PIPELINE = 14,
+    VK_OBJECT_TYPE_PIPELINE_LAYOUT = 15,
+    VK_OBJECT_TYPE_SAMPLER = 16,
+    VK_OBJECT_TYPE_DESCRIPTOR_SET = 17,
+    VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT = 18,
+    VK_OBJECT_TYPE_DESCRIPTOR_POOL = 19,
+    VK_OBJECT_TYPE_DYNAMIC_VIEWPORT_STATE = 20,
+    VK_OBJECT_TYPE_DYNAMIC_LINE_WIDTH_STATE = 21,
+    VK_OBJECT_TYPE_DYNAMIC_DEPTH_BIAS_STATE = 22,
+    VK_OBJECT_TYPE_DYNAMIC_BLEND_STATE = 23,
+    VK_OBJECT_TYPE_DYNAMIC_DEPTH_BOUNDS_STATE = 24,
+    VK_OBJECT_TYPE_DYNAMIC_STENCIL_STATE = 25,
+    VK_OBJECT_TYPE_FENCE = 26,
+    VK_OBJECT_TYPE_SEMAPHORE = 27,
+    VK_OBJECT_TYPE_EVENT = 28,
+    VK_OBJECT_TYPE_QUERY_POOL = 29,
+    VK_OBJECT_TYPE_FRAMEBUFFER = 30,
+    VK_OBJECT_TYPE_RENDER_PASS = 31,
+    VK_OBJECT_TYPE_PIPELINE_CACHE = 32,
+    VK_OBJECT_TYPE_SWAPCHAIN_KHR = 33,
+    VK_OBJECT_TYPE_CMD_POOL = 34,
+    VK_OBJECT_TYPE_BEGIN_RANGE = VK_OBJECT_TYPE_INSTANCE,
+    VK_OBJECT_TYPE_END_RANGE = VK_OBJECT_TYPE_CMD_POOL,
+    VK_OBJECT_TYPE_NUM =
+        (VK_OBJECT_TYPE_CMD_POOL - VK_OBJECT_TYPE_INSTANCE + 1),
+    VK_OBJECT_TYPE_MAX_ENUM = 0x7FFFFFFF
+} VkDbgObjectType;
+
+#define VK_DEBUG_REPORT_EXTENSION_NAME "DEBUG_REPORT"
+
+VK_DEFINE_NONDISP_HANDLE(VkDbgMsgCallback)
+
+// ------------------------------------------------------------------------------------------------
+// Enumerations
+
+typedef enum VkDbgReportFlags_ {
+    VK_DBG_REPORT_INFO_BIT = 0x0001,
+    VK_DBG_REPORT_WARN_BIT = 0x0002,
+    VK_DBG_REPORT_PERF_WARN_BIT = 0x0004,
+    VK_DBG_REPORT_ERROR_BIT = 0x0008,
+    VK_DBG_REPORT_DEBUG_BIT = 0x0010,
+} VkDbgReportFlags;
+
+// Debug Report ERROR codes
+typedef enum _DEBUG_REPORT_ERROR {
+    DEBUG_REPORT_NONE,          // Used for INFO & other non-error messages
+    DEBUG_REPORT_CALLBACK_REF,  // Callbacks were not destroyed prior to calling
+                                // DestroyInstance
+} DEBUG_REPORT_ERROR;
+
+#define VK_DEBUG_REPORT_ENUM_EXTEND(type, id) \
+    ((type)(VK_DEBUG_REPORT_EXTENSION_NUMBER * -1000 + (id)))
+
+#define VK_OBJECT_TYPE_MSG_CALLBACK \
+    VK_DEBUG_REPORT_ENUM_EXTEND(VkDbgObjectType, 0)
+// ------------------------------------------------------------------------------------------------
+// Vulkan function pointers
+
+typedef void (*PFN_vkDbgMsgCallback)(VkFlags msgFlags,
+                                     VkDbgObjectType objType,
+                                     uint64_t srcObject,
+                                     size_t location,
+                                     int32_t msgCode,
+                                     const char* pLayerPrefix,
+                                     const char* pMsg,
+                                     void* pUserData);
+
+// ------------------------------------------------------------------------------------------------
+// API functions
+
+typedef VkResult(VKAPI* PFN_vkDbgCreateMsgCallback)(
+    VkInstance instance,
+    VkFlags msgFlags,
+    const PFN_vkDbgMsgCallback pfnMsgCallback,
+    void* pUserData,
+    VkDbgMsgCallback* pMsgCallback);
+typedef VkResult(VKAPI* PFN_vkDbgDestroyMsgCallback)(
+    VkInstance instance,
+    VkDbgMsgCallback msgCallback);
+
+#ifdef VK_PROTOTYPES
+
+// DebugReport extension entrypoints
+VkResult VKAPI vkDbgCreateMsgCallback(VkInstance instance,
+                                      VkFlags msgFlags,
+                                      const PFN_vkDbgMsgCallback pfnMsgCallback,
+                                      void* pUserData,
+                                      VkDbgMsgCallback* pMsgCallback);
+
+VkResult VKAPI vkDbgDestroyMsgCallback(VkInstance instance,
+                                       VkDbgMsgCallback msgCallback);
+
+// DebugReport utility callback functions
+void VKAPI vkDbgStringCallback(VkFlags msgFlags,
+                               VkDbgObjectType objType,
+                               uint64_t srcObject,
+                               size_t location,
+                               int32_t msgCode,
+                               const char* pLayerPrefix,
+                               const char* pMsg,
+                               void* pUserData);
+
+void VKAPI vkDbgStdioCallback(VkFlags msgFlags,
+                              VkDbgObjectType objType,
+                              uint64_t srcObject,
+                              size_t location,
+                              int32_t msgCode,
+                              const char* pLayerPrefix,
+                              const char* pMsg,
+                              void* pUserData);
+
+void VKAPI vkDbgBreakCallback(VkFlags msgFlags,
+                              VkDbgObjectType objType,
+                              uint64_t srcObject,
+                              size_t location,
+                              int32_t msgCode,
+                              const char* pLayerPrefix,
+                              const char* pMsg,
+                              void* pUserData);
+
+#endif  // VK_PROTOTYPES
+
+#ifdef __cplusplus
+}  // extern "C"
+#endif  // __cplusplus
+
+#endif  // __VK_DEBUG_REPORT_LUNARG_H__
diff --git a/vulkan/libvulkan/loader.cpp b/vulkan/libvulkan/loader.cpp
index 694d8fd..ca33be1 100644
--- a/vulkan/libvulkan/loader.cpp
+++ b/vulkan/libvulkan/loader.cpp
@@ -34,6 +34,7 @@
 #include <cutils/properties.h>
 #include <hardware/hwvulkan.h>
 #include <log/log.h>
+#include <vulkan/vk_debug_report_lunarg.h>
 
 using namespace vulkan;
 
@@ -136,6 +137,7 @@
     VkPhysicalDevice physical_devices[kMaxPhysicalDevices];
 
     Vector<std::pair<String, SharedLibraryHandle> > active_layers;
+    VkDbgMsgCallback message;
 
     struct Driver {
         // Pointers to driver entry points. Used explicitly by the loader; not
@@ -331,6 +333,21 @@
               (*instance_layers_pair->layers)[layer_name_str]);
 }
 
+void LogDebugMessageCallback(VkFlags message_flags,
+                             VkDbgObjectType /*obj_type*/,
+                             uint64_t /*src_object*/,
+                             size_t /*location*/,
+                             int32_t message_code,
+                             const char* layer_prefix,
+                             const char* message,
+                             void* /*user_data*/) {
+    if (message_flags & VK_DBG_REPORT_ERROR_BIT) {
+        ALOGE("[%s] Code %d : %s", layer_prefix, message_code, message);
+    } else if (message_flags & VK_DBG_REPORT_WARN_BIT) {
+        ALOGW("[%s] Code %d : %s", layer_prefix, message_code, message);
+    }
+}
+
 // -----------------------------------------------------------------------------
 // "Bottom" functions. These are called at the end of the instance dispatch
 // chain.
@@ -345,6 +362,12 @@
     for (auto& layer : instance->active_layers) {
         dlclose(layer.second);
     }
+    if (instance->message) {
+        PFN_vkDbgDestroyMsgCallback DebugDestroyMessageCallback;
+        DebugDestroyMessageCallback = reinterpret_cast<PFN_vkDbgDestroyMsgCallback>(
+            vkGetInstanceProcAddr(instance, "vkDbgDestroyMsgCallback"));
+        DebugDestroyMessageCallback(instance, instance->message);
+    }
     const VkAllocCallbacks* alloc = instance->alloc;
     instance->~VkInstance_T();
     alloc->pfnFree(alloc->pUserData, instance);
@@ -727,6 +750,7 @@
 
     instance->vtbl_storage = kBottomInstanceFunctions;
     instance->vtbl_storage.instance = instance;
+    instance->message = VK_NULL_HANDLE;
 
     // Scan layers
     // TODO: Add more directories to scan
@@ -817,6 +841,7 @@
     // Force enable callback extension if required
     bool enable_callback =
         property_get_bool("debug.vulkan.enable_layer_callback", false);
+    bool enable_logging = enable_callback;
     const char* callback_name = "DEBUG_REPORT";
     if (enable_callback) {
         for (uint32_t i = 0; i < create_info->extensionCount; ++i) {
@@ -872,6 +897,15 @@
         // already gone at this point. Nothing to do.
     }
 
+    if (enable_logging) {
+        PFN_vkDbgCreateMsgCallback DebugCreateMessageCallback;
+        DebugCreateMessageCallback = reinterpret_cast<PFN_vkDbgCreateMsgCallback>(
+            vkGetInstanceProcAddr(instance, "vkDbgCreateMsgCallback"));
+        DebugCreateMessageCallback(instance,
+                             VK_DBG_REPORT_ERROR_BIT | VK_DBG_REPORT_WARN_BIT,
+                             LogDebugMessageCallback, NULL, &instance->message);
+    }
+
     return result;
 }