Layers initial prototype.

Includes  an auto generated layer (GenericLayer) that wraps  all api calls.
Includes a basic handwritten layer (basicLayer)  that wraps a few apis.
Adds xglGetProcAddr as a new api, which is used to chain layers together.
All layers and loader implement  a dispatch table.
diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt
index 8c01a60..f348697 100644
--- a/loader/CMakeLists.txt
+++ b/loader/CMakeLists.txt
@@ -1,8 +1,13 @@
-add_custom_command(OUTPUT dispatch.c
+add_custom_command(OUTPUT dispatch.c ${PROJECT_SOURCE_DIR}/icd/common/icd-dispatch-table.h
 	COMMAND ${PROJECT_SOURCE_DIR}/xgl-generate.py loader > dispatch.c
+        COMMAND ${PROJECT_SOURCE_DIR}/xgl-generate.py icd-dispatch-table > ${PROJECT_SOURCE_DIR}/icd/common/icd-dispatch-table.h
 	           DEPENDS ${PROJECT_SOURCE_DIR}/xgl-generate.py
 	                   ${PROJECT_SOURCE_DIR}/xgl.py)
-include_directories(${CMAKE_CURRENT_SOURCE_DIR})
+
+include_directories(
+	${CMAKE_CURRENT_SOURCE_DIR}
+	${CMAKE_CURRENT_BINARY_DIR}
+)
 
 add_library(XGL SHARED loader.c dispatch.c)
 set_target_properties(XGL PROPERTIES SOVERSION 0)
diff --git a/loader/loader.c b/loader/loader.c
index fddbc24..c86ada2 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -37,25 +37,27 @@
 #include <unistd.h>
 #include <dlfcn.h>
 #include <pthread.h>
-
+#include <assert.h>
 #include "loader.h"
 
-typedef XGL_RESULT (XGLAPI *InitAndEnumerateGpusT)(const XGL_APPLICATION_INFO* pAppInfo, const XGL_ALLOC_CALLBACKS* pAllocCb, XGL_UINT maxGpus, XGL_UINT* pGpuCount, XGL_PHYSICAL_GPU* pGpus);
-typedef XGL_RESULT (XGLAPI *DbgRegisterMsgCallbackT)(XGL_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback, XGL_VOID* pUserData);
-typedef XGL_RESULT (XGLAPI *DbgUnregisterMsgCallbackT)(XGL_DBG_MSG_CALLBACK_FUNCTION pfnMsgCallback);
-typedef XGL_RESULT (XGLAPI *DbgSetGlobalOptionT)(XGL_INT dbgOption, XGL_SIZE dataSize, const XGL_VOID* pData);
 
 struct loader_icd {
     void *handle;
 
-    InitAndEnumerateGpusT InitAndEnumerateGpus;
-    DbgRegisterMsgCallbackT DbgRegisterMsgCallback;
-    DbgUnregisterMsgCallbackT DbgUnregisterMsgCallback;
-    DbgSetGlobalOptionT DbgSetGlobalOption;
+    GetProcAddrType GetProcAddr;
+    InitAndEnumerateGpusType InitAndEnumerateGpus;
+    DbgRegisterMsgCallbackType DbgRegisterMsgCallback;
+    DbgUnregisterMsgCallbackType DbgUnregisterMsgCallback;
+    DbgSetGlobalOptionType DbgSetGlobalOption;
 
     struct loader_icd *next;
 };
 
+struct loader_layers {
+    void *lib_handle;
+    char lib_name[1024];
+};
+
 struct loader_msg_callback {
     XGL_DBG_MSG_CALLBACK_FUNCTION func;
     XGL_VOID *data;
@@ -63,10 +65,15 @@
     struct loader_msg_callback *next;
 };
 
+
 static struct {
     bool scanned;
     struct loader_icd *icds;
-
+    XGL_LAYER_DISPATCH_TABLE *loader_dispatch;
+    XGL_UINT layer_count;
+    bool layer_scaned;
+    char layer_dirs[4096];
+    struct loader_layers layer_libs[MAX_LAYER_LIBRARIES];
     struct loader_msg_callback *msg_callbacks;
 
     bool debug_echo_enable;
@@ -198,13 +205,14 @@
     }
 
 #define LOOKUP(icd, func) do {                              \
-    icd->func = (func## T) dlsym(icd->handle, "xgl" #func); \
+    icd->func = (func## Type) dlsym(icd->handle, "xgl" #func); \
     if (!icd->func) {                                       \
         loader_log(XGL_DBG_MSG_WARNING, 0, dlerror());      \
         loader_icd_destroy(icd);                            \
         return NULL;                                        \
     }                                                       \
 } while (0)
+    LOOKUP(icd, GetProcAddr);
     LOOKUP(icd, InitAndEnumerateGpus);
     LOOKUP(icd, DbgRegisterMsgCallback);
     LOOKUP(icd, DbgUnregisterMsgCallback);
@@ -351,6 +359,603 @@
     loader.scanned = true;
 }
 
+#ifndef DEFAULT_XGL_LAYERS_PATH
+// TODO: Is this a good default locations
+#define DEFAULT_XGL_LAYERS_PATH ".:/usr/lib/i386-linux-gnu/xgl:/usr/lib/x86_64-linux-gnu/xgl"
+#endif
+
+static void layer_lib_scan(const char * libInPaths, const bool useDefaultDirs, const bool openLibs)
+{
+    const char *p, *next;
+    char *libPaths = &loader.layer_dirs[0];
+    DIR *curdir;
+    struct dirent *dent;
+    int len, i, n;
+
+    if (libInPaths){
+        strncpy(libPaths, libInPaths, sizeof(loader.layer_dirs));
+    }
+    else {
+        *libPaths = '\0';
+    }
+
+    /* cleanup any previously scanned libraries */
+    for (i = 0; i < loader.layer_count; i++) {
+        if (loader.layer_libs[i].lib_handle != NULL)
+            dlclose(loader.layer_libs[i].lib_handle);
+        loader.layer_libs[i].lib_handle = NULL;
+    }
+    loader.layer_count = 0;
+
+    if (useDefaultDirs)
+       strncat(libPaths, DEFAULT_XGL_LAYERS_PATH, sizeof(loader.layer_dirs) - sizeof(DEFAULT_XGL_LAYERS_PATH));
+
+    for (p = libPaths; *p; p = next) {
+       next = strchr(p, ':');
+       if (next == NULL) {
+          len = strlen(p);
+          next = p + len;
+       }
+       else {
+          len = next - p;
+          *(char *) next = '\0';
+          next++;
+       }
+
+       curdir = opendir(p);
+       if (curdir) {
+          dent = readdir(curdir);
+          while (dent) {
+              n = loader.layer_count;
+             /* look for wrappers starting with "libXGLlayer" */
+             if (!strncmp(dent->d_name, "libXGLLayer", strlen("libXGLLayer"))) {
+                snprintf((char *) &(loader.layer_libs[n].lib_name), sizeof(loader.layer_libs[0].lib_name), "%s/%s",p,dent->d_name);
+                if ((loader.layer_libs[n].lib_handle = dlopen((const char *) &(loader.layer_libs[n].lib_name), RTLD_LAZY)) == NULL)
+                    continue;
+
+                loader.layer_count++;
+                if (!openLibs)
+                    dlclose(loader.layer_libs[n].lib_handle);
+             }
+
+             dent = readdir(curdir);
+          }
+          closedir(curdir);
+       }
+    }
+
+    loader.layer_scaned = true;
+}
+
+#if 0
+static bool layer_lib_sort(char * str, const XGL_UINT count)
+{
+    XGL_UINT i;
+    struct loader_layers temp, *cur, *start;
+
+    start = &loader.layer_libs[count];
+    for (i = count; i < loader.layer_count; i++) {
+        cur = &loader.layer_libs[i];
+
+        if (!strcmp(str, cur->lib_name) && cur->lib_handle != NULL) {
+            if (count == i)
+                return true;
+            strcpy(temp.lib_name, cur->lib_name);
+            temp.lib_handle = cur->lib_handle;
+            strcpy(cur->lib_name, start->lib_name);
+            cur->lib_handle = start->lib_handle;
+            strcpy(start->lib_name, temp.lib_name);
+            start->lib_handle = temp.lib_handle;
+            return true;
+        }
+    }
+    return false;
+}
+#endif
+LOADER_EXPORT XGL_RESULT XGLAPI ScanForLayers(const XGL_CHAR* pLibraryDirectories, XGL_CHAR * pStr)
+{
+    size_t size = 0;
+    XGL_UINT i;
+    static XGL_CHAR *lib_str=NULL;
+
+    if (!pLibraryDirectories)
+        return XGL_ERROR_INVALID_POINTER;
+
+    if (strlen((const char *) pLibraryDirectories) > sizeof(loader.layer_dirs))
+        return XGL_ERROR_INVALID_POINTER;
+
+    layer_lib_scan((const char *) pLibraryDirectories, true, false);
+
+    for (i = 0; i < loader.layer_count; i++) {
+        size += strlen(loader.layer_libs[i].lib_name) + 1;
+    }
+
+    free(lib_str);
+    lib_str = malloc(size);
+    if (!lib_str)
+        return XGL_ERROR_OUT_OF_MEMORY;
+
+   pStr = lib_str;
+   for (i = 0; i < loader.layer_count; i++) {
+        strncat((char *) pStr, loader.layer_libs[i].lib_name, strlen(loader.layer_libs[i].lib_name));
+        strcat((char *) pStr, ":");
+    }
+    return XGL_SUCCESS;
+}
+
+static void init_dispatch_table(XGL_LAYER_DISPATCH_TABLE *tab, GetProcAddrType fpGPA, XGL_PHYSICAL_GPU gpu)
+{
+    tab->GetProcAddr = fpGPA;
+    tab->InitAndEnumerateGpus = fpGPA(gpu, (const XGL_CHAR *) "xglInitAndEnumerateGpus");
+    tab->GetGpuInfo = fpGPA(gpu, (const XGL_CHAR *) "xglGetGpuInfo");
+    tab->CreateDevice = fpGPA(gpu, (const XGL_CHAR *) "xglCreateDevice");
+    tab->DestroyDevice = fpGPA(gpu, (const XGL_CHAR *) "xglDestroyDevice");
+    tab->GetExtensionSupport = fpGPA(gpu, (const XGL_CHAR *) "xglGetExtensionSupport");
+    tab->GetDeviceQueue = fpGPA(gpu, (const XGL_CHAR *) "xglGetDeviceQueue");
+    tab->QueueSubmit = fpGPA(gpu, (const XGL_CHAR *) "xglQueueSubmit");
+    tab->QueueSetGlobalMemReferences = fpGPA(gpu, (const XGL_CHAR *) "xglQueueSetGlobalMemReferences");
+    tab->QueueWaitIdle = fpGPA(gpu, (const XGL_CHAR *) "xglQueueWaitIdle");
+    tab->DeviceWaitIdle = fpGPA(gpu, (const XGL_CHAR *) "xglDeviceWaitIdle");
+    tab->GetMemoryHeapCount = fpGPA(gpu, (const XGL_CHAR *) "xglGetMemoryHeapCount");
+    tab->GetMemoryHeapInfo = fpGPA(gpu, (const XGL_CHAR *) "xglGetMemoryHeapInfo");
+    tab->AllocMemory = fpGPA(gpu, (const XGL_CHAR *) "xglAllocMemory");
+    tab->FreeMemory = fpGPA(gpu, (const XGL_CHAR *) "xglFreeMemory");
+    tab->SetMemoryPriority = fpGPA(gpu, (const XGL_CHAR *) "xglSetMemoryPriority");
+    tab->MapMemory = fpGPA(gpu, (const XGL_CHAR *) "xglMapMemory");
+    tab->UnmapMemory = fpGPA(gpu, (const XGL_CHAR *) "xglUnmapMemory");
+    tab->PinSystemMemory = fpGPA(gpu, (const XGL_CHAR *) "xglPinSystemMemory");
+    tab->RemapVirtualMemoryPages = fpGPA(gpu, (const XGL_CHAR *) "xglRemapVirtualMemoryPages");
+    tab->GetMultiGpuCompatibility = fpGPA(gpu, (const XGL_CHAR *) "xglGetMultiGpuCompatibility");
+    tab->OpenSharedMemory = fpGPA(gpu, (const XGL_CHAR *) "xglOpenSharedMemory");
+    tab->OpenSharedQueueSemaphore = fpGPA(gpu, (const XGL_CHAR *) "xglOpenSharedQueueSemaphore");
+    tab->OpenPeerMemory = fpGPA(gpu, (const XGL_CHAR *) "xglOpenPeerMemory");
+    tab->OpenPeerImage = fpGPA(gpu, (const XGL_CHAR *) "xglOpenPeerImage");
+    tab->DestroyObject = fpGPA(gpu, (const XGL_CHAR *) "xglDestroyObject");
+    tab->GetObjectInfo = fpGPA(gpu, (const XGL_CHAR *) "xglGetObjectInfo");
+    tab->BindObjectMemory = fpGPA(gpu, (const XGL_CHAR *) "xglBindObjectMemory");
+    tab->CreateFence = fpGPA(gpu, (const XGL_CHAR *) "xglCreateFence");
+    tab->GetFenceStatus = fpGPA(gpu, (const XGL_CHAR *) "xglGetFenceStatus");
+    tab->WaitForFences = fpGPA(gpu, (const XGL_CHAR *) "xglWaitForFences");
+    tab->CreateQueueSemaphore = fpGPA(gpu, (const XGL_CHAR *) "xglCreateQueueSemaphore");
+    tab->SignalQueueSemaphore = fpGPA(gpu, (const XGL_CHAR *) "xglSignalQueueSemaphore");
+    tab->WaitQueueSemaphore = fpGPA(gpu, (const XGL_CHAR *) "xglWaitQueueSemaphore");
+    tab->CreateEvent = fpGPA(gpu, (const XGL_CHAR *) "xglCreateEvent");
+    tab->GetEventStatus = fpGPA(gpu, (const XGL_CHAR *) "xglGetEventStatus");
+    tab->SetEvent = fpGPA(gpu, (const XGL_CHAR *) "xglSetEvent");
+    tab->ResetEvent = fpGPA(gpu, (const XGL_CHAR *) "xglResetEvent");
+    tab->CreateQueryPool = fpGPA(gpu, (const XGL_CHAR *) "xglCreateQueryPool");
+    tab->GetQueryPoolResults = fpGPA(gpu, (const XGL_CHAR *) "xglGetQueryPoolResults");
+    tab->GetFormatInfo = fpGPA(gpu, (const XGL_CHAR *) "xglGetFormatInfo");
+    tab->CreateImage = fpGPA(gpu, (const XGL_CHAR *) "xglCreateImage");
+    tab->GetImageSubresourceInfo = fpGPA(gpu, (const XGL_CHAR *) "xglGetImageSubresourceInfo");
+    tab->CreateImageView = fpGPA(gpu, (const XGL_CHAR *) "xglCreateImageView");
+    tab->CreateColorAttachmentView = fpGPA(gpu, (const XGL_CHAR *) "xglCreateColorAttachmentView");
+    tab->CreateDepthStencilView = fpGPA(gpu, (const XGL_CHAR *) "xglCreateDepthStencilView");
+    tab->CreateShader = fpGPA(gpu, (const XGL_CHAR *) "xglCreateShader");
+    tab->CreateGraphicsPipeline = fpGPA(gpu, (const XGL_CHAR *) "xglCreateGraphicsPipeline");
+    tab->CreateComputePipeline = fpGPA(gpu, (const XGL_CHAR *) "xglCreateComputePipeline");
+    tab->StorePipeline = fpGPA(gpu, (const XGL_CHAR *) "xglStorePipeline");
+    tab->LoadPipeline = fpGPA(gpu, (const XGL_CHAR *) "xglLoadPipeline");
+    tab->CreatePipelineDelta = fpGPA(gpu, (const XGL_CHAR *) "xglCreatePipelineDelta");
+    tab->CreateSampler = fpGPA(gpu, (const XGL_CHAR *) "xglCreateSampler");
+    tab->CreateDescriptorSet = fpGPA(gpu, (const XGL_CHAR *) "xglCreateDescriptorSet");
+    tab->BeginDescriptorSetUpdate = fpGPA(gpu, (const XGL_CHAR *) "xglBeginDescriptorSetUpdate");
+    tab->EndDescriptorSetUpdate = fpGPA(gpu, (const XGL_CHAR *) "xglEndDescriptorSetUpdate");
+    tab->AttachSamplerDescriptors = fpGPA(gpu, (const XGL_CHAR *) "xglAttachSamplerDescriptors");
+    tab->AttachImageViewDescriptors = fpGPA(gpu, (const XGL_CHAR *) "xglAttachImageViewDescriptors");
+    tab->AttachMemoryViewDescriptors = fpGPA(gpu, (const XGL_CHAR *) "xglAttachMemoryViewDescriptors");
+    tab->AttachNestedDescriptors = fpGPA(gpu, (const XGL_CHAR *) "xglAttachNestedDescriptors");
+    tab->ClearDescriptorSetSlots = fpGPA(gpu, (const XGL_CHAR *) "xglClearDescriptorSetSlots");
+    tab->CreateViewportState = fpGPA(gpu, (const XGL_CHAR *) "xglCreateViewportState");
+    tab->CreateRasterState = fpGPA(gpu, (const XGL_CHAR *) "xglCreateRasterState");
+    tab->CreateMsaaState = fpGPA(gpu, (const XGL_CHAR *) "xglCreateMsaaState");
+    tab->CreateColorBlendState = fpGPA(gpu, (const XGL_CHAR *) "xglCreateColorBlendState");
+    tab->CreateDepthStencilState = fpGPA(gpu, (const XGL_CHAR *) "xglCreateDepthStencilState");
+    tab->CreateCommandBuffer = fpGPA(gpu, (const XGL_CHAR *) "xglCreateCommandBuffer");
+    tab->BeginCommandBuffer = fpGPA(gpu, (const XGL_CHAR *) "xglBeginCommandBuffer");
+    tab->EndCommandBuffer = fpGPA(gpu, (const XGL_CHAR *) "xglEndCommandBuffer");
+    tab->ResetCommandBuffer = fpGPA(gpu, (const XGL_CHAR *) "xglResetCommandBuffer");
+    tab->CmdBindPipeline = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindPipeline");
+    tab->CmdBindPipelineDelta = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindPipelineDelta");
+    tab->CmdBindStateObject = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindStateObject");
+    tab->CmdBindDescriptorSet = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindDescriptorSet");
+    tab->CmdBindDynamicMemoryView = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindDynamicMemoryView");
+    tab->CmdBindIndexData = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindIndexData");
+    tab->CmdBindAttachments = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBindAttachments");
+    tab->CmdPrepareMemoryRegions = fpGPA(gpu, (const XGL_CHAR *) "xglCmdPrepareMemoryRegions");
+    tab->CmdPrepareImages = fpGPA(gpu, (const XGL_CHAR *) "xglCmdPrepareImages");
+    tab->CmdDraw = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDraw");
+    tab->CmdDrawIndexed = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDrawIndexed");
+    tab->CmdDrawIndirect = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDrawIndirect");
+    tab->CmdDrawIndexedIndirect = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDrawIndexedIndirect");
+    tab->CmdDispatch = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDispatch");
+    tab->CmdDispatchIndirect = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDispatchIndirect");
+    tab->CmdCopyMemory = fpGPA(gpu, (const XGL_CHAR *) "xglCmdCopyMemory");
+    tab->CmdCopyImage = fpGPA(gpu, (const XGL_CHAR *) "xglCmdCopyImage");
+    tab->CmdCopyMemoryToImage = fpGPA(gpu, (const XGL_CHAR *) "xglCmdCopyMemoryToImage");
+    tab->CmdCopyImageToMemory = fpGPA(gpu, (const XGL_CHAR *) "xglCmdCopyImageToMemory");
+    tab->CmdCloneImageData = fpGPA(gpu, (const XGL_CHAR *) "xglCmdCloneImageData");
+    tab->CmdUpdateMemory = fpGPA(gpu, (const XGL_CHAR *) "xglCmdUpdateMemory");
+    tab->CmdFillMemory = fpGPA(gpu, (const XGL_CHAR *) "xglCmdFillMemory");
+    tab->CmdClearColorImage = fpGPA(gpu, (const XGL_CHAR *) "xglCmdClearColorImage");
+    tab->CmdClearColorImageRaw = fpGPA(gpu, (const XGL_CHAR *) "xglCmdClearColorImageRaw");
+    tab->CmdClearDepthStencil = fpGPA(gpu, (const XGL_CHAR *) "xglCmdClearDepthStencil");
+    tab->CmdResolveImage = fpGPA(gpu, (const XGL_CHAR *) "xglCmdResolveImage");
+    tab->CmdSetEvent = fpGPA(gpu, (const XGL_CHAR *) "xglCmdSetEvent");
+    tab->CmdResetEvent = fpGPA(gpu, (const XGL_CHAR *) "xglCmdResetEvent");
+    tab->CmdMemoryAtomic = fpGPA(gpu, (const XGL_CHAR *) "xglCmdMemoryAtomic");
+    tab->CmdBeginQuery = fpGPA(gpu, (const XGL_CHAR *) "xglCmdBeginQuery");
+    tab->CmdEndQuery = fpGPA(gpu, (const XGL_CHAR *) "xglCmdEndQuery");
+    tab->CmdResetQueryPool = fpGPA(gpu, (const XGL_CHAR *) "xglCmdResetQueryPool");
+    tab->CmdWriteTimestamp = fpGPA(gpu, (const XGL_CHAR *) "xglCmdWriteTimestamp");
+    tab->CmdInitAtomicCounters = fpGPA(gpu, (const XGL_CHAR *) "xglCmdInitAtomicCounters");
+    tab->CmdLoadAtomicCounters = fpGPA(gpu, (const XGL_CHAR *) "xglCmdLoadAtomicCounters");
+    tab->CmdSaveAtomicCounters = fpGPA(gpu, (const XGL_CHAR *) "xglCmdSaveAtomicCounters");
+    tab->DbgSetValidationLevel = fpGPA(gpu, (const XGL_CHAR *) "xglDbgSetValidationLevel");
+    tab->DbgRegisterMsgCallback = fpGPA(gpu, (const XGL_CHAR *) "xglDbgRegisterMsgCallback");
+    tab->DbgUnregisterMsgCallback = fpGPA(gpu, (const XGL_CHAR *) "xglDbgUnregisterMsgCallback");
+    tab->DbgSetMessageFilter = fpGPA(gpu, (const XGL_CHAR *) "xglDbgSetMessageFilter");
+    tab->DbgSetObjectTag = fpGPA(gpu, (const XGL_CHAR *) "xglDbgSetObjectTag");
+    tab->DbgSetGlobalOption = fpGPA(gpu, (const XGL_CHAR *) "xglDbgSetGlobalOption");
+    tab->DbgSetDeviceOption = fpGPA(gpu, (const XGL_CHAR *) "xglDbgSetDeviceOption");
+    tab->CmdDbgMarkerBegin = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDbgMarkerBegin");
+    tab->CmdDbgMarkerEnd = fpGPA(gpu, (const XGL_CHAR *) "xglCmdDbgMarkerEnd");
+    tab->WsiX11AssociateConnection = fpGPA(gpu, (const XGL_CHAR *) "xglWsiX11AssociateConnection");
+    tab->WsiX11GetMSC = fpGPA(gpu, (const XGL_CHAR *) "xglWsiX11GetMSC");
+    tab->WsiX11CreatePresentableImage = fpGPA(gpu, (const XGL_CHAR *) "xglWsiX11CreatePresentableImage");
+    tab->WsiX11QueuePresent = fpGPA(gpu, (const XGL_CHAR *) "xglWsiX11QueuePresent");
+}
+
+extern XGL_UINT ActivateLayers(XGL_PHYSICAL_GPU *gpu)
+{
+    static bool layer_installed = false;
+    //const struct loader_icd *icd;
+    /* activate any layer libraries */
+    if (loader.layer_count > 0 && !layer_installed) {
+
+        //todo get icd from gpu
+        //icd = loader.icds;  // We are only going to configure the first driver
+        //SetDispatchType IcdSetDispatch = dlsym(icd->handle, "xglSetDispatch");
+
+        // TODO For now just assume  all layers scanned will be  activated in the order they were scanned
+        XGL_BASE_LAYER_OBJECT *gpuObj = (XGL_BASE_LAYER_OBJECT *) *gpu;
+        XGL_BASE_LAYER_OBJECT *nextGpuObj;
+        GetProcAddrType nextGPA = gpuObj->pGPA;
+        for (XGL_INT i = loader.layer_count - 1; i >= 0; i--) {
+
+            if ((loader.layer_libs[i].lib_handle = dlopen((const char *) &(loader.layer_libs[i].lib_name), RTLD_LAZY | RTLD_DEEPBIND)) == NULL) {
+                loader_log(XGL_DBG_MSG_ERROR, 0, "Failed to open layer library %s got error %d", loader.layer_libs[i].lib_name, dlerror());
+                continue;
+            } else {
+                loader_log(XGL_DBG_MSG_UNKNOWN, 0, "Inserting layer lib %s",loader.layer_libs[i].lib_name);
+            }
+
+            //create newly wrapped gpu object
+            nextGpuObj = malloc(sizeof(XGL_BASE_LAYER_OBJECT));
+            if (! nextGpuObj)
+                loader_log(XGL_DBG_MSG_ERROR, 0, "Failed to malloc Gpu object for layer");
+            nextGpuObj->pGPA = nextGPA;
+            nextGpuObj->baseObject = gpuObj->baseObject;
+            nextGpuObj->nextObject = gpuObj;
+            gpuObj = nextGpuObj;
+
+            nextGPA = dlsym(loader.layer_libs[i].lib_handle, "xglGetProcAddr");
+            if (!nextGPA) {
+                loader_log(XGL_DBG_MSG_ERROR, 0, "Failed to find xglGetProcAddr in layer %s", loader.layer_libs[i].lib_name);
+                continue;
+            }
+
+            if (i == 0) {
+                //TODO handle multiple icd case
+                init_dispatch_table(loader.loader_dispatch, nextGPA, gpuObj);
+                //IcdSetDispatch(&new_table, true);
+            }
+        }
+        *gpu = ((XGL_PHYSICAL_GPU *) gpuObj);
+        layer_installed = true;
+    }
+    return loader.layer_count;
+}
+
+#if 0
+LOADER_EXPORT XGL_RESULT xglSetLayers(const XGL_CHAR * pStr)
+{
+    char *p, *next, *str;
+    int len;
+    XGL_UINT count= 0;
+
+    if (!pStr)
+        return XGL_ERROR_INVALID_POINTER;
+
+    p= (char *) pStr;
+    str = malloc(strlen(p) + 1);
+    do {
+        next = strchr(p, ':');
+        if (next == NULL) {
+            len = strlen(p);
+            next = p + len;
+        }
+        else {
+            len = next - p;
+            *(char *) next = '\0';
+            next++;
+        }
+
+        strncpy(str, p, len);
+        str[len] = '\0';
+        if (layer_lib_sort(str, count))
+           count++;
+        p = next;
+
+    } while (*p  && count < MAX_LAYER_LIBRARIES-1);
+
+    for (int i = count; i < loader.layer_count; i++) {
+        loader.layer_libs[i].lib_handle = NULL;
+    }
+
+    loader.layer_count = count;
+    free(str);
+
+    return XGL_SUCCESS;
+}
+
+#endif
+
+LOADER_EXPORT void * XGLAPI xglGetProcAddr(XGL_PHYSICAL_GPU gpu, const XGL_CHAR * pName) {
+
+    if (gpu == NULL)
+        return NULL;
+
+    XGL_LAYER_DISPATCH_TABLE * disp_table = * (XGL_LAYER_DISPATCH_TABLE **) gpu;
+    if (disp_table == NULL)
+        return NULL;
+
+    if (!strncmp("xglGetProcAddr", (const char *) pName, sizeof("xglGetProcAddr")))
+        return xglGetProcAddr;
+    else if (!strncmp("xglInitAndEnumerateGpus", (const char *) pName, sizeof("xglInitAndEnumerateGpus")))
+        return disp_table->InitAndEnumerateGpus;
+    else if (!strncmp("xglGetGpuInfo", (const char *) pName, sizeof ("xglGetGpuInfo")))
+        return disp_table->GetGpuInfo;
+    else if (!strncmp("xglCreateDevice", (const char *) pName, sizeof ("xglCreateDevice")))
+        return disp_table->CreateDevice;
+    else if (!strncmp("xglDestroyDevice", (const char *) pName, sizeof ("xglDestroyDevice")))
+        return disp_table->DestroyDevice;
+    else if (!strncmp("xglGetExtensionSupport", (const char *) pName, sizeof ("xglGetExtensionSupport")))
+        return disp_table->GetExtensionSupport;
+    else if (!strncmp("xglGetDeviceQueue", (const char *) pName, sizeof ("xglGetDeviceQueue")))
+        return disp_table->GetDeviceQueue;
+    else if (!strncmp("xglQueueSubmit", (const char *) pName, sizeof ("xglQueueSubmit")))
+        return disp_table->QueueSubmit;
+    else if (!strncmp("xglQueueSetGlobalMemReferences", (const char *) pName, sizeof ("xglQueueSetGlobalMemReferences")))
+        return disp_table->QueueSetGlobalMemReferences;
+    else if (!strncmp("xglQueueWaitIdle", (const char *) pName, sizeof ("xglQueueWaitIdle")))
+        return disp_table->QueueWaitIdle;
+    else if (!strncmp("xglDeviceWaitIdle", (const char *) pName, sizeof ("xglDeviceWaitIdle")))
+        return disp_table->DeviceWaitIdle;
+    else if (!strncmp("xglGetMemoryHeapCount", (const char *) pName, sizeof ("xglGetMemoryHeapCount")))
+        return disp_table->GetMemoryHeapCount;
+    else if (!strncmp("xglGetMemoryHeapInfo", (const char *) pName, sizeof ("xglGetMemoryHeapInfo")))
+        return disp_table->GetMemoryHeapInfo;
+    else if (!strncmp("xglAllocMemory", (const char *) pName, sizeof ("xglAllocMemory")))
+        return disp_table->AllocMemory;
+    else if (!strncmp("xglFreeMemory", (const char *) pName, sizeof ("xglFreeMemory")))
+        return disp_table->FreeMemory;
+    else if (!strncmp("xglSetMemoryPriority", (const char *) pName, sizeof ("xglSetMemoryPriority")))
+        return disp_table->SetMemoryPriority;
+    else if (!strncmp("xglMapMemory", (const char *) pName, sizeof ("xglMapMemory")))
+        return disp_table->MapMemory;
+    else if (!strncmp("xglUnmapMemory", (const char *) pName, sizeof ("xglUnmapMemory")))
+        return disp_table->UnmapMemory;
+    else if (!strncmp("xglPinSystemMemory", (const char *) pName, sizeof ("xglPinSystemMemory")))
+        return disp_table->PinSystemMemory;
+    else if (!strncmp("xglRemapVirtualMemoryPages", (const char *) pName, sizeof ("xglRemapVirtualMemoryPages")))
+        return disp_table->RemapVirtualMemoryPages;
+    else if (!strncmp("xglGetMultiGpuCompatibility", (const char *) pName, sizeof ("xglGetMultiGpuCompatibility")))
+        return disp_table->GetMultiGpuCompatibility;
+    else if (!strncmp("xglOpenSharedMemory", (const char *) pName, sizeof ("xglOpenSharedMemory")))
+        return disp_table->OpenSharedMemory;
+    else if (!strncmp("xglOpenSharedQueueSemaphore", (const char *) pName, sizeof ("xglOpenSharedQueueSemaphore")))
+        return disp_table->OpenSharedQueueSemaphore;
+    else if (!strncmp("xglOpenPeerMemory", (const char *) pName, sizeof ("xglOpenPeerMemory")))
+        return disp_table->OpenPeerMemory;
+    else if (!strncmp("xglOpenPeerImage", (const char *) pName, sizeof ("xglOpenPeerImage")))
+        return disp_table->OpenPeerImage;
+    else if (!strncmp("xglDestroyObject", (const char *) pName, sizeof ("xglDestroyObject")))
+        return disp_table->DestroyObject;
+    else if (!strncmp("xglGetObjectInfo", (const char *) pName, sizeof ("xglGetObjectInfo")))
+        return disp_table->GetObjectInfo;
+    else if (!strncmp("xglBindObjectMemory", (const char *) pName, sizeof ("xglBindObjectMemory")))
+        return disp_table->BindObjectMemory;
+    else if (!strncmp("xglCreateFence", (const char *) pName, sizeof ("xgllCreateFence")))
+        return disp_table->CreateFence;
+    else if (!strncmp("xglGetFenceStatus", (const char *) pName, sizeof ("xglGetFenceStatus")))
+        return disp_table->GetFenceStatus;
+    else if (!strncmp("xglWaitForFences", (const char *) pName, sizeof ("xglWaitForFences")))
+        return disp_table->WaitForFences;
+    else if (!strncmp("xglCreateQueueSemaphore", (const char *) pName, sizeof ("xgllCreateQueueSemaphore")))
+        return disp_table->CreateQueueSemaphore;
+    else if (!strncmp("xglSignalQueueSemaphore", (const char *) pName, sizeof ("xglSignalQueueSemaphore")))
+        return disp_table->SignalQueueSemaphore;
+    else if (!strncmp("xglWaitQueueSemaphore", (const char *) pName, sizeof ("xglWaitQueueSemaphore")))
+        return disp_table->WaitQueueSemaphore;
+    else if (!strncmp("xglCreateEvent", (const char *) pName, sizeof ("xgllCreateEvent")))
+        return disp_table->CreateEvent;
+    else if (!strncmp("xglGetEventStatus", (const char *) pName, sizeof ("xglGetEventStatus")))
+        return disp_table->GetEventStatus;
+    else if (!strncmp("xglSetEvent", (const char *) pName, sizeof ("xglSetEvent")))
+        return disp_table->SetEvent;
+    else if (!strncmp("xglResetEvent", (const char *) pName, sizeof ("xgllResetEvent")))
+        return disp_table->ResetEvent;
+    else if (!strncmp("xglCreateQueryPool", (const char *) pName, sizeof ("xglCreateQueryPool")))
+        return disp_table->CreateQueryPool;
+    else if (!strncmp("xglGetQueryPoolResults", (const char *) pName, sizeof ("xglGetQueryPoolResults")))
+        return disp_table->GetQueryPoolResults;
+    else if (!strncmp("xglGetFormatInfo", (const char *) pName, sizeof ("xglGetFormatInfo")))
+        return disp_table->GetFormatInfo;
+    else if (!strncmp("xglCreateImage", (const char *) pName, sizeof ("xglCreateImage")))
+        return disp_table->CreateImage;
+    else if (!strncmp("xglGetImageSubresourceInfo", (const char *) pName, sizeof ("xglGetImageSubresourceInfo")))
+        return disp_table->GetImageSubresourceInfo;
+    else if (!strncmp("xglCreateImageView", (const char *) pName, sizeof ("xglCreateImageView")))
+        return disp_table->CreateImageView;
+    else if (!strncmp("xglCreateColorAttachmentView", (const char *) pName, sizeof ("xglCreateColorAttachmentView")))
+        return disp_table->CreateColorAttachmentView;
+    else if (!strncmp("xglCreateDepthStencilView", (const char *) pName, sizeof ("xglCreateDepthStencilView")))
+        return disp_table->CreateDepthStencilView;
+    else if (!strncmp("xglCreateShader", (const char *) pName, sizeof ("xglCreateShader")))
+        return disp_table->CreateShader;
+    else if (!strncmp("xglCreateGraphicsPipeline", (const char *) pName, sizeof ("xglCreateGraphicsPipeline")))
+        return disp_table->CreateGraphicsPipeline;
+    else if (!strncmp("xglCreateComputePipeline", (const char *) pName, sizeof ("xglCreateComputePipeline")))
+        return disp_table->CreateComputePipeline;
+    else if (!strncmp("xglStorePipeline", (const char *) pName, sizeof ("xglStorePipeline")))
+        return disp_table->StorePipeline;
+    else if (!strncmp("xglLoadPipeline", (const char *) pName, sizeof ("xglLoadPipeline")))
+        return disp_table->LoadPipeline;
+    else if (!strncmp("xglCreatePipelineDelta", (const char *) pName, sizeof ("xglCreatePipelineDelta")))
+        return disp_table->CreatePipelineDelta;
+    else if (!strncmp("xglCreateSampler", (const char *) pName, sizeof ("xglCreateSampler")))
+        return disp_table->CreateSampler;
+    else if (!strncmp("xglCreateDescriptorSet", (const char *) pName, sizeof ("xglCreateDescriptorSet")))
+        return disp_table->CreateDescriptorSet;
+    else if (!strncmp("xglBeginDescriptorSetUpdate", (const char *) pName, sizeof ("xglBeginDescriptorSetUpdate")))
+        return disp_table->BeginDescriptorSetUpdate;
+    else if (!strncmp("xglEndDescriptorSetUpdate", (const char *) pName, sizeof ("xglEndDescriptorSetUpdate")))
+        return disp_table->EndDescriptorSetUpdate;
+    else if (!strncmp("xglAttachSamplerDescriptors", (const char *) pName, sizeof ("xglAttachSamplerDescriptors")))
+        return disp_table->AttachSamplerDescriptors;
+    else if (!strncmp("xglAttachImageViewDescriptors", (const char *) pName, sizeof ("xglAttachImageViewDescriptors")))
+        return disp_table->AttachImageViewDescriptors;
+    else if (!strncmp("xglAttachMemoryViewDescriptors", (const char *) pName, sizeof ("xglAttachMemoryViewDescriptors")))
+        return disp_table->AttachMemoryViewDescriptors;
+    else if (!strncmp("xglAttachNestedDescriptors", (const char *) pName, sizeof ("xglAttachNestedDescriptors")))
+        return disp_table->AttachNestedDescriptors;
+    else if (!strncmp("xglClearDescriptorSetSlots", (const char *) pName, sizeof ("xglClearDescriptorSetSlots")))
+        return disp_table->ClearDescriptorSetSlots;
+    else if (!strncmp("xglCreateViewportState", (const char *) pName, sizeof ("xglCreateViewportState")))
+        return disp_table->CreateViewportState;
+    else if (!strncmp("xglCreateRasterState", (const char *) pName, sizeof ("xglCreateRasterState")))
+        return disp_table->CreateRasterState;
+    else if (!strncmp("xglCreateMsaaState", (const char *) pName, sizeof ("xglCreateMsaaState")))
+        return disp_table->CreateMsaaState;
+    else if (!strncmp("xglCreateColorBlendState", (const char *) pName, sizeof ("xglCreateColorBlendState")))
+        return disp_table->CreateColorBlendState;
+    else if (!strncmp("xglCreateDepthStencilState", (const char *) pName, sizeof ("xglCreateDepthStencilState")))
+        return disp_table->CreateDepthStencilState;
+    else if (!strncmp("xglCreateCommandBuffer", (const char *) pName, sizeof ("xglCreateCommandBuffer")))
+        return disp_table->CreateCommandBuffer;
+    else if (!strncmp("xglBeginCommandBuffer", (const char *) pName, sizeof ("xglBeginCommandBuffer")))
+        return disp_table->BeginCommandBuffer;
+    else if (!strncmp("xglEndCommandBuffer", (const char *) pName, sizeof ("xglEndCommandBuffer")))
+        return disp_table->EndCommandBuffer;
+    else if (!strncmp("xglResetCommandBuffer", (const char *) pName, sizeof ("xglResetCommandBuffer")))
+        return disp_table->ResetCommandBuffer;
+    else if (!strncmp("xglCmdBindPipeline", (const char *) pName, sizeof ("xglCmdBindPipeline")))
+        return disp_table->CmdBindPipeline;
+    else if (!strncmp("xglCmdBindPipelineDelta", (const char *) pName, sizeof ("xglCmdBindPipelineDelta")))
+        return disp_table->CmdBindPipelineDelta;
+    else if (!strncmp("xglCmdBindStateObject", (const char *) pName, sizeof ("xglCmdBindStateObject")))
+        return disp_table->CmdBindStateObject;
+    else if (!strncmp("xglCmdBindDescriptorSet", (const char *) pName, sizeof ("xglCmdBindDescriptorSet")))
+        return disp_table->CmdBindDescriptorSet;
+    else if (!strncmp("xglCmdBindDynamicMemoryView", (const char *) pName, sizeof ("xglCmdBindDynamicMemoryView")))
+        return disp_table->CmdBindDynamicMemoryView;
+    else if (!strncmp("xglCmdBindIndexData", (const char *) pName, sizeof ("xglCmdBindIndexData")))
+        return disp_table->CmdBindIndexData;
+    else if (!strncmp("xglCmdBindAttachments", (const char *) pName, sizeof ("xglCmdBindAttachments")))
+        return disp_table->CmdBindAttachments;
+    else if (!strncmp("xglCmdPrepareMemoryRegions", (const char *) pName, sizeof ("xglCmdPrepareMemoryRegions")))
+        return disp_table->CmdPrepareMemoryRegions;
+    else if (!strncmp("xglCmdPrepareImages", (const char *) pName, sizeof ("xglCmdPrepareImages")))
+        return disp_table->CmdPrepareImages;
+    else if (!strncmp("xglCmdDraw", (const char *) pName, sizeof ("xglCmdDraw")))
+        return disp_table->CmdDraw;
+    else if (!strncmp("xglCmdDrawIndexed", (const char *) pName, sizeof ("xglCmdDrawIndexed")))
+        return disp_table->CmdDrawIndexed;
+    else if (!strncmp("xglCmdDrawIndirect", (const char *) pName, sizeof ("xglCmdDrawIndirect")))
+        return disp_table->CmdDrawIndirect;
+    else if (!strncmp("xglCmdDrawIndexedIndirect", (const char *) pName, sizeof ("xglCmdDrawIndexedIndirect")))
+        return disp_table->CmdDrawIndexedIndirect;
+    else if (!strncmp("xglCmdDispatch", (const char *) pName, sizeof ("xglCmdDispatch")))
+        return disp_table->CmdDispatch;
+    else if (!strncmp("xglCmdDispatchIndirect", (const char *) pName, sizeof ("xglCmdDispatchIndirect")))
+        return disp_table->CmdDispatchIndirect;
+    else if (!strncmp("xglCmdCopyMemory", (const char *) pName, sizeof ("xglCmdCopyMemory")))
+        return disp_table->CmdCopyMemory;
+    else if (!strncmp("xglCmdCopyImage", (const char *) pName, sizeof ("xglCmdCopyImage")))
+        return disp_table->CmdCopyImage;
+    else if (!strncmp("xglCmdCopyMemoryToImage", (const char *) pName, sizeof ("xglCmdCopyMemoryToImage")))
+        return disp_table->CmdCopyMemoryToImage;
+    else if (!strncmp("xglCmdCopyImageToMemory", (const char *) pName, sizeof ("xglCmdCopyImageToMemory")))
+        return disp_table->CmdCopyImageToMemory;
+    else if (!strncmp("xglCmdCloneImageData", (const char *) pName, sizeof ("xglCmdCloneImageData")))
+        return disp_table->CmdCloneImageData;
+    else if (!strncmp("xglCmdUpdateMemory", (const char *) pName, sizeof ("xglCmdUpdateMemory")))
+        return disp_table->CmdUpdateMemory;
+    else if (!strncmp("xglCmdFillMemory", (const char *) pName, sizeof ("xglCmdFillMemory")))
+        return disp_table->CmdFillMemory;
+    else if (!strncmp("xglCmdClearColorImage", (const char *) pName, sizeof ("xglCmdClearColorImage")))
+        return disp_table->CmdClearColorImage;
+    else if (!strncmp("xglCmdClearColorImageRaw", (const char *) pName, sizeof ("xglCmdClearColorImageRaw")))
+        return disp_table->CmdClearColorImageRaw;
+    else if (!strncmp("xglCmdClearDepthStencil", (const char *) pName, sizeof ("xglCmdClearDepthStencil")))
+        return disp_table->CmdClearDepthStencil;
+    else if (!strncmp("xglCmdResolveImage", (const char *) pName, sizeof ("xglCmdResolveImage")))
+        return disp_table->CmdResolveImage;
+    else if (!strncmp("xglCmdSetEvent", (const char *) pName, sizeof ("xglCmdSetEvent")))
+        return disp_table->CmdSetEvent;
+    else if (!strncmp("xglCmdResetEvent", (const char *) pName, sizeof ("xglCmdResetEvent")))
+        return disp_table->CmdResetEvent;
+    else if (!strncmp("xglCmdMemoryAtomic", (const char *) pName, sizeof ("xglCmdMemoryAtomic")))
+        return disp_table->CmdMemoryAtomic;
+    else if (!strncmp("xglCmdBeginQuery", (const char *) pName, sizeof ("xglCmdBeginQuery")))
+        return disp_table->CmdBeginQuery;
+    else if (!strncmp("xglCmdEndQuery", (const char *) pName, sizeof ("xglCmdEndQuery")))
+        return disp_table->CmdEndQuery;
+    else if (!strncmp("xglCmdResetQueryPool", (const char *) pName, sizeof ("xglCmdResetQueryPool")))
+        return disp_table->CmdResetQueryPool;
+    else if (!strncmp("xglCmdWriteTimestamp", (const char *) pName, sizeof ("xglCmdWriteTimestamp")))
+        return disp_table->CmdWriteTimestamp;
+    else if (!strncmp("xglCmdInitAtomicCounters", (const char *) pName, sizeof ("xglCmdInitAtomicCounters")))
+        return disp_table->CmdInitAtomicCounters;
+    else if (!strncmp("xglCmdLoadAtomicCounters", (const char *) pName, sizeof ("xglCmdLoadAtomicCounters")))
+        return disp_table->CmdLoadAtomicCounters;
+    else if (!strncmp("xglCmdSaveAtomicCounters", (const char *) pName, sizeof ("xglCmdSaveAtomicCounters")))
+        return disp_table->CmdSaveAtomicCounters;
+    else if (!strncmp("xglDbgSetValidationLevel", (const char *) pName, sizeof ("xglDbgSetValidationLevel")))
+        return disp_table->DbgSetValidationLevel;
+    else if (!strncmp("xglDbgRegisterMsgCallback", (const char *) pName, sizeof ("xglDbgRegisterMsgCallback")))
+        return disp_table->DbgRegisterMsgCallback;
+    else if (!strncmp("xglDbgUnregisterMsgCallback", (const char *) pName, sizeof ("xglDbgUnregisterMsgCallback")))
+        return disp_table->DbgUnregisterMsgCallback;
+    else if (!strncmp("xglDbgSetMessageFilter", (const char *) pName, sizeof ("xglDbgSetMessageFilter")))
+        return disp_table->DbgSetMessageFilter;
+    else if (!strncmp("xglDbgSetObjectTag", (const char *) pName, sizeof ("xglDbgSetObjectTag")))
+        return disp_table->DbgSetObjectTag;
+    else if (!strncmp("xglDbgSetGlobalOption", (const char *) pName, sizeof ("xglDbgSetGlobalOption")))
+        return disp_table->DbgSetGlobalOption;
+    else if (!strncmp("xglDbgSetDeviceOption", (const char *) pName, sizeof ("xglDbgSetDeviceOption")))
+        return disp_table->DbgSetDeviceOption;
+    else if (!strncmp("xglCmdDbgMarkerBegin", (const char *) pName, sizeof ("xglCmdDbgMarkerBegin")))
+        return disp_table->CmdDbgMarkerBegin;
+    else if (!strncmp("xglCmdDbgMarkerEnd", (const char *) pName, sizeof ("xglCmdDbgMarkerEnd")))
+        return disp_table->CmdDbgMarkerEnd;
+    else if (!strncmp("xglWsiX11AssociateConnection", (const char *) pName, sizeof("xglWsiX11AssociateConnection")))
+        return disp_table->WsiX11AssociateConnection;
+    else if (!strncmp("xglWsiX11GetMSC", (const char *) pName, sizeof("xglWsiX11GetMSC")))
+        return disp_table->WsiX11GetMSC;
+    else if (!strncmp("xglWsiX11CreatePresentableImage", (const char *) pName, sizeof("xglWsiX11CreatePresentableImage")))
+        return disp_table->WsiX11CreatePresentableImage;
+    else if (!strncmp("xglWsiX11QueuePresent", (const char *) pName, sizeof("xglWsiX11QueuePresent")))
+        return disp_table->WsiX11QueuePresent;
+    else  {
+        XGL_BASE_LAYER_OBJECT* gpuw = (XGL_BASE_LAYER_OBJECT *) gpu;
+        if (gpuw->pGPA == NULL)
+            return NULL;
+        return gpuw->pGPA(gpuw->nextObject, pName);
+    }
+}
+
 LOADER_EXPORT XGL_RESULT XGLAPI xglInitAndEnumerateGpus(const XGL_APPLICATION_INFO* pAppInfo, const XGL_ALLOC_CALLBACKS* pAllocCb, XGL_UINT maxGpus, XGL_UINT* pGpuCount, XGL_PHYSICAL_GPU* pGpus)
 {
     static pthread_once_t once = PTHREAD_ONCE_INIT;
@@ -366,6 +971,8 @@
     icd = loader.icds;
     while (icd) {
         XGL_PHYSICAL_GPU gpus[XGL_MAX_PHYSICAL_GPUS];
+        XGL_BASE_LAYER_OBJECT * wrappedGpus;
+        GetProcAddrType getProcAddr = icd->GetProcAddr;
         XGL_UINT n, max = maxGpus - count;
 
         if (max > XGL_MAX_PHYSICAL_GPUS) {
@@ -374,7 +981,18 @@
 
         res = icd->InitAndEnumerateGpus(pAppInfo, pAllocCb, max, &n, gpus);
         if (res == XGL_SUCCESS && n) {
-            memcpy(pGpus + count, gpus, sizeof(*pGpus) * n);
+            wrappedGpus = (XGL_BASE_LAYER_OBJECT*) malloc(n * sizeof(XGL_BASE_LAYER_OBJECT));
+            loader.loader_dispatch = (XGL_LAYER_DISPATCH_TABLE *) malloc(n * sizeof(XGL_LAYER_DISPATCH_TABLE));
+            for (int i = 0; i < n; i++) {
+                (wrappedGpus + i)->baseObject = gpus[i];
+                (wrappedGpus + i)->pGPA = getProcAddr; //loader.loader_dispatch + i; //getProcAddr;
+                (wrappedGpus + i)->nextObject = gpus[i];
+                memcpy(pGpus + count, &wrappedGpus, sizeof(*pGpus));
+                init_dispatch_table(loader.loader_dispatch + i, getProcAddr, wrappedGpus + i);
+                const XGL_LAYER_DISPATCH_TABLE * *disp = (const XGL_LAYER_DISPATCH_TABLE *  *) gpus[i];
+                *disp = loader.loader_dispatch + i;
+            }
+
             count += n;
 
             if (count >= maxGpus) {
@@ -385,6 +1003,10 @@
         icd = icd->next;
     }
 
+    /* get layer libraries */
+    if (!loader.layer_scaned)
+        layer_lib_scan(NULL, true, false);
+
     *pGpuCount = count;
 
     return (count > 0) ? XGL_SUCCESS : res;
diff --git a/loader/loader.h b/loader/loader.h
index b76f634..d819142 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -31,7 +31,7 @@
 #include <xgl.h>
 #include <xglDbg.h>
 #include <xglWsiX11Ext.h>
-
+#include <xglLayer.h>
 #if defined(__GNUC__) && __GNUC__ >= 4
 #  define LOADER_EXPORT __attribute__((visibility("default")))
 #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
@@ -40,4 +40,6 @@
 #  define LOADER_EXPORT
 #endif
 
+extern XGL_UINT ActivateLayers(XGL_PHYSICAL_GPU *gpu);
+#define MAX_LAYER_LIBRARIES 16
 #endif /* LOADER_H */